diff --git a/src/hooks/useWebSocketDict.js b/src/hooks/useWebSocketDict.js deleted file mode 100644 index 0ded907c..00000000 --- a/src/hooks/useWebSocketDict.js +++ /dev/null @@ -1,232 +0,0 @@ -import { ref } from "vue"; -import { useUserStore } from "@/store/modules/user"; -import { useDictStoreHook } from "@/store/modules/dict.store"; -import SockJS from "sockjs-client"; -import Stomp from "webstomp-client"; -import { ElMessage } from "element-plus"; - -export function useWebSocketDict() { - const userStore = useUserStore(); - const dictStore = useDictStoreHook(); - - // WebSocket状态 - const isConnected = ref(false); - const stompClient = ref(null); - const subscriptions = ref([]); - - /** - * 初始化WebSocket - */ - const initWebSocket = async () => { - try { - await connectWebSocket(); - setupDictSubscription(); - } catch (error) { - console.error("初始化WebSocket失败:", error); - } - }; - - /** - * 关闭WebSocket - */ - const closeWebSocket = () => { - disconnectWebSocket(); - }; - - /** - * 连接WebSocket服务器 - */ - const connectWebSocket = () => { - return new Promise((resolve, reject) => { - try { - const serverUrl = import.meta.env.VITE_APP_BASE_API + "/ws"; - - // 创建SockJS连接 - const socket = new SockJS(serverUrl); - - // 创建STOMP客户端 - const client = Stomp.over(socket); - - // 禁用调试日志 - client.debug = () => {}; - - // 添加认证头信息 - const headers = { - Authorization: userStore.token, - }; - - // 连接到WebSocket服务器 - client.connect( - headers, - () => { - stompClient.value = client; - isConnected.value = true; - console.log("WebSocket连接成功"); - resolve(); - }, - (error) => { - console.error("WebSocket连接失败:", error); - isConnected.value = false; - reject(error); - } - ); - } catch (error) { - console.error("创建WebSocket连接时出错:", error); - reject(error); - } - }); - }; - - /** - * 断开WebSocket连接 - */ - const disconnectWebSocket = () => { - // 取消所有订阅 - subscriptions.value.forEach((subscription) => { - if (subscription && typeof subscription.unsubscribe === "function") { - subscription.unsubscribe(); - } - }); - subscriptions.value = []; - - // 断开连接 - if (stompClient.value && stompClient.value.connected) { - stompClient.value.disconnect(); - stompClient.value = null; - } - - isConnected.value = false; - console.log("WebSocket连接已断开"); - }; - - /** - * 设置字典订阅 - */ - const setupDictSubscription = () => { - // 订阅字典更新 - subscribe("/topic/dict", (message) => { - handleDictEvent(message); - }); - }; - - /** - * 处理字典事件 - * @param {Object} event 字典事件 - */ - const handleDictEvent = (event) => { - // 尝试解析消息,防止服务端发送字符串格式的JSON - let eventData = event; - if (typeof event === "string") { - try { - eventData = JSON.parse(event); - } catch (error) { - console.error("解析WebSocket消息失败:", error); - return; - } - } - - const { type, dictCode } = eventData; - - if (type === "DICT_UPDATED") { - // 删除缓存,强制重新加载 - dictStore.removeDictItem(dictCode); - console.log(`字典 ${dictCode} 已更新,缓存已清除`); - ElMessage.success(`字典 ${dictCode} 已更新`); - } else if (type === "DICT_DELETED") { - // 删除缓存 - dictStore.removeDictItem(dictCode); - console.log(`字典 ${dictCode} 已删除,缓存已清除`); - ElMessage.warning(`字典 ${dictCode} 已删除`); - } - }; - - /** - * 发送消息到WebSocket服务器 - * @param {string} destination 目标地址 - * @param {string} content 消息内容 - */ - const sendMessage = (destination, content) => { - if (!isConnected.value || !stompClient.value) { - console.error("WebSocket未连接,无法发送消息"); - return false; - } - - try { - // 发送消息 - stompClient.value.send( - destination, - JSON.stringify({ - content: content, - sender: userStore.userInfo.username, - timestamp: new Date().getTime(), - }), - {} - ); - return true; - } catch (error) { - console.error("发送消息失败:", error); - return false; - } - }; - - /** - * 订阅WebSocket主题 - * @param {string} destination 订阅地址 - * @param {Function} callback 回调函数 - */ - const subscribe = (destination, callback) => { - if (!isConnected.value || !stompClient.value) { - console.error("WebSocket未连接,无法订阅"); - return null; - } - - try { - // 订阅主题 - const subscription = stompClient.value.subscribe(destination, (message) => { - if (message.body) { - try { - // 尝试解析JSON格式消息 - const data = JSON.parse(message.body); - - // 如果返回的是JSON字符串,再次解析 - if (typeof data === "string" && data.startsWith("{") && data.endsWith("}")) { - try { - const parsedData = JSON.parse(data); - callback(parsedData); - } catch (e) { - // 如果再次解析失败,传递原始数据 - callback(data); - } - } else { - // 直接传递已解析的数据 - callback(data); - } - } catch (e) { - // 如果解析失败,传递原始消息 - console.warn("解析WebSocket消息失败,传递原始消息:", e); - callback(message.body); - } - } - }); - - // 保存订阅引用,以便后续取消订阅 - subscriptions.value.push(subscription); - - return subscription; - } catch (error) { - console.error("订阅失败:", error); - return null; - } - }; - - return { - isConnected, - connectWebSocket, - disconnectWebSocket, - sendMessage, - subscribe, - initWebSocket, - closeWebSocket, - handleDictEvent, - }; -} diff --git a/src/hooks/useWebSocketDict.ts b/src/hooks/useWebSocketDict.ts index 48b6d5c3..9570b701 100644 --- a/src/hooks/useWebSocketDict.ts +++ b/src/hooks/useWebSocketDict.ts @@ -1,246 +1,101 @@ import { ref } from "vue"; -import { useUserStore } from "@/store/modules/user"; import { useDictStoreHook } from "@/store/modules/dict.store"; -import SockJS from "sockjs-client"; -import Stomp, { Client, Subscription } from "webstomp-client"; +import { useStomp } from "@/hooks/useStomp"; import { ElMessage } from "element-plus"; +import { IMessage } from "@stomp/stompjs"; -// 字典WebSocket事件类型定义 -interface DictWebSocketEvent { - type: "DICT_UPDATED" | "DICT_DELETED"; +// 字典事件类型 +interface DictEvent { + type: string; dictCode: string; - timestamp: number; -} - -// 消息类型定义 -interface WebSocketMessage { - content: string; - sender: string; - timestamp: number; + timestamp?: number; } export function useWebSocketDict() { - const userStore = useUserStore(); const dictStore = useDictStoreHook(); - // WebSocket状态 - const isConnected = ref(false); - const stompClient = ref(null); - const subscriptions = ref([]); + // 使用现有的useStomp + const { isConnected, connect, subscribe, unsubscribe, disconnect } = useStomp(); + + // 存储订阅ID + const subscriptionIds = ref([]); /** * 初始化WebSocket */ - const initWebSocket = async (): Promise => { + const initWebSocket = async () => { try { - await connectWebSocket(); + // 连接WebSocket + connect(); + + // 设置字典订阅 setupDictSubscription(); + + console.log("字典WebSocket初始化完成"); } catch (error) { - console.error("初始化WebSocket失败:", error); + console.error("初始化字典WebSocket失败:", error); } }; /** * 关闭WebSocket */ - const closeWebSocket = (): void => { - disconnectWebSocket(); - }; - - /** - * 连接WebSocket服务器 - */ - const connectWebSocket = (): Promise => { - return new Promise((resolve, reject) => { - try { - const serverUrl = import.meta.env.VITE_APP_BASE_API + "/ws"; - - // 创建SockJS连接 - const socket = new SockJS(serverUrl); - - // 创建STOMP客户端 - const client = Stomp.over(socket); - - // 禁用调试日志 - client.debug = () => {}; - - // 添加认证头信息 - const headers = { - Authorization: userStore.token, - }; - - // 连接到WebSocket服务器 - client.connect( - headers, - () => { - stompClient.value = client; - isConnected.value = true; - console.log("WebSocket连接成功"); - resolve(); - }, - (error) => { - console.error("WebSocket连接失败:", error); - isConnected.value = false; - reject(error); - } - ); - } catch (error) { - console.error("创建WebSocket连接时出错:", error); - reject(error); - } - }); - }; - - /** - * 断开WebSocket连接 - */ - const disconnectWebSocket = (): void => { + const closeWebSocket = () => { // 取消所有订阅 - subscriptions.value.forEach((subscription) => { - if (subscription && typeof subscription.unsubscribe === "function") { - subscription.unsubscribe(); - } + subscriptionIds.value.forEach((id) => { + unsubscribe(id); }); - subscriptions.value = []; + subscriptionIds.value = []; // 断开连接 - if (stompClient.value && stompClient.value.connected) { - stompClient.value.disconnect(); - stompClient.value = null; - } + disconnect(); - isConnected.value = false; - console.log("WebSocket连接已断开"); + console.log("字典WebSocket已关闭"); }; /** * 设置字典订阅 */ - const setupDictSubscription = (): void => { + const setupDictSubscription = () => { // 订阅字典更新 - subscribe("/topic/dict", (message: any) => { + const subId = subscribe("/topic/dict", (message: IMessage) => { handleDictEvent(message); }); + + if (subId) { + subscriptionIds.value.push(subId); + } }; /** * 处理字典事件 - * @param {Object | string} event 字典事件 + * @param message STOMP消息 */ - const handleDictEvent = (event: any): void => { - // 尝试解析消息,防止服务端发送字符串格式的JSON - let eventData: DictWebSocketEvent; - if (typeof event === "string") { - try { - eventData = JSON.parse(event) as DictWebSocketEvent; - } catch (error) { - console.error("解析WebSocket消息失败:", error); - return; + const handleDictEvent = (message: IMessage) => { + if (!message.body) return; + + try { + // 尝试解析消息 + const eventData = JSON.parse(message.body) as DictEvent; + + if (eventData.type === "DICT_UPDATED") { + // 删除缓存,强制重新加载 + dictStore.removeDictItem(eventData.dictCode); + console.log(`字典 ${eventData.dictCode} 已更新,缓存已清除`); + ElMessage.success(`字典 ${eventData.dictCode} 已更新`); + } else if (eventData.type === "DICT_DELETED") { + // 删除缓存 + dictStore.removeDictItem(eventData.dictCode); + console.log(`字典 ${eventData.dictCode} 已删除,缓存已清除`); + ElMessage.warning(`字典 ${eventData.dictCode} 已删除`); } - } else { - eventData = event as DictWebSocketEvent; - } - - const { type, dictCode } = eventData; - - if (type === "DICT_UPDATED") { - // 删除缓存,强制重新加载 - dictStore.removeDictItem(dictCode); - console.log(`字典 ${dictCode} 已更新,缓存已清除`); - ElMessage.success(`字典 ${dictCode} 已更新`); - } else if (type === "DICT_DELETED") { - // 删除缓存 - dictStore.removeDictItem(dictCode); - console.log(`字典 ${dictCode} 已删除,缓存已清除`); - ElMessage.warning(`字典 ${dictCode} 已删除`); - } - }; - - /** - * 发送消息到WebSocket服务器 - * @param {string} destination 目标地址 - * @param {string} content 消息内容 - * @returns {boolean} 是否发送成功 - */ - const sendMessage = (destination: string, content: string): boolean => { - if (!isConnected.value || !stompClient.value) { - console.error("WebSocket未连接,无法发送消息"); - return false; - } - - try { - // 发送消息 - const message: WebSocketMessage = { - content: content, - sender: userStore.userInfo.username, - timestamp: new Date().getTime(), - }; - - stompClient.value.send(destination, JSON.stringify(message), {}); - return true; } catch (error) { - console.error("发送消息失败:", error); - return false; - } - }; - - /** - * 订阅WebSocket主题 - * @param {string} destination 订阅地址 - * @param {Function} callback 回调函数 - * @returns {Subscription | null} 订阅对象 - */ - const subscribe = (destination: string, callback: (data: any) => void): Subscription | null => { - if (!isConnected.value || !stompClient.value) { - console.error("WebSocket未连接,无法订阅"); - return null; - } - - try { - // 订阅主题 - const subscription = stompClient.value.subscribe(destination, (message) => { - if (message.body) { - try { - // 尝试解析JSON格式消息 - const data = JSON.parse(message.body); - - // 如果返回的是JSON字符串,再次解析 - if (typeof data === "string" && data.startsWith("{") && data.endsWith("}")) { - try { - const parsedData = JSON.parse(data); - callback(parsedData); - } catch { - // 如果再次解析失败,传递原始数据 - callback(data); - } - } else { - // 直接传递已解析的数据 - callback(data); - } - } catch (e) { - // 如果解析失败,传递原始消息 - console.warn("解析WebSocket消息失败,传递原始消息:", e); - callback(message.body); - } - } - }); - - // 保存订阅引用,以便后续取消订阅 - subscriptions.value.push(subscription); - - return subscription; - } catch (error) { - console.error("订阅失败:", error); - return null; + console.error("解析字典WebSocket消息失败:", error); } }; return { isConnected, - connectWebSocket, - disconnectWebSocket, - sendMessage, - subscribe, initWebSocket, closeWebSocket, handleDictEvent, diff --git a/src/plugins/websocket.ts b/src/plugins/websocket.ts index 55a4d403..520b10a3 100644 --- a/src/plugins/websocket.ts +++ b/src/plugins/websocket.ts @@ -8,6 +8,7 @@ export function setupWebSocket() { // 初始化字典WebSocket服务 dictWebSocket.initWebSocket(); + console.log("字典WebSocket初始化完成"); // 在窗口关闭前断开WebSocket连接 window.addEventListener("beforeunload", () => {