wkw 6 月之前
父节点
当前提交
ebdf3e74c5
共有 3 个文件被更改,包括 71 次插入24 次删除
  1. 63 19
      comment/socket.js
  2. 8 1
      src/App.vue
  3. 0 4
      src/views/home.vue

+ 63 - 19
comment/socket.js

@@ -1,35 +1,59 @@
 // src/utils/socket.js
 import { ElMessage } from 'element-plus'
 import { ROOTPATH2 } from '../comment/httpUrl.js'
-var WSS = null // 全局唯一的 WebSocket 实例
+
+let WSS = null              // 全局唯一 WebSocket 实例
+let heartTimer = null       // 心跳定时器
+let reconnectTimer = null   // 重连定时器
+let reconnectCount = 0      // 当前重连次数
+const MAX_RECONNECT = 10    // 最大重连次数
+const RECONNECT_INTERVAL = 3000 // 重连间隔 3 秒
+let manuallyClosed = false
 
 /**
  * 连接 WebSocket
  * @param {string} userId 当前用户 ID
+ * @param {object} store Vuex store 实例
+ * @param {object} router Vue Router 实例
  */
 export function connectSocket(userId, store, router) {
     if (!userId) return
-    // 若已有连接则关闭
+    manuallyClosed = false
+
+    // 若已有连接则关闭旧连接
     if (WSS) {
-        try {
-            WSS.close()
-        } catch { }
+        try { WSS.close() } catch { }
     }
-    let tabId = sessionStorage.getItem('tabId');
+
+    // 生成 tabId
+    let tabId = sessionStorage.getItem('tabId')
     if (!tabId) {
-        tabId = Date.now() + '_' + Math.random().toString(36).slice(2);
-        sessionStorage.setItem('tabId', tabId);
+        tabId = Date.now() + '_' + Math.random().toString(36).slice(2)
+        sessionStorage.setItem('tabId', tabId)
     }
+
     const wsUrl = `${ROOTPATH2}${userId}?tabId=${tabId}`
     WSS = new WebSocket(wsUrl)
-    console.log('🔗 WebSocket 连接中:', wsUrl)
-    console.log(WSS)
+    console.log('WebSocket 连接中:', wsUrl)
+
+    /** 连接成功 */
     WSS.onopen = () => {
-        console.log('✅ WebSocket 已连接:', wsUrl)
+        console.log('WebSocket 已连接:', wsUrl)
+        reconnectCount = 0
+
+        // 启动心跳
+        if (heartTimer) clearInterval(heartTimer)
+        heartTimer = setInterval(() => {
+            if (WSS && WSS.readyState === WebSocket.OPEN) {
+                WSS.send('HeartBeat')
+            }
+        }, 5000)
     }
 
+    /** 接收消息 */
     WSS.onmessage = (event) => {
-        if (event.data === 'HeartBeat') return
+        console.log('收到消息:', event.data)
+        if (event.data === 'HeartBeat' || event.data === 'Pong') return
         let msg
         try {
             msg = JSON.parse(event.data)
@@ -37,14 +61,13 @@ export function connectSocket(userId, store, router) {
             console.warn('非 JSON 消息:', event.data)
             return
         }
+
         if (msg.type === 'kickOut') {
             ElMessage({
                 message: msg.content || '您的账号已在其他设备登录',
                 type: 'warning',
                 duration: 1500
             })
-
-            // 清空本地存储
             localStorage.removeItem('token')
             localStorage.removeItem('userId')
             localStorage.removeItem('userType')
@@ -55,12 +78,30 @@ export function connectSocket(userId, store, router) {
         }
     }
 
+    /** 错误处理 */
     WSS.onerror = (err) => {
-        console.error('WebSocket 错误:', err)
+        console.error('WebSocket 错误:', err)
     }
 
+    /** 连接关闭 */
     WSS.onclose = () => {
-        console.log('🔌 WebSocket 已关闭')
+        console.log('WebSocket 已关闭')
+
+        if (heartTimer) clearInterval(heartTimer)
+        WSS = null
+
+        // 自动重连
+        if (!manuallyClosed) {
+            if (reconnectCount < MAX_RECONNECT) {
+                reconnectCount++
+                console.warn(`WebSocket 断开,尝试第 ${reconnectCount} 次重连...`)
+                reconnectTimer = setTimeout(() => {
+                    connectSocket(userId, store, router)
+                }, RECONNECT_INTERVAL)
+            } else {
+                console.error('达到最大重连次数,停止重连')
+            }
+        }
     }
 }
 
@@ -74,14 +115,17 @@ export function sendSocketMsg(data) {
     if (WSS && WSS.readyState === WebSocket.OPEN) {
         WSS.send(data)
     } else {
-        console.warn('⚠️ WebSocket 未连接,无法发送')
+        console.warn('WebSocket 未连接,尝试重连后再发送')
     }
 }
 
 /** 关闭连接 */
 export function closeSocket() {
+    manuallyClosed = true
+    if (heartTimer) clearInterval(heartTimer)
+    if (reconnectTimer) clearTimeout(reconnectTimer)
     if (WSS) {
-        WSS.close()
+        try { WSS.close() } catch { }
         WSS = null
     }
-}
+}

+ 8 - 1
src/App.vue

@@ -1,4 +1,11 @@
-<script setup>
+<script>
+	export default {
+		created() {
+			const userId = localStorage.getItem('userId');
+			// 连接websocket
+			this.$socket.connectSocket(userId, this.$store, this.$router)
+		},
+	}
 </script>
 
 <template>

+ 0 - 4
src/views/home.vue

@@ -40,10 +40,6 @@
 			if (localStorage.getItem('token')) {
 				this.getUserInfo();
 			}
-			const userId = localStorage.getItem('userId');
-			// 连接websocket
-			this.$socket.connectSocket(userId, this.$store, this.$router)
-			
 		},
 		methods: {
 			//获取用户信息