diff --git a/mocks/demo/dict.ts b/mocks/demo/dict.ts new file mode 100644 index 000000000..ef819d18e --- /dev/null +++ b/mocks/demo/dict.ts @@ -0,0 +1,37 @@ +import { http, HttpResponse, delay } from 'msw'; +import { getQuery, resultSuccess, serverApi } from '../_util'; + +const getDictData = (dictType: string) => { + if (dictType === 'gender') { + return [ + { + label: '男', + value: 1, + }, + { + label: '女', + value: 0, + }, + ]; + } else if (dictType === 'sell_status') { + return [ + { + label: '已售罄', + value: 0, + }, + { + label: '热卖中', + value: 1, + }, + ]; + } + return []; +}; + +export default [ + http.get(serverApi('/dict/data'), async ({ request }) => { + await delay(1800); + const { type } = getQuery(request); + return HttpResponse.json(resultSuccess(getDictData(type))); + }), +]; diff --git a/src/api/demo/dict.ts b/src/api/demo/dict.ts new file mode 100644 index 000000000..cf149c47e --- /dev/null +++ b/src/api/demo/dict.ts @@ -0,0 +1,11 @@ +import { request } from '@/utils/request'; + +export type DictType = 'gender' | 'sell_status'; + +export async function getDictData(params: { type: DictType }) { + return request({ + url: '/dict/data', + method: 'GET', + params, + }); +} diff --git a/src/store/modules/dict.ts b/src/store/modules/dict.ts new file mode 100644 index 000000000..1a4d1d331 --- /dev/null +++ b/src/store/modules/dict.ts @@ -0,0 +1,55 @@ +import { ref } from 'vue'; +import { defineStore } from 'pinia'; +import { type DictType, getDictData } from '@/api/demo/dict'; + +export const useDictStore = defineStore('dict', () => { + const dictMap = ref(new Map()); + const dictValueLabelMap = ref(new Map>()); + const dictPendingMap = ref(new Map()); + + const fetchDict = (dictType: DictType | DictType[]) => { + const dictTypes = Array.isArray(dictType) ? dictType : [dictType]; + const promises = dictTypes.map(async (type) => { + if (dictMap.value.has(type) && !dictPendingMap.value.has(type)) { + return dictMap.value.get(type)!; + } + + dictMap.value.set(type, []); + dictPendingMap.value.set(type, true); + const res = await getDictData({ type }).finally(() => dictPendingMap.value.delete(type)); + dictMap.value.set(type, res); + dictValueLabelMap.value.set(type, new Map(res.map((item) => [item.value, item.label]))); + return res; + }); + return Promise.all(promises); + }; + + const dictData = new Proxy({} as Record, { + get(_, prop: DictType) { + if (prop.startsWith('__v_')) { + // console.trace('get', prop); + return; + } + if (dictMap.value.has(prop)) { + return dictMap.value.get(prop); + } + if (!dictPendingMap.value.has(prop)) { + fetchDict(prop); + } + return dictMap.value.get(prop); + }, + }); + + const showDictLabel = (dictType: DictType, code: any) => { + dictData[dictType]; + return dictValueLabelMap.value.get(dictType)?.get(code) || ''; + }; + + const dictPending = new Proxy({} as Record, { + get(_, prop: DictType) { + return dictPendingMap.value.get(prop) || false; + }, + }); + + return { dictData, dictPending, fetchDict, showDictLabel }; +}); diff --git a/src/views/demos/tables/search-table/columns.tsx b/src/views/demos/tables/search-table/columns.tsx index ccd2f755d..081c1e92b 100644 --- a/src/views/demos/tables/search-table/columns.tsx +++ b/src/views/demos/tables/search-table/columns.tsx @@ -1,22 +1,18 @@ import { debounce } from 'lodash-es'; -import { Tag } from 'ant-design-vue'; +import { Tag, Spin } from 'ant-design-vue'; import type { TableColumn } from '@/components/core/dynamic-table'; import { waitTime } from '@/utils/common'; +import { useDictStore } from '@/store/modules/dict'; const names = ['王路飞', '王大蛇', '李白', '刺客伍六七']; +const { fetchDict, dictPending, showDictLabel } = useDictStore(); -export const fetchStatusMapData = (keyword = '') => { - const data = [ - { - label: '已售罄', - value: 0, - }, - { - label: '热卖中', - value: 1, - }, - ].filter((n) => n.label.includes(keyword)); - return waitTime(2000, data); +export const fetchStatusMapData = async (keyword = '') => { + const [data] = await fetchDict('sell_status'); + return waitTime( + 100, + data.filter((n) => n.label.includes(keyword)), + ); }; export const getClothesByGender = (gender: number) => { @@ -88,16 +84,10 @@ export const columns: TableColumn[] = [ formItemProps: { component: 'Select', componentProps: ({ formInstance, formModel }) => ({ - options: [ - { - label: '男', - value: 1, - }, - { - label: '女', - value: 0, - }, - ], + request: async () => { + const [data] = await fetchDict('gender'); + return data; + }, onChange() { // 根据当前选择的性别,更新衣服可选项 formInstance?.updateSchema({ @@ -111,7 +101,12 @@ export const columns: TableColumn[] = [ }, }), }, - customRender: ({ record }) => ['女', '男'][record.gender], + // customRender: ({ record }) => ['女', '男'][record.gender], + customRender: ({ record }) => ( + + {showDictLabel('gender', record.gender)} + + ), }, { title: '衣服', @@ -170,9 +165,11 @@ export const columns: TableColumn[] = [ }), }, customRender: ({ record }) => ( - - {['已售罄', '热卖中'][record.status]} - + + + {showDictLabel('sell_status', record.status)} + + ), }, ];