项目概况

字典设计

2026-01-292 min read未分类
vue

用法

text
1const { options: statusOptions, load } = useDictOptions( 2 'user_status', 3 async () => { 4 const res = await axios.get('/api/user/status') 5 return res.data.data.map((item: any) => ({ 6 value: item.id, 7 label: item.name, 8 disabled: item.status === 1 9 })) 10 }, 11 { immediate: true } 12)

useDictOptions

text
1import {ref, onMounted} from 'vue' 2import {useDictStore} from '@/stores/dict' 3 4interface UseDictOptions { 5 immediate?: boolean 6} 7 8/** 9 * 用法示例 10 * const { options: statusOptions, load } = useDictOptions( 11 * 'user_status', 12 * async () => { 13 * const res = await axios.get('/api/user/status') 14 * return res.data.data.map((item: any) => ({ 15 * value: item.id, 16 * label: item.name, 17 * disabled: item.status === 1 18 * })) 19 * }, 20 * { immediate: true } 21 * ) 22 * @param dictKey 23 * @param converter 24 * @param options 25 */ 26export function useDictOptions( 27 dictKey: string, 28 converter: () => Promise<any[]>, 29 options: UseDictOptions = {} 30) { 31 const dictStore = useDictStore() 32 33 const opts = ref<any[]>([]) 34 35 // 加载静态字典 36 const load = async () => { 37 opts.value = await dictStore.fetchDict(dictKey, converter) 38 } 39 40 // 远程搜索 41 const search = async (searchKey: string) => { 42 opts.value = await dictStore.searchDict(dictKey, searchKey, async (key) => { 43 return converter() 44 }) 45 } 46 47 if (options.immediate) { 48 onMounted(load) 49 } 50 51 return { 52 options: opts, 53 load, 54 search 55 } 56} 57

defineStore

text
1import {defineStore} from 'pinia' 2import {ref} from 'vue' 3 4export const useDictStore = defineStore('dict', () => { 5 6 const dicts = ref<Record<string, any[]>>({}) 7 8 const searchCache = ref<Record<string, Record<string, any[]>>>({}) 9 10 const timestamps = ref<Record<string, number>>({}) 11 12 const CACHE_DURATION = 10 * 60 * 1000 13 14 const isExpired = (type: string) => { 15 if (!timestamps.value[type]) return true 16 return Date.now() - timestamps.value[type] > CACHE_DURATION 17 } 18 19 /** 20 * 普通字典获取 21 */ 22 const fetchDict = async (type: string, converter: () => Promise<any[]>) => { 23 if (!dicts.value[type] || isExpired(type)) { 24 dicts.value[type] = await converter() 25 timestamps.value[type] = Date.now() 26 } 27 return dicts.value[type] 28 } 29 30 /** 31 * 远程搜索字典 32 * @param type 字典类型 33 * @param searchKey 搜索关键字 34 * @param converter 转换函数,接收 searchKey 返回字典数组 35 * @param cache 是否缓存结果 36 */ 37 const searchDict = async ( 38 type: string, 39 searchKey: string, 40 converter: (searchKey: string) => Promise<any[]>, 41 cache = true 42 ) => { 43 if (cache && searchCache.value[type]?.[searchKey]) { 44 return searchCache.value[type][searchKey] 45 } 46 47 const result = await converter(searchKey) 48 49 if (cache) { 50 if (!searchCache.value[type]) searchCache.value[type] = {} 51 searchCache.value[type][searchKey] = result 52 } 53 54 return result 55 } 56 57 const clearDict = (type?: string) => { 58 if (type) { 59 delete dicts.value[type] 60 delete timestamps.value[type] 61 delete searchCache.value[type] 62 } else { 63 dicts.value = {} 64 timestamps.value = {} 65 searchCache.value = {} 66 } 67 } 68 69 return { 70 fetchDict, 71 searchDict, 72 clearDict, 73 isExpired 74 } 75}) 76