import { ref } from 'vue'; import { useSystemApi } from '@/api/system'; export interface DictItem { dictType: string; dictValue: string; dictLabel: string; isDefault?: number; } // 字典全局缓存,避免多页面或多组件切换时重复请求 const dictCache = new Map(); const pendingRequests = new Map>(); /** * 获取系统字典并提供回显方法的 Hook * @param args 字典类型参数数组,例如: 'sci_leader_type', 'sys_user_sex' * @returns { dicts, getDictLabel } */ export function useDict(...args: string[]) { const { getDictDataByType } = useSystemApi(); // 用于响应式绑定到视图的字典集合 const dicts = ref>({}); args.forEach((dictType) => { // 默认初始化为空数组,防页面渲染时为空报错 dicts.value[dictType] = []; // 如果已有缓存,直接使用缓存 if (dictCache.has(dictType)) { dicts.value[dictType] = dictCache.get(dictType)!; } else { // 如果没有缓存,检查是否在请求中,避免并发时重复请求相同的字典 let req = pendingRequests.get(dictType); if (!req) { req = getDictDataByType(dictType) .then((res: any) => { // 解析出字典数组列表 (兼容不同拦截器返回的结构) const values = res?.data?.values || []; // 存入缓存 dictCache.set(dictType, values); return values; }) .catch((err: any) => { console.error(`获取字典 [${dictType}] 失败:`, err); return []; }) .finally(() => { // 请求结束,无论成功或失败都清除 pending 状态 pendingRequests.delete(dictType); }); pendingRequests.set(dictType, req); } // 等待请求结束并赋值给响应式对象 req.then((values: DictItem[]) => { dicts.value[dictType] = values; }); } }); /** * 字典回显方法 * @param dictType 字典类型 * @param dictValue 字典值 * @returns 匹配的字典标签 (dictLabel),如果没有匹配到则返回原值 */ const getDictLabel = (dictType: string, dictValue: string | number | undefined | null) => { if (dictValue === undefined || dictValue === null || dictValue === '') { return ''; } const list = dicts.value[dictType] || dictCache.get(dictType) || []; const item = list.find((item: DictItem) => item.dictValue == dictValue); return item ? item.dictLabel : dictValue; }; return { dicts, getDictLabel, }; }