useDict.ts 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import { ref } from 'vue';
  2. import { useSystemApi } from '@/api/system';
  3. export interface DictItem {
  4. dictType: string;
  5. dictValue: string;
  6. dictLabel: string;
  7. isDefault?: number;
  8. }
  9. // 字典全局缓存,避免多页面或多组件切换时重复请求
  10. const dictCache = new Map<string, DictItem[]>();
  11. const pendingRequests = new Map<string, Promise<DictItem[]>>();
  12. /**
  13. * 获取系统字典并提供回显方法的 Hook
  14. * @param args 字典类型参数数组,例如: 'sci_leader_type', 'sys_user_sex'
  15. * @returns { dicts, getDictLabel }
  16. */
  17. export function useDict(...args: string[]) {
  18. const { getDictDataByType } = useSystemApi();
  19. // 用于响应式绑定到视图的字典集合
  20. const dicts = ref<Record<string, DictItem[]>>({});
  21. args.forEach((dictType) => {
  22. // 默认初始化为空数组,防页面渲染时为空报错
  23. dicts.value[dictType] = [];
  24. // 如果已有缓存,直接使用缓存
  25. if (dictCache.has(dictType)) {
  26. dicts.value[dictType] = dictCache.get(dictType)!;
  27. } else {
  28. // 如果没有缓存,检查是否在请求中,避免并发时重复请求相同的字典
  29. let req = pendingRequests.get(dictType);
  30. if (!req) {
  31. req = getDictDataByType(dictType)
  32. .then((res: any) => {
  33. // 解析出字典数组列表 (兼容不同拦截器返回的结构)
  34. const values = res?.data?.values || [];
  35. // 存入缓存
  36. dictCache.set(dictType, values);
  37. return values;
  38. })
  39. .catch((err: any) => {
  40. console.error(`获取字典 [${dictType}] 失败:`, err);
  41. return [];
  42. })
  43. .finally(() => {
  44. // 请求结束,无论成功或失败都清除 pending 状态
  45. pendingRequests.delete(dictType);
  46. });
  47. pendingRequests.set(dictType, req);
  48. }
  49. // 等待请求结束并赋值给响应式对象
  50. req.then((values: DictItem[]) => {
  51. dicts.value[dictType] = values;
  52. });
  53. }
  54. });
  55. /**
  56. * 字典回显方法
  57. * @param dictType 字典类型
  58. * @param dictValue 字典值
  59. * @returns 匹配的字典标签 (dictLabel),如果没有匹配到则返回原值
  60. */
  61. const getDictLabel = (dictType: string, dictValue: string | number | undefined | null) => {
  62. if (dictValue === undefined || dictValue === null || dictValue === '') {
  63. return '';
  64. }
  65. const list = dicts.value[dictType] || dictCache.get(dictType) || [];
  66. const item = list.find((item: DictItem) => item.dictValue == dictValue);
  67. return item ? item.dictLabel : dictValue;
  68. };
  69. return {
  70. dicts,
  71. getDictLabel,
  72. };
  73. }