import { ref } from 'vue' import eventBus from '@/utils/eventBus' // 标志位区分是手动断开还是意外断开 let isManualDisconnect = false export const useWebSocket = { socket: null as WebSocket | null, // 声明 isConnected: ref(false), // 判断当前连接状态 reconnectAttempts: 0, // 当前重连数 maxReconnectAttempts: 5, // 最大重连数 reconnectInterval: 3000, // 重连间隔 lastUrl: '', // 保存最后连接的URL // 连接 WebSocket 服务器,监听相关事件 connect(url: string) { if (this.socket && this.socket.readyState === WebSocket.OPEN) { return } this.lastUrl = url this.socket = new WebSocket(url) this.socket.onopen = () => { this.isConnected.value = true this.reconnectAttempts = 0 heartCheck.start() console.log('WebSocket连接已打开') } this.socket.onclose = () => { this.isConnected.value = false console.log('WebSocket连接已关闭') heartCheck.stop() if (!isManualDisconnect) { this.reconnect(url) } } this.socket.onerror = (error: Event) => { console.error('WebSocket error:', error) } this.socket.onmessage = (event: MessageEvent) => { try { // console.log('收到消息:', event.data) const data = JSON.parse(event.data) || {} if (data.messageType) { eventBus.emit('socketMsg', data) } } catch (error) { console.error('WebSocket消息解析错误:', error) } } }, // 关闭链接 disconnect() { isManualDisconnect = true heartCheck.stop() if (this.socket) { this.socket.close() this.socket = null this.isConnected.value = false } this.reconnectAttempts = 0 }, // 尝试重连 reconnect(url?: string) { if (isManualDisconnect) { console.log('主动断开,无需重连') heartCheck.stop() return } if (this.reconnectAttempts < this.maxReconnectAttempts) { this.reconnectAttempts++ console.log(`重连次数 ${this.reconnectAttempts}`) // 清理旧连接 if (this.socket) { this.socket = null } setTimeout(() => { this.connect(url || this.lastUrl || '') }, this.reconnectInterval) } else { console.error(`已达到最大重连次数${this.maxReconnectAttempts},放弃重连`) heartCheck.stop() } }, // 发送消息 sendMessage(message: string) { if (this.isConnected.value && this.socket) { this.socket.send(message) // console.log('WebSocket 消息发送成功:', message) } else { console.error('WebSocket 连接未打开,无法发送消息') } }, getReadyState() { if (!this.socket) return '' return this.socket.readyState } } export const heartCheck = { timeout: null as NodeJS.Timeout | null, // 更具体的类型 timeoutInterval: 60000, // 心跳超时时间 start() { if (this.timeout) { console.warn('心跳检测已经启动') return } this.timeout = setInterval(() => { this.check() }, this.timeoutInterval) }, stop() { if (this.timeout) { clearInterval(this.timeout) this.timeout = null console.log('心跳检测已停止') } else { // console.warn('心跳检测未启动,无需停止') } }, check() { const readyState = useWebSocket.getReadyState() if (readyState === WebSocket.CLOSED || readyState === WebSocket.CLOSING) { console.log('心跳检测readyState:', readyState) console.error('WebSocket 连接已断开,尝试重连') this.stop() useWebSocket.reconnect() } else if (readyState === WebSocket.OPEN) { this.sendPing() } }, sendPing() { try { useWebSocket.sendMessage(JSON.stringify({ messageType: 'ping' })) } catch (error) { console.error('发送心跳消息时出错:', error) this.stop() // 停止心跳检测,如果消息发送失败,可能是连接已经断开 } } } export function initWebSocket(url: string) { useWebSocket.connect(url) } export function destroyWebSocket() { isManualDisconnect = true heartCheck.stop() useWebSocket.disconnect() }