import { goto_login_fun } from '@/api/request' export default class WebSocketUtil { /** * WebSocket工具类,用于管理WebSocket连接 * @param {string} url - WebSocket服务器地址 * @param {Object} options - 配置选项 * @param {number} [options.maxReconnectCount=5] - 最大重连次数 * @param {number} [options.reconnectInterval=3000] - 重连间隔时间(ms) * @param {number} [options.heartbeatInterval=30000] - 心跳间隔时间(ms) * @param {string|Object} [options.heartbeatMsg='ping'] - 心跳消息 */ constructor(url, options = {}) { this.url = url; this.options = options; this.socketTask = null; // WebSocket任务实例 this.reconnectTimer = null; // 重连计时器 this.reconnectCount = 0; // 当前重连次数 this.maxReconnectCount = options.maxReconnectCount || 5; // 最大重连次数 this.reconnectInterval = options.reconnectInterval || 3000; // 重连间隔(ms) this.heartbeatTimer = null; // 心跳计时器 this.heartbeatInterval = options.heartbeatInterval || 30000; // 心跳间隔(ms) this.heartbeatMsg = options.heartbeatMsg || 'ping'; // 心跳消息 this.isClose = false; // 手动关闭 this.callbacks = { open: [], // 连接打开回调 message: [], // 消息接收回调 close: [], // 连接关闭回调 error: [] // 错误处理回调 }; this.init(true); // 初始化WebSocket连接 } /** * 初始化WebSocket连接 */ init(flag = false) { if(flag) this.reconnectCount = 0 this.isClose = false; // 手动关闭 // 创建WebSocket连接 this.socketTask = uni.connectSocket({ url: this.url, header: this.options.header || {}, protocols: this.options.protocols || [], success: () => { console.log('WebSocket连接创建成功'); }, fail: (err) => { console.error('WebSocket连接创建失败', err); this.triggerEvent('error', err); this.tryReconnect(); // 连接失败时尝试重连 } }); // 监听WebSocket连接打开事件 this.socketTask.onOpen(() => { console.log('WebSocket连接已打开'); this.reconnectCount = 0; // 重置重连计数 clearInterval(this.reconnectTimer); // 清除重连计时器 // this.startHeartbeat(); // 启动心跳机制 this.triggerEvent('open'); // 触发连接打开事件 }); // 监听WebSocket消息接收事件 this.socketTask.onMessage((res) => { if(res.data){ const { rtnCode } = JSON.parse(res.data) // console.log('收到WebSocket消息', JSON.parse(res.data) ); if(['0005', 'QQ0005'].includes(rtnCode)) { clearInterval(this.reconnectTimer); this.reconnectTimer = null this.close() goto_login_fun(); return } }else{ clearInterval(this.reconnectTimer); // 清除重连计时器 this.reconnectTimer = null goto_login_fun(); return } this.triggerEvent('message', res); // 触发消息接收事件 }); // 监听WebSocket连接关闭事件 this.socketTask.onClose((res) => { console.log('WebSocket连接已关闭', res); clearInterval(this.heartbeatTimer); // 清除心跳计时器 this.triggerEvent('close', res); // 触发连接关闭事件 this.tryReconnect(); // 尝试重连 }); // 监听WebSocket错误事件 this.socketTask.onError((err) => { console.error('WebSocket发生错误', err); clearInterval(this.heartbeatTimer); // 清除心跳计时器 this.triggerEvent('error', err); // 触发错误事件 this.tryReconnect(); // 尝试重连 }); } /** * 注册事件回调 * @param {string} event - 事件名称(open/message/close/error) * @param {Function} callback - 回调函数 * @returns {WebSocketUtil} - 返回当前实例,支持链式调用 */ on(event, callback) { if (this.callbacks[event]) { this.callbacks[event].push(callback); } return this; } /** * 移除事件回调 * @param {string} event - 事件名称(open/message/close/error) * @param {Function} callback - 要移除的回调函数 * @returns {WebSocketUtil} - 返回当前实例,支持链式调用 */ off(event, callback) { if (this.callbacks[event]) { this.callbacks[event] = this.callbacks[event].filter(cb => cb !== callback); } return this; } /** * 触发事件回调 * @param {string} event - 事件名称 * @param {any} [data] - 传递给回调函数的数据 */ triggerEvent(event, data) { if (this.callbacks[event]) { this.callbacks[event].forEach(callback => callback(data)); } } /** * 通过WebSocket发送消息 * @param {string|Object} message - 要发送的消息,可以是字符串或对象 * @returns {WebSocketUtil} - 返回当前实例,支持链式调用 */ send(message) { if (this.socketTask && this.getStatus() === 1) { // 发送消息,对象会自动转换为JSON字符串 this.socketTask.send({ data: typeof message === 'string' ? message : JSON.stringify(message), success: () => { console.log('WebSocket消息发送成功'); }, fail: (err) => { console.error('WebSocket消息发送失败', err); this.triggerEvent('error', err); } }); } else { console.error('WebSocket连接未打开,无法发送消息'); this.triggerEvent('error', new Error('WebSocket连接未打开')); setTimeout(()=>{ this.send(message) },500) } return this; } /** * 关闭WebSocket连接 * @param {number} [code=1000] - 关闭码 * @param {string} [reason=''] - 关闭原因 * @returns {WebSocketUtil} - 返回当前实例,支持链式调用 */ close(code = 1000, reason = '') { this.isClose = true if (this.socketTask) { clearInterval(this.heartbeatTimer); // 清除心跳计时器 clearInterval(this.reconnectTimer); // 清除重连计时器 // 关闭WebSocket连接 this.socketTask.close({ code, reason, success: () => { console.log('WebSocket连接正在关闭'); }, fail: (err) => { console.error('WebSocket关闭失败', err); this.triggerEvent('error', err); } }); } return this; } /** * 获取WebSocket连接状态 * @returns {number} - 连接状态:0-连接中,1-已连接,2-连接关闭中,3-已关闭,-1-未知 */ getStatus() { if (this.socketTask) { try { return this.socketTask.readyState; } catch (e) { console.error('获取WebSocket状态失败', e); return -1; } } return -1; } /** * 尝试重新连接WebSocket */ tryReconnect() { if(this.isClose) return if (this.reconnectCount < this.maxReconnectCount) { clearInterval(this.reconnectTimer); this.reconnectTimer = setTimeout(() => { this.reconnectCount++; console.log(`尝试重新连接WebSocket (${this.reconnectCount}/${this.maxReconnectCount})`); this.init(); // 重新初始化WebSocket连接 }, this.reconnectInterval); } else { console.error('达到最大重连次数,停止尝试'); this.triggerEvent('error', new Error('达到最大重连次数')); this.reconnectTimer = null this.close() goto_login_fun() } } /** * 启动心跳机制 */ startHeartbeat() { clearInterval(this.heartbeatTimer); this.heartbeatTimer = setInterval(() => { if (this.getStatus() === 1) { this.send(this.heartbeatMsg); // 发送心跳消息 } }, this.heartbeatInterval); } }