created
This commit is contained in:
188
src/hooks/websocket/services/useDictSync.ts
Normal file
188
src/hooks/websocket/services/useDictSync.ts
Normal file
@ -0,0 +1,188 @@
|
||||
import { useDictStore } from "@/store/modules/dict";
|
||||
import { useStomp } from "../core/useStomp";
|
||||
import { ref } from "vue";
|
||||
|
||||
// 字典消息类型
|
||||
export interface DictMessage {
|
||||
dictCode: string;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
// 字典事件回调类型
|
||||
export type DictMessageCallback = (message: DictMessage) => void;
|
||||
|
||||
// 全局单例实例
|
||||
let instance: ReturnType<typeof createDictSyncHook> | null = null;
|
||||
|
||||
/**
|
||||
* 创建字典同步Hook
|
||||
* 负责监听后端字典变更并同步到前端
|
||||
*/
|
||||
function createDictSyncHook() {
|
||||
const dictStore = useDictStore();
|
||||
|
||||
// 使用现有的useStomp,配置适合字典场景的重连参数
|
||||
const { isConnected, connect, subscribe, unsubscribe, disconnect } = useStomp({
|
||||
reconnectDelay: 10000, // 使用更长的重连延迟 - 10秒
|
||||
connectionTimeout: 15000, // 更长的连接超时时间 - 15秒
|
||||
useExponentialBackoff: false, // 字典数据不需要指数退避策略
|
||||
});
|
||||
|
||||
// 存储订阅ID
|
||||
const subscriptionIds = ref<string[]>([]);
|
||||
|
||||
// 已订阅的主题
|
||||
const subscribedTopics = ref<Set<string>>(new Set());
|
||||
|
||||
// 消息回调函数列表
|
||||
const messageCallbacks = ref<DictMessageCallback[]>([]);
|
||||
|
||||
/**
|
||||
* 注册字典消息回调
|
||||
* @param callback 回调函数
|
||||
*/
|
||||
const onDictMessage = (callback: DictMessageCallback) => {
|
||||
messageCallbacks.value.push(callback);
|
||||
return () => {
|
||||
// 返回取消注册的函数
|
||||
const index = messageCallbacks.value.indexOf(callback);
|
||||
if (index !== -1) {
|
||||
messageCallbacks.value.splice(index, 1);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* 初始化WebSocket
|
||||
*/
|
||||
const initWebSocket = async () => {
|
||||
try {
|
||||
// 连接WebSocket
|
||||
connect();
|
||||
|
||||
// 设置字典订阅
|
||||
setupDictSubscription();
|
||||
} catch (error) {
|
||||
console.error("[WebSocket] 初始化失败:", error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 关闭WebSocket
|
||||
*/
|
||||
const closeWebSocket = () => {
|
||||
// 取消所有订阅
|
||||
subscriptionIds.value.forEach((id) => {
|
||||
unsubscribe(id);
|
||||
});
|
||||
subscriptionIds.value = [];
|
||||
subscribedTopics.value.clear();
|
||||
|
||||
// 断开连接
|
||||
disconnect();
|
||||
};
|
||||
|
||||
/**
|
||||
* 设置字典订阅
|
||||
*/
|
||||
const setupDictSubscription = () => {
|
||||
const topic = "/topic/dict";
|
||||
|
||||
// 防止重复订阅
|
||||
if (subscribedTopics.value.has(topic)) {
|
||||
console.log(`跳过重复订阅: ${topic}`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`开始尝试订阅字典主题: ${topic}`);
|
||||
|
||||
// 使用简化的重试逻辑,依赖useStomp的连接管理
|
||||
const attemptSubscribe = () => {
|
||||
if (!isConnected.value) {
|
||||
console.log("等待WebSocket连接建立...");
|
||||
// 3秒后再次尝试
|
||||
setTimeout(attemptSubscribe, 3000);
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否已订阅
|
||||
if (subscribedTopics.value.has(topic)) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`连接已建立,开始订阅: ${topic}`);
|
||||
|
||||
// 订阅字典更新
|
||||
const subId = subscribe(topic, (message: any) => {
|
||||
handleDictEvent(message);
|
||||
});
|
||||
|
||||
if (subId) {
|
||||
subscriptionIds.value.push(subId);
|
||||
subscribedTopics.value.add(topic);
|
||||
console.log(`字典主题订阅成功: ${topic}`);
|
||||
} else {
|
||||
console.warn(`字典主题订阅失败: ${topic}`);
|
||||
}
|
||||
};
|
||||
|
||||
// 开始尝试订阅
|
||||
attemptSubscribe();
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理字典事件
|
||||
* @param message STOMP消息
|
||||
*/
|
||||
const handleDictEvent = (message: any) => {
|
||||
if (!message.body) return;
|
||||
|
||||
try {
|
||||
// 记录接收到的消息
|
||||
console.log(`收到字典更新消息: ${message.body}`);
|
||||
|
||||
// 尝试解析消息
|
||||
const parsedData = JSON.parse(message.body) as DictMessage;
|
||||
const dictCode = parsedData.dictCode;
|
||||
|
||||
if (!dictCode) return;
|
||||
|
||||
// 清除缓存,等待按需加载
|
||||
dictStore.removeDictItem(dictCode);
|
||||
console.log(`字典缓存已清除: ${dictCode}`);
|
||||
|
||||
// 调用所有注册的回调函数
|
||||
messageCallbacks.value.forEach((callback) => {
|
||||
try {
|
||||
callback(parsedData);
|
||||
} catch (callbackError) {
|
||||
console.error("[WebSocket] 回调执行失败:", callbackError);
|
||||
}
|
||||
});
|
||||
|
||||
// 显示提示消息
|
||||
console.info(`字典 ${dictCode} 已变更,将在下次使用时自动加载`);
|
||||
} catch (error) {
|
||||
console.error("[WebSocket] 解析消息失败:", error);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
isConnected,
|
||||
initWebSocket,
|
||||
closeWebSocket,
|
||||
handleDictEvent,
|
||||
onDictMessage,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 字典同步Hook
|
||||
* 用于监听后端字典变更并同步到前端
|
||||
*/
|
||||
export function useDictSync() {
|
||||
if (!instance) {
|
||||
instance = createDictSyncHook();
|
||||
}
|
||||
return instance;
|
||||
}
|
Reference in New Issue
Block a user