用法
const { options: statusOptions, load } = useDictOptions(
'user_status',
async () => {
const res = await axios.get('/api/user/status')
return res.data.data.map((item: any) => ({
value: item.id,
label: item.name,
disabled: item.status === 1
}))
},
{ immediate: true }
)
useDictOptions
import {ref, onMounted} from 'vue'
import {useDictStore} from '@/stores/dict'
interface UseDictOptions {
immediate?: boolean
}
/**
* 用法示例
* const { options: statusOptions, load } = useDictOptions(
* 'user_status',
* async () => {
* const res = await axios.get('/api/user/status')
* return res.data.data.map((item: any) => ({
* value: item.id,
* label: item.name,
* disabled: item.status === 1
* }))
* },
* { immediate: true }
* )
* @param dictKey
* @param converter
* @param options
*/
export function useDictOptions(
dictKey: string,
converter: () => Promise<any[]>,
options: UseDictOptions = {}
) {
const dictStore = useDictStore()
const opts = ref<any[]>([])
// 加载静态字典
const load = async () => {
opts.value = await dictStore.fetchDict(dictKey, converter)
}
// 远程搜索
const search = async (searchKey: string) => {
opts.value = await dictStore.searchDict(dictKey, searchKey, async (key) => {
return converter()
})
}
if (options.immediate) {
onMounted(load)
}
return {
options: opts,
load,
search
}
}
defineStore
import {defineStore} from 'pinia'
import {ref} from 'vue'
export const useDictStore = defineStore('dict', () => {
const dicts = ref<Record<string, any[]>>({})
const searchCache = ref<Record<string, Record<string, any[]>>>({})
const timestamps = ref<Record<string, number>>({})
const CACHE_DURATION = 10 * 60 * 1000
const isExpired = (type: string) => {
if (!timestamps.value[type]) return true
return Date.now() - timestamps.value[type] > CACHE_DURATION
}
/**
* 普通字典获取
*/
const fetchDict = async (type: string, converter: () => Promise<any[]>) => {
if (!dicts.value[type] || isExpired(type)) {
dicts.value[type] = await converter()
timestamps.value[type] = Date.now()
}
return dicts.value[type]
}
/**
* 远程搜索字典
* @param type 字典类型
* @param searchKey 搜索关键字
* @param converter 转换函数,接收 searchKey 返回字典数组
* @param cache 是否缓存结果
*/
const searchDict = async (
type: string,
searchKey: string,
converter: (searchKey: string) => Promise<any[]>,
cache = true
) => {
if (cache && searchCache.value[type]?.[searchKey]) {
return searchCache.value[type][searchKey]
}
const result = await converter(searchKey)
if (cache) {
if (!searchCache.value[type]) searchCache.value[type] = {}
searchCache.value[type][searchKey] = result
}
return result
}
const clearDict = (type?: string) => {
if (type) {
delete dicts.value[type]
delete timestamps.value[type]
delete searchCache.value[type]
} else {
dicts.value = {}
timestamps.value = {}
searchCache.value = {}
}
}
return {
fetchDict,
searchDict,
clearDict,
isExpired
}
})
想法或问题?在 GitHub Issue 下方参与讨论
去评论