Browse Source

feat: 添加Feature功能

pull/127/head
WangJunZzz 2 years ago
parent
commit
b2879e8407
  1. 28
      aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Features/Dtos/DeleteFeatureInput.cs
  2. 20
      aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Features/Dtos/GetFeatureListResultInput.cs
  3. 25
      aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Features/Dtos/UpdateFeatureInput.cs
  4. 22
      aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Features/IVoloFeatureAppService.cs
  5. 9
      aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Permissions/BasicManagementPermissionDefinitionProvider.cs
  6. 1
      aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Permissions/BasicManagementPermissions.cs
  7. 9
      aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application/ApplicationConfigurations/AbpProApplicationConfigurationAppService.cs
  8. 33
      aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application/Features/VoloFeatureAppService.cs
  9. 1
      aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Domain.Shared/Localization/BasicManagement/en.json
  10. 2
      aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Domain.Shared/Localization/BasicManagement/zh-Hans.json
  11. 37
      aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.HttpApi/Systems/FeatureController.cs
  12. 1
      aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Lion.AbpPro.HttpApi.Host.csproj
  13. 13
      aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/appsettings.json
  14. 34
      aspnet-core/services/src/Lion.AbpPro.Domain.Shared/Features/AbpProFeatureDefinitionProvider.cs
  15. 10
      aspnet-core/services/src/Lion.AbpPro.Domain.Shared/Features/AbpProFeatures.cs
  16. 5
      aspnet-core/services/src/Lion.AbpPro.Domain.Shared/Localization/AbpPro/en.json
  17. 5
      aspnet-core/services/src/Lion.AbpPro.Domain.Shared/Localization/AbpPro/zh-Hans.json
  18. 2
      vben28/src/api/sys/user.ts
  19. 1
      vben28/src/locales/lang/en/routes/admin.ts
  20. 1
      vben28/src/locales/lang/en/routes/tenant.ts
  21. 1
      vben28/src/locales/lang/zh-CN/routes/admin.ts
  22. 1
      vben28/src/locales/lang/zh-CN/routes/tenant.ts
  23. 10
      vben28/src/router/routes/modules/admin.ts
  24. 837
      vben28/src/services/ServiceProxies.ts
  25. 19
      vben28/src/views/admin/manageFeatrue/index.ts
  26. 137
      vben28/src/views/admin/manageFeatrue/index.vue
  27. 137
      vben28/src/views/tenants/ManageFeatrue.vue
  28. 20
      vben28/src/views/tenants/Tenant.ts
  29. 24
      vben28/src/views/tenants/Tenant.vue

28
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<ValidationResult> Validate(ValidationContext validationContext)
{
var localization = validationContext.GetRequiredService<IStringLocalizer<AbpProLocalizationResource>>();
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) }
);
}
}
}

20
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<ValidationResult> Validate(ValidationContext validationContext)
{
var localization = validationContext.GetRequiredService<IStringLocalizer<AbpProLocalizationResource>>();
if (ProviderName.IsNullOrWhiteSpace())
{
yield return new ValidationResult(
localization[AbpProLocalizationErrorCodes.ErrorCode100003, nameof(ProviderName)],
new[] { nameof(ProviderName) }
);
}
}
}

25
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<ValidationResult> Validate(ValidationContext validationContext)
{
var localization = validationContext.GetRequiredService<IStringLocalizer<AbpProLocalizationResource>>();
if (ProviderName.IsNullOrWhiteSpace())
{
yield return new ValidationResult(
localization[AbpProLocalizationErrorCodes.ErrorCode100003, nameof(ProviderName)],
new[] { nameof(ProviderName) }
);
}
}
}

22
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
{
/// <summary>
/// 获取Features
/// </summary>
Task<GetFeatureListResultDto> GetAsync(GetFeatureListResultInput input);
/// <summary>
/// 更新Features
/// </summary>
Task UpdateAsync(UpdateFeatureInput input);
/// <summary>
/// 删除Features
/// </summary>
Task DeleteAsync(DeleteFeatureInput input);
}

9
aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Permissions/BasicManagementPermissionDefinitionProvider.cs

@ -14,11 +14,14 @@ public class BasicManagementPermissionDefinitionProvider : PermissionDefinitionP
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,

1
aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application.Contracts/Permissions/BasicManagementPermissions.cs

@ -16,6 +16,7 @@ public class BasicManagementPermissions
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";

