cashier-web/src/utils/websocket.ts

140 lines
3.9 KiB
TypeScript

import qs from "qs";
import { useUserStoreHook } from "@/store";
const user = useUserStoreHook()
export interface ApifoxModel {
account: string;
/**
* 操作类型
*/
operate_type: string;
shop_id: string;
/**
* 桌码
*/
table_code?: string;
/**
* 消息类型
*/
type: string;
[property: string]: any;
}
export type msgType = 'add' | 'reduce' | 'remove' | 'edit' | 'init' | 'cleanup' | 'del' | 'rottable'
class WebSocketManager {
private client: WebSocket | null = null;
private connected: boolean = false;
private initParams: ApifoxModel = {
type: 'manage',
account: `${user.userInfo.shopId}`,
operate_type: 'init',
table_code: '',
shop_id: `${user.userInfo.shopId}`,
};
private onMessage: (message: any) => void = function () { };
private messageHandlers: Map<string, ((message: string) => void)[]> = new Map();
private type: string = 'manage';
private reconnectAttempts = 0;
private maxReconnectAttempts = 3; // 自定义最大重试次数
private reconnectDelay = 5000; // 重试延迟(单位:毫秒)
// 初始化 WebSocket 客户端
setupWebSocket() {
const endpoint = import.meta.env.VITE_APP_WS_ENDPOINT;
// 如果没有配置 WebSocket 端点或显式关闭,直接返回
if (!endpoint) {
console.log("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 连接已建立");
// ElNotification.success('WebSocket 连接已建立')
this.sendMessage(this.initParams)
};
this.client.onclose = () => {
if (!this.connected) {
// ElMessageBox.alert('WebSocket 连接已断开', 'Title', {
// confirmButtonText: '立即重连',
// callback: () => {
// this.sendMessage(this.initParams)
// },
// })
}
this.connected = false;
console.log("WebSocket 连接已断开");
};
this.client.onerror = (error) => {
console.error("WebSocket 发生错误:", error);
// ElNotification({
// title: "提示",
// message: "WebSocket 发生错误",
// type: "error",
// });
// ElMessageBox.alert('WebSocket 发生错误', 'Title', {
// confirmButtonText: '立即重连',
// callback: () => {
// this.sendMessage(this.initParams)
// },
// })
};
this.client.onmessage = (event) => {
const message = event.data;
const msg = JSON.parse(message)
if (msg && msg.msg_id) {
this.onMessageHandler({ msg_id: msg.msg_id })
}
this.onMessage(msg);
};
}
// 消息回执
public onMessageHandler(data: any) {
if (this.client) {
this.client.send(JSON.stringify({ ...data, type: 'receipt' }));
}
}
// 订阅主题
public subscribeToTopic(initParams: ApifoxModel, onMessage: (message: any) => void) {
console.log(`正在订阅主题: `);
this.initParams = { ...this.initParams, ...initParams }
if (this.client && this.connected) {
this.disconnect();
}
this.setupWebSocket();
this.onMessage = onMessage;
}
public sendMessage(message: any) {
if (this.client) {
const msg = JSON.stringify({
...this.initParams,
...message,
})
this.client.send(msg);
}
}
public canSendMessage() {
return this.client && this.connected;
}
// 断开 WebSocket 连接
public disconnect() {
if (this.client) {
console.log("断开 WebSocket 连接");
this.client.close();
this.client = null;
}
}
}
export default new WebSocketManager();