import qs from "qs"; import { useUserStoreHook } from "@/store"; import { ElMessage, ElMessageBox } from "element-plus"; const user = useUserStoreHook(); 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: 'manage', 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 = 'manage'; private reconnectAttempts = 0; private maxReconnectAttempts = 10; // 自定义最大重试次数 private reconnectDelay = 5000; // 重试延迟(单位:毫秒) private timer: any | null = null; private reconnectTimer: any | null = null // 初始化 WebSocket 客户端 setupWebSocket() { const endpoint = import.meta.env.VITE_APP_WS_ENDPOINT; 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.onopen = () => { this.connected = true; console.log("WebSocket 连接已建立"); this.sendMessage(this.initParams); this.clearTimer(); this.timer = setInterval(() => { this.sendMessage({ type: "ping_interval", set: 'manage' }); }, 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); } }; } // 消息回执 public onMessageHandler(data: any) { if (this.client && this.connected) { this.client.send(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) { if (!this.client || !this.connected) { // ElMessage.error('发送失败,已重新连接,请重新操作'); this.reconnect(); return; } if (message.operate_type == 'disconnect') { this.disconnect(); return } const msg = JSON.stringify({ ...this.initParams, ...message }); try { this.client?.send(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(); this.client.close(); 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();