Files
cn-rdms-web/src/store/modules/dict/index.ts

211 lines
5.7 KiB
TypeScript
Raw Normal View History

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<string, Api.Dict.DictData[]>) {
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<string, Api.Dict.DictData[]>) {
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<Api.Dict.DictType[]>([]);
const dictDataMap = ref<Record<string, Api.Dict.DictData[]>>({});
const loadedAt = ref<number | null>(null);
let initPromise: Promise<boolean> | 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<DictValue> | 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
};
});