180 lines
4.6 KiB
JavaScript
180 lines
4.6 KiB
JavaScript
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<Array>} 字典项数组
|
|
*/
|
|
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<string>} codes - 字典编码数组
|
|
* @returns {Promise<void>}
|
|
*/
|
|
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<Array>}
|
|
*/
|
|
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,
|
|
}
|
|
})
|