Files
vue3-element-admin/src/plugins/websocket.ts
2025-11-27 13:32:27 +08:00

142 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useDictSync } from "@/composables";
import { AuthStorage } from "@/utils/auth";
/**
* WebSocket 服务实例约定接口
* 至少包含 disconnect/closeWebSocket/cleanup 三者之一
*/
type WebSocketService = {
disconnect?: () => void;
closeWebSocket?: () => void;
cleanup?: () => void;
[key: string]: any;
};
// 全局 WebSocket 实例管理
const websocketInstances = new Map<string, WebSocketService>();
// 用于防止重复初始化的状态标记
let isInitialized = false;
let dictWebSocketInstance: ReturnType<typeof useDictSync> | null = null;
/**
* 注册 WebSocket 实例,便于统一清理
*/
export function registerWebSocketInstance(key: string, instance: WebSocketService) {
websocketInstances.set(key, instance);
}
/**
* 获取 WebSocket 实例
*/
export function getWebSocketInstance(key: string) {
return websocketInstances.get(key);
}
/**
* 初始化WebSocket服务
*/
export function setupWebSocket() {
// 检查是否已经初始化
if (isInitialized) {
return;
}
// 检查环境变量是否配置
const wsEndpoint = import.meta.env.VITE_APP_WS_ENDPOINT;
if (!wsEndpoint) {
console.log("[WebSocketPlugin] 未配置WebSocket端点,跳过WebSocket初始化");
return;
}
// 检查是否已登录(基于是否存在访问令牌)
if (!AuthStorage.getAccessToken()) {
console.warn(
"[WebSocketPlugin] 未找到访问令牌WebSocket初始化已跳过。用户登录后将自动重新连接。"
);
return;
}
try {
// 延迟初始化,确保应用完全启动
setTimeout(() => {
// 保存实例引用
dictWebSocketInstance = useDictSync();
registerWebSocketInstance("dictSync", dictWebSocketInstance);
// 初始化字典WebSocket服务
dictWebSocketInstance.initWebSocket();
// 初始化在线用户计数WebSocket
import("@/composables").then(({ useOnlineCount }) => {
const onlineCountInstance = useOnlineCount({ autoInit: false });
onlineCountInstance.initWebSocket();
});
// 在窗口关闭前断开WebSocket连接
window.addEventListener("beforeunload", handleWindowClose);
isInitialized = true;
}, 1000); // 延迟1秒初始化
} catch (error) {
console.error("[WebSocketPlugin] 初始化WebSocket服务失败:", error);
}
}
/**
* 处理窗口关闭
*/
function handleWindowClose() {
cleanupWebSocket();
}
/**
* 清理WebSocket连接
*/
export function cleanupWebSocket() {
// 清理字典 WebSocket
if (dictWebSocketInstance) {
try {
dictWebSocketInstance.closeWebSocket();
} catch (error) {
console.error("[WebSocketPlugin] 断开字典WebSocket连接失败:", error);
}
}
// 清理所有注册的 WebSocket 实例
websocketInstances.forEach((instance, key) => {
try {
if (instance && typeof instance.disconnect === "function") {
instance.disconnect();
} else if (instance && typeof instance.closeWebSocket === "function") {
instance.closeWebSocket();
} else if (instance && typeof instance.cleanup === "function") {
instance.cleanup();
}
} catch (error) {
console.error(`[WebSocketPlugin] 断开 ${key} WebSocket连接失败:`, error);
}
});
// 清空实例映射
websocketInstances.clear();
// 移除事件监听器
window.removeEventListener("beforeunload", handleWindowClose);
// 重置状态
dictWebSocketInstance = null;
isInitialized = false;
}
/**
* 重新初始化WebSocket用于登录后重连
*/
export function reinitializeWebSocket() {
// 先清理现有连接
cleanupWebSocket();
// 延迟后重新初始化
setTimeout(() => {
setupWebSocket();
}, 500);
}