dict.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import { defineStore } from "pinia";
  2. import { localForage } from "@/utils/localforage";
  3. import { getDictDataByType } from "@/api/system/dict";
  4. const DICT_PREFIX = "dict:";
  5. const DEFAULT_TTL_MINUTES = 60;
  6. export const useDictStore = defineStore("dict", {
  7. state: () => ({
  8. dict: [] as Array<{ key: string; value: any[] }>
  9. }),
  10. actions: {
  11. // 内存读取
  12. getDict(key: string) {
  13. try {
  14. const item = this.dict.find(item => item.key === key);
  15. return item ? item.value : null;
  16. } catch (e) {
  17. console.error("获取字典失败:", e);
  18. return null;
  19. }
  20. },
  21. // 内存写入
  22. setDict(key: string, value: any[]) {
  23. if (!key || typeof key !== "string") return;
  24. const index = this.dict.findIndex(item => item.key === key);
  25. if (index !== -1) {
  26. this.dict[index].value = value;
  27. } else {
  28. this.dict.push({ key, value });
  29. }
  30. },
  31. // 从持久层加载(未过期则返回)
  32. async loadFromStorage(key: string) {
  33. const cacheKey = `${DICT_PREFIX}${key}`;
  34. const cached = await localForage().getItem<any[]>(cacheKey);
  35. if (cached && cached.length) {
  36. this.setDict(key, cached);
  37. return cached;
  38. }
  39. return null;
  40. },
  41. // 写入持久层(带 TTL,单位分钟)
  42. async persistDict(
  43. key: string,
  44. value: any[],
  45. ttlMinutes = DEFAULT_TTL_MINUTES
  46. ) {
  47. const cacheKey = `${DICT_PREFIX}${key}`;
  48. await localForage().setItem(cacheKey, value, ttlMinutes);
  49. },
  50. // 统一拉取入口(内存→持久层→后端)
  51. async fetchDictByType(
  52. key: string,
  53. opts?: { forceRefresh?: boolean; ttlMinutes?: number }
  54. ) {
  55. // 1) 内存命中
  56. const inMemory = this.getDict(key);
  57. if (inMemory && !opts?.forceRefresh) return inMemory;
  58. // 2) 持久层命中
  59. const fromStorage = await this.loadFromStorage(key);
  60. if (fromStorage && !opts?.forceRefresh) return fromStorage;
  61. // 3) 后端拉取
  62. const resp = await getDictDataByType(key);
  63. const dictData = resp.data.map((p: any) => ({
  64. label: p.dictLabel,
  65. value: p.dictValue,
  66. class: p.listClass
  67. }));
  68. this.setDict(key, dictData);
  69. await this.persistDict(
  70. key,
  71. dictData,
  72. opts?.ttlMinutes ?? DEFAULT_TTL_MINUTES
  73. );
  74. return dictData;
  75. },
  76. // 删除:内存 + 持久层
  77. async removeDict(key: string) {
  78. try {
  79. const index = this.dict.findIndex(item => item.key === key);
  80. if (index !== -1) this.dict.splice(index, 1);
  81. await localForage().removeItem(`${DICT_PREFIX}${key}`);
  82. return true;
  83. } catch (e) {
  84. console.error("移除字典失败:", e);
  85. return false;
  86. }
  87. },
  88. // 清空:内存 + 持久层(仅清理字典前缀)
  89. async clearAll() {
  90. this.dict = [];
  91. const keys = await localForage().keys();
  92. const dictKeys = keys.filter(k => k.startsWith(DICT_PREFIX));
  93. await Promise.all(dictKeys.map(k => localForage().removeItem(k)));
  94. }
  95. }
  96. });