import { MESSAGETYPES, getMessageTypeName } from "@/constants"; let socket = null; let heartbeatInterval = null; let reconnectTimer = null; /** * 建立 WebSocket 连接 */ function createWebSocket(token, onMessage) { let url = "wss://api.shelingxingqiu.com/socket"; try { const accountInfo = uni.getAccountInfoSync(); const envVersion = accountInfo.miniProgram.envVersion; switch (envVersion) { case "develop": // 开发版 // url = "ws://192.168.1.30:8000/socket"; url = "wss://apitest.shelingxingqiu.com/socket"; break; case "trial": // 体验版 url = "wss://apitest.shelingxingqiu.com/socket"; break; case "release": // 正式版 url = "wss://api.shelingxingqiu.com/socket"; break; default: // 保持默认值 break; } } catch (e) { console.error("获取环境信息失败,使用默认正式环境", e); } url += `?authorization=${token}`; socket = uni.connectSocket({ url, success: () => { console.log("websocket 连接成功"); // 启动心跳 startHeartbeat(onMessage); }, fail: () => { reconnect(onMessage); }, }); // 接收消息 uni.onSocketMessage((res) => { const { data, event } = JSON.parse(res.data); if (event === "pong") return; if (data.type) { console.log("收到消息:", getMessageTypeName(data.type), data.data); if (onMessage) onMessage({ ...(data.data || {}), type: data.type }); return; } if (onMessage && data.updates) onMessage(data.updates); const msg = data.updates[0]; if (msg) { console.log("收到消息:", getMessageTypeName(msg.constructor), msg); if (msg.constructor === MESSAGETYPES.RankUpdate) { uni.setStorageSync("latestRank", msg.lvl); } else if (msg.constructor === MESSAGETYPES.LvlUpdate) { uni.setStorageSync("latestLvl", msg.lvl); } else if (msg.constructor === MESSAGETYPES.DeviceOnline) { uni.$emit("update-online"); } else if (msg.constructor === MESSAGETYPES.DeviceOffline) { uni.$emit("update-online"); } } }); // 错误处理 uni.onSocketError((err) => { console.error("WebSocket 错误", err); reconnect(onMessage); }); uni.onSocketClose((result) => { console.log("WebSocket 已关闭", result); stopHeartbeat(); reconnect(onMessage); }); } /** * 重连机制 */ function reconnect(onMessage) { reconnectTimer && clearTimeout(reconnectTimer); closeWebSocket(); // 确保关闭旧连接 const token = uni.getStorageSync( `${uni.getAccountInfoSync().miniProgram.envVersion}_token` ); if (!token) return; reconnectTimer = setTimeout(() => { console.log("reconnecting..."); createWebSocket(token, onMessage); }, 1000); } function closeWebSocket() { if (socket) { reconnectTimer && clearTimeout(reconnectTimer); stopHeartbeat(); try { socket.close(); } catch (err) { console.error("关闭WebSocket连接失败", err); } socket = null; // 清除socket引用 } } function sendHeartbeat(onMessage) { uni.sendSocketMessage({ data: JSON.stringify({ event: "ping", data: {} }), success: () => { // console.log("发送心跳成功"); }, fail: (err) => { console.error("发送心跳失败", err); stopHeartbeat(); closeWebSocket(); // 关闭失效的连接 reconnect(onMessage); // 触发重连 }, }); } /** * 启动心跳 */ function startHeartbeat(onMessage) { stopHeartbeat(); // 防止重复启动 heartbeatInterval = setInterval(() => { if (socket && socket.readyState === 1) { // 检查连接状态 sendHeartbeat(onMessage); } }, 10000); } /** * 停止心跳 */ function stopHeartbeat() { if (heartbeatInterval) { clearInterval(heartbeatInterval); heartbeatInterval = null; } } export default { createWebSocket, closeWebSocket, };