diff --git a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Features/Dtos/DeleteFeatureInput.cs b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Features/Dtos/DeleteFeatureInput.cs new file mode 100644 index 000000000..8ed5560b3 --- /dev/null +++ b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Features/Dtos/DeleteFeatureInput.cs @@ -0,0 +1,28 @@ +namespace Lion.AbpPro.BasicManagement.Features.Dtos; + +public class DeleteFeatureInput : IValidatableObject +{ + public string ProviderName { get; set; } + + public string ProviderKey { get; set; } + + public IEnumerable Validate(ValidationContext validationContext) + { + var localization = validationContext.GetRequiredService>(); + if (ProviderName.IsNullOrWhiteSpace()) + { + yield return new ValidationResult( + localization[AbpProLocalizationErrorCodes.ErrorCode100003, nameof(ProviderName)], + new[] { nameof(ProviderName) } + ); + } + + if (ProviderKey.IsNullOrWhiteSpace()) + { + yield return new ValidationResult( + localization[AbpProLocalizationErrorCodes.ErrorCode100003, nameof(ProviderKey)], + new[] { nameof(ProviderKey) } + ); + } + } +} \ No newline at end of file diff --git a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Features/Dtos/GetFeatureListResultInput.cs b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Features/Dtos/GetFeatureListResultInput.cs new file mode 100644 index 000000000..44a555e1a --- /dev/null +++ b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Features/Dtos/GetFeatureListResultInput.cs @@ -0,0 +1,20 @@ +namespace Lion.AbpPro.BasicManagement.Features.Dtos; + +public class GetFeatureListResultInput : IValidatableObject +{ + public string ProviderName { get; set; } + + public string ProviderKey { get; set; } + + public IEnumerable Validate(ValidationContext validationContext) + { + var localization = validationContext.GetRequiredService>(); + if (ProviderName.IsNullOrWhiteSpace()) + { + yield return new ValidationResult( + localization[AbpProLocalizationErrorCodes.ErrorCode100003, nameof(ProviderName)], + new[] { nameof(ProviderName) } + ); + } + } +} \ No newline at end of file diff --git a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Features/Dtos/UpdateFeatureInput.cs b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Features/Dtos/UpdateFeatureInput.cs new file mode 100644 index 000000000..d79f7c366 --- /dev/null +++ b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Features/Dtos/UpdateFeatureInput.cs @@ -0,0 +1,25 @@ +using Volo.Abp.FeatureManagement; + +namespace Lion.AbpPro.BasicManagement.Features.Dtos; + +public class UpdateFeatureInput : IValidatableObject +{ + public string ProviderName { get; set; } + + public string ProviderKey { get; set; } + + public UpdateFeaturesDto UpdateFeaturesDto { get; set; } + + + public IEnumerable Validate(ValidationContext validationContext) + { + var localization = validationContext.GetRequiredService>(); + if (ProviderName.IsNullOrWhiteSpace()) + { + yield return new ValidationResult( + localization[AbpProLocalizationErrorCodes.ErrorCode100003, nameof(ProviderName)], + new[] { nameof(ProviderName) } + ); + } + } +} \ No newline at end of file diff --git a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Features/IVoloFeatureAppService.cs b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Features/IVoloFeatureAppService.cs new file mode 100644 index 000000000..6988f0169 --- /dev/null +++ b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Features/IVoloFeatureAppService.cs @@ -0,0 +1,22 @@ +using Lion.AbpPro.BasicManagement.Features.Dtos; +using Volo.Abp.FeatureManagement; + +namespace Lion.AbpPro.BasicManagement.Features; + +public interface IVoloFeatureAppService : IApplicationService +{ + /// + /// 获取Features + /// + Task GetAsync(GetFeatureListResultInput input); + + /// + /// 更新Features + /// + Task UpdateAsync(UpdateFeatureInput input); + + /// + /// 删除Features + /// + Task DeleteAsync(DeleteFeatureInput input); +} \ No newline at end of file diff --git a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Permissions/BasicManagementPermissionDefinitionProvider.cs b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Permissions/BasicManagementPermissionDefinitionProvider.cs index 7ae78427d..1312154d1 100644 --- a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Permissions/BasicManagementPermissionDefinitionProvider.cs +++ b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Permissions/BasicManagementPermissionDefinitionProvider.cs @@ -14,11 +14,14 @@ public override void Define(IPermissionDefinitionContext context) userManagement.AddChild(BasicManagementPermissions.SystemManagement.UserEnable, L("Permission:Enable"), multiTenancySide: MultiTenancySides.Both); userManagement.AddChild(BasicManagementPermissions.SystemManagement.UserExport, L("Permission:Export"), multiTenancySide: MultiTenancySides.Both); - var auditManagement = - abpIdentityGroup.AddPermission(BasicManagementPermissions.SystemManagement.AuditLog, L("Permission:AuditLogManagement"), multiTenancySide: MultiTenancySides.Both); + abpIdentityGroup.AddPermission(BasicManagementPermissions.SystemManagement.AuditLog, L("Permission:AuditLogManagement"), multiTenancySide: MultiTenancySides.Both); abpIdentityGroup.AddPermission(BasicManagementPermissions.SystemManagement.Setting, L("Permission:SettingManagement"), multiTenancySide: MultiTenancySides.Both); abpIdentityGroup.AddPermission(BasicManagementPermissions.SystemManagement.IdentitySecurityLog, L("Permission:IdentitySecurityLog"), multiTenancySide: MultiTenancySides.Both); - var organizationUnitManagement = abpIdentityGroup.AddPermission(BasicManagementPermissions.SystemManagement.OrganizationUnit, L("Permission:OrganizationUnitManagement"), multiTenancySide: MultiTenancySides.Both); + abpIdentityGroup.AddPermission(BasicManagementPermissions.SystemManagement.FeatureManagement, L("Permission:FeatureManagement"), multiTenancySide: MultiTenancySides.Both); + + var organizationUnitManagement = abpIdentityGroup + .AddPermission(BasicManagementPermissions.SystemManagement.OrganizationUnit, L("Permission:OrganizationUnitManagement"), multiTenancySide: MultiTenancySides.Both); + organizationUnitManagement.AddChild ( BasicManagementPermissions.SystemManagement.OrganizationUnitManagement.Create, diff --git a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Permissions/BasicManagementPermissions.cs b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Permissions/BasicManagementPermissions.cs index 8c1b94fd7..f6367c0c4 100644 --- a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Permissions/BasicManagementPermissions.cs +++ b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Permissions/BasicManagementPermissions.cs @@ -16,6 +16,7 @@ public static class SystemManagement public const string Setting = Default + ".Setting"; public const string IdentitySecurityLog = Default + ".IdentitySecurityLogs"; public const string OrganizationUnit = Default + ".OrganizationUnitManagement"; + public const string FeatureManagement = Default + ".FeatureManagement"; public static class OrganizationUnitManagement { public const string Default = SystemManagement.Default + ".OrganizationUnitManagement"; diff --git a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application/ApplicationConfigurations/AbpProApplicationConfigurationAppService.cs b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application/ApplicationConfigurations/AbpProApplicationConfigurationAppService.cs index 49ce6da67..b6f299fb9 100644 --- a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application/ApplicationConfigurations/AbpProApplicationConfigurationAppService.cs +++ b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application/ApplicationConfigurations/AbpProApplicationConfigurationAppService.cs @@ -323,6 +323,15 @@ protected virtual async Task GetFeaturesConf continue; } + if (featureDefinition.Name == "SettingManagement.Enable") + { + continue; + } + + if (featureDefinition.Name == "SettingManagement.AllowChangingEmailSettings") + { + continue; + } result.Values[featureDefinition.Name] = await FeatureChecker.GetOrNullAsync(featureDefinition.Name); } diff --git a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application/Features/VoloFeatureAppService.cs b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application/Features/VoloFeatureAppService.cs new file mode 100644 index 000000000..40e38228d --- /dev/null +++ b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application/Features/VoloFeatureAppService.cs @@ -0,0 +1,33 @@ +using Lion.AbpPro.BasicManagement.Features.Dtos; +using Volo.Abp.FeatureManagement; + +namespace Lion.AbpPro.BasicManagement.Features; + +[Authorize] +public class VoloFeatureAppService : BasicManagementAppService, IVoloFeatureAppService +{ + private readonly IFeatureAppService _featureAppService; + + public VoloFeatureAppService(IFeatureAppService featureAppService) + { + _featureAppService = featureAppService; + } + + public virtual async Task GetAsync(GetFeatureListResultInput input) + { + var result = await _featureAppService.GetAsync(input.ProviderName, input.ProviderKey); + // 过滤自带的SettingManagement设置 + result.Groups = result.Groups.Where(e => e.Name != "SettingManagement").ToList(); + return result; + } + + public virtual async Task UpdateAsync(UpdateFeatureInput input) + { + await _featureAppService.UpdateAsync(input.ProviderName, input.ProviderKey, input.UpdateFeaturesDto); + } + + public virtual async Task DeleteAsync(DeleteFeatureInput input) + { + await _featureAppService.DeleteAsync(input.ProviderName, input.ProviderKey); + } +} \ No newline at end of file diff --git a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Domain.Shared/Localization/BasicManagement/en.json b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Domain.Shared/Localization/BasicManagement/en.json index f2840490b..079005f3f 100644 --- a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Domain.Shared/Localization/BasicManagement/en.json +++ b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Domain.Shared/Localization/BasicManagement/en.json @@ -15,6 +15,7 @@ "Permission:SettingManagement": "SettingManagement", "Permission:IdentitySecurityLog": "IdentitySecurityLog", "Permission:OrganizationUnitManagement": "OrganizationUnitManagement", + "Permission:FeatureManagement": "FeatureManagement", "Setting.Group.System": "System", "Lion.AbpPro.BasicManagement:100001": "OrganizationUnit Not Exist", "Lion.AbpPro.BasicManagement:100002": "UserLockedOut", diff --git a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Domain.Shared/Localization/BasicManagement/zh-Hans.json b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Domain.Shared/Localization/BasicManagement/zh-Hans.json index 6595b0fe4..2a0a3fead 100644 --- a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Domain.Shared/Localization/BasicManagement/zh-Hans.json +++ b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Domain.Shared/Localization/BasicManagement/zh-Hans.json @@ -15,7 +15,7 @@ "Permission:SettingManagement": "设置管理", "Permission:IdentitySecurityLog": "登录日志", "Permission:OrganizationUnitManagement": "组织结构管理", - + "Permission:FeatureManagement": "功能管理", "Setting.Group.System": "系统", "Lion.AbpPro.BasicManagement:100001": "组织机构不存在", "Lion.AbpPro.BasicManagement:100002": "用户被锁定", diff --git a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.HttpApi/Systems/FeatureController.cs b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.HttpApi/Systems/FeatureController.cs new file mode 100644 index 000000000..e6dd8856b --- /dev/null +++ b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.HttpApi/Systems/FeatureController.cs @@ -0,0 +1,37 @@ +using Lion.AbpPro.BasicManagement.Features; +using Lion.AbpPro.BasicManagement.Features.Dtos; +using Volo.Abp.FeatureManagement; + +namespace Lion.AbpPro.BasicManagement.Systems; + +[Route("Features")] +public class FeatureController : BasicManagementController, IVoloFeatureAppService +{ + private readonly IVoloFeatureAppService _featureAppService; + + public FeatureController(IVoloFeatureAppService featureAppService) + { + _featureAppService = featureAppService; + } + + [HttpPost("list")] + [SwaggerOperation(summary: "获取Features", Tags = new[] {"Features"})] + public Task GetAsync(GetFeatureListResultInput input) + { + return _featureAppService.GetAsync(input); + } + + [HttpPost("update")] + [SwaggerOperation(summary: "更新Features", Tags = new[] {"Features"})] + public Task UpdateAsync(UpdateFeatureInput input) + { + return _featureAppService.UpdateAsync(input); + } + + [HttpPost("delete")] + [SwaggerOperation(summary: "删除Features", Tags = new[] {"Features"})] + public Task DeleteAsync(DeleteFeatureInput input) + { + return _featureAppService.DeleteAsync(input); + } +} \ No newline at end of file diff --git a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Lion.AbpPro.HttpApi.Host.csproj b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Lion.AbpPro.HttpApi.Host.csproj index 622bc412b..f485e5385 100644 --- a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Lion.AbpPro.HttpApi.Host.csproj +++ b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Lion.AbpPro.HttpApi.Host.csproj @@ -58,6 +58,7 @@ + diff --git a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/appsettings.json b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/appsettings.json index 13d4daf11..51cbb003a 100644 --- a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/appsettings.json +++ b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/appsettings.json @@ -34,16 +34,16 @@ "CorsOrigins": "https://*.AbpPro.com,http://localhost:4200,http://localhost:3100" }, "ConnectionStrings": { - "Default": "Data Source=localhost;Port=3306;Database=LionAbpProDB;uid=root;pwd=1q2w3E*;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true" + "Default": "Data Source=43.139.143.143;Port=3306;Database=tenantdb;uid=root;pwd=1q2w3E*;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true" }, "Hangfire": { "Redis": { - "Host": "localhost:6379,password=1q2w3E*", + "Host": "43.139.143.143:6379,password=1q2w3E*", "DB": "2" } }, "Redis": { - "Configuration": "localhost:6379,password=1q2w3E*,defaultdatabase=1" + "Configuration": "43.139.143.143:6379,password=1q2w3E*,defaultdatabase=5" }, "Jwt": { "Audience": "Lion.AbpPro", @@ -52,11 +52,12 @@ "ExpirationTime": 2 }, "Cap": { - "Enabled": false, + "Enabled": true, "RabbitMq": { - "HostName": "localhost", + "HostName": "43.139.143.143", "UserName": "admin", - "Password": "admin" + "Password": "1q2w3E*", + "Port": 5672 } }, "ElasticSearch": { diff --git a/aspnet-core/services/src/Lion.AbpPro.Domain.Shared/Features/AbpProFeatureDefinitionProvider.cs b/aspnet-core/services/src/Lion.AbpPro.Domain.Shared/Features/AbpProFeatureDefinitionProvider.cs new file mode 100644 index 000000000..62fd6d87d --- /dev/null +++ b/aspnet-core/services/src/Lion.AbpPro.Domain.Shared/Features/AbpProFeatureDefinitionProvider.cs @@ -0,0 +1,34 @@ +using Volo.Abp.Features; +using Volo.Abp.Validation.StringValues; + +namespace Lion.AbpPro.Features; + +public class AbpProFeatureDefinitionProvider : FeatureDefinitionProvider +{ + public override void Define(IFeatureDefinitionContext context) + { + + var group = context.AddGroup(AbpProFeatures.GroupName,L("Feature:TestGroup")); + + // ToggleStringValueType bool类型 前端渲染为checkbox + group.AddFeature(AbpProFeatures.TestEnable, + "true", + L("Feature:TestEnable"), + L("Feature:TestEnable"), + new ToggleStringValueType()); + + // ToggleStringValueType string类型 前端渲染为input + group.AddFeature(AbpProFeatures.TestString, + "输入需要设定的值", + L("Feature:TestString"), + L("Feature:TestString"), + new FreeTextStringValueType()); + + // todo SelectionStringValueType select标签待定 + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } +} \ No newline at end of file diff --git a/aspnet-core/services/src/Lion.AbpPro.Domain.Shared/Features/AbpProFeatures.cs b/aspnet-core/services/src/Lion.AbpPro.Domain.Shared/Features/AbpProFeatures.cs new file mode 100644 index 000000000..aea6ecffb --- /dev/null +++ b/aspnet-core/services/src/Lion.AbpPro.Domain.Shared/Features/AbpProFeatures.cs @@ -0,0 +1,10 @@ +namespace Lion.AbpPro.Features; + +public class AbpProFeatures +{ + public const string GroupName = "AbpPro"; + + public const string TestEnable = GroupName + ".TestEnable"; + + public const string TestString = GroupName + ".TestString"; +} \ No newline at end of file diff --git a/aspnet-core/services/src/Lion.AbpPro.Domain.Shared/Localization/AbpPro/en.json b/aspnet-core/services/src/Lion.AbpPro.Domain.Shared/Localization/AbpPro/en.json index a6302f74c..14712133a 100644 --- a/aspnet-core/services/src/Lion.AbpPro.Domain.Shared/Localization/AbpPro/en.json +++ b/aspnet-core/services/src/Lion.AbpPro.Domain.Shared/Localization/AbpPro/en.json @@ -24,6 +24,9 @@ "Description:Setting.Group.Other.Github": "Github", "Enum:TestType:Created:1":"Created", "Enum:TestType:Cancel:1":"Cancel", - "Enum:TestType:Delete:1":"Delete" + "Enum:TestType:Delete:1":"Delete", + "Feature:TestEnable": "TestEnable", + "Feature:TestString": "TestString", + "Feature:TestGroup": "TestGroup" } } diff --git a/aspnet-core/services/src/Lion.AbpPro.Domain.Shared/Localization/AbpPro/zh-Hans.json b/aspnet-core/services/src/Lion.AbpPro.Domain.Shared/Localization/AbpPro/zh-Hans.json index b8e4daa80..3ae8d8c30 100644 --- a/aspnet-core/services/src/Lion.AbpPro.Domain.Shared/Localization/AbpPro/zh-Hans.json +++ b/aspnet-core/services/src/Lion.AbpPro.Domain.Shared/Localization/AbpPro/zh-Hans.json @@ -25,6 +25,9 @@ "Description:Setting.Group.Other.Github": "Github", "Enum:TestType:Created:1":"创建", "Enum:TestType:Cancel:1":"取消", - "Enum:TestType:Delete:1":"删除" + "Enum:TestType:Delete:1":"删除", + "Feature:TestGroup": "测试功能分组", + "Feature:TestEnable": "测试Checkbox-bool类型", + "Feature:TestString": "测试Input-string类型" } } \ No newline at end of file diff --git a/vben28/src/api/sys/user.ts b/vben28/src/api/sys/user.ts index 1f3eca45d..1a84674e9 100644 --- a/vben28/src/api/sys/user.ts +++ b/vben28/src/api/sys/user.ts @@ -58,7 +58,7 @@ export function login(input: LoginInput): Promise { */ export function getAbpApplicationConfiguration() { const _abpApplicationConfigurationServiceProxy = new AbpApplicationConfigurationServiceProxy(); - return _abpApplicationConfigurationServiceProxy.applicationConfiguration(); + return _abpApplicationConfigurationServiceProxy.applicationConfiguration(false); } diff --git a/vben28/src/locales/lang/en/routes/admin.ts b/vben28/src/locales/lang/en/routes/admin.ts index fc3c88a2f..e56025a84 100644 --- a/vben28/src/locales/lang/en/routes/admin.ts +++ b/vben28/src/locales/lang/en/routes/admin.ts @@ -65,6 +65,7 @@ export default { logLevel: 'Level', logContent: 'Content', settingManagement: 'SettingManagement', + featureManagement: 'FeatureManagement', dictionaryManagement: 'DataDictionary', dictionaryTypeName: 'Type', dictionaryCode: 'Code', diff --git a/vben28/src/locales/lang/en/routes/tenant.ts b/vben28/src/locales/lang/en/routes/tenant.ts index 5e227b5b2..3b270ecde 100644 --- a/vben28/src/locales/lang/en/routes/tenant.ts +++ b/vben28/src/locales/lang/en/routes/tenant.ts @@ -1,6 +1,7 @@ export default { name: 'Name', connectionString: 'ConnectionString', + manageFeatures : 'Manage Features', tenantManagement: 'TenantManagement', tenantList: 'TenantList', adminPassword: 'AdminPassword', diff --git a/vben28/src/locales/lang/zh-CN/routes/admin.ts b/vben28/src/locales/lang/zh-CN/routes/admin.ts index c7b16b948..1bbb40644 100644 --- a/vben28/src/locales/lang/zh-CN/routes/admin.ts +++ b/vben28/src/locales/lang/zh-CN/routes/admin.ts @@ -64,6 +64,7 @@ export default { logContent: '内容', detail: '详情', settingManagement: '设置管理', + featureManagement: '功能管理', dictionaryManagement: '数据字典', dictionaryTypeName: '字典类型', dictionaryCode: '编码', diff --git a/vben28/src/locales/lang/zh-CN/routes/tenant.ts b/vben28/src/locales/lang/zh-CN/routes/tenant.ts index 9549d9201..f1ab119e3 100644 --- a/vben28/src/locales/lang/zh-CN/routes/tenant.ts +++ b/vben28/src/locales/lang/zh-CN/routes/tenant.ts @@ -1,6 +1,7 @@ export default { name: '名称', connectionString: '连接字符串', + manageFeatures : '功能管理', tenantManagement: '租户管理', tenantList: '租户列表', adminPassword: '管理员密码', diff --git a/vben28/src/router/routes/modules/admin.ts b/vben28/src/router/routes/modules/admin.ts index c39daa103..aa9250130 100644 --- a/vben28/src/router/routes/modules/admin.ts +++ b/vben28/src/router/routes/modules/admin.ts @@ -54,6 +54,16 @@ const admin: AppRouteModule = { icon: 'ant-design:unordered-list-outlined', }, }, + { + path: 'manageFeatrue', + name: 'manageFeatrue', + component: () => import('/@/views/admin/manageFeatrue/index.vue'), + meta: { + title: t('routes.admin.featureManagement'), + policy: 'AbpIdentity.FeatureManagement', + icon: 'ant-design:tool-outlined', + }, + }, { path: 'abpAuditLogs', name: 'AuditLogs', diff --git a/vben28/src/services/ServiceProxies.ts b/vben28/src/services/ServiceProxies.ts index 76b81f201..3164a3e4b 100644 --- a/vben28/src/services/ServiceProxies.ts +++ b/vben28/src/services/ServiceProxies.ts @@ -1471,6 +1471,313 @@ export class DataDictionaryServiceProxy extends ServiceProxyBase { } } +export class FeaturesServiceProxy extends ServiceProxyBase { + private instance: AxiosInstance; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(baseUrl?: string, instance?: AxiosInstance) { + super(); + this.instance = instance ? instance : axios.create(); + this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : ""; + } + + /** + * 获取Features + * @param body (optional) + * @return Success + */ + list(body: GetFeatureListResultInput | undefined , cancelToken?: CancelToken | undefined): Promise { + let url_ = this.baseUrl + "/Features/list"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(body); + + let options_ = { + data: content_, + method: "POST", + url: url_, + headers: { + "Content-Type": "application/json", + "Accept": "text/plain" + }, + cancelToken + }; + + return this.transformOptions(options_).then(transformedOptions_ => { + return this.instance.request(transformedOptions_); + }).catch((_error: any) => { + if (isAxiosError(_error) && _error.response) { + return _error.response; + } else { + throw _error; + } + }).then((_response: AxiosResponse) => { + return this.transformResult(url_, _response, (_response: AxiosResponse) => this.processList(_response)); + }); + } + + protected processList(response: AxiosResponse): Promise { + const status = response.status; + let _headers: any = {}; + if (response.headers && typeof response.headers === "object") { + for (let k in response.headers) { + if (response.headers.hasOwnProperty(k)) { + _headers[k] = response.headers[k]; + } + } + } + if (status === 200) { + const _responseText = response.data; + let result200: any = null; + let resultData200 = _responseText; + result200 = GetFeatureListResultDto.fromJS(resultData200); + return Promise.resolve(result200); + + } else if (status === 403) { + const _responseText = response.data; + let result403: any = null; + let resultData403 = _responseText; + result403 = RemoteServiceErrorResponse.fromJS(resultData403); + return throwException("Forbidden", status, _responseText, _headers, result403); + + } else if (status === 401) { + const _responseText = response.data; + let result401: any = null; + let resultData401 = _responseText; + result401 = RemoteServiceErrorResponse.fromJS(resultData401); + return throwException("Unauthorized", status, _responseText, _headers, result401); + + } else if (status === 400) { + const _responseText = response.data; + let result400: any = null; + let resultData400 = _responseText; + result400 = RemoteServiceErrorResponse.fromJS(resultData400); + return throwException("Bad Request", status, _responseText, _headers, result400); + + } else if (status === 404) { + const _responseText = response.data; + let result404: any = null; + let resultData404 = _responseText; + result404 = RemoteServiceErrorResponse.fromJS(resultData404); + return throwException("Not Found", status, _responseText, _headers, result404); + + } else if (status === 501) { + const _responseText = response.data; + let result501: any = null; + let resultData501 = _responseText; + result501 = RemoteServiceErrorResponse.fromJS(resultData501); + return throwException("Server Error", status, _responseText, _headers, result501); + + } else if (status === 500) { + const _responseText = response.data; + let result500: any = null; + let resultData500 = _responseText; + result500 = RemoteServiceErrorResponse.fromJS(resultData500); + return throwException("Server Error", status, _responseText, _headers, result500); + + } else if (status !== 200 && status !== 204) { + const _responseText = response.data; + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + } + return Promise.resolve(null as any); + } + + /** + * 更新Features + * @param body (optional) + * @return Success + */ + update(body: UpdateFeatureInput | undefined , cancelToken?: CancelToken | undefined): Promise { + let url_ = this.baseUrl + "/Features/update"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(body); + + let options_ = { + data: content_, + method: "POST", + url: url_, + headers: { + "Content-Type": "application/json", + }, + cancelToken + }; + + return this.transformOptions(options_).then(transformedOptions_ => { + return this.instance.request(transformedOptions_); + }).catch((_error: any) => { + if (isAxiosError(_error) && _error.response) { + return _error.response; + } else { + throw _error; + } + }).then((_response: AxiosResponse) => { + return this.transformResult(url_, _response, (_response: AxiosResponse) => this.processUpdate(_response)); + }); + } + + protected processUpdate(response: AxiosResponse): Promise { + const status = response.status; + let _headers: any = {}; + if (response.headers && typeof response.headers === "object") { + for (let k in response.headers) { + if (response.headers.hasOwnProperty(k)) { + _headers[k] = response.headers[k]; + } + } + } + if (status === 200) { + const _responseText = response.data; + return Promise.resolve(null as any); + + } else if (status === 403) { + const _responseText = response.data; + let result403: any = null; + let resultData403 = _responseText; + result403 = RemoteServiceErrorResponse.fromJS(resultData403); + return throwException("Forbidden", status, _responseText, _headers, result403); + + } else if (status === 401) { + const _responseText = response.data; + let result401: any = null; + let resultData401 = _responseText; + result401 = RemoteServiceErrorResponse.fromJS(resultData401); + return throwException("Unauthorized", status, _responseText, _headers, result401); + + } else if (status === 400) { + const _responseText = response.data; + let result400: any = null; + let resultData400 = _responseText; + result400 = RemoteServiceErrorResponse.fromJS(resultData400); + return throwException("Bad Request", status, _responseText, _headers, result400); + + } else if (status === 404) { + const _responseText = response.data; + let result404: any = null; + let resultData404 = _responseText; + result404 = RemoteServiceErrorResponse.fromJS(resultData404); + return throwException("Not Found", status, _responseText, _headers, result404); + + } else if (status === 501) { + const _responseText = response.data; + let result501: any = null; + let resultData501 = _responseText; + result501 = RemoteServiceErrorResponse.fromJS(resultData501); + return throwException("Server Error", status, _responseText, _headers, result501); + + } else if (status === 500) { + const _responseText = response.data; + let result500: any = null; + let resultData500 = _responseText; + result500 = RemoteServiceErrorResponse.fromJS(resultData500); + return throwException("Server Error", status, _responseText, _headers, result500); + + } else if (status !== 200 && status !== 204) { + const _responseText = response.data; + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + } + return Promise.resolve(null as any); + } + + /** + * 删除Features + * @param body (optional) + * @return Success + */ + delete(body: DeleteFeatureInput | undefined , cancelToken?: CancelToken | undefined): Promise { + let url_ = this.baseUrl + "/Features/delete"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(body); + + let options_ = { + data: content_, + method: "POST", + url: url_, + headers: { + "Content-Type": "application/json", + }, + cancelToken + }; + + return this.transformOptions(options_).then(transformedOptions_ => { + return this.instance.request(transformedOptions_); + }).catch((_error: any) => { + if (isAxiosError(_error) && _error.response) { + return _error.response; + } else { + throw _error; + } + }).then((_response: AxiosResponse) => { + return this.transformResult(url_, _response, (_response: AxiosResponse) => this.processDelete(_response)); + }); + } + + protected processDelete(response: AxiosResponse): Promise { + const status = response.status; + let _headers: any = {}; + if (response.headers && typeof response.headers === "object") { + for (let k in response.headers) { + if (response.headers.hasOwnProperty(k)) { + _headers[k] = response.headers[k]; + } + } + } + if (status === 200) { + const _responseText = response.data; + return Promise.resolve(null as any); + + } else if (status === 403) { + const _responseText = response.data; + let result403: any = null; + let resultData403 = _responseText; + result403 = RemoteServiceErrorResponse.fromJS(resultData403); + return throwException("Forbidden", status, _responseText, _headers, result403); + + } else if (status === 401) { + const _responseText = response.data; + let result401: any = null; + let resultData401 = _responseText; + result401 = RemoteServiceErrorResponse.fromJS(resultData401); + return throwException("Unauthorized", status, _responseText, _headers, result401); + + } else if (status === 400) { + const _responseText = response.data; + let result400: any = null; + let resultData400 = _responseText; + result400 = RemoteServiceErrorResponse.fromJS(resultData400); + return throwException("Bad Request", status, _responseText, _headers, result400); + + } else if (status === 404) { + const _responseText = response.data; + let result404: any = null; + let resultData404 = _responseText; + result404 = RemoteServiceErrorResponse.fromJS(resultData404); + return throwException("Not Found", status, _responseText, _headers, result404); + + } else if (status === 501) { + const _responseText = response.data; + let result501: any = null; + let resultData501 = _responseText; + result501 = RemoteServiceErrorResponse.fromJS(resultData501); + return throwException("Server Error", status, _responseText, _headers, result501); + + } else if (status === 500) { + const _responseText = response.data; + let result500: any = null; + let resultData500 = _responseText; + result500 = RemoteServiceErrorResponse.fromJS(resultData500); + return throwException("Server Error", status, _responseText, _headers, result500); + + } else if (status !== 200 && status !== 204) { + const _responseText = response.data; + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + } + return Promise.resolve(null as any); + } +} + export class IdentitySecurityLogsServiceProxy extends ServiceProxyBase { private instance: AxiosInstance; private baseUrl: string; @@ -8959,6 +9266,46 @@ export interface IDeleteDataDictionaryDetailInput { dataDictionayDetailId: string; } +export class DeleteFeatureInput implements IDeleteFeatureInput { + providerName!: string | undefined; + providerKey!: string | undefined; + + constructor(data?: IDeleteFeatureInput) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; + } + } + } + + init(_data?: any) { + if (_data) { + this.providerName = _data["providerName"]; + this.providerKey = _data["providerKey"]; + } + } + + static fromJS(data: any): DeleteFeatureInput { + data = typeof data === 'object' ? data : {}; + let result = new DeleteFeatureInput(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + data["providerName"] = this.providerName; + data["providerKey"] = this.providerKey; + return data; + } +} + +export interface IDeleteFeatureInput { + providerName: string | undefined; + providerKey: string | undefined; +} + /** 删除语言 */ export class DeleteLanguageInput implements IDeleteLanguageInput { /** 语言Id */ @@ -9584,7 +9931,160 @@ export interface IExtensionPropertyUiLookupDto { export class ExtensionPropertyUiTableDto implements IExtensionPropertyUiTableDto { isVisible!: boolean; - constructor(data?: IExtensionPropertyUiTableDto) { + constructor(data?: IExtensionPropertyUiTableDto) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; + } + } + } + + init(_data?: any) { + if (_data) { + this.isVisible = _data["isVisible"]; + } + } + + static fromJS(data: any): ExtensionPropertyUiTableDto { + data = typeof data === 'object' ? data : {}; + let result = new ExtensionPropertyUiTableDto(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + data["isVisible"] = this.isVisible; + return data; + } +} + +export interface IExtensionPropertyUiTableDto { + isVisible: boolean; +} + +export class FeatureDto implements IFeatureDto { + name!: string | undefined; + displayName!: string | undefined; + value!: string | undefined; + provider!: FeatureProviderDto; + description!: string | undefined; + valueType!: IStringValueType; + depth!: number; + parentName!: string | undefined; + + constructor(data?: IFeatureDto) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; + } + } + } + + init(_data?: any) { + if (_data) { + this.name = _data["name"]; + this.displayName = _data["displayName"]; + this.value = _data["value"]; + this.provider = _data["provider"] ? FeatureProviderDto.fromJS(_data["provider"]) : undefined; + this.description = _data["description"]; + this.valueType = _data["valueType"] ? IStringValueType.fromJS(_data["valueType"]) : undefined; + this.depth = _data["depth"]; + this.parentName = _data["parentName"]; + } + } + + static fromJS(data: any): FeatureDto { + data = typeof data === 'object' ? data : {}; + let result = new FeatureDto(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + data["name"] = this.name; + data["displayName"] = this.displayName; + data["value"] = this.value; + data["provider"] = this.provider ? this.provider.toJSON() : undefined; + data["description"] = this.description; + data["valueType"] = this.valueType ? this.valueType.toJSON() : undefined; + data["depth"] = this.depth; + data["parentName"] = this.parentName; + return data; + } +} + +export interface IFeatureDto { + name: string | undefined; + displayName: string | undefined; + value: string | undefined; + provider: FeatureProviderDto; + description: string | undefined; + valueType: IStringValueType; + depth: number; + parentName: string | undefined; +} + +export class FeatureGroupDto implements IFeatureGroupDto { + name!: string | undefined; + displayName!: string | undefined; + features!: FeatureDto[] | undefined; + + constructor(data?: IFeatureGroupDto) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; + } + } + } + + init(_data?: any) { + if (_data) { + this.name = _data["name"]; + this.displayName = _data["displayName"]; + if (Array.isArray(_data["features"])) { + this.features = [] as any; + for (let item of _data["features"]) + this.features!.push(FeatureDto.fromJS(item)); + } + } + } + + static fromJS(data: any): FeatureGroupDto { + data = typeof data === 'object' ? data : {}; + let result = new FeatureGroupDto(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + data["name"] = this.name; + data["displayName"] = this.displayName; + if (Array.isArray(this.features)) { + data["features"] = []; + for (let item of this.features) + data["features"].push(item.toJSON()); + } + return data; + } +} + +export interface IFeatureGroupDto { + name: string | undefined; + displayName: string | undefined; + features: FeatureDto[] | undefined; +} + +export class FeatureProviderDto implements IFeatureProviderDto { + name!: string | undefined; + key!: string | undefined; + + constructor(data?: IFeatureProviderDto) { if (data) { for (var property in data) { if (data.hasOwnProperty(property)) @@ -9595,26 +10095,29 @@ export class ExtensionPropertyUiTableDto implements IExtensionPropertyUiTableDto init(_data?: any) { if (_data) { - this.isVisible = _data["isVisible"]; + this.name = _data["name"]; + this.key = _data["key"]; } } - static fromJS(data: any): ExtensionPropertyUiTableDto { + static fromJS(data: any): FeatureProviderDto { data = typeof data === 'object' ? data : {}; - let result = new ExtensionPropertyUiTableDto(); + let result = new FeatureProviderDto(); result.init(data); return result; } toJSON(data?: any) { data = typeof data === 'object' ? data : {}; - data["isVisible"] = this.isVisible; + data["name"] = this.name; + data["key"] = this.key; return data; } } -export interface IExtensionPropertyUiTableDto { - isVisible: boolean; +export interface IFeatureProviderDto { + name: string | undefined; + key: string | undefined; } export class FileAggregateRoute implements IFileAggregateRoute { @@ -10737,6 +11240,90 @@ export interface IFindTenantResultDto { isActive: boolean; } +export class GetFeatureListResultDto implements IGetFeatureListResultDto { + groups!: FeatureGroupDto[] | undefined; + + constructor(data?: IGetFeatureListResultDto) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; + } + } + } + + init(_data?: any) { + if (_data) { + if (Array.isArray(_data["groups"])) { + this.groups = [] as any; + for (let item of _data["groups"]) + this.groups!.push(FeatureGroupDto.fromJS(item)); + } + } + } + + static fromJS(data: any): GetFeatureListResultDto { + data = typeof data === 'object' ? data : {}; + let result = new GetFeatureListResultDto(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + if (Array.isArray(this.groups)) { + data["groups"] = []; + for (let item of this.groups) + data["groups"].push(item.toJSON()); + } + return data; + } +} + +export interface IGetFeatureListResultDto { + groups: FeatureGroupDto[] | undefined; +} + +export class GetFeatureListResultInput implements IGetFeatureListResultInput { + providerName!: string | undefined; + providerKey!: string | undefined; + + constructor(data?: IGetFeatureListResultInput) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; + } + } + } + + init(_data?: any) { + if (_data) { + this.providerName = _data["providerName"]; + this.providerKey = _data["providerKey"]; + } + } + + static fromJS(data: any): GetFeatureListResultInput { + data = typeof data === 'object' ? data : {}; + let result = new GetFeatureListResultInput(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + data["providerName"] = this.providerName; + data["providerKey"] = this.providerKey; + return data; + } +} + +export interface IGetFeatureListResultInput { + providerName: string | undefined; + providerKey: string | undefined; +} + export class GetOrganizationUnitRoleInput implements IGetOrganizationUnitRoleInput { /** 当前页面.默认从1开始 */ pageIndex!: number; @@ -11429,6 +12016,114 @@ export enum HttpStatusCode { GatewayTimeout = 511, } +export class IStringValueType implements IIStringValueType { + readonly name!: string | undefined; + readonly properties!: { [key: string]: any; } | undefined; + validator!: IValueValidator; + + constructor(data?: IIStringValueType) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; + } + } + } + + init(_data?: any) { + if (_data) { + (this).name = _data["name"]; + if (_data["properties"]) { + (this).properties = {} as any; + for (let key in _data["properties"]) { + if (_data["properties"].hasOwnProperty(key)) + ((this).properties)![key] = _data["properties"][key]; + } + } + this.validator = _data["validator"] ? IValueValidator.fromJS(_data["validator"]) : undefined; + } + } + + static fromJS(data: any): IStringValueType { + data = typeof data === 'object' ? data : {}; + let result = new IStringValueType(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + data["name"] = this.name; + if (this.properties) { + data["properties"] = {}; + for (let key in this.properties) { + if (this.properties.hasOwnProperty(key)) + (data["properties"])[key] = (this.properties)[key]; + } + } + data["validator"] = this.validator ? this.validator.toJSON() : undefined; + return data; + } +} + +export interface IIStringValueType { + name: string | undefined; + properties: { [key: string]: any; } | undefined; + validator: IValueValidator; +} + +export class IValueValidator implements IIValueValidator { + readonly name!: string | undefined; + readonly properties!: { [key: string]: any; } | undefined; + + constructor(data?: IIValueValidator) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; + } + } + } + + init(_data?: any) { + if (_data) { + (this).name = _data["name"]; + if (_data["properties"]) { + (this).properties = {} as any; + for (let key in _data["properties"]) { + if (_data["properties"].hasOwnProperty(key)) + ((this).properties)![key] = _data["properties"][key]; + } + } + } + } + + static fromJS(data: any): IValueValidator { + data = typeof data === 'object' ? data : {}; + let result = new IValueValidator(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + data["name"] = this.name; + if (this.properties) { + data["properties"] = {}; + for (let key in this.properties) { + if (this.properties.hasOwnProperty(key)) + (data["properties"])[key] = (this.properties)[key]; + } + } + return data; + } +} + +export interface IIValueValidator { + name: string | undefined; + properties: { [key: string]: any; } | undefined; +} + export class IanaTimeZone implements IIanaTimeZone { timeZoneName!: string | undefined; @@ -16134,6 +16829,134 @@ export interface IUpdateDetailInput { order: number; } +export class UpdateFeatureDto implements IUpdateFeatureDto { + name!: string | undefined; + value!: string | undefined; + + constructor(data?: IUpdateFeatureDto) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; + } + } + } + + init(_data?: any) { + if (_data) { + this.name = _data["name"]; + this.value = _data["value"]; + } + } + + static fromJS(data: any): UpdateFeatureDto { + data = typeof data === 'object' ? data : {}; + let result = new UpdateFeatureDto(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + data["name"] = this.name; + data["value"] = this.value; + return data; + } +} + +export interface IUpdateFeatureDto { + name: string | undefined; + value: string | undefined; +} + +export class UpdateFeatureInput implements IUpdateFeatureInput { + providerName!: string | undefined; + providerKey!: string | undefined; + updateFeaturesDto!: UpdateFeaturesDto; + + constructor(data?: IUpdateFeatureInput) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; + } + } + } + + init(_data?: any) { + if (_data) { + this.providerName = _data["providerName"]; + this.providerKey = _data["providerKey"]; + this.updateFeaturesDto = _data["updateFeaturesDto"] ? UpdateFeaturesDto.fromJS(_data["updateFeaturesDto"]) : undefined; + } + } + + static fromJS(data: any): UpdateFeatureInput { + data = typeof data === 'object' ? data : {}; + let result = new UpdateFeatureInput(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + data["providerName"] = this.providerName; + data["providerKey"] = this.providerKey; + data["updateFeaturesDto"] = this.updateFeaturesDto ? this.updateFeaturesDto.toJSON() : undefined; + return data; + } +} + +export interface IUpdateFeatureInput { + providerName: string | undefined; + providerKey: string | undefined; + updateFeaturesDto: UpdateFeaturesDto; +} + +export class UpdateFeaturesDto implements IUpdateFeaturesDto { + features!: UpdateFeatureDto[] | undefined; + + constructor(data?: IUpdateFeaturesDto) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; + } + } + } + + init(_data?: any) { + if (_data) { + if (Array.isArray(_data["features"])) { + this.features = [] as any; + for (let item of _data["features"]) + this.features!.push(UpdateFeatureDto.fromJS(item)); + } + } + } + + static fromJS(data: any): UpdateFeaturesDto { + data = typeof data === 'object' ? data : {}; + let result = new UpdateFeaturesDto(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + if (Array.isArray(this.features)) { + data["features"] = []; + for (let item of this.features) + data["features"].push(item.toJSON()); + } + return data; + } +} + +export interface IUpdateFeaturesDto { + features: UpdateFeatureDto[] | undefined; +} + /** 删除语言 */ export class UpdateLanguageInput implements IUpdateLanguageInput { /** 语言Id */ diff --git a/vben28/src/views/admin/manageFeatrue/index.ts b/vben28/src/views/admin/manageFeatrue/index.ts new file mode 100644 index 000000000..d44a68df5 --- /dev/null +++ b/vben28/src/views/admin/manageFeatrue/index.ts @@ -0,0 +1,19 @@ +import { FeaturesServiceProxy, GetFeatureListResultInput,UpdateFeatureInput,UpdateFeaturesDto} from '/@/services/ServiceProxies'; + +export async function getHostFeatureListAsync() { + const _featuresServiceProxy = new FeaturesServiceProxy(); + const request = new GetFeatureListResultInput(); + request.providerName = 'T'; + return await _featuresServiceProxy.list(request); + } + + export async function updateHostFeatureListAsync(params) { + const _featuresServiceProxy = new FeaturesServiceProxy(); + const request = new UpdateFeatureInput(); + + request.providerName = 'T'; + request.updateFeaturesDto= new UpdateFeaturesDto(); + request.updateFeaturesDto.features=params; + return await _featuresServiceProxy.update(request); + } + \ No newline at end of file diff --git a/vben28/src/views/admin/manageFeatrue/index.vue b/vben28/src/views/admin/manageFeatrue/index.vue new file mode 100644 index 000000000..fdc4b9a9a --- /dev/null +++ b/vben28/src/views/admin/manageFeatrue/index.vue @@ -0,0 +1,137 @@ + + + + \ No newline at end of file diff --git a/vben28/src/views/tenants/ManageFeatrue.vue b/vben28/src/views/tenants/ManageFeatrue.vue new file mode 100644 index 000000000..608b374e7 --- /dev/null +++ b/vben28/src/views/tenants/ManageFeatrue.vue @@ -0,0 +1,137 @@ + + + + diff --git a/vben28/src/views/tenants/Tenant.ts b/vben28/src/views/tenants/Tenant.ts index a1292263c..986addd47 100644 --- a/vben28/src/views/tenants/Tenant.ts +++ b/vben28/src/views/tenants/Tenant.ts @@ -2,7 +2,7 @@ import { FormSchema } from '/@/components/Table'; import { BasicColumn } from '/@/components/Table'; import { useI18n } from '/@/hooks/web/useI18n'; const { t } = useI18n(); -import { TenantsServiceProxy, PagingTenantInput, IdInput, PageTenantConnectionStringInput} from '/@/services/ServiceProxies'; +import { TenantsServiceProxy, PagingTenantInput, IdInput, PageTenantConnectionStringInput, FeaturesServiceProxy, GetFeatureListResultInput,UpdateFeatureInput,UpdateFeaturesDto, UpdateFeatureDto} from '/@/services/ServiceProxies'; export const searchFormSchema: FormSchema[] = [ { field: 'filter', @@ -173,3 +173,21 @@ export async function addOrUpdateConnectionString({ request }) { const _tenantsServiceProxy = new TenantsServiceProxy(); return await _tenantsServiceProxy.addOrUpdateConnectionString(request); } + +export async function getTenantFeatureListAsync(tenantId) { + const _featuresServiceProxy = new FeaturesServiceProxy(); + const request = new GetFeatureListResultInput(); + request.providerKey = tenantId; + request.providerName = 'T'; + return await _featuresServiceProxy.list(request); +} + +export async function updateTenantFeatureListAsync(tenantId, params) { + const _featuresServiceProxy = new FeaturesServiceProxy(); + const request = new UpdateFeatureInput(); + request.providerKey = tenantId; + request.providerName = 'T'; + request.updateFeaturesDto= new UpdateFeaturesDto(); + request.updateFeaturesDto.features=params; + return await _featuresServiceProxy.update(request); +} diff --git a/vben28/src/views/tenants/Tenant.vue b/vben28/src/views/tenants/Tenant.vue index 13a3dd60f..4339708bf 100644 --- a/vben28/src/views/tenants/Tenant.vue +++ b/vben28/src/views/tenants/Tenant.vue @@ -27,6 +27,12 @@ label: t('routes.tenant.connectionString'), onClick: handleConnectionString.bind(null, record), }, + { + icon: 'ant-design:edit-outlined', + auth: 'AbpTenantManagement.Tenants.ManageFeatures', + label: t('routes.tenant.manageFeatures'), + onClick: handleManageFeatures.bind(null, record), + }, { icon: 'ant-design:minus-outlined', auth: 'AbpTenantManagement.Tenants.Delete', @@ -52,6 +58,11 @@ @reload="reload" :bodyStyle="{ 'padding-top': '0' }" /> + @@ -68,7 +79,7 @@ deleteTenantAsync, } from '/@/views/tenants/Tenant'; import CreateTenant from './CreateTenant.vue'; - + import ManageFeatrue from './ManageFeatrue.vue'; import EditConnectionString from './EditConnectionString.vue'; import EditTenant from './EditTenant.vue'; import { useMessage } from '/@/hooks/web/useMessage'; @@ -80,11 +91,13 @@ CreateTenant, EditTenant, EditConnectionString, + ManageFeatrue }, setup() { const { t } = useI18n(); const [registerCreateTenantModal, { openModal: openCreateTenantModal }] = useModal(); + const [registerTenantFeatureModal, { openModal: openFeatureTenantModal }] = useModal(); const [registerEditTenantModal, { openModal: openEditTenantModal }] = useModal(); const [registerEditConnectionStringModal, { openModal: openEditConnectionStringModal }] = useModal(); @@ -106,7 +119,7 @@ slots: { customRender: 'action', }, - width: 250, + width: 350, fixed: 'right', }, }); @@ -115,7 +128,7 @@ const handleEdit = (record: Recordable) => { openEditTenantModal(true, { record: record }); }; - + // 删除 const handleDelete = async (record: Recordable) => { let msg = t('common.askDelete'); @@ -133,6 +146,9 @@ const handleConnectionString = async (record: Recordable) => { openEditConnectionStringModal(true, { record: record }); }; + const handleManageFeatures = async (record: Recordable) => { + openFeatureTenantModal(true, { id: record.id }); + }; return { t, registerTable, @@ -145,6 +161,8 @@ handleEdit, registerEditTenantModal, registerEditConnectionStringModal, + handleManageFeatures, + registerTenantFeatureModal }; }, });