From 4f6c5a113926f255c1050f8c3b5cff3615f278a3 Mon Sep 17 00:00:00 2001 From: colin Date: Mon, 10 Mar 2025 11:53:33 +0800 Subject: [PATCH 1/3] feat(vben5): add @abp/features package --- .../vben5/packages/@abp/features/package.json | 39 +++ .../packages/@abp/features/src/api/index.ts | 1 + .../@abp/features/src/api/useFeaturesApi.ts | 62 +++++ .../src/components/features/FeatureModal.vue | 258 ++++++++++++++++++ .../@abp/features/src/components/index.ts | 1 + .../@abp/features/src/constants/index.ts | 1 + .../features/src/constants/permissions.ts | 0 .../vben5/packages/@abp/features/src/index.ts | 4 + .../@abp/features/src/types/features.ts | 63 +++++ .../packages/@abp/features/src/types/index.ts | 1 + .../packages/@abp/features/tsconfig.json | 6 + apps/vben5/packages/@abp/saas/package.json | 1 + .../vben5/packages/@abp/saas/src/api/index.ts | 4 +- .../src/components/tenants/TenantTable.vue | 21 ++ .../vben5/packages/@abp/settings/package.json | 1 + .../src/components/settings/SettingForm.vue | 23 +- .../src/components/settings/SystemSetting.vue | 23 ++ 17 files changed, 497 insertions(+), 12 deletions(-) create mode 100644 apps/vben5/packages/@abp/features/package.json create mode 100644 apps/vben5/packages/@abp/features/src/api/index.ts create mode 100644 apps/vben5/packages/@abp/features/src/api/useFeaturesApi.ts create mode 100644 apps/vben5/packages/@abp/features/src/components/features/FeatureModal.vue create mode 100644 apps/vben5/packages/@abp/features/src/components/index.ts create mode 100644 apps/vben5/packages/@abp/features/src/constants/index.ts create mode 100644 apps/vben5/packages/@abp/features/src/constants/permissions.ts create mode 100644 apps/vben5/packages/@abp/features/src/index.ts create mode 100644 apps/vben5/packages/@abp/features/src/types/features.ts create mode 100644 apps/vben5/packages/@abp/features/src/types/index.ts create mode 100644 apps/vben5/packages/@abp/features/tsconfig.json diff --git a/apps/vben5/packages/@abp/features/package.json b/apps/vben5/packages/@abp/features/package.json new file mode 100644 index 000000000..67751a202 --- /dev/null +++ b/apps/vben5/packages/@abp/features/package.json @@ -0,0 +1,39 @@ +{ + "name": "@abp/features", + "version": "9.0.4", + "homepage": "https://github.com/colinin/abp-next-admin", + "bugs": "https://github.com/colinin/abp-next-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/colinin/abp-next-admin.git", + "directory": "packages/@abp/features" + }, + "license": "MIT", + "type": "module", + "sideEffects": [ + "**/*.css" + ], + "exports": { + ".": { + "types": "./src/index.ts", + "default": "./src/index.ts" + } + }, + "dependencies": { + "@abp/auditing": "workspace:*", + "@abp/core": "workspace:*", + "@abp/request": "workspace:*", + "@abp/ui": "workspace:*", + "@ant-design/icons-vue": "catalog:", + "@vben/access": "workspace:*", + "@vben/common-ui": "workspace:*", + "@vben/hooks": "workspace:*", + "@vben/icons": "workspace:*", + "@vben/locales": "workspace:*", + "ant-design-vue": "catalog:", + "dayjs": "catalog:", + "vue": "catalog:*", + "vxe-table": "catalog:" + }, + "devDependencies": {} +} diff --git a/apps/vben5/packages/@abp/features/src/api/index.ts b/apps/vben5/packages/@abp/features/src/api/index.ts new file mode 100644 index 000000000..0d11e3ec4 --- /dev/null +++ b/apps/vben5/packages/@abp/features/src/api/index.ts @@ -0,0 +1 @@ +export { useFeaturesApi } from './useFeaturesApi'; diff --git a/apps/vben5/packages/@abp/features/src/api/useFeaturesApi.ts b/apps/vben5/packages/@abp/features/src/api/useFeaturesApi.ts new file mode 100644 index 000000000..116817733 --- /dev/null +++ b/apps/vben5/packages/@abp/features/src/api/useFeaturesApi.ts @@ -0,0 +1,62 @@ +import type { + FeatureProvider, + GetFeatureListResultDto, + UpdateFeaturesDto, +} from '../types/features'; + +import { useRequest } from '@abp/request'; + +export function useFeaturesApi() { + const { cancel, request } = useRequest(); + + /** + * 删除功能 + * @param {FeatureProvider} provider 参数 + * @returns {Promise} + */ + function deleteApi(provider: FeatureProvider): Promise { + return request(`/api/feature-management/features`, { + method: 'DELETE', + params: provider, + }); + } + + /** + * 查询功能 + * @param {FeatureProvider} provider 参数 + * @returns {Promise} 功能实体数据传输对象 + */ + function getApi(provider: FeatureProvider): Promise { + return request( + `/api/feature-management/features`, + { + method: 'GET', + params: provider, + }, + ); + } + + /** + * 更新功能 + * @param {FeatureProvider} provider + * @param {UpdateFeaturesDto} input 参数 + * @returns {Promise} + */ + function updateApi( + provider: FeatureProvider, + input: UpdateFeaturesDto, + ): Promise { + return request(`/api/feature-management/features`, { + data: input, + method: 'PUT', + params: provider, + }); + } + + return { + cancel, + deleteApi, + getApi, + updateApi, + }; +} diff --git a/apps/vben5/packages/@abp/features/src/components/features/FeatureModal.vue b/apps/vben5/packages/@abp/features/src/components/features/FeatureModal.vue new file mode 100644 index 000000000..106fde2df --- /dev/null +++ b/apps/vben5/packages/@abp/features/src/components/features/FeatureModal.vue @@ -0,0 +1,258 @@ + + + + + diff --git a/apps/vben5/packages/@abp/features/src/components/index.ts b/apps/vben5/packages/@abp/features/src/components/index.ts new file mode 100644 index 000000000..6714d5ae5 --- /dev/null +++ b/apps/vben5/packages/@abp/features/src/components/index.ts @@ -0,0 +1 @@ +export { default as FeatureModal } from './features/FeatureModal.vue'; diff --git a/apps/vben5/packages/@abp/features/src/constants/index.ts b/apps/vben5/packages/@abp/features/src/constants/index.ts new file mode 100644 index 000000000..c85954d3e --- /dev/null +++ b/apps/vben5/packages/@abp/features/src/constants/index.ts @@ -0,0 +1 @@ +export * from './permissions'; diff --git a/apps/vben5/packages/@abp/features/src/constants/permissions.ts b/apps/vben5/packages/@abp/features/src/constants/permissions.ts new file mode 100644 index 000000000..e69de29bb diff --git a/apps/vben5/packages/@abp/features/src/index.ts b/apps/vben5/packages/@abp/features/src/index.ts new file mode 100644 index 000000000..f43dbaee0 --- /dev/null +++ b/apps/vben5/packages/@abp/features/src/index.ts @@ -0,0 +1,4 @@ +export * from './api'; +export * from './components'; +export * from './constants'; +export * from './types'; diff --git a/apps/vben5/packages/@abp/features/src/types/features.ts b/apps/vben5/packages/@abp/features/src/types/features.ts new file mode 100644 index 000000000..930c53957 --- /dev/null +++ b/apps/vben5/packages/@abp/features/src/types/features.ts @@ -0,0 +1,63 @@ +import type { Dictionary, NameValue } from '@abp/core'; + +interface FeatureProvider { + providerKey?: string; + providerName: string; +} + +interface IValueValidator { + [key: string]: any; + isValid(value?: any): boolean; + name: string; + properties: Dictionary; +} + +interface IStringValueType { + [key: string]: any; + name: string; + properties: Dictionary; + validator: IValueValidator; +} + +interface FeatureProviderDto { + key: string; + name: string; +} + +interface FeatureDto { + depth: number; + description?: string; + displayName: string; + name: string; + parentName?: string; + provider: FeatureProviderDto; + value?: any; + valueType: IStringValueType; +} + +interface FeatureGroupDto { + displayName: string; + features: FeatureDto[]; + name: string; +} + +interface GetFeatureListResultDto { + groups: FeatureGroupDto[]; +} + +type UpdateFeatureDto = NameValue; + +interface UpdateFeaturesDto { + features: UpdateFeatureDto[]; +} + +export type { + FeatureDto, + FeatureGroupDto, + FeatureProvider, + GetFeatureListResultDto, + IStringValueType, + IValueValidator, + UpdateFeatureDto, + UpdateFeaturesDto, +}; diff --git a/apps/vben5/packages/@abp/features/src/types/index.ts b/apps/vben5/packages/@abp/features/src/types/index.ts new file mode 100644 index 000000000..b8795830d --- /dev/null +++ b/apps/vben5/packages/@abp/features/src/types/index.ts @@ -0,0 +1 @@ +export * from './features'; diff --git a/apps/vben5/packages/@abp/features/tsconfig.json b/apps/vben5/packages/@abp/features/tsconfig.json new file mode 100644 index 000000000..ce1a891fb --- /dev/null +++ b/apps/vben5/packages/@abp/features/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/web.json", + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/apps/vben5/packages/@abp/saas/package.json b/apps/vben5/packages/@abp/saas/package.json index 1f6815328..d8fe93258 100644 --- a/apps/vben5/packages/@abp/saas/package.json +++ b/apps/vben5/packages/@abp/saas/package.json @@ -22,6 +22,7 @@ "dependencies": { "@abp/auditing": "workspace:*", "@abp/core": "workspace:*", + "@abp/features": "workspace:*", "@abp/request": "workspace:*", "@abp/ui": "workspace:*", "@ant-design/icons-vue": "catalog:", diff --git a/apps/vben5/packages/@abp/saas/src/api/index.ts b/apps/vben5/packages/@abp/saas/src/api/index.ts index 3f43296a6..beba3fb43 100644 --- a/apps/vben5/packages/@abp/saas/src/api/index.ts +++ b/apps/vben5/packages/@abp/saas/src/api/index.ts @@ -1,2 +1,2 @@ -export * from './useEditionsApi'; -export * from './useTenantsApi'; +export { useEditionsApi } from './useEditionsApi'; +export { useTenantsApi } from './useTenantsApi'; diff --git a/apps/vben5/packages/@abp/saas/src/components/tenants/TenantTable.vue b/apps/vben5/packages/@abp/saas/src/components/tenants/TenantTable.vue index 8f2232c23..3132bd7bb 100644 --- a/apps/vben5/packages/@abp/saas/src/components/tenants/TenantTable.vue +++ b/apps/vben5/packages/@abp/saas/src/components/tenants/TenantTable.vue @@ -13,6 +13,7 @@ import { $t } from '@vben/locales'; import { AuditLogPermissions, EntityChangeDrawer } from '@abp/auditing'; import { useFeatures } from '@abp/core'; +import { FeatureModal } from '@abp/features'; import { useVbenVxeGrid } from '@abp/ui'; import { DeleteOutlined, @@ -33,6 +34,7 @@ const CheckIcon = createIconifyIcon('ant-design:check-outlined'); const CloseIcon = createIconifyIcon('ant-design:close-outlined'); const AuditLogIcon = createIconifyIcon('fluent-mdl2:compliance-audit'); const ConnectionIcon = createIconifyIcon('mdi:connection'); +const FeatureIcon = createIconifyIcon('pajamas:feature-flag'); const { isEnabled } = useFeatures(); const { hasAccessByCodes } = useAccess(); @@ -131,6 +133,9 @@ const [TenantConnectionStringsModal, connectionStringsModalApi] = useVbenModal({ const [TenantChangeDrawer, entityChangeDrawerApi] = useVbenDrawer({ connectedComponent: EntityChangeDrawer, }); +const [TenantFeatureModal, tenantFeatureModalApi] = useVbenModal({ + connectedComponent: FeatureModal, +}); const [Grid, { query }] = useVbenVxeGrid({ formOptions, gridEvents, @@ -179,6 +184,14 @@ const onMenuClick = (row: TenantDto, info: MenuInfo) => { entityChangeDrawerApi.open(); break; } + case 'features': { + tenantFeatureModalApi.setData({ + displayName: row.name, + providerKey: row.id, + providerName: 'T', + }); + tenantFeatureModalApi.open(); + } } }; @@ -233,6 +246,13 @@ const onMenuClick = (row: TenantDto, info: MenuInfo) => { > {{ $t('AbpSaas.ConnectionStrings') }} + + {{ $t('AbpSaas.ManageFeatures') }} + query()" /> + diff --git a/apps/vben5/packages/@abp/settings/package.json b/apps/vben5/packages/@abp/settings/package.json index 0f8f957ac..1e2c40f78 100644 --- a/apps/vben5/packages/@abp/settings/package.json +++ b/apps/vben5/packages/@abp/settings/package.json @@ -21,6 +21,7 @@ }, "dependencies": { "@abp/core": "workspace:*", + "@abp/features": "workspace:*", "@abp/request": "workspace:*", "@abp/ui": "workspace:*", "@ant-design/icons-vue": "catalog:", diff --git a/apps/vben5/packages/@abp/settings/src/components/settings/SettingForm.vue b/apps/vben5/packages/@abp/settings/src/components/settings/SettingForm.vue index 59b7b7fc9..e7b0a6104 100644 --- a/apps/vben5/packages/@abp/settings/src/components/settings/SettingForm.vue +++ b/apps/vben5/packages/@abp/settings/src/components/settings/SettingForm.vue @@ -110,16 +110,19 @@ onMounted(onGet);