Просмотр исходного кода

refactor(student): 重构WebSocket连接逻辑,提取复用函数

1. 提取cleanupWebSocketConnection统一清理双Socket连接
2. 提取initializeYjsData封装Yjs数据初始化逻辑
3. 修复并启用token定时更新逻辑
4. 调整连接状态日志与错误处理逻辑
lsc 13 часов назад
Родитель
Сommit
713e79c8fc
1 измененных файлов с 120 добавлено и 72 удалено
  1. 120 72
      src/views/Student/index.vue

+ 120 - 72
src/views/Student/index.vue

@@ -4137,6 +4137,21 @@ const manualReconnect = () => {
   createWebSocketConnection()
   createWebSocketConnection()
 }
 }
 
 
+// 清理 WebSocket 连接(提取为独立函数)
+const cleanupWebSocketConnection = () => {
+  if (providerSocket.value) {
+    // 销毁连接
+    providerSocket.value.destroy()
+    providerSocket.value = null
+  }
+  
+  if (docSocket.value) {
+    // 注意:doc 会被 provider.destroy() 自动销毁,不需要手动 destroy
+    // 但如果 provider 已经被销毁,这里置空即可
+    docSocket.value = null
+  }
+}
+
 // 创建WebSocket连接
 // 创建WebSocket连接
 const createWebSocketConnection = async (type = 1) => {
 const createWebSocketConnection = async (type = 1) => {
   if (!api.yweb_socket || isConnecting.value) return
   if (!api.yweb_socket || isConnecting.value) return
@@ -4150,6 +4165,7 @@ const createWebSocketConnection = async (type = 1) => {
     //   providerSocket.value.destroy()
     //   providerSocket.value.destroy()
     //   providerSocket.value = null
     //   providerSocket.value = null
     // }
     // }
+    cleanupWebSocketConnection()
     
     
     // 清理之前的 token 更新定时器
     // 清理之前的 token 更新定时器
     if (authTokenUpdateTimer.value) {
     if (authTokenUpdateTimer.value) {
@@ -4181,10 +4197,10 @@ const createWebSocketConnection = async (type = 1) => {
     
     
     // 启动定期更新 token
     // 启动定期更新 token
     // 30分钟后再次更新
     // 30分钟后再次更新
-    // if (authTokenUpdateTimer.value) {
-    //   clearTimeout(authTokenUpdateTimer.value)
-    // }
-    // authTokenUpdateTimer.value = setTimeout(updateAuthToken, 30 * 60 * 1000) as unknown as NodeJS.Timeout
+    if (authTokenUpdateTimer.value) {
+      clearTimeout(authTokenUpdateTimer.value)
+    }
+    authTokenUpdateTimer.value = setTimeout(updateAuthToken, 30 * 60 * 1000) as unknown as NodeJS.Timeout
     // authTokenUpdateTimer.value = setTimeout(updateAuthToken, 10 * 1000) as unknown as NodeJS.Timeout
     // authTokenUpdateTimer.value = setTimeout(updateAuthToken, 10 * 1000) as unknown as NodeJS.Timeout
 
 
     providerSocket.value.on('status', (event: any) => {
     providerSocket.value.on('status', (event: any) => {
@@ -4206,94 +4222,126 @@ const createWebSocketConnection = async (type = 1) => {
         messageInit()
         messageInit()
         // 连接成功后,读取当前计时器状态(Map)
         // 连接成功后,读取当前计时器状态(Map)
         if (docSocket.value) {
         if (docSocket.value) {
-          yTimerState.value = docSocket.value.getMap('timerState')
-          const snapshot = yTimerState.value.toJSON()
-          applyTimerStateSnapshot(snapshot)
-          // 激光笔 map
-          yLaserState.value = docSocket.value.getMap('laserState')
-          const ls = yLaserState.value.toJSON()
-          applyLaserStateSnapshot(ls)
-          yLaserState.value.observe(() => {
-            const s = yLaserState.value.toJSON()
-            applyLaserStateSnapshot(s)
-          })
-          // 画图 map
-          yWritingBoardState.value = docSocket.value.getMap('writingBoardState')
-          const ws = yWritingBoardState.value.toJSON()
-          console.log('📝 WebSocket连接成功,读取画图状态:', ws, '当前幻灯片:', currentSlide.value?.id)
-          // 延迟应用,确保 currentSlide 已初始化
-          nextTick(() => {
-            // 如果 currentSlide 还没准备好,再等一帧
-            if (currentSlide.value && currentSlide.value.id) {
-              applyWritingBoardStateSnapshot(ws)
-            }
-            else {
-              // 如果还没准备好,等待 currentSlide 变化(最多等待3秒)
-              let timeoutId: any = null
-              const unwatch = watch(() => currentSlide.value?.id, (slideId) => {
-                if (slideId) {
-                  applyWritingBoardStateSnapshot(ws)
-                  unwatch()
-                  if (timeoutId) clearTimeout(timeoutId)
-                }
-              }, { immediate: true })
-              // 3秒后如果还没准备好,强制应用一次
-              timeoutId = setTimeout(() => {
-                if (currentSlide.value && currentSlide.value.id) {
-                  applyWritingBoardStateSnapshot(ws)
-                }
-                unwatch()
-              }, 3000)
-            }
-          })
-          yWritingBoardState.value.observe(() => {
-            const s = yWritingBoardState.value.toJSON()
-            if (currentSlide.value && currentSlide.value.id) {
-              applyWritingBoardStateSnapshot(s)
-            }
-          })
+          initializeYjsData()
         }
         }
       }
       }
       else if (event.status === 'disconnected') {
       else if (event.status === 'disconnected') {
-        console.log('👉 WebSocket连接断开')
-        connectionStatus.value = 'disconnected'
+        console.log('👉 连接断开,等待自动重连...')
         isConnecting.value = false
         isConnecting.value = false
-        setTimeout(() => {
-          createWebSocketConnection(2)
-        }, 5000)
-      }
-      else if (event.status === 'closed') {
-        console.log('👉 WebSocket连接断开closed')
-        updateAuthToken().then(() => {
-          providerSocket.value.connect() // 尝试重新连接
-        })
       }
       }
+      // else if (event.status === 'disconnected') {
+      //   console.log('👉 WebSocket连接断开')
+      //   connectionStatus.value = 'disconnected'
+      //   isConnecting.value = false
+      //   setTimeout(() => {
+      //     createWebSocketConnection(2)
+      //   }, 5000)
+      // }
+      // else if (event.status === 'closed') {
+      //   console.log('👉 WebSocket连接断开closed')
+      //   updateAuthToken().then(() => {
+      //     providerSocket.value.connect() // 尝试重新连接
+      //   })
+      // }
     })
     })
-    
-    // 监听连接错误
+
+    // ✅ 只记录日志,不干预状态
     providerSocket.value.on('connection-error', (error: any) => {
     providerSocket.value.on('connection-error', (error: any) => {
-      console.error('👉 WebSocket连接错误:', error)
-      connectionStatus.value = 'disconnected'
-      isConnecting.value = false
-      setTimeout(() => {
-        createWebSocketConnection(2)
-      }, 5000)
+      console.error('👉 WebSocket 连接错误(将自动重连):', error)
     })
     })
     
     
+    providerSocket.value.on('connection-close', (event: any) => {
+      console.log('👉 WebSocket 连接关闭(将自动重连):', event)
+    })
+    // 监听连接错误
+    // providerSocket.value.on('connection-error', (error: any) => {
+    //   console.error('👉 WebSocket连接错误:', error)
+    // connectionStatus.value = 'disconnected'
+    // isConnecting.value = false
+    // setTimeout(() => {
+    //   createWebSocketConnection(2)
+    // }, 5000)
+    // })
+    
+    // 监听连接关闭
+    // providerSocket.value.on('connection-close', (error: any) => {
+    //   console.error('👉 WebSocket连接关闭:', error)
+    // connectionStatus.value = 'disconnected'
+    // isConnecting.value = false
+    // setTimeout(() => {
+    //   updateAuthToken().then(() => {
+    //     providerSocket.value.connect() // 尝试重新连接
+    //   })
+    // }, 5000)
+    // })
   }
   }
   catch (error) {
   catch (error) {
     console.error('👉 创建WebSocket连接失败:', error)
     console.error('👉 创建WebSocket连接失败:', error)
     connectionStatus.value = 'disconnected'
     connectionStatus.value = 'disconnected'
     isConnecting.value = false
     isConnecting.value = false
-    setTimeout(() => {
-      createWebSocketConnection(2)
-    }, 5000)
+    // setTimeout(() => {
+    //   createWebSocketConnection(2)
+    // }, 5000)
+    cleanupWebSocketConnection()
+    setTimeout(createWebSocketConnection, 5000)
   }
   }
 
 
   // 启动 socket 连接检查定时器
   // 启动 socket 连接检查定时器
   // startSocketCheckTimer()
   // startSocketCheckTimer()
 }
 }
 
 
+// ✅ 提取业务初始化逻辑
+const initializeYjsData = () => {
+  if (!docSocket.value) return
+  
+  yTimerState.value = docSocket.value.getMap('timerState')
+  const snapshot = yTimerState.value.toJSON()
+  applyTimerStateSnapshot(snapshot)
+  // 激光笔 map
+  yLaserState.value = docSocket.value.getMap('laserState')
+  const ls = yLaserState.value.toJSON()
+  applyLaserStateSnapshot(ls)
+  yLaserState.value.observe(() => {
+    const s = yLaserState.value.toJSON()
+    applyLaserStateSnapshot(s)
+  })
+  // 画图 map
+  yWritingBoardState.value = docSocket.value.getMap('writingBoardState')
+  const ws = yWritingBoardState.value.toJSON()
+  console.log('📝 WebSocket连接成功,读取画图状态:', ws, '当前幻灯片:', currentSlide.value?.id)
+  // 延迟应用,确保 currentSlide 已初始化
+  nextTick(() => {
+    // 如果 currentSlide 还没准备好,再等一帧
+    if (currentSlide.value && currentSlide.value.id) {
+      applyWritingBoardStateSnapshot(ws)
+    }
+    else {
+      // 如果还没准备好,等待 currentSlide 变化(最多等待3秒)
+      let timeoutId: any = null
+      const unwatch = watch(() => currentSlide.value?.id, (slideId) => {
+        if (slideId) {
+          applyWritingBoardStateSnapshot(ws)
+          unwatch()
+          if (timeoutId) clearTimeout(timeoutId)
+        }
+      }, { immediate: true })
+      // 3秒后如果还没准备好,强制应用一次
+      timeoutId = setTimeout(() => {
+        if (currentSlide.value && currentSlide.value.id) {
+          applyWritingBoardStateSnapshot(ws)
+        }
+        unwatch()
+      }, 3000)
+    }
+  })
+  yWritingBoardState.value.observe(() => {
+    const s = yWritingBoardState.value.toJSON()
+    if (currentSlide.value && currentSlide.value.id) {
+      applyWritingBoardStateSnapshot(s)
+    }
+  })
+}
+
 // 处理连接断开
 // 处理连接断开
 const handleDisconnection = () => {
 const handleDisconnection = () => {
   if (reconnectAttempts.value < maxReconnectAttempts.value) {
   if (reconnectAttempts.value < maxReconnectAttempts.value) {