diff --git a/main.js b/main.js index fb62569..b9eb67a 100644 --- a/main.js +++ b/main.js @@ -203,7 +203,7 @@ app.on('ready', () => { break; case 'joinChannel': // 设置某个人的设备列表 - await connection.invoke(str, data.roomNum, data.enableMicr, data.enableCamera) + await connection.invoke(str, data.roomNum, data.enableMicr, data.enableCamera, data.isRoomManager || false) break; case 'levelChannel': // 设置某个人的设备列表 @@ -712,14 +712,14 @@ function mainWindowHide() { } const startSignalr = async (user) => { - connection = new signalR.HubConnectionBuilder().withAutomaticReconnect() + connection = new signalR.HubConnectionBuilder() .withUrl(`${env === 'development' ? 'http://192.168.2.9:5192' : 'https://meeting-api.23544.com/pc'}/session-manage`, { skipNegotiation: true, transport: signalR.HttpTransportType.WebSockets, accessTokenFactory: () => user.token }) + .withAutomaticReconnect([0, 3000, 3000, 3000]) .build(); - onStart() mainWindow.webContents.send('changeLocalStorage', { isSignalr: true, reconnect: true, @@ -735,13 +735,21 @@ const startSignalr = async (user) => { reconnect: false, }); }); + connection.start(); } const onStart = async () => { if (connection) { + if (connection.state === signalR.HubConnectionState.Disconnected) { + connection.start().then(() => { + mainWindow.webContents.send('changeLocalStorage', { + reconnect: true, + }); + }).catch((err) => { + + }); + } if (connection.state !== signalR.HubConnectionState.Connected) { - connection.start(); - } else { setTimeout(onStart, 3000); } } diff --git a/src/page/Home/User/index.tsx b/src/page/Home/User/index.tsx index 46b6fd2..4a1ad55 100644 --- a/src/page/Home/User/index.tsx +++ b/src/page/Home/User/index.tsx @@ -423,7 +423,7 @@ const User: React.FC = () => { if (!addUserFrom.UserName && isCreateUser !== 'batch') { return message.error('请输入用户名称!') } - if (!addUserFrom.year) { + if (addUserFrom.year === '') { return message.error('请输入届!') } if (isCreateUser === 'add') { diff --git a/src/page/Meeting/index.tsx b/src/page/Meeting/index.tsx index 7ec1aa7..5d79b88 100644 --- a/src/page/Meeting/index.tsx +++ b/src/page/Meeting/index.tsx @@ -166,7 +166,7 @@ const Meeting: React.FC = () => { const [currentLookUserAccount, setCurrentLookUserAccount] = useState('') const [recorder, setRecorder] = useState('') const [_currentRequestSpeakType, setCurrentRequestSpeakType] = useState<'video' | 'audio' | ''>('') - const [_mediaStream, setMediaStream] = useState('') + const [_mediaStream, setMediaStream] = useState([]) const [isShare, setIsShare] = useState(null) const [isSharePopConfirm, setIsSharePopConfirm] = useState(false) const [_isNetworkDisconnected, setIsNetworkDisconnected] = useState(false) @@ -191,6 +191,7 @@ const Meeting: React.FC = () => { let userInfo = JSON.parse(storage.getItem('user') as string) const msgTips = '您不是管理员或发言人,无法开启此功能!' const channel = new BroadcastChannel('meeting_channel'); + let storeDevice: any; useEffect(() => { let time: NodeJS.Timeout; setUser(userInfo) @@ -841,7 +842,7 @@ const Meeting: React.FC = () => { const mp4Path = `${setting.recordingFilesPath}会议录制_${state.roomName}_${state.channelId}_${dayjs().format('YYYY年MM月DD日HH时mm分')}.webm`; await fs.writeFile(mp4Path, buffer, {}); setRecorder('') - setMediaStream('') + setMediaStream([]) confirm({ title: '提示', icon: , @@ -974,12 +975,6 @@ const Meeting: React.FC = () => { view: null, channelId: connection.channelId, }); - setCurrentVideoId((res: any) => { - if (Number(res) === remoteUid) { - getShowUser(); - } - return res - }) } }, onAudioVolumeIndication: async (speakers: AudioVolumeInfo[]) => { @@ -1036,22 +1031,24 @@ const Meeting: React.FC = () => { onRtcStats: async (stats: RtcStats) => { setNetworkOther(stats) }, - onConnectionStateChanged: async (_connection: RtcConnection, stateNumber: ConnectionStateType, reason: ConnectionChangedReasonType) => { + onConnectionStateChanged: async (_connection: RtcConnection, state: ConnectionStateType, reason: ConnectionChangedReasonType) => { const reconnectingCode = [2, 16, 11, 13, 14, 12] - if (stateNumber === 4 && reconnectingCode.indexOf(reason) >= 0) { - message.error('网络断开,请检查网络') - meetingDisconnectedRef.current.changeModal(true) - setIsScreenCapture(bool => { - if (bool) { - setIsNetworkDisconnected(true) - stopScreenCapture() - } - return bool - }) - } else if (stateNumber === 3) { + if (state === 4 && reconnectingCode.indexOf(reason) >= 0) { + + } else if (state === 3) { meetingDisconnectedRef.current.changeModal(false) } }, + onConnectionLost: () => { + meetingDisconnectedRef.current.changeModal(true) + setIsScreenCapture(bool => { + if (bool) { + setIsNetworkDisconnected(true) + stopScreenCapture() + } + return bool + }) + }, onLocalVideoStateChanged: async (_source: VideoSourceType, _state: LocalVideoStreamState, reason: LocalVideoStreamReason) => { if (reason === 12) { setIsScreenCapture(bool => { @@ -1214,6 +1211,12 @@ const Meeting: React.FC = () => { } return res }) + setCurrentVideoId((res: any) => { + if (Number(res) === Number(item.uid)) { + getShowUser(); + } + return res + }) break; case 'OperAllMicr': setRoomUserList((res: any) => { @@ -1489,7 +1492,7 @@ const Meeting: React.FC = () => { // 录制所有音频输入设备 audioInputDevices.forEach(async device => { const micStream = await navigator.mediaDevices.getUserMedia({ audio: { deviceId: { exact: device.deviceId } } }); - setMediaStream(micStream); + setMediaStream((res: any) => [...res, micStream]); const micSoundSource = audioCtx.createMediaStreamSource(micStream); micSoundSource.connect(systemSoundDestination); }) @@ -1557,9 +1560,11 @@ const Meeting: React.FC = () => { return res }) setMediaStream((res: any) => { - if (res) { - res.getTracks().forEach((track: any) => { - track.stop() + if (res.length) { + res.forEach((item: any) => { + item.getTracks().forEach((track: any) => { + track.stop() + }); }); } return res @@ -1730,21 +1735,21 @@ const Meeting: React.FC = () => { break; case 'reconnect': if (e.value == true) { - await window.electron.onInvoke('joinChannel', { - roomNum: state.channelId, - enableMicr: !footerList[0][0].active, - enableCamera: !footerList[0][1].active - }) message.success('网络已连接。') meetingDisconnectedRef.current.changeModal(false) - setRoomUserList((res: any) => { + async function setUserStatus(res: any) { let userItem = res.find((item: any) => item.uid === userInfo.uid) + await window.electron.onInvoke('joinChannel', { + roomNum: state.channelId, + enableMicr: !storeDevice[0][0].active, + enableCamera: !storeDevice[0][1].active, + isRoomManager: userItem.isRoomManager + }) + await getRoomUser() + await getShowUser() if (userItem.isRoomManager) { - DeleteRoomManager({ - roomId: state.roomId, - roomNum: state.channelId, - userId: userInfo.uid - }) + await postOpenMicr(!storeDevice[0][0].active, userInfo.uid) + await postOpenCamera(!storeDevice[0][1].active, userInfo.uid) } setIsNetworkDisconnected(bool => { if (bool) { @@ -1754,13 +1759,17 @@ const Meeting: React.FC = () => { }) setIsScreenCapture(bool => { if (bool) { - allUserLook(userItem.uid, userItem.userName) + allUserLook(userItem.screenShareId, userItem.userName) } return bool }) + } + setRoomUserList((res: any) => { + setUserStatus(res) return res }) - + } else { + storeDevice = JSON.parse(JSON.stringify(footerList)) } break; } @@ -2925,7 +2934,7 @@ const networkIcon = (network: number) => { switch (network) { case 0: return - + diff --git a/src/utils/package/agora.ts b/src/utils/package/agora.ts index 63b7516..041dab9 100644 --- a/src/utils/package/agora.ts +++ b/src/utils/package/agora.ts @@ -150,7 +150,7 @@ export const agora = { }, 1000); }, // 事件回调 - registerEventHandler: ({ onJoinChannelSuccess, onUserJoined, onUserOffline, onAudioVolumeIndication, onNetworkQuality, onRtcStats, onConnectionStateChanged, onLocalVideoStateChanged }: any) => { + registerEventHandler: ({ onJoinChannelSuccess, onUserJoined, onUserOffline, onAudioVolumeIndication, onNetworkQuality, onRtcStats, onConnectionStateChanged, onLocalVideoStateChanged, onConnectionLost }: any) => { rtcEngine.registerEventHandler({ // 监听本地用户加入频道事件 onJoinChannelSuccess: async (connection: RtcConnection, elapsed: number) => { @@ -196,6 +196,10 @@ export const agora = { onLocalVideoStateChanged: async (source: VideoSourceType, state: LocalVideoStreamState, reason: LocalVideoStreamReason) => { await onLocalVideoStateChanged?.(source, state, reason) }, + // 网络连接中断,且 SDK 无法在 10 秒内连接服务器回调。 + onConnectionLost: (_connection: RtcConnection) => { + onConnectionLost?.() + } }); }, // 获取视图模式