diff --git a/src/hooks/websocket/core/useStomp.ts b/src/hooks/websocket/core/useStomp.ts index 7b7cdb16..4a02a6ba 100644 --- a/src/hooks/websocket/core/useStomp.ts +++ b/src/hooks/websocket/core/useStomp.ts @@ -28,10 +28,10 @@ export interface UseStompOptions { export function useStomp(options: UseStompOptions = {}) { // 默认值:brokerURL 从环境变量中获取,token 从 getAccessToken() 获取 const defaultBrokerURL = import.meta.env.VITE_APP_WS_ENDPOINT || ""; - const defaultToken = getAccessToken(); + // 不再使用defaultToken,每次连接时直接获取最新token const brokerURL = ref(options.brokerURL ?? defaultBrokerURL); - const token = options.token ?? defaultToken; + // 不再存储token,改为在初始化时获取 const reconnectDelay = options.reconnectDelay ?? 8000; const connectionTimeout = options.connectionTimeout ?? 10000; const useExponentialBackoff = options.useExponentialBackoff ?? false; @@ -60,11 +60,20 @@ export function useStomp(options: UseStompOptions = {}) { return; } + // 每次连接前重新获取最新令牌,不依赖之前的token值 + const currentToken = getAccessToken(); + + // 检查令牌是否为空,如果为空则不进行连接 + if (!currentToken) { + console.error("WebSocket连接失败:授权令牌为空,请先登录"); + return; + } + // 创建 STOMP 客户端 client.value = new Client({ brokerURL: brokerURL.value, connectHeaders: { - Authorization: `Bearer ${token}`, + Authorization: `Bearer ${currentToken}`, }, debug: options.debug ? console.log : () => {}, reconnectDelay: useExponentialBackoff ? 0 : reconnectDelay, // 使用自定义退避策略时禁用内置重连 @@ -95,11 +104,40 @@ export function useStomp(options: UseStompOptions = {}) { client.value.onWebSocketClose = (event) => { isConnected.value = false; console.log(`WebSocket已关闭: ${event?.code} ${event?.reason}`); + + // 如果是授权问题导致的关闭,尝试重新获取令牌 + if (event?.code === 1000 || event?.code === 1006 || event?.code === 1008) { + console.log("可能是授权问题导致连接关闭,尝试重新建立连接"); + + // 等待一段时间后再尝试重连,避免立即重连 + setTimeout(() => { + // 强制重新初始化客户端,获取最新令牌 + client.value = null; + + // 检查当前是否有有效令牌 + const freshToken = getAccessToken(); + if (freshToken) { + initializeClient(); + connect(); + } else { + console.warn("没有有效令牌,暂不重连WebSocket"); + } + }, 3000); + } }; // 设置错误监听器 client.value.onStompError = (frame) => { console.error("STOMP错误:", frame.headers, frame.body); + + // 检查是否是授权错误 + if ( + frame.headers?.message?.includes("Unauthorized") || + frame.body?.includes("Unauthorized") || + frame.body?.includes("Token") + ) { + console.warn("WebSocket授权错误,请检查登录状态"); + } }; }; diff --git a/src/hooks/websocket/services/useOnlineCount.ts b/src/hooks/websocket/services/useOnlineCount.ts index 587532fe..20f8a749 100644 --- a/src/hooks/websocket/services/useOnlineCount.ts +++ b/src/hooks/websocket/services/useOnlineCount.ts @@ -1,6 +1,7 @@ import { ref, onMounted, onUnmounted, watch } from "vue"; import { useStomp } from "../core/useStomp"; import { ElMessage } from "element-plus"; +import { getAccessToken } from "@/utils/auth"; /** * 在线用户计数Hook @@ -86,16 +87,35 @@ export function useOnlineCount() { const initWebSocket = () => { if (isConnecting.value) return; + // 检查是否有可用的令牌 + const hasToken = !!getAccessToken(); + if (!hasToken) { + console.log("没有检测到有效令牌,不尝试WebSocket连接"); + return; + } + isConnecting.value = true; // 连接WebSocket connect(); // 设置连接超时显示UI提示 + clearTimeout(connectionTimeoutTimer); connectionTimeoutTimer = setTimeout(() => { if (!isConnected.value) { console.warn("WebSocket连接超时,将自动尝试重连"); ElMessage.warning("正在尝试连接服务器,请稍候..."); + + // 超时后尝试重新连接 + closeWebSocket(); + setTimeout(() => { + // 再次检查令牌有效性 + if (getAccessToken()) { + initWebSocket(); + } else { + console.log("令牌无效,放弃重连"); + } + }, 3000); } }, 10000); // 较长的UI提示超时