9
aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Application/ApplicationConfigurations/AbpProApplicationConfigurationAppService.cs

@ -323,6 +323,15 @@ public class AbpProApplicationConfigurationAppService : ApplicationService, IAbp
continue;
}
if (featureDefinition.Name == "SettingManagement.Enable")
{
continue;
}
if (featureDefinition.Name == "SettingManagement.AllowChangingEmailSettings")
{
continue;
}
result.Values[featureDefinition.Name] = await FeatureChecker.GetOrNullAsync(featureDefinition.Name);
}

33
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<GetFeatureListResultDto> 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);
}
}

1
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",

2
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": "用户被锁定",

37
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<GetFeatureListResultDto> 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);
}
}

1
aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Lion.AbpPro.HttpApi.Host.csproj

@ -58,6 +58,7 @@
<None Remove="Logs\**" />
</ItemGroup>
<ItemGroup>
<Content Remove="$(UserProfile)\.nuget\packages\*\*\contentFiles\any\*\*.abppkg*.json" />
</ItemGroup>

13
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": {

34
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<AbpProResource>(name);
}
}

10
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";
}

5
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"
}
}

5
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类型"
}
}

2
vben28/src/api/sys/user.ts

@ -58,7 +58,7 @@ export function login(input: LoginInput): Promise<LoginOutput> {
*/
export function getAbpApplicationConfiguration() {
const _abpApplicationConfigurationServiceProxy = new AbpApplicationConfigurationServiceProxy();
return _abpApplicationConfigurationServiceProxy.applicationConfiguration();
return _abpApplicationConfigurationServiceProxy.applicationConfiguration(false);
}

1
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',

1
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',

1
vben28/src/locales/lang/zh-CN/routes/admin.ts

@ -64,6 +64,7 @@ export default {
logContent: '内容',
detail: '详情',
settingManagement: '设置管理',
featureManagement: '功能管理',
dictionaryManagement: '数据字典',
dictionaryTypeName: '字典类型',
dictionaryCode: '编码',

1
vben28/src/locales/lang/zh-CN/routes/tenant.ts

@ -1,6 +1,7 @@
export default {
name: '名称',
connectionString: '连接字符串',
manageFeatures : '功能管理',
tenantManagement: '租户管理',
tenantList: '租户列表',
adminPassword: '管理员密码',

10
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',

837
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<GetFeatureListResultDto> {
let url_ = this.baseUrl + "/Features/list";
url_ = url_.replace(/[?&]$/, "");
const content_ = JSON.stringify(body);
let options_ = <AxiosRequestConfig>{
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<GetFeatureListResultDto> {
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<GetFeatureListResultDto>(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<GetFeatureListResultDto>(null as any);
}
/**
* Features
* @param body (optional)
* @return Success
*/
update(body: UpdateFeatureInput | undefined , cancelToken?: CancelToken | undefined): Promise<void> {
let url_ = this.baseUrl + "/Features/update";
url_ = url_.replace(/[?&]$/, "");
const content_ = JSON.stringify(body);
let options_ = <AxiosRequestConfig>{
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<void> {
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<void>(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<void>(null as any);
}
/**
* Features
* @param body (optional)
* @return Success
*/
delete(body: DeleteFeatureInput | undefined , cancelToken?: CancelToken | undefined): Promise<void> {
let url_ = this.baseUrl + "/Features/delete";
url_ = url_.replace(/[?&]$/, "");
const content_ = JSON.stringify(body);
let options_ = <AxiosRequestConfig>{
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<void> {
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<void>(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<void>(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))
(<any>this)[property] = (<any>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))
(<any>this)[property] = (<any>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))
(<any>this)[property] = (<any>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"]) : <any>undefined;
this.description = _data["description"];
this.valueType = _data["valueType"] ? IStringValueType.fromJS(_data["valueType"]) : <any>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() : <any>undefined;
data["description"] = this.description;
data["valueType"] = this.valueType ? this.valueType.toJSON() : <any>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))
(<any>this)[property] = (<any>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))
(<any>this)[property] = (<any>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))
(<any>this)[property] = (<any>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))
(<any>this)[property] = (<any>data)[property];
}
}
}
init(_data?: any) {
if (_data) {
(<any>this).name = _data["name"];
if (_data["properties"]) {
(<any>this).properties = {} as any;
for (let key in _data["properties"]) {
if (_data["properties"].hasOwnProperty(key))
(<any>(<any>this).properties)![key] = _data["properties"][key];
}
}
this.validator = _data["validator"] ? IValueValidator.fromJS(_data["validator"]) : <any>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))
(<any>data["properties"])[key] = (<any>this.properties)[key];
}
}
data["validator"] = this.validator ? this.validator.toJSON() : <any>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))
(<any>this)[property] = (<any>data)[property];
}
}
}
init(_data?: any) {
if (_data) {
(<any>this).name = _data["name"];
if (_data["properties"]) {
(<any>this).properties = {} as any;
for (let key in _data["properties"]) {
if (_data["properties"].hasOwnProperty(key))
(<any>(<any>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))
(<any>data["properties"])[key] = (<any>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))
(<any>this)[property] = (<any>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))
(<any>this)[property] = (<any>data)[property];
}
}
}
init(_data?: any) {
if (_data) {
this.providerName = _data["providerName"];
this.providerKey = _data["providerKey"];
this.updateFeaturesDto = _data["updateFeaturesDto"] ? UpdateFeaturesDto.fromJS(_data["updateFeaturesDto"]) : <any>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() : <any>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))
(<any>this)[property] = (<any>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 */

19
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);
}

