bzkf3 2 år sedan
förälder
incheckning
b6a77b5011

+ 38 - 3
src/components/rtc-dialog/index.vue

@@ -342,7 +342,9 @@ async function handleAudioChatStart() {
           console.info('摄像头权限验证结束 : ', camerasInfo)
         }
       } catch (error) {
-        console.error(error)
+        console.error('权限验证失败 :', error)
+        showFailToast('应用未进行相关授权,请授权后重启应用后再尝试')
+        handleClose()
       }
       console.info('相关权限验证结束')
     }
@@ -421,13 +423,46 @@ async function handleAudioChatAccept() {
     console.info('发送接听信息结束')
     // ...
     if (RTC_USE) {
+      {
+
+        console.info('验证相关权限')
+        // 手机版跳过验证
+        try {
+          console.info('验证麦克风权限')
+          const microInfo = await AgoraRTC.getMicrophones()
+          console.info('麦克风权限验证结束 : ', microInfo)
+          if (mode === 'video') {
+            console.info('验证摄像头权限')
+            const camerasInfo = await AgoraRTC.getCameras()
+            console.info('摄像头权限验证结束 : ', camerasInfo)
+          }
+        } catch (error) {
+          console.error('权限验证失败 :', error)
+          showFailToast('应用未进行相关授权,请授权后重启应用后再尝试')
+          try {
+            const fullSendData = await handleInfoEdit({ dxzl_status: '4' }, '出错')
+            socketSend(ws2, {
+              dxzl_stu_user_id: dyaw_xlfw_zxhd!.dxz_stu_user_id,
+              dxzl_tea_user_id: dyaw_xlfw_zxhd!.dxz_tea_user_id,
+              operate: CHAT_OPERATION.DENY,
+              fullSendData
+            })
+            isOpen = false
+            console.info('[success] handleAudioChatError end')
+          } catch (error) {
+            console.error('[error] handleAudioChatError', error)
+          }
+        }
+        console.info('相关权限验证结束')
+      }
       console.info('初始化rtc频道')
       initRtcClient()
+      console.info('初始化rtc频道结束')
 
       await getRtcOption()
-      console.info('初始化rtc频道')
+      console.info('加入会话频道')
       await rtcInstance.client!.join(rtcOptions.appId, rtcOptions.channel, rtcOptions?.token, /*rtcOptions.uid*/ user.user_id);
-      console.info('初始化rtc频道结束,开始创建本地音视频轨道')
+      console.info('加入会话频道结束,开始创建本地音视频轨道')
       rtcInstance.localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack();
       console.info('创建本地音频轨道结束,发布本地音频')
       await rtcInstance.client!.publish(rtcInstance.localAudioTrack);

+ 5 - 2
src/pages/student/consult.vue

@@ -122,9 +122,12 @@ async function handleClickSend(val?: string) {
           { teacher: teacher!.user_id, student: user.user_id },
           {
             message(socketRes: TSocketRes<type_dyaw_xlfw_zxhd_log>) {
-              if (socketRes.from_client_name.endsWith('teacher')) {
-                infoList.push(socketRes.content)
+              if (socketRes.from_client_name!.endsWith('teacher')) {
+                infoList.push(socketRes.content!)
               }
+            },
+            reload(){
+              location.reload()
             }
           }
         )

+ 6 - 3
src/pages/teacher/consult.vue

@@ -17,13 +17,16 @@ onMounted(() => {
     {
       message(socketRes: TSocketRes<type_dyaw_xlfw_zxhd_log & { operate: CHAT_OPERATION }>) {
         console.info('enter message', socketRes);
-        if (socketRes.from_client_name.endsWith('student')) {
+        if (socketRes.from_client_name!.endsWith('student')) {
           // infoList.push(socketRes.content)
-          if (socketRes.content.dxzl_tea_user_id === user.user_id) {
+          if (socketRes.content!.dxzl_tea_user_id === user.user_id) {
             console.info('start publisher ')
             RtcDialogRef!.publisher(socketRes.content)
           }
         }
+      },
+      reload() {
+        location.reload()
       }
     }
   )
@@ -35,7 +38,7 @@ onBeforeUnmount(() => {
 })
 
 function openRtcDialog(dyaw_xlfw_zxhd: type_dyaw_xlfw_zxhd, type: 'audio' | 'video') {
-  if(!ws2||ws2.readyState !== 1){
+  if (!ws2 || ws2.readyState !== 1) {
     ws2 = createSocket(
       { teacher: user.user_id, student: '*' },
       {

+ 7 - 5
src/pages/teacher/consult/chat-list.vue

@@ -73,19 +73,19 @@ async function handleClickSend(val?: string) {
         ...reqDate,
         dxzl_id: `${res.data.insert_id}`
       }
-      if (!ws||ws.readyState !== 1) {
+      if (!ws || ws.readyState !== 1) {
         ws = createSocket(
           { teacher: user.user_id, student: dyaw_xlfw_zxhd.dxz_stu_user_id },
           {
             message(socketRes: TSocketRes<type_dyaw_xlfw_zxhd_log & { $?: boolean, dxz_stu_user_id?: string, dyaw_xlfw_zxhd: type_dyaw_xlfw_zxhd }>) {
-              if (socketRes.from_client_name.endsWith('student')) {
-                if (socketRes.content.$) {
+              if (socketRes.from_client_name!.endsWith('student')) {
+                if (socketRes.content!.$) {
                   if (socketRes.content?.dxz_stu_user_id === dyaw_xlfw_zxhd?.dxz_stu_user_id) {
                     dyaw_xlfw_zxhd = socketRes.content.dyaw_xlfw_zxhd
                   }
                   return;
                 }
-                infoList.push(socketRes.content)
+                infoList.push(socketRes.content!)
                 request({
                   url: '/dyaw/xlfw_zxhd_log/index',
                   data: {
@@ -94,8 +94,10 @@ async function handleClickSend(val?: string) {
                     limit: 0
                   }
                 })
-
               }
+            },
+            reload() {
+              location.reload()
             }
           }
         )

+ 41 - 12
src/utils/ws.ts

@@ -1,11 +1,13 @@
 import user, { UserRole } from '~/store/user';
 
 export type TSocketRes<T> = {
-  content: T
-  from_client_id: string
-  from_client_name: string
+  content?: T,
+  client_name?: string
+  client_id?: string
+  from_client_id?: string
+  from_client_name?: string
   time: string
-  to_client_id: string
+  to_client_id?: string
   type: string
 }
 
@@ -13,20 +15,40 @@ const CLIENT_NAME = `${user.user_id}|${user.user_realname}|${UserRole}`
 export function createSocket(
   options: { teacher: string, student: string },
   hooks: {
-    message: Function
+    message: Function,
+    reload?: Function
   }
 ) {
-  const ws = new WebSocket("wss://socket.bozedu.net")
+  const ws: WebSocket & { LastPingTime?: number } = new WebSocket("wss://socket.bozedu.net")
+  ws.LastPingTime = Date.now()
+
+  setInterval(() => {
+    const now = Date.now()
+    console.log(`[SOCKET 心跳检测](${options.teacher}_${options.student}) :`);
+    console.log(new Date(now).toLocaleString(), new Date(ws.LastPingTime!).toLocaleString(), `${(now - ws.LastPingTime!) / 1000}s`);
+
+    if (ws.LastPingTime && now - ws.LastPingTime > 15000) {
+      console.log(`[SOCKET PONG](${options.teacher}_${options.student}): ${CLIENT_NAME}`);
+      // 重新连接
+      hooks?.reload?.()
+      ws.LastPingTime = Date.now()
+    }
+  }, 10000);
 
   ws.addEventListener('message', (e) => {
     if (e.data) {
       try {
         const data: TSocketRes<string> = JSON.parse(e.data)
+        if (data.type === 'ping') {
+          console.log(`[SOCKET PING](${options.teacher}_${options.student})`);
+          ws.LastPingTime = Date.now()
+          return
+        }
         if (CLIENT_NAME === data.from_client_name) return
         if (!['ping'].includes(data.type)) {
-          console.groupCollapsed(`Socket : ${data.type}-${data.from_client_name}`)
+          ws.LastPingTime = Date.now()
+          console.groupCollapsed(`[SOCKET ${data.type.toLocaleUpperCase()}](${options.teacher}_${options.student}) ${data.time} : ${data.client_name ?? data.from_client_name}`)
           console.log(data);
-          console.groupEnd();
         }
 
         if (data.type === 'login') {
@@ -36,16 +58,17 @@ export function createSocket(
         if (data.type === 'say') {
           const content = {
             ...data,
-            content: JSON.parse(decodeURIComponent(data.content))
+            content: JSON.parse(decodeURIComponent(data.content!))
           }
-          console.groupCollapsed(`├─ Socket Say:`)
           console.log(content);
-          console.groupEnd();
 
           hooks.message(content)
         }
+
       } catch (error) {
         console.error(error);
+      } finally {
+        console.groupEnd();
       }
     }
   })
@@ -55,6 +78,7 @@ export function createSocket(
   })
 
   ws.addEventListener('open', (e) => {
+    console.log(`[ws open](${options.teacher}_${options.student})`);
     ws.send(JSON.stringify({
       "type": "login",
       "client_name": CLIENT_NAME,
@@ -62,11 +86,16 @@ export function createSocket(
     }))
   })
 
+  ws.addEventListener('close', (e) => {
+    console.log(`[ws close](${options.teacher}_${options.student})`);
+  })
 
   return ws
 }
 
-export function socketSend(ws: WebSocket, content: unknown) {
+export function socketSend(ws: WebSocket & { LastPingTime?: number }, content: unknown) {
+  console.log('socketSend ws : ')
+  ws.LastPingTime = Date.now()
   if (ws.readyState === WebSocket.OPEN) {
     // WebSocket 连接已建立
     ws.send(