| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- import { defineStore } from "pinia";
- import { ref } from "vue";
- /**
- * WebSocket Store(浏览器端)
- * 与商家端 @/store/websocket 消息格式一致,用于分享动态、聊天等
- */
- export const useWebSocketStore = defineStore("websocket", () => {
- const socket = ref<WebSocket | null>(null);
- const isConnected = ref(false);
- const isConnecting = ref(false);
- const lastConnectedUrl = ref("");
- // 消息订阅(用于聊天等)
- const messageHandlers = new Map<string, Array<(msg: any) => void>>();
- const connect = (url: string): Promise<boolean> => {
- if (isConnected.value && lastConnectedUrl.value === url) {
- return Promise.resolve(true);
- }
- if (socket.value) {
- try {
- socket.value.close();
- } catch (e) {
- console.warn("关闭旧连接失败:", e);
- }
- socket.value = null;
- isConnected.value = false;
- }
- isConnecting.value = true;
- lastConnectedUrl.value = url;
- return new Promise(resolve => {
- try {
- const ws = new WebSocket(url);
- socket.value = ws;
- ws.onopen = () => {
- isConnected.value = true;
- isConnecting.value = false;
- resolve(true);
- };
- ws.onmessage = (event: MessageEvent) => {
- try {
- const message = JSON.parse(event.data);
- const category = message.category || "message";
- // 按 category 分发
- const handlers = messageHandlers.get(category);
- if (handlers?.length) {
- handlers.forEach(cb => cb(message));
- }
- // 兼容:若后端推送的 category 不是 "message" 但明显是聊天消息,也派发给 message 订阅者(解决业主发消息不实时更新)
- const isChatLike =
- category !== "message" &&
- (message.senderId != null || message.receiverId != null) &&
- (message.text != null || message.content != null || message.type != null);
- if (isChatLike) {
- const messageHandlersList = messageHandlers.get("message");
- if (messageHandlersList?.length) {
- messageHandlersList.forEach(cb => cb(message));
- }
- }
- } catch (_) {}
- };
- ws.onclose = () => {
- isConnected.value = false;
- isConnecting.value = false;
- socket.value = null;
- };
- ws.onerror = () => {
- isConnected.value = false;
- isConnecting.value = false;
- resolve(false);
- };
- } catch (e) {
- console.error("WebSocket 连接异常:", e);
- isConnecting.value = false;
- resolve(false);
- }
- });
- };
- /** 订阅消息(返回取消订阅函数) */
- const subscribe = (type: string, callback: (msg: any) => void) => {
- if (!messageHandlers.has(type)) {
- messageHandlers.set(type, []);
- }
- messageHandlers.get(type)!.push(callback);
- return () => {
- const handlers = messageHandlers.get(type) || [];
- messageHandlers.set(
- type,
- handlers.filter(h => h !== callback)
- );
- };
- };
- const sendMessage = (data: Record<string, unknown>): Promise<boolean> => {
- return new Promise(resolve => {
- if (!isConnected.value || !socket.value || socket.value.readyState !== WebSocket.OPEN) {
- console.warn("WebSocket 未连接,无法发送消息");
- resolve(false);
- return;
- }
- try {
- const message = JSON.stringify(data);
- socket.value.send(message);
- resolve(true);
- } catch (e) {
- console.error("消息发送异常:", e);
- resolve(false);
- }
- });
- };
- const disconnect = () => {
- if (socket.value) {
- try {
- socket.value.close();
- } catch (_) {}
- socket.value = null;
- }
- isConnected.value = false;
- isConnecting.value = false;
- lastConnectedUrl.value = "";
- messageHandlers.clear();
- };
- return {
- socket,
- isConnected,
- isConnecting,
- lastConnectedUrl,
- connect,
- sendMessage,
- disconnect,
- subscribe
- };
- });
|