| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- // src/utils/socket.js
- import { ElMessage } from 'element-plus'
- import { ROOTPATH2 } from '../comment/httpUrl.js'
- 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 { }
- }
- // 生成 tabId
- let tabId = sessionStorage.getItem('tabId')
- if (!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)
- /** 连接成功 */
- WSS.onopen = () => {
- 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) => {
- console.log('收到消息:', event.data)
- if (event.data === 'HeartBeat' || event.data === 'Pong') return;
- let msg
- try {
- msg = JSON.parse(event.data)
- } catch (e) {
- 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')
- localStorage.removeItem('companyId')
- if (store) store.dispatch('SET_DATA')
- if (router) router.push({ name: 'login' })
- }
- }
- /** 错误处理 */
- WSS.onerror = (err) => {
- console.error('WebSocket 错误:', err)
- }
- /** 连接关闭 */
- WSS.onclose = () => {
- 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('达到最大重连次数,停止重连')
- }
- }
- }
- }
- /** 获取 WebSocket 实例 */
- export function getSocket() {
- return WSS
- }
- /** 发送消息 */
- export function sendSocketMsg(data) {
- if (WSS && WSS.readyState === WebSocket.OPEN) {
- WSS.send(data)
- } else {
- console.warn('WebSocket 未连接,尝试重连后再发送')
- }
- }
- /** 关闭连接 */
- export function closeSocket() {
- manuallyClosed = true
- if (heartTimer) clearInterval(heartTimer)
- if (reconnectTimer) clearTimeout(reconnectTimer)
- if (WSS) {
- try { WSS.close() } catch { }
- WSS = null
- }
- }
|