From c8801d576c9ff7e1e745ae78fbf9b94891d89b4e Mon Sep 17 00:00:00 2001 From: colin Date: Wed, 23 Apr 2025 17:00:40 +0800 Subject: [PATCH 1/3] feat: add data dictionary management --- .../app-antd/src/locales/langs/en-US/abp.json | 3 +- .../app-antd/src/locales/langs/zh-CN/abp.json | 3 +- .../app-antd/src/router/routes/modules/abp.ts | 10 + .../platform/data-dictionaries/index.vue | 15 ++ .../packages/@abp/platform/src/api/index.ts | 1 + .../src/api/useDataDictionariesApi.ts | 110 +++++++++ .../DataDictionaryItemDrawer.vue | 222 ++++++++++++++++++ .../data-dictionaries/DataDictionaryTable.vue | 213 +++++++++++++++++ .../@abp/platform/src/components/index.ts | 1 + .../platform/src/types/dataDictionaries.ts | 76 ++++++ .../packages/@abp/platform/src/types/index.ts | 1 + 11 files changed, 653 insertions(+), 2 deletions(-) create mode 100644 apps/vben5/apps/app-antd/src/views/platform/data-dictionaries/index.vue create mode 100644 apps/vben5/packages/@abp/platform/src/api/useDataDictionariesApi.ts create mode 100644 apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryItemDrawer.vue create mode 100644 apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryTable.vue create mode 100644 apps/vben5/packages/@abp/platform/src/types/dataDictionaries.ts diff --git a/apps/vben5/apps/app-antd/src/locales/langs/en-US/abp.json b/apps/vben5/apps/app-antd/src/locales/langs/en-US/abp.json index fb7826de2..cf0bec37c 100644 --- a/apps/vben5/apps/app-antd/src/locales/langs/en-US/abp.json +++ b/apps/vben5/apps/app-antd/src/locales/langs/en-US/abp.json @@ -97,7 +97,8 @@ "title": "Message Manage", "email": "Email Messages", "sms": "Sms Messages" - } + }, + "dataDictionaries": "Data Dictionaries" }, "saas": { "title": "Saas", diff --git a/apps/vben5/apps/app-antd/src/locales/langs/zh-CN/abp.json b/apps/vben5/apps/app-antd/src/locales/langs/zh-CN/abp.json index 275e9f92d..d5334ae22 100644 --- a/apps/vben5/apps/app-antd/src/locales/langs/zh-CN/abp.json +++ b/apps/vben5/apps/app-antd/src/locales/langs/zh-CN/abp.json @@ -97,7 +97,8 @@ "title": "消息管理", "email": "邮件消息", "sms": "短信消息" - } + }, + "dataDictionaries": "数据字典" }, "saas": { "title": "Saas", diff --git a/apps/vben5/apps/app-antd/src/router/routes/modules/abp.ts b/apps/vben5/apps/app-antd/src/router/routes/modules/abp.ts index 62625ed22..020a35e98 100644 --- a/apps/vben5/apps/app-antd/src/router/routes/modules/abp.ts +++ b/apps/vben5/apps/app-antd/src/router/routes/modules/abp.ts @@ -399,6 +399,16 @@ const routes: RouteRecordRaw[] = [ icon: 'ep:platform', }, children: [ + { + meta: { + title: $t('abp.platform.dataDictionaries'), + icon: 'material-symbols:dictionary-outline', + }, + name: 'PlatformDataDictionaries', + path: '/platform/data-dictionaries', + component: () => + import('#/views/platform/data-dictionaries/index.vue'), + }, { meta: { title: $t('abp.platform.messages.title'), diff --git a/apps/vben5/apps/app-antd/src/views/platform/data-dictionaries/index.vue b/apps/vben5/apps/app-antd/src/views/platform/data-dictionaries/index.vue new file mode 100644 index 000000000..2ed4fd7ce --- /dev/null +++ b/apps/vben5/apps/app-antd/src/views/platform/data-dictionaries/index.vue @@ -0,0 +1,15 @@ + + + diff --git a/apps/vben5/packages/@abp/platform/src/api/index.ts b/apps/vben5/packages/@abp/platform/src/api/index.ts index 340455006..481660d28 100644 --- a/apps/vben5/packages/@abp/platform/src/api/index.ts +++ b/apps/vben5/packages/@abp/platform/src/api/index.ts @@ -1,2 +1,3 @@ +export { useDataDictionariesApi } from './useDataDictionariesApi'; export { useEmailMessagesApi } from './useEmailMessagesApi'; export { useSmsMessagesApi } from './useSmsMessagesApi'; diff --git a/apps/vben5/packages/@abp/platform/src/api/useDataDictionariesApi.ts b/apps/vben5/packages/@abp/platform/src/api/useDataDictionariesApi.ts new file mode 100644 index 000000000..c6f172aea --- /dev/null +++ b/apps/vben5/packages/@abp/platform/src/api/useDataDictionariesApi.ts @@ -0,0 +1,110 @@ +import type { ListResultDto, PagedResultDto } from '@abp/core'; + +import type { + DataCreateDto, + DataDto, + DataItemCreateDto, + DataItemUpdateDto, + DataMoveDto, + DataUpdateDto, + GetDataListInput, +} from '../types/dataDictionaries'; + +import { useRequest } from '@abp/request'; + +export function useDataDictionariesApi() { + const { cancel, request } = useRequest(); + + function createApi(input: DataCreateDto): Promise { + return request('/api/platform/datas', { + data: input, + method: 'POST', + }); + } + + function deleteApi(id: string): Promise { + return request(`/api/platform/datas/${id}`, { + method: 'DELETE', + }); + } + + function createItemApi(id: string, input: DataItemCreateDto): Promise { + return request(`/api/platform/datas/${id}/items`, { + data: input, + method: 'POST', + }); + } + + function deleteItemApi(id: string, name: string): Promise { + return request(`/api/platform/datas/${id}/items/${name}`, { + method: 'DELETE', + }); + } + + function getApi(id: string): Promise { + return request(`/api/platform/datas/${id}`, { + method: 'GET', + }); + } + + function getByNameApi(name: string): Promise { + return request(`/api/platform/datas/by-name/${name}`, { + method: 'GET', + }); + } + + function getAllApi(): Promise> { + return request>(`/api/platform/datas/all`, { + method: 'GET', + }); + } + + function getPagedListApi( + input?: GetDataListInput, + ): Promise> { + return request>(`/api/platform/datas`, { + method: 'GET', + params: input, + }); + } + + function moveApi(id: string, input: DataMoveDto): Promise { + return request(`/api/platform/datas/${id}/move`, { + data: input, + method: 'PUT', + }); + } + + function updateApi(id: string, input: DataUpdateDto): Promise { + return request(`/api/platform/datas/${id}`, { + data: input, + method: 'PUT', + }); + } + + function updateItemApi( + id: string, + name: string, + input: DataItemUpdateDto, + ): Promise { + return request(`/api/platform/datas/${id}/items/${name}`, { + data: input, + method: 'PUT', + }); + } + + return { + cancel, + createApi, + createItemApi, + deleteApi, + deleteItemApi, + getAllApi, + getApi, + getByNameApi, + getPagedListApi, + moveApi, + updateApi, + updateItemApi, + }; +} diff --git a/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryItemDrawer.vue b/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryItemDrawer.vue new file mode 100644 index 000000000..124c8ebe0 --- /dev/null +++ b/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryItemDrawer.vue @@ -0,0 +1,222 @@ + + + + + diff --git a/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryTable.vue b/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryTable.vue new file mode 100644 index 000000000..c945b6af9 --- /dev/null +++ b/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryTable.vue @@ -0,0 +1,213 @@ + + + + + diff --git a/apps/vben5/packages/@abp/platform/src/components/index.ts b/apps/vben5/packages/@abp/platform/src/components/index.ts index c1a40b9f7..7c7cc632e 100644 --- a/apps/vben5/packages/@abp/platform/src/components/index.ts +++ b/apps/vben5/packages/@abp/platform/src/components/index.ts @@ -1,2 +1,3 @@ +export { default as DataDictionaryTable } from './data-dictionaries/DataDictionaryTable.vue'; export { default as EmailMessageTable } from './messages/email/EmailMessageTable.vue'; export { default as SmsMessageTable } from './messages/sms/SmsMessageTable.vue'; diff --git a/apps/vben5/packages/@abp/platform/src/types/dataDictionaries.ts b/apps/vben5/packages/@abp/platform/src/types/dataDictionaries.ts new file mode 100644 index 000000000..2c050e714 --- /dev/null +++ b/apps/vben5/packages/@abp/platform/src/types/dataDictionaries.ts @@ -0,0 +1,76 @@ +import type { EntityDto, PagedAndSortedResultRequestDto } from '@abp/core'; + +enum ValueType { + Array = 5, + Boolean = 2, + Date = 3, + DateTime = 4, + Numeic = 1, + Object = 6, + String = 0, +} + +interface DataItemDto extends EntityDto { + allowBeNull: boolean; + defaultValue?: string; + description?: string; + displayName: string; + name: string; + valueType: ValueType; +} + +interface DataDto extends EntityDto { + code: string; + description?: string; + displayName: string; + items: DataItemDto[]; + name: string; + parentId?: string; +} + +interface DataCreateOrUpdateDto { + description?: string; + displayName: string; + name: string; +} + +interface DataCreateDto extends DataCreateOrUpdateDto { + parentId?: string; +} + +interface DataItemCreateOrUpdateDto { + allowBeNull: boolean; + defaultValue?: string; + description?: string; + displayName: string; + valueType: ValueType; +} + +interface DataItemCreateDto extends DataItemCreateOrUpdateDto { + name: string; +} + +interface GetDataListInput extends PagedAndSortedResultRequestDto { + filter?: string; +} + +interface DataMoveDto { + parentId?: string; +} + +type DataUpdateDto = DataCreateOrUpdateDto; + +type DataItemUpdateDto = DataItemCreateOrUpdateDto; + +export { ValueType }; + +export type { + DataCreateDto, + DataDto, + DataItemCreateDto, + DataItemDto, + DataItemUpdateDto, + DataMoveDto, + DataUpdateDto, + GetDataListInput, +}; diff --git a/apps/vben5/packages/@abp/platform/src/types/index.ts b/apps/vben5/packages/@abp/platform/src/types/index.ts index e4f239712..7ddde6be9 100644 --- a/apps/vben5/packages/@abp/platform/src/types/index.ts +++ b/apps/vben5/packages/@abp/platform/src/types/index.ts @@ -1 +1,2 @@ +export * from './dataDictionaries'; export * from './messages'; From 3217e1ab890863e02ba14ded3509950c3e7fe260 Mon Sep 17 00:00:00 2001 From: colin Date: Thu, 24 Apr 2025 16:00:49 +0800 Subject: [PATCH 2/3] feat(vben5): Realize the management of data dictionaries --- .../data-dictionaries/DataDictionaryModal.vue | 140 ++++++++++++++++++ .../data-dictionaries/DataDictionaryTable.vue | 88 +++++++++-- 2 files changed, 218 insertions(+), 10 deletions(-) create mode 100644 apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryModal.vue diff --git a/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryModal.vue b/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryModal.vue new file mode 100644 index 000000000..03a67c63a --- /dev/null +++ b/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryModal.vue @@ -0,0 +1,140 @@ + + + + + diff --git a/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryTable.vue b/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryTable.vue index c945b6af9..46488eb8d 100644 --- a/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryTable.vue +++ b/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryTable.vue @@ -6,10 +6,11 @@ import type { DataDto } from '../../types/dataDictionaries'; import { defineAsyncComponent, h, onMounted, reactive, ref } from 'vue'; -import { useVbenDrawer } from '@vben/common-ui'; +import { useVbenDrawer, useVbenModal } from '@vben/common-ui'; import { createIconifyIcon } from '@vben/icons'; import { $t } from '@vben/locales'; +import { listToTree } from '@abp/core'; import { useVbenVxeGrid } from '@abp/ui'; import { DeleteOutlined, @@ -17,7 +18,7 @@ import { EllipsisOutlined, PlusOutlined, } from '@ant-design/icons-vue'; -import { Button, Dropdown, Menu } from 'ant-design-vue'; +import { Button, Dropdown, Menu, message, Modal } from 'ant-design-vue'; import { useDataDictionariesApi } from '../../api/useDataDictionariesApi'; @@ -28,8 +29,9 @@ defineOptions({ const MenuItem = Menu.Item; const ItemsIcon = createIconifyIcon('material-symbols:align-items-stretch'); -const { getAllApi } = useDataDictionariesApi(); +const { deleteApi, getAllApi } = useDataDictionariesApi(); +const expandRowKeys = ref([]); const dataDictionaries = ref([]); const pageState = reactive({ current: 1, @@ -74,17 +76,22 @@ const gridOptions: VxeGridProps = { ], exportConfig: {}, keepSource: true, + rowConfig: { + keyField: 'id', + }, toolbarConfig: { custom: true, export: true, - refresh: false, + refresh: { + queryMethod: onGet, + }, zoom: true, }, treeConfig: { accordion: true, parentField: 'parentId', rowField: 'id', - transform: true, + transform: false, }, }; const gridEvents: VxeGridListeners = { @@ -93,6 +100,16 @@ const gridEvents: VxeGridListeners = { pageState.size = params.pageSize; onPageChange(); }, + toggleTreeExpand(params) { + if (params.expanded) { + expandRowKeys.value.push(params.row.id); + } else { + expandRowKeys.value = expandRowKeys.value.filter( + (key) => key !== params.row.id, + ); + } + onExpandChange(); + }, }; const [Grid, gridApi] = useVbenVxeGrid({ @@ -100,6 +117,11 @@ const [Grid, gridApi] = useVbenVxeGrid({ gridOptions, }); +const [DataDictionaryModal, modalApi] = useVbenModal({ + connectedComponent: defineAsyncComponent( + () => import('./DataDictionaryModal.vue'), + ), +}); const [DataDictionaryItemDrawer, itemDrawerApi] = useVbenDrawer({ connectedComponent: defineAsyncComponent( () => import('./DataDictionaryItemDrawer.vue'), @@ -110,14 +132,26 @@ async function onGet() { try { gridApi.setLoading(true); const { items } = await getAllApi(); - pageState.total = items.length; - dataDictionaries.value = items; + const treeItems = listToTree(items, { + id: 'id', + pid: 'parentId', + }); + pageState.total = treeItems.length; + dataDictionaries.value = treeItems; onPageChange(); } finally { gridApi.setLoading(false); } } +function onExpandChange() { + gridApi.setGridOptions({ + treeConfig: { + expandRowKeys: expandRowKeys.value, + }, + }); +} + function onPageChange() { const items = dataDictionaries.value.slice( (pageState.current - 1) * pageState.size, @@ -133,14 +167,47 @@ function onPageChange() { }); } -function onCreate() {} +function onCreate() { + modalApi.setData({}); + modalApi.open(); +} -function onUpdate(_row: DataDto) {} +function onUpdate(row: DataDto) { + modalApi.setData(row); + modalApi.open(); +} -function onDelete(_row: DataDto) {} +function onDelete(row: DataDto) { + Modal.confirm({ + afterClose: () => { + gridApi.setLoading(false); + }, + centered: true, + content: `${$t('AbpUi.ItemWillBeDeletedMessage')}`, + onOk: async () => { + try { + gridApi.setLoading(true); + await deleteApi(row.id); + message.success($t('AbpUi.DeletedSuccessfully')); + onGet(); + } finally { + gridApi.setLoading(false); + } + }, + title: $t('AbpUi.AreYouSure'), + }); +} function onMenuClick(row: DataDto, info: MenuInfo) { switch (info.key) { + case 'children': { + modalApi.setData({ + displayName: row.displayName, + parentId: row.id, + }); + modalApi.open(); + break; + } case 'items': { onManageItems(row); break; @@ -207,6 +274,7 @@ onMounted(onGet); + From 8ec9a28d7caea60a1e0ca0b5cd118bc4db108bea Mon Sep 17 00:00:00 2001 From: colin Date: Thu, 24 Apr 2025 17:27:23 +0800 Subject: [PATCH 3/3] feat(vben5): Realize the item management of the data dictionary --- .../vben5/packages/@abp/platform/package.json | 4 + .../DataDictionaryItemDrawer.vue | 49 ++- .../DataDictionaryItemModal.vue | 293 ++++++++++++++++++ 3 files changed, 339 insertions(+), 7 deletions(-) create mode 100644 apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryItemModal.vue diff --git a/apps/vben5/packages/@abp/platform/package.json b/apps/vben5/packages/@abp/platform/package.json index d7f491d4c..59c6ac156 100644 --- a/apps/vben5/packages/@abp/platform/package.json +++ b/apps/vben5/packages/@abp/platform/package.json @@ -32,7 +32,11 @@ "@vben/layouts": "workspace:*", "@vben/locales": "workspace:*", "ant-design-vue": "catalog:", + "lodash.clonedeep": "catalog:", "vue": "catalog:*", "vxe-table": "catalog:" + }, + "devDependencies": { + "@types/lodash.clonedeep": "catalog:" } } diff --git a/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryItemDrawer.vue b/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryItemDrawer.vue index 124c8ebe0..c6c1f05d7 100644 --- a/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryItemDrawer.vue +++ b/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryItemDrawer.vue @@ -3,9 +3,9 @@ import type { VxeGridListeners, VxeGridProps } from '@abp/ui'; import type { DataDto, DataItemDto } from '../../types/dataDictionaries'; -import { h, reactive, ref } from 'vue'; +import { defineAsyncComponent, h, reactive, ref } from 'vue'; -import { useVbenDrawer } from '@vben/common-ui'; +import { useVbenDrawer, useVbenModal } from '@vben/common-ui'; import { $t } from '@vben/locales'; import { isNullOrWhiteSpace } from '@abp/core'; @@ -17,12 +17,12 @@ import { EditOutlined, PlusOutlined, } from '@ant-design/icons-vue'; -import { Button } from 'ant-design-vue'; +import { Button, message, Modal } from 'ant-design-vue'; import { useDataDictionariesApi } from '../../api'; import { ValueType } from '../../types/dataDictionaries'; -const { getApi } = useDataDictionariesApi(); +const { deleteItemApi, getApi } = useDataDictionariesApi(); const dataItems = ref([]); const pageState = reactive({ @@ -140,6 +140,12 @@ const [Grid, gridApi] = useVbenVxeGrid({ gridOptions, }); +const [DataDictionaryItemModal, itemModalApi] = useVbenModal({ + connectedComponent: defineAsyncComponent( + () => import('./DataDictionaryItemModal.vue'), + ), +}); + async function onGet() { const { id } = drawerApi.getData(); if (isNullOrWhiteSpace(id)) { @@ -173,11 +179,39 @@ function onPageChange() { }); } -function onCreate() {} +function onCreate() { + const data = drawerApi.getData(); + itemModalApi.setData({ data }); + itemModalApi.open(); +} -function onUpdate(_row: DataItemDto) {} +function onUpdate(row: DataItemDto) { + const data = drawerApi.getData(); + itemModalApi.setData({ data, item: row }); + itemModalApi.open(); +} -function onDelete(_row: DataItemDto) {} +function onDelete(row: DataItemDto) { + Modal.confirm({ + afterClose: () => { + gridApi.setLoading(false); + }, + centered: true, + content: `${$t('AbpUi.ItemWillBeDeletedMessage')}`, + onOk: async () => { + try { + gridApi.setLoading(true); + const { id } = drawerApi.getData(); + await deleteItemApi(id, row.name); + message.success($t('AbpUi.DeletedSuccessfully')); + onGet(); + } finally { + gridApi.setLoading(false); + } + }, + title: $t('AbpUi.AreYouSure'), + }); +} + diff --git a/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryItemModal.vue b/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryItemModal.vue new file mode 100644 index 000000000..2c7eeb55c --- /dev/null +++ b/apps/vben5/packages/@abp/platform/src/components/data-dictionaries/DataDictionaryItemModal.vue @@ -0,0 +1,293 @@ + + + + +