import { ref } from 'vue'; import { defineStore } from 'pinia'; import { RDMS_OBJECT_DIRECTION_DICT_CODE, RDMS_OBJECT_DIRECTION_LEGACY_DICT_CODE } from '@/constants/dict'; import { fetchGetFrontendDictCache } from '@/service/api'; import { SetupStoreId } from '@/enum'; type DictValue = string | number | null | undefined; type DictFilterOptions = { onlyEnabled?: boolean; }; type DictLabelOptions = DictFilterOptions & { fallback?: string; }; type DictLabelsOptions = DictLabelOptions & { separator?: string; }; function sortDictData(list: Api.Dict.DictData[]) { return list.slice().sort((left, right) => left.sort - right.sort || left.label.localeCompare(right.label, 'zh-CN')); } function normalizeFrontendDictData( dictType: string, list: Api.Dict.FrontendDictData[], dictIndex: number ): Api.Dict.DictData[] { const normalizedList = list.map((item, itemIndex) => ({ id: -((dictIndex + 1) * 100000 + itemIndex + 1), label: item.label, value: item.value, dictType: item.dictType || dictType, sort: item.sort, status: item.status ?? 0, remark: null, createTime: 0 })); return sortDictData(normalizedList); } function normalizeFrontendDictCache(cache: Api.Dict.FrontendDictCache) { const entries = Object.entries(cache); return Object.fromEntries( entries.map(([dictType, list], index) => [dictType, normalizeFrontendDictData(dictType, list, index)]) ); } function applyDictTypeAliases(dictDataMap: Record) { const nextDictDataMap = { ...dictDataMap }; // 兼容后端尚未切换完成的过渡期:旧编码仍返回时,前端统一映射到新编码。 if (!nextDictDataMap[RDMS_OBJECT_DIRECTION_DICT_CODE] && nextDictDataMap[RDMS_OBJECT_DIRECTION_LEGACY_DICT_CODE]) { nextDictDataMap[RDMS_OBJECT_DIRECTION_DICT_CODE] = nextDictDataMap[RDMS_OBJECT_DIRECTION_LEGACY_DICT_CODE].map( item => ({ ...item, dictType: RDMS_OBJECT_DIRECTION_DICT_CODE }) ); } return nextDictDataMap; } function createRuntimeDictTypes(dictDataMap: Record) { return Object.keys(dictDataMap).map((dictType, index) => ({ id: -(index + 1), name: dictType, type: dictType, status: 0 as const, remark: null, createTime: 0 })); } function findDictItem(list: Api.Dict.DictData[], value?: DictValue) { if (value === null || value === undefined || value === '') { return undefined; } return list.find(item => item.value === String(value)); } export const useDictStore = defineStore(SetupStoreId.Dict, () => { const loading = ref(false); const initialized = ref(false); const dictTypes = ref([]); const dictDataMap = ref>({}); const loadedAt = ref(null); let initPromise: Promise | null = null; function resetDictCache() { dictTypes.value = []; dictDataMap.value = {}; loadedAt.value = null; initialized.value = false; initPromise = null; } async function initDictCache(force = false) { if (initialized.value && !force) { return true; } if (initPromise && !force) { return initPromise; } if (force) { resetDictCache(); } initPromise = (async () => { loading.value = true; const result = await fetchGetFrontendDictCache(); loading.value = false; if (result.error) { initPromise = null; return false; } const normalizedDictDataMap = applyDictTypeAliases(normalizeFrontendDictCache(result.data || {})); dictTypes.value = createRuntimeDictTypes(normalizedDictDataMap); dictDataMap.value = normalizedDictDataMap; loadedAt.value = Date.now(); initialized.value = true; initPromise = null; return true; })(); return initPromise; } function getDictData(dictType: string, onlyEnabled = false) { if (!dictType) { return []; } const list = dictDataMap.value[dictType] || []; if (!onlyEnabled) { return list; } return list.filter(item => item.status === 0); } function getDictOptions(dictType: string, onlyEnabled = true) { return getDictData(dictType, onlyEnabled).map(item => ({ label: item.label, value: item.value })); } function getDictItem(dictType: string, value?: DictValue, options: DictFilterOptions = {}) { return findDictItem(getDictData(dictType, options.onlyEnabled), value); } function getDictLabel(dictType: string, value?: DictValue, options: DictLabelOptions = {}) { const { fallback = '--', onlyEnabled = false } = options; if (value === null || value === undefined || value === '') { return fallback; } const matched = getDictItem(dictType, value, { onlyEnabled }); return matched?.label || String(value); } function getDictLabels(dictType: string, values?: Array | null, options: DictLabelsOptions = {}) { const { fallback = '--', separator = ' / ', onlyEnabled = false } = options; if (!values?.length) { return fallback; } const labels = values .filter(value => value !== null && value !== undefined && value !== '') .map(value => getDictLabel(dictType, value, { fallback: String(value), onlyEnabled })); return labels.length ? labels.join(separator) : fallback; } function hasDictValue(dictType: string, value?: DictValue, options: DictFilterOptions = {}) { return Boolean(getDictItem(dictType, value, options)); } return { loading, initialized, dictTypes, dictDataMap, loadedAt, initDictCache, resetDictCache, getDictData, getDictOptions, getDictItem, getDictLabel, getDictLabels, hasDictValue }; });