137
vben28/src/views/admin/manageFeatrue/index.vue

@ -0,0 +1,137 @@
<template>
<PageWrapper v-loading="loading">
<div ref="wrapperRef" :class="prefixCls">
<Tabs tab-position="left" :tabBarStyle="tabBarStyle" @change="change">
<template v-for="item in featureList" :key="item.name">
<TabPane :tab="item.displayName">
<CollapseContainer :title="item.displayName" :canExpan="false">
<a-form :label-col="labelCol" :wrapper-col="wrapperCol">
<a-form-item v-for="feature in item.features" :label="feature.displayName">
<div v-if="feature.valueType.name === 'FreeTextStringValueType'">
<a-input v-model:value="feature.value" style="width: 80%" />
</div>
<div v-if="feature.valueType.name === 'ToggleStringValueType'">
<a-checkbox :checked="!(feature.value == 'false' || feature.value == false)"
@update:checked="(val) => (feature.value = val)">
</a-checkbox>
</div>
</a-form-item>
</a-form>
<a-button style="margin-left: 65%" type="primary" @click="update(item)">{{
t('common.saveText')
}}</a-button>
</CollapseContainer>
</TabPane>
</template>
</Tabs>
</div>
</PageWrapper>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs, onMounted } from 'vue';
import { useI18n } from '/@/hooks/web/useI18n';
import { Tabs } from 'ant-design-vue';
import { CollapseContainer, ScrollContainer } from '/@/components/Container/index';
import { PageWrapper } from '/@/components/Page';
import { getHostFeatureListAsync, updateHostFeatureListAsync } from '/@/views/admin/manageFeatrue/index';
import { FeatureGroupDto, UpdateFeatureDto } from '/@/services/ServiceProxies';
import { message } from 'ant-design-vue';
export default defineComponent({
name: 'ManageHostFeatrue',
components: {
ScrollContainer,
CollapseContainer,
Tabs,
TabPane: Tabs.TabPane,
PageWrapper,
},
setup() {
const { t } = useI18n();
let featureList: FeatureGroupDto[] = [];
const state = reactive({
featureList,
loading: true,
});
onMounted(async () => {
state.loading = true;
const result = await getHostFeatureListAsync();
state.featureList = result.groups as FeatureGroupDto[];
state.loading = false;
});
const update = async (item) => {
console.log(item)
let features = item.features?.map(e => {
let item = new UpdateFeatureDto();
item.name = e.name;
item.value = e.value?.toString();
return item;
})
try {
state.loading = true;
await updateHostFeatureListAsync(features)
message.success(t('common.operationSuccess'));
} catch (error) {
message.success(t('common.operationFail'));
} finally {
state.loading = false;
}
}
const submit = async () => {
if (currentFeature) {
let features = currentFeature.features?.map(e => {
let item = new UpdateFeatureDto();
item.name = e.name;
item.value = e.value?.toString();
return item;
})
try {
state.loading = true;
await updateHostFeatureListAsync(features)
message.success(t('common.operationSuccess'));
} catch (error) {
message.success(t('common.operationFail'));
} finally {
state.loading = false;
}
}
};
const cancel = () => {
};
return {
t,
submit,
cancel,
...toRefs(state),
prefixCls: 'account-setting',
tabBarStyle: {
width: '220px',
},
labelCol: { span: 4 },
wrapperCol: { span: 14 },
update
};
},
});
</script>
<style lang="less">
.account-setting {
margin: 12px;
background-color: @component-background;
.base-title {
padding-left: 0;
}
.ant-tabs-tab-active {
background-color: @item-active-bg;
}
}
</style>

