refactor: ♻️ 字典缓存加载方式修改为按需加载,添加字典实时更新通知
This commit is contained in:
9984
pnpm-lock.yaml
generated
9984
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -292,11 +292,14 @@ export interface DictItemForm {
|
||||
*/
|
||||
export interface DictItemOption {
|
||||
/** 字典数据值 */
|
||||
value: string;
|
||||
value: string | number;
|
||||
|
||||
/** 字典数据标签 */
|
||||
label: string;
|
||||
|
||||
/** 标签类型 */
|
||||
tagType: string;
|
||||
tagType?: "" | "success" | "info" | "warning" | "danger" | "primary";
|
||||
|
||||
/** 允许其他属性 */
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
@@ -19,31 +19,44 @@ const props = defineProps({
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
type TagType = "success" | "warning" | "primary" | "danger" | "default";
|
||||
|
||||
const label = ref("");
|
||||
const tagType = ref<TagType>();
|
||||
const tagType = ref<string | undefined>();
|
||||
|
||||
const getLabelAndTagByValue = async (dictCode: string, value: any) => {
|
||||
// 先从本地缓存中获取字典数据
|
||||
const dictData = dictStore.getDictionary(dictCode);
|
||||
console.log("dictData", dictData);
|
||||
// 按需加载字典数据
|
||||
await dictStore.loadDictItems(dictCode);
|
||||
|
||||
// 从缓存中获取字典数据
|
||||
const dictItems = dictStore.getDictItems(dictCode);
|
||||
|
||||
// 查找对应的字典项
|
||||
const dictEntry = dictData.find((item: any) => item.value == value);
|
||||
const dictItem = dictItems.find((item) => item.value == value);
|
||||
|
||||
return {
|
||||
label: dictEntry ? dictEntry.label : "",
|
||||
tag: dictEntry ? dictEntry.tagType : undefined,
|
||||
label: dictItem?.label || "",
|
||||
tagType: dictItem?.tagType,
|
||||
};
|
||||
};
|
||||
|
||||
// 监听字典数据变化,确保WebSocket更新时刷新标签
|
||||
watch(
|
||||
() => props.code && dictStore.getDictItems(props.code),
|
||||
async () => {
|
||||
if (props.code) {
|
||||
await fetchLabelAndTag();
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
// 监听 props 的变化,获取并更新 label 和 tag
|
||||
const fetchLabelAndTag = async () => {
|
||||
const result = await getLabelAndTagByValue(props.code as string, props.modelValue);
|
||||
console.log("result", result);
|
||||
if (!props.code || props.modelValue === undefined) return;
|
||||
|
||||
const result = await getLabelAndTagByValue(props.code, props.modelValue);
|
||||
label.value = result.label;
|
||||
if (result.tag === "info") {
|
||||
result.tag = "default";
|
||||
}
|
||||
tagType.value = result.tag as "success" | "warning" | "primary" | "danger" | "default";
|
||||
tagType.value = result.tagType;
|
||||
};
|
||||
|
||||
// 首次挂载时获取字典数据
|
||||
|
||||
@@ -114,13 +114,28 @@ function handleChange(val: any) {
|
||||
|
||||
// 获取字典数据
|
||||
onMounted(async () => {
|
||||
if (!props.type) {
|
||||
if (!props.code) {
|
||||
return;
|
||||
}
|
||||
let dictData = dictStore.getDictionary(props.code);
|
||||
options.value = dictData.map((item) => ({
|
||||
// 按需加载字典数据
|
||||
await dictStore.loadDictItems(props.code);
|
||||
options.value = dictStore.getDictItems(props.code).map((item) => ({
|
||||
label: item.label,
|
||||
value: item.value,
|
||||
}));
|
||||
});
|
||||
|
||||
// 监听字典数据变化,确保WebSocket更新时刷新选项
|
||||
watch(
|
||||
() => dictStore.getDictItems(props.code),
|
||||
(newItems) => {
|
||||
if (newItems.length > 0) {
|
||||
options.value = newItems.map((item) => ({
|
||||
label: item.label,
|
||||
value: item.value,
|
||||
}));
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
7
src/hooks/index.ts
Normal file
7
src/hooks/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* 全局Hooks入口文件
|
||||
* 导出所有可用的Hooks
|
||||
*/
|
||||
|
||||
// 导出WebSocket相关Hook
|
||||
export * from "./websocket";
|
||||
285
src/hooks/websocket/core/useStomp.ts
Normal file
285
src/hooks/websocket/core/useStomp.ts
Normal file
@@ -0,0 +1,285 @@
|
||||
import { getToken as getAccessToken } from "@/utils/cache";
|
||||
|
||||
export interface UseStompOptions {
|
||||
/** WebSocket 地址,不传时使用 VITE_APP_WS_ENDPOINT 环境变量 */
|
||||
brokerURL?: string;
|
||||
/** 重连延迟,单位毫秒,默认为 8000 */
|
||||
reconnectDelay?: number;
|
||||
/** 连接超时时间,单位毫秒,默认为 10000 */
|
||||
connectionTimeout?: number;
|
||||
/** 是否开启指数退避重连策略 */
|
||||
useExponentialBackoff?: boolean;
|
||||
/** 最大重连次数,默认为 5 */
|
||||
maxReconnectAttempts?: number;
|
||||
/** 最大重连延迟,单位毫秒,默认为 60000 */
|
||||
maxReconnectDelay?: number;
|
||||
/** 是否开启调试日志 */
|
||||
debug?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* STOMP WebSocket连接Hook (UniApp版本)
|
||||
* 用于管理WebSocket连接的建立、断开、重连和消息订阅
|
||||
*/
|
||||
export function useStomp(options: UseStompOptions = {}) {
|
||||
// 默认配置
|
||||
const defaultBrokerURL = import.meta.env.VITE_APP_WS_ENDPOINT || "";
|
||||
const brokerURL = ref(options.brokerURL ?? defaultBrokerURL);
|
||||
const reconnectDelay = options.reconnectDelay ?? 8000;
|
||||
const connectionTimeout = options.connectionTimeout ?? 10000;
|
||||
const useExponentialBackoff = options.useExponentialBackoff ?? false;
|
||||
const maxReconnectAttempts = options.maxReconnectAttempts ?? 5;
|
||||
const maxReconnectDelay = options.maxReconnectDelay ?? 60000;
|
||||
|
||||
// 连接状态和计数
|
||||
const isConnected = ref(false);
|
||||
const reconnectCount = ref(0);
|
||||
let reconnectTimer: number | null = null;
|
||||
let connectionTimeoutTimer: number | null = null;
|
||||
|
||||
// 存储所有订阅
|
||||
const subscriptions = ref<Record<string, any>>({});
|
||||
|
||||
// WebSocket实例
|
||||
let socketTask: any = null;
|
||||
const client = ref<any>(null);
|
||||
|
||||
/**
|
||||
* 创建WebSocket连接
|
||||
*/
|
||||
const createSocketConnection = () => {
|
||||
const token = getAccessToken();
|
||||
if (!token) {
|
||||
console.error("WebSocket连接失败:未找到有效token");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 创建WebSocket连接
|
||||
try {
|
||||
// 构建带有token的URL
|
||||
let url = brokerURL.value;
|
||||
if (url.indexOf("?") > -1) {
|
||||
url += "&token=" + token;
|
||||
} else {
|
||||
url += "?token=" + token;
|
||||
}
|
||||
|
||||
// 创建WebSocket连接
|
||||
socketTask = uni.connectSocket({
|
||||
url: url,
|
||||
complete: () => {},
|
||||
});
|
||||
|
||||
if (!socketTask) {
|
||||
console.error("WebSocket连接创建失败");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 设置WebSocket事件处理函数
|
||||
socketTask.onOpen(() => {
|
||||
isConnected.value = true;
|
||||
reconnectCount.value = 0;
|
||||
if (connectionTimeoutTimer) clearTimeout(connectionTimeoutTimer);
|
||||
console.log("WebSocket连接已建立");
|
||||
});
|
||||
|
||||
socketTask.onClose(() => {
|
||||
isConnected.value = false;
|
||||
console.log("WebSocket连接已关闭");
|
||||
|
||||
// 如果使用指数退避重连策略,则处理重连
|
||||
if (useExponentialBackoff && reconnectCount.value < maxReconnectAttempts) {
|
||||
handleReconnect();
|
||||
}
|
||||
});
|
||||
|
||||
socketTask.onError((error: any) => {
|
||||
console.error("WebSocket连接错误:", error);
|
||||
});
|
||||
|
||||
socketTask.onMessage((res: any) => {
|
||||
const message = JSON.parse(res.data);
|
||||
// 处理订阅消息
|
||||
if (message.subscription && subscriptions.value[message.subscription]) {
|
||||
const subscription = subscriptions.value[message.subscription];
|
||||
if (subscription.callback) {
|
||||
subscription.callback(message);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return socketTask;
|
||||
} catch (error) {
|
||||
console.error("创建WebSocket连接时出错:", error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理重连逻辑
|
||||
*/
|
||||
const handleReconnect = () => {
|
||||
if (reconnectCount.value >= maxReconnectAttempts) {
|
||||
console.error(`已达到最大重连次数(${maxReconnectAttempts}),停止重连`);
|
||||
return;
|
||||
}
|
||||
|
||||
reconnectCount.value++;
|
||||
console.log(`尝试重连(${reconnectCount.value}/${maxReconnectAttempts})...`);
|
||||
|
||||
// 使用指数退避策略
|
||||
const delay = useExponentialBackoff
|
||||
? Math.min(reconnectDelay * Math.pow(2, reconnectCount.value - 1), maxReconnectDelay)
|
||||
: reconnectDelay;
|
||||
|
||||
// 清除之前的计时器
|
||||
if (reconnectTimer) {
|
||||
clearTimeout(reconnectTimer);
|
||||
}
|
||||
|
||||
// 设置重连计时器
|
||||
reconnectTimer = setTimeout(() => {
|
||||
if (!isConnected.value) {
|
||||
connect();
|
||||
}
|
||||
}, delay) as unknown as number;
|
||||
};
|
||||
|
||||
/**
|
||||
* 建立WebSocket连接
|
||||
*/
|
||||
const connect = () => {
|
||||
if (isConnected.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建WebSocket连接
|
||||
socketTask = createSocketConnection();
|
||||
client.value = socketTask;
|
||||
|
||||
// 设置连接超时
|
||||
if (connectionTimeoutTimer) {
|
||||
clearTimeout(connectionTimeoutTimer);
|
||||
}
|
||||
|
||||
connectionTimeoutTimer = setTimeout(() => {
|
||||
if (!isConnected.value) {
|
||||
console.warn("WebSocket连接超时");
|
||||
if (useExponentialBackoff) {
|
||||
handleReconnect();
|
||||
}
|
||||
}
|
||||
}, connectionTimeout) as unknown as number;
|
||||
};
|
||||
|
||||
/**
|
||||
* 订阅主题
|
||||
* @param destination 主题地址
|
||||
* @param callback 回调函数
|
||||
* @returns 订阅ID
|
||||
*/
|
||||
const subscribe = (destination: string, callback: (message: any) => void): string => {
|
||||
if (!socketTask || !isConnected.value) {
|
||||
console.warn("WebSocket未连接,无法订阅:", destination);
|
||||
return "";
|
||||
}
|
||||
|
||||
// 生成唯一订阅ID
|
||||
const subscriptionId = "sub-" + Math.random().toString(36).substr(2, 9);
|
||||
|
||||
// 发送订阅消息
|
||||
socketTask.send({
|
||||
data: JSON.stringify({
|
||||
command: "SUBSCRIBE",
|
||||
headers: {
|
||||
id: subscriptionId,
|
||||
destination: destination,
|
||||
},
|
||||
}),
|
||||
success: () => {
|
||||
console.log(`订阅成功: ${destination}, ID: ${subscriptionId}`);
|
||||
},
|
||||
fail: (err: any) => {
|
||||
console.error(`订阅失败(${destination}):`, err);
|
||||
},
|
||||
});
|
||||
|
||||
// 保存订阅
|
||||
subscriptions.value[subscriptionId] = {
|
||||
destination,
|
||||
callback,
|
||||
};
|
||||
|
||||
return subscriptionId;
|
||||
};
|
||||
|
||||
/**
|
||||
* 取消订阅
|
||||
* @param subscriptionId 订阅ID
|
||||
*/
|
||||
const unsubscribe = (subscriptionId: string) => {
|
||||
if (!socketTask || !isConnected.value || !subscriptions.value[subscriptionId]) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 发送取消订阅消息
|
||||
socketTask.send({
|
||||
data: JSON.stringify({
|
||||
command: "UNSUBSCRIBE",
|
||||
headers: {
|
||||
id: subscriptionId,
|
||||
},
|
||||
}),
|
||||
success: () => {
|
||||
console.log(`已取消订阅: ${subscriptionId}`);
|
||||
},
|
||||
fail: (err: any) => {
|
||||
console.error(`取消订阅失败(${subscriptionId}):`, err);
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`取消订阅失败(${subscriptionId}):`, error);
|
||||
} finally {
|
||||
Reflect.deleteProperty(subscriptions.value, subscriptionId);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 断开WebSocket连接
|
||||
*/
|
||||
const disconnect = () => {
|
||||
if (!socketTask) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 取消所有订阅
|
||||
Object.keys(subscriptions.value).forEach(unsubscribe);
|
||||
|
||||
// 断开WebSocket连接
|
||||
try {
|
||||
socketTask.close({
|
||||
success: () => {
|
||||
console.log("WebSocket连接已断开");
|
||||
isConnected.value = false;
|
||||
socketTask = null;
|
||||
},
|
||||
fail: (err: any) => {
|
||||
console.error("断开WebSocket连接失败:", err);
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("断开WebSocket连接失败:", error);
|
||||
}
|
||||
};
|
||||
|
||||
// 返回公开的API
|
||||
return {
|
||||
isConnected,
|
||||
client,
|
||||
connect,
|
||||
disconnect,
|
||||
subscribe,
|
||||
unsubscribe,
|
||||
};
|
||||
}
|
||||
10
src/hooks/websocket/index.ts
Normal file
10
src/hooks/websocket/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* WebSocket相关Hook入口文件
|
||||
* 统一导出所有WebSocket相关Hook
|
||||
*/
|
||||
|
||||
// 核心基础Hook
|
||||
export { useStomp } from "./core/useStomp";
|
||||
|
||||
// 业务服务Hook
|
||||
export { useDictSync } from "./services/useDictSync";
|
||||
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;
|
||||
}
|
||||
@@ -1,38 +1,80 @@
|
||||
import { defineStore } from "pinia";
|
||||
import DictAPI, { type DictVO, type DictData } from "@/api/system/dict";
|
||||
import { setDictCache, getDictCache } from "@/utils/cache";
|
||||
import DictAPI, { type DictItemOption } from "@/api/system/dict";
|
||||
|
||||
const DICT_CACHE_KEY = "dict_cache";
|
||||
|
||||
export const useDictStore = defineStore("dict", () => {
|
||||
const dictionary = ref<Record<string, DictData[]>>(getDictCache());
|
||||
// 字典数据缓存
|
||||
const dictCache = ref<Record<string, DictItemOption[]>>(uni.getStorageSync(DICT_CACHE_KEY) || {});
|
||||
|
||||
const setDictionary = (dict: DictVO) => {
|
||||
dictionary.value[dict.dictCode] = dict.dictDataList;
|
||||
setDictCache(dictionary.value);
|
||||
// 监听dictCache变化,同步到本地存储
|
||||
watch(
|
||||
dictCache,
|
||||
(newVal) => {
|
||||
uni.setStorageSync(DICT_CACHE_KEY, newVal);
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
// 请求队列(防止重复请求)
|
||||
const requestQueue: Record<string, Promise<void>> = {};
|
||||
|
||||
/**
|
||||
* 缓存字典数据
|
||||
* @param dictCode 字典编码
|
||||
* @param data 字典项列表
|
||||
*/
|
||||
const cacheDictItems = (dictCode: string, data: DictItemOption[]) => {
|
||||
dictCache.value[dictCode] = data;
|
||||
};
|
||||
|
||||
const loadDictionaries = async () => {
|
||||
const dictList = await DictAPI.getList();
|
||||
dictList.forEach(setDictionary);
|
||||
/**
|
||||
* 加载字典数据(如果缓存中没有则请求)
|
||||
* @param dictCode 字典编码
|
||||
*/
|
||||
const loadDictItems = async (dictCode: string) => {
|
||||
if (dictCache.value[dictCode]) return;
|
||||
|
||||
// 防止重复请求
|
||||
if (!requestQueue[dictCode]) {
|
||||
requestQueue[dictCode] = DictAPI.getDictItems(dictCode).then((data) => {
|
||||
cacheDictItems(dictCode, data);
|
||||
Reflect.deleteProperty(requestQueue, dictCode);
|
||||
});
|
||||
}
|
||||
await requestQueue[dictCode];
|
||||
};
|
||||
|
||||
const getDictionary = (dictCode: string): DictData[] => {
|
||||
return dictionary.value[dictCode] || [];
|
||||
/**
|
||||
* 获取字典项列表
|
||||
* @param dictCode 字典编码
|
||||
* @returns 字典项列表
|
||||
*/
|
||||
const getDictItems = (dictCode: string): DictItemOption[] => {
|
||||
return dictCache.value[dictCode] || [];
|
||||
};
|
||||
|
||||
const clearDictionaryCache = () => {
|
||||
dictionary.value = {};
|
||||
/**
|
||||
* 移除指定字典项
|
||||
* @param dictCode 字典编码
|
||||
*/
|
||||
const removeDictItem = (dictCode: string) => {
|
||||
if (dictCache.value[dictCode]) {
|
||||
Reflect.deleteProperty(dictCache.value, dictCode);
|
||||
}
|
||||
};
|
||||
|
||||
const updateDictionaryCache = async () => {
|
||||
clearDictionaryCache(); // 先清除旧缓存
|
||||
await loadDictionaries(); // 重新加载最新字典数据
|
||||
/**
|
||||
* 清空字典缓存
|
||||
*/
|
||||
const clearDictCache = () => {
|
||||
dictCache.value = {};
|
||||
};
|
||||
|
||||
return {
|
||||
dictionary,
|
||||
setDictionary,
|
||||
loadDictionaries,
|
||||
getDictionary,
|
||||
clearDictionaryCache,
|
||||
updateDictionaryCache,
|
||||
loadDictItems,
|
||||
getDictItems,
|
||||
removeDictItem,
|
||||
clearDictCache,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
const TOKEN_KEY = "app-token";
|
||||
const USER_INFO_KEY = "user-info";
|
||||
const DICT_KEY = "dict";
|
||||
import { type DictData } from "@/api/system/dict";
|
||||
|
||||
// 设置 token
|
||||
export function setToken(token: string) {
|
||||
@@ -33,24 +31,10 @@ export function clearUserInfo() {
|
||||
uni.removeStorageSync(USER_INFO_KEY);
|
||||
}
|
||||
|
||||
// 设置字典缓存
|
||||
export function setDictCache(dict: Record<string, DictData[]>) {
|
||||
uni.setStorageSync(DICT_KEY, dict);
|
||||
}
|
||||
|
||||
// 获取字典缓存
|
||||
export function getDictCache(): Record<string, DictData[]> {
|
||||
return uni.getStorageSync(DICT_KEY) || {};
|
||||
}
|
||||
|
||||
// 清除字典缓存
|
||||
export function clearDictCache() {
|
||||
uni.removeStorageSync(DICT_KEY);
|
||||
}
|
||||
|
||||
// 清除所有缓存信息
|
||||
export function clearAll() {
|
||||
clearToken();
|
||||
clearUserInfo();
|
||||
clearDictCache();
|
||||
// 清除字典缓存
|
||||
uni.removeStorageSync("dict_cache");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user