import { error } from "../../uni_modules/uview-plus"; // import qs from "qs"; const qs = { stringify: (obj) => { const str= Object.keys(obj).reduce((prve, key) => { return prve + `${key}=${obj[key]}&` }, '?') return str.substring(0,str.length-1) } } function ElMessage() { } function ElMessageBox() { } const user = { userInfo: { shopId: '' } } export interface ApifoxModel { account : string; operate_type : string; shop_id : string; table_code ?: string; type : string; [property : string] : string | number | undefined; // 限制额外属性类型 } export type msgType = 'add' | 'reduce' | 'remove' | 'edit' | 'init' | 'cleanup' | 'del' | 'rottable' | 'batch' | 'disconnect' | 'clearOrder'; class WebSocketManager { private client : WebSocket | null = null; private connected : boolean = false; private shop_id = user.userInfo.shopId ? String(user.userInfo.shopId) : ''; private autoConnect : boolean = true; private initParams : ApifoxModel = { type: 'shopping', account: this.shop_id || '', // 提供默认值 operate_type: 'init', table_code: '', shop_id: this.shop_id || '', // 提供默认值 }; private onMessage : (message : any) => void = () => { }; private messageHandlers : Map void)[]> = new Map(); private type : string = 'shopping'; private reconnectAttempts = 0; private maxReconnectAttempts = Infinity; // 自定义最大重试次数 private reconnectDelay = 5000; // 重试延迟(单位:毫秒) private timer : any | null = null; private reconnectTimer : any | null = null connectSocketSuccsss(){ if(!this.client){ return } this.client.onOpen(() => { this.connected = true; console.log("WebSocket 连接已建立"); console.log(this.initParams); this.sendMessage(this.initParams); this.clearTimer(); this.timer = setInterval(() => { this.sendMessage({ type: "ping_interval", set: 'shopping' }, false); }, 1000 * 10); }) this.client.onClose(() => { this.clearTimer(); this.connected = false; console.log("WebSocket 连接已断开"); if (this.autoConnect) { this.reconnect(); // 自动重连 } }) this.client.onError((error : Event) => { this.clearTimer(); console.error("WebSocket 发生错误:", error); this.reconnect(); // 自动重连 }) this.client.onMessage((event : MessageEvent) => { try { const message = JSON.parse(event.data); if (message && message.msg_id) { this.onMessageHandler({ msg_id: message.msg_id }); } this.onMessage(message); } catch (e) { console.error("消息解析失败:", e); } }) } // 初始化 WebSocket 客户端 setupWebSocket() { // #ifdef H5 const endpoint = "http://192.168.1.31:2348/" // #endif // #ifdef MP-WEIXIN const endpoint = "ws://192.168.1.31:2348/" // #endif if (!endpoint) { console.warn("WebSocket 已被禁用,请在配置文件中配置 VITE_APP_WS_ENDPOINT"); return; } if (this.client && this.connected) { console.log("客户端已存在并且连接正常"); return this.client; } const url = qs.stringify(this.initParams); // this.client = new WebSocket(endpoint + '?' + url); this.client = uni.connectSocket({ url: endpoint + url, success: (res) => { console.log('连接成功'); }, fail: (err) => { console.error(error(err)) console.error('WebSocket 连接失败,尝试重连'); } }); this.connectSocketSuccsss() console.log('this.client'); console.log(this.client); } // 消息回执 public onMessageHandler(data : any) { if (this.client && this.connected) { this.client.send({data:JSON.stringify({ ...data, type: 'receipt' })}); } } // 订阅主题 public subscribeToTopic(initParams : ApifoxModel, onMessage : (message : any) => void) { console.log(`正在订阅主题: `, initParams); this.initParams = { ...this.initParams, ...initParams }; this.disconnect(); this.setupWebSocket(); this.onMessage = onMessage; this.autoConnect = true } public sendMessage(message : any, isSendInitParams : boolean = true) { if (!this.client || !this.connected) { // ElMessage.error('发送失败,已重新连接,请重新操作'); this.reconnect(); return; } if (message.operate_type == 'disconnect') { this.disconnect(); return } const msg = JSON.stringify(isSendInitParams ? { ...this.initParams, ...message } : message); try { this.client?.send({data:msg}); } catch (error) { console.error("发送消息失败:", error); // ElMessage.error('发送失败,已重新连接,请重新操作'); this.reconnect(); } } public canSendMessage() { return this.client && this.connected; } // 断开 WebSocket 连接 public disconnect() { if (this.client && this.connected) { console.log("断开 WebSocket 连接"); this.clearTimer(); try { if(this.client){ this.client.closeSocket(); } } catch (error) { //TODO handle the exception console.error('关闭WebSocket连接失败') } this.client = null; this.connected = false; this.autoConnect = false; } } // 自动重连机制 private reconnect() { if (!this.autoConnect) { return; } if (this.reconnectAttempts < this.maxReconnectAttempts) { this.reconnectAttempts++; console.log(`尝试第 ${this.reconnectAttempts} 次重连...`); this.reconnectTimer = setTimeout(() => { this.setupWebSocket(); }, this.reconnectDelay); } else { clearTimeout(this.reconnectTimer); console.error("达到最大重连次数,停止重连"); ElMessageBox.confirm('达到最大重连次数' + this.maxReconnectAttempts + '次,已停止重连,是否立即重连?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', callback: (action : string) => { console.log(action); if (action == 'confirm') { this.setupWebSocket(); this.reconnectAttempts = 0; } } }); } } // 清除定时器 private clearTimer() { if (this.timer) { clearInterval(this.timer); this.timer = null; } if (this.reconnectTimer) { clearInterval(this.reconnectTimer); this.reconnectTimer = null; } } } export default new WebSocketManager();