优化更新

This commit is contained in:
2026-02-18 22:28:08 +08:00
parent b6c133952b
commit 0ecb088569
8 changed files with 107 additions and 38 deletions
+343
View File
@@ -0,0 +1,343 @@
import { ref } from "vue";
import { getWebSocket } from "@/utils/websocket";
import { useUserStore } from "@/stores/modules/user";
import { useMessageStore } from "@/stores/modules/message";
import { useDictionaryStore } from "@/stores/modules/dictionary";
import { useNotificationStore } from "@/stores/modules/notification";
import { message, notification } from "ant-design-vue";
import config from "@/config";
/**
* WebSocket Composable
*
* 处理 WebSocket 连接和消息监听
*/
export function useWebSocket() {
const ws = ref(null);
const userStore = useUserStore();
const messageStore = useMessageStore();
const dictionaryStore = useDictionaryStore();
const notificationStore = useNotificationStore();
const reconnectTimer = ref(null);
const isInitialized = ref(false);
/**
* 初始化 WebSocket 连接
*/
function initWebSocket() {
// 如果已经初始化,不再重复初始化
if (isInitialized.value) {
console.log("WebSocket 已初始化,跳过重复初始化");
return;
}
// 检查用户信息是否完整
if (!userStore.isUserInfoComplete()) {
console.warn("用户信息不完整,等待用户信息加载...");
// 延迟重试,等待用户信息加载
if (reconnectTimer.value) {
clearTimeout(reconnectTimer.value);
}
reconnectTimer.value = setTimeout(() => {
initWebSocket();
}, 1000);
return;
}
try {
console.log("开始初始化 WebSocket...", {
userId: userStore.userInfo.id,
username: userStore.userInfo.username,
});
// 使用配置文件中的 WS_URL
// getWebSocket 会自动处理重复连接问题
ws.value = getWebSocket(userStore.userInfo.id, userStore.token, {
wsUrl: config.WS_URL,
onOpen: handleOpen,
onMessage: handleMessage,
onError: handleError,
onClose: handleClose,
});
// 注册消息处理器
registerMessageHandlers();
// 标记为已初始化
isInitialized.value = true;
// 连接(如果还未连接)
if (ws.value && !ws.value.isConnected) {
ws.value.connect();
}
} catch (error) {
console.error("初始化 WebSocket 失败:", error);
isInitialized.value = false;
}
}
/**
* 注册所有消息处理器
*/
function registerMessageHandlers() {
if (!ws.value) return;
// 字典更新
ws.value.on("dictionary_update", handleDictionaryUpdate);
ws.value.on("dictionary_item_update", handleDictionaryItemUpdate);
// 系统通知
ws.value.on("notification", handleNotification);
// 数据更新
ws.value.on("data_update", handleDataUpdate);
// 心跳响应
ws.value.on("heartbeat_response", handleHeartbeatResponse);
// 连接确认
ws.value.on("connected", handleConnected);
}
/**
* 取消注册所有消息处理器
*/
function unregisterMessageHandlers() {
if (!ws.value) return;
ws.value.off("dictionary_update");
ws.value.off("dictionary_item_update");
ws.value.off("notification");
ws.value.off("data_update");
ws.value.off("heartbeat_response");
ws.value.off("connected");
}
/**
* 处理连接打开
* 注意:认证已在连接时通过 URL 参数完成,无需单独发送 auth 事件
*/
function handleOpen(event) {
console.log("WebSocket 连接已建立(已通过 URL 参数完成认证)", event);
}
/**
* 处理连接确认
*/
function handleConnected(data) {
console.log("WebSocket 连接已确认", data);
message.success("实时连接已建立");
}
/**
* 处理接收消息
*/
function handleMessage(message, event) {
console.log("收到 WebSocket 消息:", message);
}
/**
* 处理错误
*/
function handleError(error) {
console.error("WebSocket 错误:", error);
message.error("实时连接出现错误,正在重连...");
}
/**
* 处理连接关闭
*/
function handleClose(event) {
console.log("WebSocket 连接已关闭", event);
// 如果不是手动关闭,显示提示
if (event.code !== 1000) {
message.warning("实时连接已断开");
}
}
/**
* 处理心跳响应
*/
function handleHeartbeatResponse(data) {
console.log("收到心跳响应:", data);
}
/**
* 处理系统通知
*/
function handleNotification(data) {
console.log("收到系统通知:", data);
const { title, message: content, type, timestamp, ...rest } = data;
// 构建通知数据格式
const notificationData = {
id: rest.id || Date.now(),
title: title || "系统通知",
content: content || "",
type: type || "info",
category: rest.category || "system",
is_read: false,
created_at: rest.created_at || new Date().toISOString(),
...rest,
};
// 更新通知 store
notificationStore.handleWebSocketMessage({
type: "notification",
data: notificationData,
});
// 添加到消息 store(保持兼容性)
messageStore.addMessage({
type: type || "notification",
title: title || "系统通知",
content: content || "",
timestamp: timestamp || Date.now(),
});
// 显示通知(根据类型)
const notificationConfig = {
message: title || "系统通知",
description: content,
duration: 4.5,
placement: "topRight",
};
// 根据类型设置不同样式
switch (type) {
case "success":
notification.success(notificationConfig);
break;
case "error":
notification.error(notificationConfig);
break;
case "warning":
notification.warning(notificationConfig);
break;
default:
notification.info(notificationConfig);
}
}
/**
* 处理数据更新
*/
async function handleDataUpdate(data) {
console.log("收到数据更新:", data);
const { resource_type, action, timestamp } = data;
// 添加到消息 store
messageStore.handleDataUpdate(data);
// 根据资源类型执行相应操作
switch (resource_type) {
case "dictionary":
case "dictionary_item":
// 刷新字典缓存
try {
await dictionaryStore.refresh(true);
} catch (error) {
console.error("刷新字典缓存失败:", error);
}
break;
// 可以添加其他资源类型的处理
}
}
/**
* 处理字典分类更新
*/
async function handleDictionaryUpdate(data) {
console.log("字典分类已更新:", data);
try {
// 刷新字典缓存
await dictionaryStore.refresh(true);
// 显示通知
message.success("字典数据已更新");
} catch (error) {
console.error("刷新字典缓存失败:", error);
}
}
/**
* 处理字典项更新
*/
async function handleDictionaryItemUpdate(data) {
console.log("字典项已更新:", data);
try {
// 刷新字典缓存
await dictionaryStore.refresh(true);
// 显示通知
message.success("字典数据已更新");
} catch (error) {
console.error("刷新字典缓存失败:", error);
}
}
/**
* 发送消息到服务器
*/
function send(type, data) {
if (ws.value && ws.value.isConnected) {
ws.value.send(type, data);
} else {
console.warn("WebSocket 未连接,无法发送消息");
}
}
/**
* 关闭 WebSocket 连接
*/
function closeWebSocket() {
// 清除重试定时器
if (reconnectTimer.value) {
clearTimeout(reconnectTimer.value);
reconnectTimer.value = null;
}
if (ws.value) {
// 取消注册消息处理器
unregisterMessageHandlers();
ws.value.disconnect();
ws.value = null;
}
// 重置初始化标记
isInitialized.value = false;
}
/**
* 重新连接 WebSocket
*/
function reconnect() {
closeWebSocket();
setTimeout(() => {
initWebSocket();
}, 1000);
}
/**
* 检查连接状态
*/
function isConnected() {
return ws.value && ws.value.isConnected;
}
return {
ws,
initWebSocket,
closeWebSocket,
reconnect,
isConnected,
send,
};
}