import { defineStore } from "pinia"; // #ifdef H5 const socketUrl = "http://192.168.1.42:2348"; // #endif // #ifndef H5 const socketUrl = "ws://192.168.1.42:2348"; // #endif // 聊天 export const useChatStore = defineStore("chat", { state: () => { return { socketUrl, isConnect: false, socketTask: null, onReceiveMsg: () => {}, chatList: [], // ========== 新增:Socket 保活与重连状态 ========== isManualClose: false, // 是否主动关闭(true:不重连;false:自动重连) heartbeatTimer: null, // 心跳定时器 reconnectTimer: null, // 重连定时器 reconnectCount: 0, // 当前重连次数 maxReconnectCount: 5, // 最大重连次数(避免无限重连) reconnectDelay: 1000, // 初始重连延迟(ms) maxReconnectDelay: 8000, // 最大重连延迟(ms) heartbeatInterval: 30000, // 心跳间隔(30s,根据服务器调整) }; }, actions: { init() { if (!this.isConnect) { return uni.showToast({ title: "请先连接socket", icon: "none", }); } this.sendMessage( { type: "OnbocChat", operate_type: "init", shop_id: uni.getStorageSync("shopId"), token: uni.getStorageSync("iToken").tokenValue || "", }, false ); }, sendMessage(msg, isAutoAppend = true) { // 1. 主动关闭状态:提示用户 if (this.isManualClose) { return uni.showToast({ title: "Socket已主动关闭,请重新连接", icon: "none", }); } // 2. 连接未建立:尝试重连后发送 if (!this.isConnect) { this.reconnect(); // 延迟发送,确保重连成功 setTimeout(() => { this.sendMessage(msg, isAutoAppend); }, this.reconnectDelay); return; } // 3. 正常发送消息 console.log('发送的消息', msg); const message = isAutoAppend ? { type: "OnbocChat", operate_type: "sendMsg", shop_id: uni.getStorageSync("shopId"), token: uni.getStorageSync("iToken").tokenValue || "", ...msg, } : msg; this.socketTask.send({ data: JSON.stringify(message), success: (res) => { console.log("发送成功", res); }, fail: (error) => { console.log("发送失败", error); // 发送失败可能是连接断开,触发重连 if (!this.isManualClose) { this.reconnect(); } }, }); }, // ========== 新增:发送心跳包 ========== sendHeartbeat() { if (!this.isConnect || this.isManualClose) return; this.socketTask.send({ data: JSON.stringify({ type: "OnbocChat", operate_type: "heartbeat", // 心跳类型(需与服务器约定) shop_id: uni.getStorageSync("shopId"), token: uni.getStorageSync("iToken").tokenValue || "", timestamp: Date.now(), // 时间戳(可选,用于服务器校验) }), fail: (error) => { console.log("心跳发送失败,触发重连", error); this.reconnect(); }, }); }, // ========== 新增:启动心跳定时器 ========== startHeartbeat() { // 清除旧定时器,避免重复 if (this.heartbeatTimer) { clearInterval(this.heartbeatTimer); } // 每30s发送一次心跳 this.heartbeatTimer = setInterval(() => { this.sendHeartbeat(); }, this.heartbeatInterval); }, // ========== 新增:停止心跳定时器 ========== stopHeartbeat() { if (this.heartbeatTimer) { clearInterval(this.heartbeatTimer); this.heartbeatTimer = null; } }, // ========== 新增:智能重连逻辑 ========== reconnect() { // 1. 主动关闭或已连接:不重连 if (this.isManualClose || this.isConnect) return; // 2. 超过最大重连次数:停止重连 if (this.reconnectCount >= this.maxReconnectCount) { console.log("已达最大重连次数,停止重连"); return; } // 3. 清除旧重连定时器 if (this.reconnectTimer) { clearTimeout(this.reconnectTimer); } // 4. 计算重连延迟(退避算法:1s → 2s → 4s → 8s → 8s...) const delay = Math.min( this.reconnectDelay * Math.pow(2, this.reconnectCount), this.maxReconnectDelay ); console.log(`第${this.reconnectCount + 1}次重连,延迟${delay}ms`); // 5. 延迟执行重连 this.reconnectTimer = setTimeout(() => { this.connectSocket(); this.reconnectCount++; }, delay); }, // ========== 优化:连接Socket ========== connectSocket() { // 1. 避免重复连接 if (this.isConnect || this.socketTask) { return; } // 2. 重置主动关闭标记 this.isManualClose = false; // 3. 创建Socket连接 this.socketTask = uni.connectSocket({ url: this.socketUrl, success: (res) => { console.log("Socket连接请求发送成功"); }, fail: (res) => { console.log("Socket连接请求失败", res); // 请求失败,触发重连 this.reconnect(); }, }); // 4. 连接成功回调 this.socketTask.onOpen((res) => { console.log("Socket连接成功"); this.isConnect = true; this.reconnectCount = 0; // 重置重连次数 this.init(); // 初始化聊天 this.startHeartbeat(); // 启动心跳 }); // 5. 接收消息回调(添加容错处理) this.socketTask.onMessage((res) => { try { const data = JSON.parse(res.data); console.log("收到服务器消息", data); if (data.msg) { uni.showToast({ title: data.msg, icon: "none", }); } // 处理发送消息 if (data?.operate_type === "sendMsg") { this.chatList.unshift(data.data); this.onReceiveMsg(data.data); } // 处理接收消息 if (data?.operate_type === "receive_msg") { const msg = { ...data.data, operate_type: "receive_msg", }; this.chatList.unshift(msg); this.onReceiveMsg(msg); } // 处理心跳响应(如果服务器返回) if (data?.operate_type === "heartbeat_ack") { console.log("心跳响应正常"); } } catch (error) { console.error("消息解析失败", error); } }); // 6. 连接错误回调 this.socketTask.onError((res) => { console.log("Socket连接错误", res); this.isConnect = false; // 错误触发重连 this.reconnect(); }); // 7. 连接关闭回调(区分主动/意外关闭) this.socketTask.onClose(() => { console.log("Socket连接已关闭"); this.isConnect = false; this.stopHeartbeat(); // 停止心跳 // 只有非主动关闭时才重连 if (!this.isManualClose) { console.log("意外断开,触发重连"); this.reconnect(); } else { console.log("主动关闭,不重连"); } }); }, // ========== 优化:主动关闭Socket ========== closeSocket() { // 1. 设置主动关闭标记(关键:避免自动重连) this.isManualClose = true; // 2. 停止所有定时器,清理资源 this.stopHeartbeat(); if (this.reconnectTimer) { clearTimeout(this.reconnectTimer); this.reconnectTimer = null; } // 3. 关闭Socket连接 if (this.socketTask) { this.socketTask.close(); this.socketTask = null; // 释放引用 } // 4. 重置连接状态 this.isConnect = false; this.reconnectCount = 0; // 重置重连次数 console.log("Socket已主动关闭"); }, }, unistorage: false, // 开启后对 state 的数据读写都将持久化 });