diff --git a/apps/web-contract/forge.config.ts b/apps/web-contract/forge.config.ts new file mode 100644 index 00000000..75b83e68 --- /dev/null +++ b/apps/web-contract/forge.config.ts @@ -0,0 +1,63 @@ +const createEntry = (description = '', data: any = []) => ({ + description, + data, +}); + +const staticDicts = { + cancel_reson: createEntry('变更原因', [ + { label: '未填写原因', value: '0' }, + { label: '用户取消', value: '1' }, + { label: '系统取消', value: '2' }, + { label: '其他原因', value: '3' }, + ]), +}; + +export default { + // 配置路径,如果存在,则使用配置路径下的文件 + configPath: '', + // 接口配置,仅用于生成 api 接口文件 + apis: { + enable: true, + generator: [ + { + input: '', + templatePath: 'src/api/template', + output: 'src/api/index.ts', + needTs: true, + outputTs: 'src/api/globals.d.ts', + handleApi: (apiDescriptor) => { + // 返回falsy值表示过滤此api + if (!apiDescriptor.path.startWith('/user')) { + return; + } + + apiDescriptor.parameter = apiDescriptor.parameter.filter( + (param) => param.in === 'header' && param.name === 'token', + ); + delete apiDescriptor.requestBody.id; + apiDescriptor.url = apiDescriptor.url.replace('/user', ''); + return apiDescriptor; + }, + }, + ], + }, + // 字典配置,仅用于生成字典枚举文件 + dicts: { + enable: true, + generator: [ + { + input: '', + templatePath: 'src/api/template', + output: 'src/utils/dict/shared.ts', + handleDict: async (dictDescriptor) => { + // await dictDescriptor.request(); + + // 请求数据类型表为了生成对应注释 + // 返回falsy值表示过滤此api + staticDicts[dictDescriptor.name] = dictDescriptor; + return dictDescriptor; + }, + }, + ], + }, +}; diff --git a/apps/web-contract/src/app.vue b/apps/web-contract/src/app.vue index 9b6a9cbd..f8ca521a 100644 --- a/apps/web-contract/src/app.vue +++ b/apps/web-contract/src/app.vue @@ -33,7 +33,7 @@ const tokenTheme = computed(() => { const dictStore = useDictStore(); if (dictStore.initDict) { - dictStore.setDictMap(); + // dictStore.setDictMap(); } diff --git a/apps/web-contract/src/main.ts b/apps/web-contract/src/main.ts index a069bc52..5d728a02 100644 --- a/apps/web-contract/src/main.ts +++ b/apps/web-contract/src/main.ts @@ -3,12 +3,6 @@ import { unmountGlobalLoading } from '@vben/utils'; import { overridesPreferences } from './preferences'; -// const dict = new Dictionary(http.get, {}); - -// dict.getAll('dict').then((res) => { -// console.log('dict', res); -// }); - /** * 应用初始化完成之后再进行页面加载渲染 */ diff --git a/apps/web-contract/src/utils/dict/index.ts b/apps/web-contract/src/utils/dict/index.ts index d8a86108..05a1f496 100644 --- a/apps/web-contract/src/utils/dict/index.ts +++ b/apps/web-contract/src/utils/dict/index.ts @@ -1,5 +1,7 @@ /** 数据字典工具类 */ +import Apis from '#/api'; import { useDictStore } from '#/store/dict'; +import dataModule from '#/utils/dict/static.data'; export * from './shared'; @@ -12,9 +14,9 @@ const dictStore = useDictStore(); * @returns {any | Array} 数据字典数组 */ export interface DictDataType { - dictTyp?: string; + dictType?: string; label: string; - value: null | number | string; + value: boolean | null | number | string; key?: any; colorType?: string; cssClass?: string; @@ -39,6 +41,58 @@ export function getDictOpts(dictType: string) { return getDictDatas(dictType); } +export async function getDictDatasAsync(dictTypes: string[]) { + const dictDataMap: Record = {}; + const foundTypes = new Set(); + + // Process static dictionary data + for (const dictType of Object.keys(dataModule)) { + if (dictTypes.includes(dictType)) { + const dictEntries = dataModule[dictType]; + dictEntries.data.forEach((dictData) => { + dictData.type = dictType; + + if (!dictDataMap[dictType]) { + dictDataMap[dictType] = []; + } + dictDataMap[dictType].push({ + ...dictData, + value: dictData.value, + label: dictData.name, + colorType: dictData.colorType, + cssClass: dictData.cssClass, + } as DictDataType); + }); + foundTypes.add(dictType); + + // If all types are found, return early + if (foundTypes.size === dictTypes.length) { + return dictDataMap; + } + } + } + + // Fetch remote dictionary data in parallel + const promises = dictTypes.map(async (type) => { + if (!foundTypes.has(type)) { + try { + const data = await Apis.dictData.get_page({ params: { type } }); + dictDataMap[type] = (data.rows || []).map((dictData: any) => ({ + value: dictData.value, + label: dictData.name, + colorType: dictData.colorType, + cssClass: dictData.cssClass, + })); + } catch (error) { + console.error(`Failed to fetch data for type ${type}:`, error); + } + } + }); + + await Promise.all(promises); + return dictDataMap; +} + export function getDictOptions( dictType: string, valueType?: 'boolean' | 'number' | 'string', @@ -52,12 +106,7 @@ export function getDictOptions( dictOption.push({ ...dict, key: dict.value, - value: - valueType === 'string' - ? `${dict.value}` - : valueType === 'boolean' - ? `${dict.value}` === 'true' - : Number.parseInt(`${dict.value}`), + value: convertValue(dict.value, valueType), }); }); } @@ -65,6 +114,41 @@ export function getDictOptions( return dictOption; } +function convertValue(value, type) { + switch (type) { + case 'boolean': { + return value === 'true'; + } + case 'number': { + return Number.parseInt(value, 10); + } + case 'string': { + return String(value); + } + default: { + return value; + } + } +} +export async function getDictOptionsAsync( + dictType: string, + valueType: 'boolean' | 'number' | 'string' = 'string', +): Promise { + try { + const response = await getDictDatasAsync([dictType]); + const dictOptions: DictDataType[] = response[dictType] || []; + + return dictOptions.map((dict: DictDataType) => ({ + ...dict, + key: dict.value, + value: convertValue(dict.value, valueType), + })); + } catch (error) { + console.error('Error fetching dictionary data:', error); + return []; + } +} + /** 获取指定 value 的字典数据 */ export function getDictObj(dictType: string, value: any): DictDataType | null { const dictOptions: DictDataType[] = getDictDatas(dictType); diff --git a/apps/web-contract/src/views/contract/sign-authorization/edit/curd.tsx b/apps/web-contract/src/views/contract/sign-authorization/edit/curd.tsx index 244bbfd7..51d9bab8 100644 --- a/apps/web-contract/src/views/contract/sign-authorization/edit/curd.tsx +++ b/apps/web-contract/src/views/contract/sign-authorization/edit/curd.tsx @@ -8,7 +8,12 @@ import dayjs, { type Dayjs } from 'dayjs'; import { VxeGrid, type VxeGridPropTypes } from 'vxe-table'; import { unitComponentProps } from '#/common/unit'; -import { DICT_TYPE, getDictObj, getDictOptions } from '#/utils/dict'; +import { + DICT_TYPE, + getDictObj, + getDictOptions, + getDictOptionsAsync, +} from '#/utils/dict'; import chooseUserModal from '#/views/system/user/choose-user-modal.vue'; const [ChooseUserModal, chooseUserModalApi] = useVbenModal({ @@ -122,7 +127,11 @@ export function getFormSchema(params?: any): any { vModel: 'value', allowClear: false, dict: dict({ - data: getDictOptions(DICT_TYPE.contract_authorization_type2), + async getData(_context) { + return await getDictOptionsAsync( + DICT_TYPE.contract_authorization_type2, + ); + }, }), }, valueChange: { diff --git a/apps/web-contract/vite.config.mts b/apps/web-contract/vite.config.mts index 899482c4..8d532ae1 100644 --- a/apps/web-contract/vite.config.mts +++ b/apps/web-contract/vite.config.mts @@ -30,7 +30,7 @@ export default defineConfig(async () => { changeOrigin: true, rewrite: (path) => path.replace(/^\/api\/app/, '/'), // target: `http://10.71.220.24:8083/rl`, - target: `http://192.168.148.88:8083/rl`, + target: `http://192.168.147.164:8083/rl`, ws: true, }, '/api/czg/app': { @@ -43,15 +43,15 @@ export default defineConfig(async () => { '/api/czg/uc': { changeOrigin: true, rewrite: (path) => path.replace(/^\/api\/czg\/uc/, '/'), - target: `http://192.168.148.88:8082`, - // target: `http://192.168.148.88:8082`, + target: `http://192.168.147.164:8082`, + // target: `http://192.168.147.164:8082`, ws: true, }, '/api/uc': { changeOrigin: true, rewrite: (path) => path.replace(/^\/api\/uc/, '/'), // target: `http://10.71.220.24:8082`, - target: `http://192.168.148.88:8082`, + target: `http://192.168.147.164:8082`, ws: true, }, '/api/xmh/app': { @@ -65,7 +65,7 @@ export default defineConfig(async () => { changeOrigin: true, rewrite: (path) => path.replace(/^\/api\/xmh\/uc/, '/'), // mock代理目标地址 - target: `http://192.168.148.88:8082`, + target: `http://192.168.147.164:8082`, ws: true, }, '/api/zp/app': { @@ -79,21 +79,21 @@ export default defineConfig(async () => { changeOrigin: true, rewrite: (path) => path.replace(/^\/api\/zp\/uc/, '/'), // mock代理目标地址 - target: `http://192.168.148.88:8082`, + target: `http://192.168.147.164:8082`, ws: true, }, '/api/zzz/app': { changeOrigin: true, rewrite: (path) => path.replace(/^\/api\/zzz\/app/, '/'), // target: `http://192.168.0.193:8083/rl`, - target: `http://192.168.148.88:8089/rl`, + target: `http://192.168.147.164:8089/rl`, ws: true, }, '/api/zzz/uc': { changeOrigin: true, rewrite: (path) => path.replace(/^\/api\/zzz\/uc/, '/'), - target: `http://192.168.148.88:8082`, - // target: `http://192.168.148.88:8082`, + target: `http://192.168.147.164:8082`, + // target: `http://192.168.147.164:8082`, ws: true, }, }, diff --git a/apps/web-office/src/utils/dict/index.ts b/apps/web-office/src/utils/dict/index.ts index d8a86108..05a1f496 100644 --- a/apps/web-office/src/utils/dict/index.ts +++ b/apps/web-office/src/utils/dict/index.ts @@ -1,5 +1,7 @@ /** 数据字典工具类 */ +import Apis from '#/api'; import { useDictStore } from '#/store/dict'; +import dataModule from '#/utils/dict/static.data'; export * from './shared'; @@ -12,9 +14,9 @@ const dictStore = useDictStore(); * @returns {any | Array} 数据字典数组 */ export interface DictDataType { - dictTyp?: string; + dictType?: string; label: string; - value: null | number | string; + value: boolean | null | number | string; key?: any; colorType?: string; cssClass?: string; @@ -39,6 +41,58 @@ export function getDictOpts(dictType: string) { return getDictDatas(dictType); } +export async function getDictDatasAsync(dictTypes: string[]) { + const dictDataMap: Record = {}; + const foundTypes = new Set(); + + // Process static dictionary data + for (const dictType of Object.keys(dataModule)) { + if (dictTypes.includes(dictType)) { + const dictEntries = dataModule[dictType]; + dictEntries.data.forEach((dictData) => { + dictData.type = dictType; + + if (!dictDataMap[dictType]) { + dictDataMap[dictType] = []; + } + dictDataMap[dictType].push({ + ...dictData, + value: dictData.value, + label: dictData.name, + colorType: dictData.colorType, + cssClass: dictData.cssClass, + } as DictDataType); + }); + foundTypes.add(dictType); + + // If all types are found, return early + if (foundTypes.size === dictTypes.length) { + return dictDataMap; + } + } + } + + // Fetch remote dictionary data in parallel + const promises = dictTypes.map(async (type) => { + if (!foundTypes.has(type)) { + try { + const data = await Apis.dictData.get_page({ params: { type } }); + dictDataMap[type] = (data.rows || []).map((dictData: any) => ({ + value: dictData.value, + label: dictData.name, + colorType: dictData.colorType, + cssClass: dictData.cssClass, + })); + } catch (error) { + console.error(`Failed to fetch data for type ${type}:`, error); + } + } + }); + + await Promise.all(promises); + return dictDataMap; +} + export function getDictOptions( dictType: string, valueType?: 'boolean' | 'number' | 'string', @@ -52,12 +106,7 @@ export function getDictOptions( dictOption.push({ ...dict, key: dict.value, - value: - valueType === 'string' - ? `${dict.value}` - : valueType === 'boolean' - ? `${dict.value}` === 'true' - : Number.parseInt(`${dict.value}`), + value: convertValue(dict.value, valueType), }); }); } @@ -65,6 +114,41 @@ export function getDictOptions( return dictOption; } +function convertValue(value, type) { + switch (type) { + case 'boolean': { + return value === 'true'; + } + case 'number': { + return Number.parseInt(value, 10); + } + case 'string': { + return String(value); + } + default: { + return value; + } + } +} +export async function getDictOptionsAsync( + dictType: string, + valueType: 'boolean' | 'number' | 'string' = 'string', +): Promise { + try { + const response = await getDictDatasAsync([dictType]); + const dictOptions: DictDataType[] = response[dictType] || []; + + return dictOptions.map((dict: DictDataType) => ({ + ...dict, + key: dict.value, + value: convertValue(dict.value, valueType), + })); + } catch (error) { + console.error('Error fetching dictionary data:', error); + return []; + } +} + /** 获取指定 value 的字典数据 */ export function getDictObj(dictType: string, value: any): DictDataType | null { const dictOptions: DictDataType[] = getDictDatas(dictType); diff --git a/apps/web-office/src/views/meeting/list/crud.tsx b/apps/web-office/src/views/meeting/list/crud.tsx index e4db7e00..3d49ebf9 100644 --- a/apps/web-office/src/views/meeting/list/crud.tsx +++ b/apps/web-office/src/views/meeting/list/crud.tsx @@ -4,7 +4,7 @@ import { dict } from '@fast-crud/fast-crud'; import dayjs from 'dayjs'; import { useRender } from '#/hooks/useRender'; -import { DICT_TYPE, getDictOptions } from '#/utils/dict'; +import { DICT_TYPE, getDictOptionsAsync } from '#/utils/dict'; export const PrimaryKey = 'guid'; @@ -31,7 +31,7 @@ export function getColumns(params: any = {}): VxeGridPropTypes.Columns { }, }, { - field: 'meetingDate', + field: 'meetingInfo', title: '会议信息', width: 200, slots: { default: 'meetingInfoSlot' }, @@ -171,7 +171,9 @@ export function getFormSchema(_params: any = {}) { class: 'min-w-[180px]', allowClear: true, dict: dict({ - data: getDictOptions(DICT_TYPE.meeting_room), + async getData() { + return await getDictOptionsAsync(DICT_TYPE.meeting_room); + }, }), }, autoSearchTrigger: 'enter', @@ -186,7 +188,9 @@ export function getFormSchema(_params: any = {}) { class: 'min-w-[180px]', allowClear: true, dict: dict({ - data: getDictOptions(DICT_TYPE.meeting_type), + async getData() { + return await getDictOptionsAsync(DICT_TYPE.meeting_type); + }, }), }, autoSearchTrigger: 'enter', diff --git a/apps/web-office/src/views/meeting/standing-book/crud.tsx b/apps/web-office/src/views/meeting/standing-book/crud.tsx index ded94ea3..ba22c3c5 100644 --- a/apps/web-office/src/views/meeting/standing-book/crud.tsx +++ b/apps/web-office/src/views/meeting/standing-book/crud.tsx @@ -12,7 +12,7 @@ export function getColumns(_params?: any): VxeGridPropTypes.Columns { { field: 'meetingDate', title: '会议时间', - width: 200, + width: 230, slots: { default: ({ row }) => { return ( @@ -49,7 +49,7 @@ export function getColumns(_params?: any): VxeGridPropTypes.Columns { { field: 'otherEquipment', title: '备注', - minWidth: 200, + minWidth: 150, }, ]; diff --git a/apps/web-office/src/views/meeting/standing-book/index.vue b/apps/web-office/src/views/meeting/standing-book/index.vue index 2b69ed64..f368960a 100644 --- a/apps/web-office/src/views/meeting/standing-book/index.vue +++ b/apps/web-office/src/views/meeting/standing-book/index.vue @@ -143,7 +143,7 @@ const searchForm = ref({