import { defineStore } from 'pinia' import { ref, computed } from 'vue' import { getDictItemsByCode } from '@/api/dict' /** * 字典 Store * * 用于全局管理系统字典数据 * 缓存字典数据避免重复请求,提高性能 * * 使用示例: * const dictStore = useDictStore() * const statusDict = await dictStore.getDictItems('user_status') * const roleDict = dictStore.getDictItemsSync('user_role') // 已加载则同步返回 */ export const useDictStore = defineStore('dict', () => { // 字典缓存:{ dictCode: [...items] } const dictCache = ref({}) // 正在加载的字典代码集合 const loadingCodes = ref(new Set()) /** * 获取字典项(异步) * @param {string} code - 字典编码,如 'user_status' * @returns {Promise} 字典项数组 */ async function getDictItems(code) { // 如果缓存中已有,直接返回 if (dictCache.value[code]) { return dictCache.value[code] } // 避免重复请求:如果已在加载中,等待 if (loadingCodes.value.has(code)) { // 等待加载完成(最多 5 秒) return await new Promise((resolve) => { let count = 0 const timer = setInterval(() => { if (dictCache.value[code]) { clearInterval(timer) resolve(dictCache.value[code]) } count++ if (count > 50) { clearInterval(timer) resolve([]) } }, 100) }) } // 标记为正在加载 loadingCodes.value.add(code) try { const res = await getDictItemsByCode(code) let items = [] // 兼容不同的 API 响应格式 if (res?.data && Array.isArray(res.data)) { items = res.data } else if (Array.isArray(res)) { items = res } else if (res?.data?.data && Array.isArray(res.data.data)) { items = res.data.data } // 缓存字典项 dictCache.value[code] = items // console.log(`✅ 字典 [${code}] 已加载,共 ${items.length} 项`) return items } catch (error) { console.error(`❌ 加载字典 [${code}] 失败:`, error) dictCache.value[code] = [] return [] } finally { // 移除加载标记 loadingCodes.value.delete(code) } } /** * 同步获取字典项(如果已缓存) * @param {string} code - 字典编码 * @returns {Array} 字典项数组,未缓存则返回空数组 */ function getDictItemsSync(code) { return dictCache.value[code] || [] } /** * 预加载字典(在应用启动时调用) * @param {Array} codes - 字典编码数组 * @returns {Promise} */ async function preloadDicts(codes) { const promises = codes.map(code => getDictItems(code)) await Promise.all(promises) } /** * 根据字典编码和值获取标签 * @param {string} code - 字典编码 * @param {any} value - 字典值 * @returns {string} 字典标签 */ function getDictLabel(code, value) { const items = getDictItemsSync(code) if (!items.length) { console.warn(`⚠️ 字典 [${code}] 未加载,无法获取标签`) return String(value) } const item = items.find(i => String(i.dict_value) === String(value) || i.dict_value === value) return item ? item.dict_label : String(value) } /** * 根据字典编码和标签获取值 * @param {string} code - 字典编码 * @param {string} label - 字典标签 * @returns {any} 字典值 */ function getDictValue(code, label) { const items = getDictItemsSync(code) if (!items.length) { console.warn(`⚠️ 字典 [${code}] 未加载,无法获取值`) return null } const item = items.find(i => i.dict_label === label) return item ? item.dict_value : null } /** * 清空缓存 * @param {string} code - 字典编码,不指定则清空所有 */ function clearCache(code) { if (code) { delete dictCache.value[code] // console.log(`✅ 已清除字典 [${code}] 缓存`) } else { dictCache.value = {} // console.log(`✅ 已清除所有字典缓存`) } } /** * 刷新字典 * @param {string} code - 字典编码 * @returns {Promise} */ async function refreshDict(code) { clearCache(code) return getDictItems(code) } /** * 获取所有已缓存的字典 * @returns {Object} */ const allDicts = computed(() => dictCache.value) return { dictCache, loadingCodes, getDictItems, getDictItemsSync, preloadDicts, getDictLabel, getDictValue, clearCache, refreshDict, allDicts, } })