@ithinkdt/core
Version:
iThinkDT Core
160 lines (144 loc) • 4.59 kB
JavaScript
import { computed, shallowRef, isRef, shallowReactive, watch, nextTick, unref } from 'vue'
import { tryOnUnmounted } from '@vueuse/core'
import { useI18n } from '../i18n'
export let init
export function setInit(init0) {
init = init0
}
const layzePool = []
function batchFetchDicts() {
const _layzePool = [...layzePool]
layzePool.length = 0
init.fetchDicts(_layzePool.map(([dictType]) => dictType)).then(
(res) => {
for (const [dictType, cb] of _layzePool) {
cb(res?.[dictType] ?? [])
}
},
(error) => {
console.error('[dict]: 请求字典项数据失败:', error)
for (const [_dictType, cb] of _layzePool) {
cb([])
}
},
)
}
export async function _getDict(dictType, forceCache) {
if (forceCache || !hasDictType(dictType)) {
if (typeof dictType !== 'string' || !dictType?.trim()) {
console.error('[dict]: 字典类型错误:', dictType)
return []
}
removeDict(dictType)
const $fetch = new Promise((resolve) => {
layzePool.push([dictType, resolve])
})
if (layzePool.length === 1) {
nextTick(batchFetchDicts)
}
registerDict(dictType, $fetch, {
label: init.labelGetter,
value: init.valueGetter,
disabled: init.disabledGetter,
})
await $fetch
}
await dictMap[dictType]?.$
return unref(dictMap[dictType]?.data) ?? []
}
export const dictMap = {}
export const dictValueMap = {}
export function registerDict(dictType, dicts, { autoClean = false, cleanUseless = true, label, value, disabled } = {}) {
let _dicts
let $
if (typeof dicts === 'function') {
dicts = Promise.resolve(dicts(_getDict))
}
if (dicts instanceof Promise) {
_dicts = shallowRef([])
$ = dicts.then((dicts) => {
_dicts.value = dicts
})
} else {
_dicts = isRef(dicts) ? dicts : shallowRef(dicts)
}
const _label = typeof label === 'function' ? label : (d) => d[label ?? 'label']
const _value = typeof value === 'function' ? value : (d) => d[value ?? 'value']
const _disabled = typeof disabled === 'function' ? disabled : (d) => d[disabled ?? 'disabled']
const { locale } = useI18n()
const $dicts = computed(() => {
return _dicts.value?.map((dict) => {
return {
label: _label(dict, locale.value),
value: _value(dict),
disabled: _disabled(dict),
orign: dict,
}
})
})
dictMap[dictType] = {
date: cleanUseless ? Date.now() : undefined,
data: $dicts,
$,
}
const unregister = () => removeDict(dictType)
if (autoClean) {
tryOnUnmounted(unregister)
}
return {
dictType,
dicts: getDicts(dictType),
unregister,
}
}
export function getDicts(dictType, hideDisabled = true, valueType = 'string') {
const cache = dictMap[dictType]
cache.date = Date.now()
const dicts = shallowReactive([])
watch(
cache.data,
(data = []) => {
dicts.length = 0
let array = valueType === 'number' ? data.map((it) => ({ ...it, value: Number(it.value) })) : data
if (hideDisabled) {
array = array.filter((it) => it.disabled !== true)
}
dicts.push(...array)
},
{ immediate: true },
)
return dicts
}
export function getDictMap(dictType, hideDisabled = false, valueType = 'string') {
if (!dictValueMap[dictType + hideDisabled]) {
const map = shallowReactive(new Map())
watch(
getDicts(dictType, hideDisabled, valueType),
(dicts) => {
map.clear()
for (const dict of dicts) {
map.set(dict.value, dict)
}
},
{ immediate: true },
)
dictValueMap[dictType + hideDisabled] = map
}
return dictValueMap[dictType + hideDisabled]
}
export function hasDictType(dictType) {
return !!dictMap[dictType]
}
export function removeDict(dictType) {
delete dictMap[dictType]
delete dictValueMap[dictType]
}
export function cleanUseless(delay = 1 * 60 * 1000) {
const now = Date.now()
for (const key of Object.keys(dictMap)) {
const date = dictMap[key]?.date
if (date && now - date > delay) {
removeDict(key)
}
}
}