137
vben28/src/views/tenants/ManageFeatrue.vue

@ -0,0 +1,137 @@
<template>
<BasicModal :title="t('routes.tenant.manageFeatures')" :canFullscreen="false" :defaultFullscreen="true" @ok="submit"
@cancel="cancel" @register="registerModal">
<PageWrapper v-loading="loading">
<div ref="wrapperRef" :class="prefixCls">
<Tabs tab-position="left" :tabBarStyle="tabBarStyle" @change="change">
<template v-for="item in featureList" :key="item.name">
<TabPane :tab="item.displayName">
<CollapseContainer :title="item.displayName" :canExpan="false">
<a-form :label-col="labelCol" :wrapper-col="wrapperCol">
<a-form-item v-for="feature in item.features" :label="feature.displayName">
<div v-if="feature.valueType.name === 'FreeTextStringValueType'">
<a-input v-model:value="feature.value" style="width: 80%" />
</div>
<div v-if="feature.valueType.name === 'ToggleStringValueType'">
<a-checkbox :checked="!(feature.value == 'false' || feature.value == false)"
@update:checked="(val) => (feature.value = val)">
</a-checkbox>
</div>
</a-form-item>
</a-form>
</CollapseContainer>
</TabPane>
</template>
</Tabs>
</div>
</PageWrapper>
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { useI18n } from '/@/hooks/web/useI18n';
import { Tabs } from 'ant-design-vue';
import { CollapseContainer, ScrollContainer } from '/@/components/Container/index';
import { PageWrapper } from '/@/components/Page';
import { getTenantFeatureListAsync, updateTenantFeatureListAsync } from '/@/views/tenants/Tenant';
import { FeatureGroupDto, UpdateFeatureDto } from '/@/services/ServiceProxies';
import { message } from 'ant-design-vue';
export default defineComponent({
name: 'ManageFeatrue',
components: {
BasicModal,
ScrollContainer,
CollapseContainer,
Tabs,
TabPane: Tabs.TabPane,
PageWrapper,
},
setup() {
const { t } = useI18n();
let featureList: FeatureGroupDto[] = [];
// id
let tenantId = '';
// tab
let currentFeature: FeatureGroupDto | undefined;
const state = reactive({
featureList,
loading: true,
});
const [registerModal] = useModalInner(async (data) => {
state.loading = true;
tenantId = data.id;
const result = await getTenantFeatureListAsync(data.id);
state.featureList = result.groups as FeatureGroupDto[];
if (state.featureList.length > 0) {
currentFeature = state.featureList[0]
}
state.loading = false;
});
const submit = async () => {
if (currentFeature) {
let features = currentFeature.features?.map(e => {
let item = new UpdateFeatureDto();
item.name = e.name;
item.value = e.value?.toString();
return item;
})
try {
state.loading = true;
await updateTenantFeatureListAsync(tenantId, features)
message.success(t('common.operationSuccess'));
} catch (error) {
message.success(t('common.operationFail'));
}finally{
state.loading = false;
}
}
};
const change = (key) => {
currentFeature = state.featureList.find(e => e.name == key);
};
const cancel = () => {
};
return {
t,
registerModal,
submit,
cancel,
...toRefs(state),
prefixCls: 'account-setting',
tabBarStyle: {
width: '220px',
},
labelCol: { span: 4 },
wrapperCol: { span: 14 },
change
};
},
});
</script>
<style lang="less">
.account-setting {
margin: 12px;
background-color: @component-background;
.base-title {
padding-left: 0;
}
.ant-tabs-tab-active {
background-color: @item-active-bg;
}
}
</style>

20
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);
}

24
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' }"
/>
<ManageFeatrue
@register="registerTenantFeatureModal"
@reload="reload"
:bodyStyle="{ 'padding-top': '0' }"
/>
</div>
</template>
@ -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
};
},
});

Loading…
Cancel
Save