From 89a08aa285aa4b5db1faa9bbdc0888932bb791da Mon Sep 17 00:00:00 2001 From: sunlei Date: Wed, 3 Jun 2026 22:51:18 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8E=A5=E5=85=A5=E5=AD=97=E5=85=B8?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web-antdv-next/src/api/core/menu.ts | 4 + apps/web-antdv-next/src/api/system/dict.ts | 77 +++++++ apps/web-antdv-next/src/api/system/index.ts | 1 + .../src/locales/langs/en-US/system.json | 16 ++ .../src/locales/langs/zh-CN/system.json | 16 ++ .../src/router/routes/modules/system.ts | 9 + .../src/views/system/dict/data.ts | 127 +++++++++++ .../src/views/system/dict/list.vue | 203 ++++++++++++++++++ .../src/views/system/dict/modules/form.vue | 88 ++++++++ 9 files changed, 541 insertions(+) create mode 100644 apps/web-antdv-next/src/api/system/dict.ts create mode 100644 apps/web-antdv-next/src/views/system/dict/data.ts create mode 100644 apps/web-antdv-next/src/views/system/dict/list.vue create mode 100644 apps/web-antdv-next/src/views/system/dict/modules/form.vue diff --git a/apps/web-antdv-next/src/api/core/menu.ts b/apps/web-antdv-next/src/api/core/menu.ts index 58e0172..fd3ab92 100644 --- a/apps/web-antdv-next/src/api/core/menu.ts +++ b/apps/web-antdv-next/src/api/core/menu.ts @@ -51,6 +51,10 @@ const SUPPORTED_ADMIN_MENU_NAMES = new Set([ 'SystemDeptCreate', 'SystemDeptDelete', 'SystemDeptEdit', + 'SystemDict', + 'SystemDictCreate', + 'SystemDictDelete', + 'SystemDictEdit', 'SystemKtTableDemo', 'SystemKtTableDemoCreate', 'SystemKtTableDemoDelete', diff --git a/apps/web-antdv-next/src/api/system/dict.ts b/apps/web-antdv-next/src/api/system/dict.ts new file mode 100644 index 0000000..ccc79b3 --- /dev/null +++ b/apps/web-antdv-next/src/api/system/dict.ts @@ -0,0 +1,77 @@ +import type { Recordable } from '@vben/types'; + +import { requestClient } from '#/api/request'; + +export namespace SystemDictApi { + export interface DictItem { + [key: string]: any; + childrenCode?: null | string; + createTime?: string; + dictCode: string; + id: string; + label: string; + sort: number; + status: 0 | 1; + updateTime?: string; + value: string; + } + + export type DictInput = Omit; + + export interface DictCodeOption { + label: string; + value: string; + } + + export interface PageResult { + items: T[]; + total: number; + } +} + +async function getDictList(params: Recordable) { + return requestClient.get>( + '/dict/list', + { params }, + ); +} + +async function getDictCodeOptions() { + return requestClient.get('/dict/codes'); +} + +async function createDict(data: SystemDictApi.DictInput) { + return requestClient.post('/dict/save', data); +} + +async function updateDict(id: string, data: Partial) { + return requestClient.post('/dict/update', { + ...data, + id, + }); +} + +async function deleteDict(id: string) { + return requestClient.delete(`/dict/${id}`); +} + +async function toggleDictStatus( + id: string, + status: SystemDictApi.DictItem['status'], +) { + return requestClient.post('/dict/toggle', undefined, { + params: { + id, + status, + }, + }); +} + +export { + createDict, + deleteDict, + getDictCodeOptions, + getDictList, + toggleDictStatus, + updateDict, +}; diff --git a/apps/web-antdv-next/src/api/system/index.ts b/apps/web-antdv-next/src/api/system/index.ts index 1b28fb6..5137978 100644 --- a/apps/web-antdv-next/src/api/system/index.ts +++ b/apps/web-antdv-next/src/api/system/index.ts @@ -1,4 +1,5 @@ export * from './dept'; +export * from './dict'; export * from './menu'; export * from './role'; export * from './user'; diff --git a/apps/web-antdv-next/src/locales/langs/en-US/system.json b/apps/web-antdv-next/src/locales/langs/en-US/system.json index 0803c7a..6ffa373 100644 --- a/apps/web-antdv-next/src/locales/langs/en-US/system.json +++ b/apps/web-antdv-next/src/locales/langs/en-US/system.json @@ -27,6 +27,22 @@ "operation": "Operation", "parentDept": "Parent Department" }, + "dict": { + "childrenCode": "Children Code", + "deleteConfirm": "Confirm deleting \"{0} / {1}\"?", + "dictCode": "Dict Code", + "disableSuccess": "Dictionary item disabled", + "enableSuccess": "Dictionary item enabled", + "label": "Label", + "list": "Dictionary List", + "name": "Dictionary", + "sort": "Sort", + "status": "Status", + "title": "Dictionary Management", + "toggle": "Toggle", + "updateTime": "Update Time", + "value": "Value" + }, "menu": { "title": "Menu Management", "parent": "Parent Menu", diff --git a/apps/web-antdv-next/src/locales/langs/zh-CN/system.json b/apps/web-antdv-next/src/locales/langs/zh-CN/system.json index 00043d6..9959fef 100644 --- a/apps/web-antdv-next/src/locales/langs/zh-CN/system.json +++ b/apps/web-antdv-next/src/locales/langs/zh-CN/system.json @@ -28,6 +28,22 @@ "status": "状态", "title": "部门管理" }, + "dict": { + "childrenCode": "子级编码", + "deleteConfirm": "确认删除「{0} / {1}」吗?", + "dictCode": "字典编码", + "disableSuccess": "字典项已停用", + "enableSuccess": "字典项已启用", + "label": "字典标签", + "list": "字典列表", + "name": "字典", + "sort": "排序", + "status": "状态", + "title": "字典管理", + "toggle": "启停", + "updateTime": "更新时间", + "value": "字典值" + }, "menu": { "list": "菜单列表", "activeIcon": "激活图标", diff --git a/apps/web-antdv-next/src/router/routes/modules/system.ts b/apps/web-antdv-next/src/router/routes/modules/system.ts index 371d235..139f355 100644 --- a/apps/web-antdv-next/src/router/routes/modules/system.ts +++ b/apps/web-antdv-next/src/router/routes/modules/system.ts @@ -39,6 +39,15 @@ const routes: RouteRecordRaw[] = [ }, component: () => import('#/views/system/menu/list.vue'), }, + { + path: '/system/dict', + name: 'SystemDict', + meta: { + icon: 'carbon:data-structured', + title: $t('system.dict.title'), + }, + component: () => import('#/views/system/dict/list.vue'), + }, { path: '/system/dept', name: 'SystemDept', diff --git a/apps/web-antdv-next/src/views/system/dict/data.ts b/apps/web-antdv-next/src/views/system/dict/data.ts new file mode 100644 index 0000000..7247f37 --- /dev/null +++ b/apps/web-antdv-next/src/views/system/dict/data.ts @@ -0,0 +1,127 @@ +import type { VbenFormSchema } from '#/adapter/form'; + +import { z } from '#/adapter/form'; +import { $t } from '#/locales'; + +export function getStatusOptions() { + return [ + { color: 'success', label: $t('common.enabled'), value: 1 }, + { color: 'default', label: $t('common.disabled'), value: 0 }, + ]; +} + +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + componentProps: { + placeholder: '如 COMPONENT_TYPE', + }, + fieldName: 'dictCode', + label: $t('system.dict.dictCode'), + rules: z + .string() + .min(1, $t('ui.formRules.required', [$t('system.dict.dictCode')])) + .max( + 120, + $t('ui.formRules.maxLength', [$t('system.dict.dictCode'), 120]), + ), + }, + { + component: 'Input', + fieldName: 'label', + label: $t('system.dict.label'), + rules: z + .string() + .min(1, $t('ui.formRules.required', [$t('system.dict.label')])) + .max(120, $t('ui.formRules.maxLength', [$t('system.dict.label'), 120])), + }, + { + component: 'Input', + fieldName: 'value', + label: $t('system.dict.value'), + rules: z + .string() + .min(1, $t('ui.formRules.required', [$t('system.dict.value')])) + .max(120, $t('ui.formRules.maxLength', [$t('system.dict.value'), 120])), + }, + { + component: 'Input', + componentProps: { + allowClear: true, + placeholder: '如 CHART', + }, + fieldName: 'childrenCode', + label: $t('system.dict.childrenCode'), + }, + { + component: 'InputNumber', + componentProps: { + class: 'w-full', + min: 0, + precision: 0, + }, + defaultValue: 0, + fieldName: 'sort', + label: $t('system.dict.sort'), + }, + { + component: 'RadioGroup', + componentProps: { + buttonStyle: 'solid', + options: getStatusOptions(), + optionType: 'button', + }, + defaultValue: 1, + fieldName: 'status', + label: $t('system.dict.status'), + }, + ]; +} + +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + componentProps: { + allowClear: true, + placeholder: '如 COMPONENT_TYPE', + }, + fieldName: 'dictCode', + label: $t('system.dict.dictCode'), + }, + { + component: 'Input', + componentProps: { + allowClear: true, + }, + fieldName: 'label', + label: $t('system.dict.label'), + }, + { + component: 'Input', + componentProps: { + allowClear: true, + }, + fieldName: 'value', + label: $t('system.dict.value'), + }, + { + component: 'Input', + componentProps: { + allowClear: true, + }, + fieldName: 'childrenCode', + label: $t('system.dict.childrenCode'), + }, + { + component: 'Select', + componentProps: { + allowClear: true, + options: getStatusOptions(), + }, + fieldName: 'status', + label: $t('system.dict.status'), + }, + ]; +} diff --git a/apps/web-antdv-next/src/views/system/dict/list.vue b/apps/web-antdv-next/src/views/system/dict/list.vue new file mode 100644 index 0000000..45d2091 --- /dev/null +++ b/apps/web-antdv-next/src/views/system/dict/list.vue @@ -0,0 +1,203 @@ + + + diff --git a/apps/web-antdv-next/src/views/system/dict/modules/form.vue b/apps/web-antdv-next/src/views/system/dict/modules/form.vue new file mode 100644 index 0000000..4419091 --- /dev/null +++ b/apps/web-antdv-next/src/views/system/dict/modules/form.vue @@ -0,0 +1,88 @@ + + +