Browse Source

add abp-feature-management-module

pull/75/head
cKey 5 years ago
parent
commit
99f459909f
  1. 27
      aspnet-core/database/ApiGateway-Init.sql
  2. 49
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/Features/AbpFileManagementFeatureDefinitionProvider.cs
  3. 23
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/Features/AbpFileManagementFeatureNames.cs
  4. 4
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN/Abp/FileManagement/FileSystemAppService.cs
  5. 10
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/en.json
  6. 10
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/zh-Hans.json
  7. 4
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/FileSystemController.cs
  8. 5
      aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/BackendAdminHostModule.cs
  9. 2
      aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/EntityFrameworkCore/BackendAdminHostMigrationsDbContext.cs
  10. 3
      aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/LINGYUN.BackendAdminApp.Host.csproj
  11. 206
      aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/Migrations/20200910080638_Add-abp-feature-module.Designer.cs
  12. 37
      aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/Migrations/20200910080638_Add-abp-feature-module.cs
  13. 49
      aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/Migrations/BackendAdminHostMigrationsDbContextModelSnapshot.cs
  14. BIN
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db
  15. 2
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs
  16. 1
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj
  17. 56
      vueJs/src/api/feature-management.ts
  18. 4
      vueJs/src/store/modules/abp.ts
  19. 1
      vueJs/src/utils/request.ts
  20. 317
      vueJs/src/views/admin/components/FeatureManagement.vue
  21. 41
      vueJs/src/views/admin/tenants/components/TenantFeatureEditForm.vue
  22. 24
      vueJs/src/views/admin/tenants/index.vue
  23. 2
      vueJs/src/views/file-management/index.vue

27
aspnet-core/database/ApiGateway-Init.sql

@ -11,7 +11,7 @@
Target Server Version : 80020
File Encoding : 65001
Date: 08/09/2020 10:17:07
Date: 12/09/2020 10:33:17
*/
SET NAMES utf8mb4;
@ -54,7 +54,7 @@ CREATE TABLE `appapigatewayaggregate` (
`Priority` int(0) NULL DEFAULT NULL,
`UpstreamHttpMethod` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`Id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of appapigatewayaggregate
@ -76,7 +76,7 @@ CREATE TABLE `appapigatewayaggregateconfig` (
PRIMARY KEY (`Id`) USING BTREE,
INDEX `IX_AppApiGatewayAggregateConfig_AggregateReRouteId`(`AggregateReRouteId`) USING BTREE,
CONSTRAINT `FK_AppApiGatewayAggregateConfig_AppApiGatewayAggregate_Aggregat~` FOREIGN KEY (`AggregateReRouteId`) REFERENCES `appapigatewayaggregate` (`Id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for appapigatewayauthoptions
@ -188,6 +188,7 @@ INSERT INTO `appapigatewayauthoptions` VALUES (121, 1299273770182737920, '', '')
INSERT INTO `appapigatewayauthoptions` VALUES (122, 1299273978023084032, '', '');
INSERT INTO `appapigatewayauthoptions` VALUES (123, 1299274123225694208, '', '');
INSERT INTO `appapigatewayauthoptions` VALUES (124, 1299274222299348992, '', '');
INSERT INTO `appapigatewayauthoptions` VALUES (125, 1304238876758495232, '', '');
-- ----------------------------
-- Table structure for appapigatewaybalanceroptions
@ -304,6 +305,7 @@ INSERT INTO `appapigatewaybalanceroptions` VALUES (124, NULL, 129927377018273792
INSERT INTO `appapigatewaybalanceroptions` VALUES (125, NULL, 1299273978023084032, '', '', 0);
INSERT INTO `appapigatewaybalanceroptions` VALUES (126, NULL, 1299274123225694208, '', '', 0);
INSERT INTO `appapigatewaybalanceroptions` VALUES (127, NULL, 1299274222299348992, '', '', 0);
INSERT INTO `appapigatewaybalanceroptions` VALUES (128, NULL, 1304238876758495232, '', '', 0);
-- ----------------------------
-- Table structure for appapigatewaycacheoptions
@ -415,6 +417,7 @@ INSERT INTO `appapigatewaycacheoptions` VALUES (121, 1299273770182737920, NULL,
INSERT INTO `appapigatewaycacheoptions` VALUES (122, 1299273978023084032, NULL, NULL);
INSERT INTO `appapigatewaycacheoptions` VALUES (123, 1299274123225694208, NULL, NULL);
INSERT INTO `appapigatewaycacheoptions` VALUES (124, 1299274222299348992, NULL, NULL);
INSERT INTO `appapigatewaycacheoptions` VALUES (125, 1304238876758495232, 0, '');
-- ----------------------------
-- Table structure for appapigatewaydiscovery
@ -434,7 +437,7 @@ CREATE TABLE `appapigatewaydiscovery` (
PRIMARY KEY (`Id`) USING BTREE,
UNIQUE INDEX `IX_AppApiGatewayDiscovery_ItemId`(`ItemId`) USING BTREE,
CONSTRAINT `FK_AppApiGatewayDiscovery_AppApiGatewayGlobalConfiguration_Item~` FOREIGN KEY (`ItemId`) REFERENCES `appapigatewayglobalconfiguration` (`ItemId`) ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of appapigatewaydiscovery
@ -455,7 +458,7 @@ CREATE TABLE `appapigatewaydynamicreroute` (
`AppId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
PRIMARY KEY (`Id`) USING BTREE,
UNIQUE INDEX `AK_AppApiGatewayDynamicReRoute_DynamicReRouteId`(`DynamicReRouteId`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for appapigatewayglobalconfiguration
@ -475,7 +478,7 @@ CREATE TABLE `appapigatewayglobalconfiguration` (
`AppId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
PRIMARY KEY (`Id`) USING BTREE,
UNIQUE INDEX `AK_AppApiGatewayGlobalConfiguration_ItemId`(`ItemId`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of appapigatewayglobalconfiguration
@ -623,6 +626,7 @@ INSERT INTO `appapigatewayhttpoptions` VALUES (124, NULL, 1299273770182737920, 0
INSERT INTO `appapigatewayhttpoptions` VALUES (125, NULL, 1299273978023084032, 0, 0, 0, 0, 0);
INSERT INTO `appapigatewayhttpoptions` VALUES (126, NULL, 1299274123225694208, 0, 0, 0, 0, 0);
INSERT INTO `appapigatewayhttpoptions` VALUES (127, NULL, 1299274222299348992, 0, 0, 0, 0, 0);
INSERT INTO `appapigatewayhttpoptions` VALUES (128, NULL, 1304238876758495232, 0, 0, 0, 0, 0);
-- ----------------------------
-- Table structure for appapigatewayqosoptions
@ -739,6 +743,7 @@ INSERT INTO `appapigatewayqosoptions` VALUES (124, NULL, 1299273770182737920, 50
INSERT INTO `appapigatewayqosoptions` VALUES (125, NULL, 1299273978023084032, 50, 60000, 30000);
INSERT INTO `appapigatewayqosoptions` VALUES (126, NULL, 1299274123225694208, 50, 60000, 30000);
INSERT INTO `appapigatewayqosoptions` VALUES (127, NULL, 1299274222299348992, 50, 60000, 30000);
INSERT INTO `appapigatewayqosoptions` VALUES (128, NULL, 1304238876758495232, 50, 60000, 30000);
-- ----------------------------
-- Table structure for appapigatewayratelimitoptions
@ -755,7 +760,7 @@ CREATE TABLE `appapigatewayratelimitoptions` (
PRIMARY KEY (`Id`) USING BTREE,
UNIQUE INDEX `IX_AppApiGatewayRateLimitOptions_ItemId`(`ItemId`) USING BTREE,
CONSTRAINT `FK_AppApiGatewayRateLimitOptions_AppApiGatewayGlobalConfigurati~` FOREIGN KEY (`ItemId`) REFERENCES `appapigatewayglobalconfiguration` (`ItemId`) ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of appapigatewayratelimitoptions
@ -878,6 +883,7 @@ INSERT INTO `appapigatewayratelimitrule` VALUES (121, 1299273770182737920, NULL,
INSERT INTO `appapigatewayratelimitrule` VALUES (122, 1299273978023084032, NULL, '', 0, NULL, NULL, NULL);
INSERT INTO `appapigatewayratelimitrule` VALUES (123, 1299274123225694208, NULL, '', 0, NULL, NULL, NULL);
INSERT INTO `appapigatewayratelimitrule` VALUES (124, 1299274222299348992, NULL, '', 0, NULL, NULL, NULL);
INSERT INTO `appapigatewayratelimitrule` VALUES (125, 1304238876758495232, NULL, '', 0, NULL, NULL, NULL);
-- ----------------------------
-- Table structure for appapigatewayreroute
@ -1015,6 +1021,7 @@ INSERT INTO `appapigatewayreroute` VALUES (128, '{}', 'f8d2b2f0f1d649c2a07eeef23
INSERT INTO `appapigatewayreroute` VALUES (129, '{}', '9785be7a29774b468e271b23009fe115', 1299273978023084032, '【消息服务】- Hangfire仪表板 - 重试', '/hangfire/retries', '', '', '/hangfire/retries', 'GET,POST,PUT,DELETE,', '', '', '', '', '', '', '', 1, '', '', 'HTTP', '127.0.0.1:30020,', '', '', '', 0, 30000, 1, '', 'TEST-APP');
INSERT INTO `appapigatewayreroute` VALUES (130, '{}', '9c0c1cd196bb45c0bc03fafb7a1eb8f2', 1299274123225694208, '【消息服务】- Hangfire仪表板 - 周期性作业', '/hangfire/recurring', '', '', '/hangfire/recurring', 'GET,POST,DELETE,PUT,', '', '', '', '', '', '', '', 1, '', '', 'HTTP', '127.0.0.1:30020,', '', '', '', 0, 30000, 1, '', 'TEST-APP');
INSERT INTO `appapigatewayreroute` VALUES (131, '{}', '243bafe828be463ea63a3e2b521f9923', 1299274222299348992, '【消息服务】- Hangfire仪表板 - 服务器列表', '/hangfire/servers', '', '', '/hangfire/servers', 'GET,', '', '', '', '', '', '', '', 1, '', '', 'HTTP', '127.0.0.1:30020,', '', '', '', 0, 30000, 1, '', 'TEST-APP');
INSERT INTO `appapigatewayreroute` VALUES (132, '{}', '57a8ac1b41bb434cad38fbde0e2ba2f0', 1304238876758495232, '【后台管理】- 管理功能', '/api/feature-management/features', '', '', '/api/feature-management/features', 'GET,PUT,', '', '', '', '', '', '', '', 1, '', '', 'HTTP', '127.0.0.1:30010,', '', '', '', 0, 30000, 1, '', 'TEST-APP');
-- ----------------------------
-- Table structure for appapigatewayroutegroup
@ -1156,6 +1163,7 @@ INSERT INTO `appapigatewaysecurityoptions` VALUES (121, 1299273770182737920, '12
INSERT INTO `appapigatewaysecurityoptions` VALUES (122, 1299273978023084032, '127.0.0.1', '');
INSERT INTO `appapigatewaysecurityoptions` VALUES (123, 1299274123225694208, '127.0.0.1', '');
INSERT INTO `appapigatewaysecurityoptions` VALUES (124, 1299274222299348992, '127.0.0.1', '');
INSERT INTO `appapigatewaysecurityoptions` VALUES (125, 1304238876758495232, '', '');
-- ----------------------------
-- Table structure for cap.published
@ -1174,6 +1182,11 @@ CREATE TABLE `cap.published` (
INDEX `IX_ExpiresAt`(`ExpiresAt`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of cap.published
-- ----------------------------
INSERT INTO `cap.published` VALUES (1304238878134226944, 'v1', 'LINGYUN.ApiGateway.EventBus.ApigatewayConfigChangeEventData', '{\"Headers\":{\"cap-callback-name\":null,\"cap-msg-id\":\"1304238878134226944\",\"cap-msg-name\":\"LINGYUN.ApiGateway.EventBus.ApigatewayConfigChangeEventData\",\"cap-msg-type\":\"Object\",\"cap-senttime\":\"2020/9/11 10:02:34 +08:00\",\"cap-corr-id\":\"1304238878134226944\",\"cap-corr-seq\":\"0\"},\"Value\":{\"DateTime\":\"2020-09-11T10:02:34.7884591+08:00\",\"AppId\":\"TEST-APP\",\"Method\":\"Create\",\"Object\":\"ReRoute\"}}', 0, '2020-09-11 10:02:35', '2020-09-12 10:02:35', 'Succeeded');
-- ----------------------------
-- Table structure for cap.received
-- ----------------------------

49
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/Features/AbpFileManagementFeatureDefinitionProvider.cs

@ -0,0 +1,49 @@
using LINGYUN.Abp.FileManagement.Localization;
using Volo.Abp.Features;
using Volo.Abp.Localization;
using Volo.Abp.Validation.StringValues;
namespace LINGYUN.Abp.FileManagement.Features
{
public class AbpFileManagementFeatureDefinitionProvider : FeatureDefinitionProvider
{
public override void Define(IFeatureDefinitionContext context)
{
var featureGroup = context.AddGroup(
name: AbpFileManagementFeatureNames.GroupName,
displayName: L("Features:FileManagement"));
var fileSystemFeature = featureGroup.AddFeature(
name: AbpFileManagementFeatureNames.FileSystem.Default,
displayName: L("Features:DisplayName:FileSystem"),
description: L("Features:Description:FileSystem"));
fileSystemFeature.CreateChild(
name: AbpFileManagementFeatureNames.FileSystem.DownloadFile,
defaultValue: false.ToString(),
displayName: L("Features:DisplayName:DownloadFile"),
description: L("Features:Description:DownloadFile"),
valueType: new ToggleStringValueType(new BooleanValueValidator()));
fileSystemFeature.CreateChild(
name: AbpFileManagementFeatureNames.FileSystem.UploadFile,
defaultValue: true.ToString(),
displayName: L("Features:DisplayName:UploadFile"),
description: L("Features:Description:UploadFile"),
valueType: new ToggleStringValueType(new BooleanValueValidator()));
// TODO: 此功能需要控制器协同,暂时不实现
fileSystemFeature.CreateChild(
name: AbpFileManagementFeatureNames.FileSystem.MaxUploadFileCount,
defaultValue: 1.ToString(),
displayName: L("Features:DisplayName:MaxUploadFileCount"),
description: L("Features:Description:MaxUploadFileCount"),
valueType: new ToggleStringValueType(new NumericValueValidator(1, 10)));
}
protected ILocalizableString L(string name)
{
return LocalizableString.Create<AbpFileManagementResource>(name);
}
}
}

23
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/Features/AbpFileManagementFeatureNames.cs

@ -0,0 +1,23 @@
namespace LINGYUN.Abp.FileManagement.Features
{
public class AbpFileManagementFeatureNames
{
public const string GroupName = "Abp.FileManagement";
public class FileSystem
{
public const string Default = GroupName + ".FileSystem";
/// <summary>
/// 下载文件功能
/// </summary>
public const string DownloadFile = Default + ".DownloadFile";
/// <summary>
/// 上传文件功能
/// </summary>
public const string UploadFile = Default + ".UploadFile";
/// <summary>
/// 最大上传文件
/// </summary>
public const string MaxUploadFileCount = Default + ".MaxUploadFileCount";
}
}
}

4
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN/Abp/FileManagement/FileSystemAppService.cs

@ -53,12 +53,12 @@ namespace LINGYUN.Abp.FileManagement
string fileSystemPath = GetFileSystemPath(path);
if (!Directory.Exists(fileSystemPath))
{
throw new UserFriendlyException("指定目录不存在!");
throw new UserFriendlyException(L["PathNotFound"]);
}
var copyToFilePath = GetFileSystemPath(input.CopyToPath);
if (Directory.Exists(copyToFilePath))
{
throw new UserFriendlyException("指定的路径中已经有同名的目录存在!");
throw new UserFriendlyException(L["FilePathAlreadyExists"]);
}
CopyDirectory(fileSystemPath, copyToFilePath);

10
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/en.json

@ -26,6 +26,14 @@
"DisplayName:FileLimitLength": "File limit size",
"Description:FileLimitLength": "Limit size of uploaded file in MB",
"DisplayName:AllowFileExtensions": "File extension",
"Description:AllowFileExtensions": "List of allowed extensions to upload files, with multiple extensions separated by, don't need a notation"
"Description:AllowFileExtensions": "List of allowed extensions to upload files, with multiple extensions separated by, don't need a notation",
"Features:FileManagement": "File management",
"Features:DisplayName:FileSystem": "File system",
"Features:DisplayName:DownloadFile": "Download file",
"Features:Description:DownloadFile": "Whether to allow users to download files",
"Features:DisplayName:UploadFile": "Upload file",
"Features:Description:UploadFile": "Whether to allow users to upload files",
"Features:DisplayName:MaxUploadFileCount": "Maximum number of upload files",
"Features:Description:MaxUploadFileCount": "Limit the number of files a user uploads at a time"
}
}

10
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/zh-Hans.json

@ -26,6 +26,14 @@
"DisplayName:FileLimitLength": "文件限制大小",
"Description:FileLimitLength": "上传文件的限制大小,单位(MB)",
"DisplayName:AllowFileExtensions": "文件扩展名",
"Description:AllowFileExtensions": "允许的上传文件扩展名列表,多个扩展名以,分隔,无需输入.符号"
"Description:AllowFileExtensions": "允许的上传文件扩展名列表,多个扩展名以,分隔,无需输入.符号",
"Features:FileManagement": "文件管理",
"Features:DisplayName:FileSystem": "文件系统",
"Features:DisplayName:DownloadFile": "下载文件",
"Features:Description:DownloadFile": "是否允许用户下载文件",
"Features:DisplayName:UploadFile": "上传文件",
"Features:Description:UploadFile": "是否允许用户上传文件",
"Features:DisplayName:MaxUploadFileCount": "上传文件数量",
"Features:Description:MaxUploadFileCount": "用户单次上传文件的限制数量"
}
}

4
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/FileSystemController.cs

@ -15,6 +15,8 @@ using Volo.Abp.Application.Dtos;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.IO;
using Volo.Abp.Settings;
using Volo.Abp.Features;
using LINGYUN.Abp.FileManagement.Features;
namespace LINGYUN.Abp.FileManagement
{
@ -52,6 +54,7 @@ namespace LINGYUN.Abp.FileManagement
[HttpPost]
[Route("files")]
[RequiresFeature(AbpFileManagementFeatureNames.FileSystem.UploadFile)]
[Authorize(AbpFileManagementPermissions.FileSystem.FileManager.Create)]
public virtual async Task CreateFileAsync([FromForm] FileUploadDto input)
{
@ -164,6 +167,7 @@ namespace LINGYUN.Abp.FileManagement
[HttpGet]
[Route("files")]
[RequiresFeature(AbpFileManagementFeatureNames.FileSystem.DownloadFile)]
[Authorize(AbpFileManagementPermissions.FileSystem.FileManager.Download)]
public virtual async Task<IActionResult> DownloadFileAsync(FileSystemDownloadDto input)
{

5
aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/BackendAdminHostModule.cs

@ -36,6 +36,8 @@ using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.MySQL;
using Volo.Abp.FeatureManagement;
using Volo.Abp.FeatureManagement.EntityFrameworkCore;
using Volo.Abp.Identity.Localization;
using Volo.Abp.IdentityServer.EntityFrameworkCore;
using Volo.Abp.Localization;
@ -75,6 +77,8 @@ namespace LINGYUN.BackendAdmin
typeof(AbpSettingManagementHttpApiModule),
typeof(AbpPermissionManagementApplicationModule),
typeof(AbpPermissionManagementHttpApiModule),
typeof(AbpFeatureManagementApplicationModule),
typeof(AbpFeatureManagementHttpApiModule),
typeof(AbpTenantManagementApplicationModule),
typeof(AbpTenantManagementHttpApiModule),
typeof(AbpEntityFrameworkCoreMySQLModule),
@ -83,6 +87,7 @@ namespace LINGYUN.BackendAdmin
typeof(AbpTenantManagementEntityFrameworkCoreModule),
typeof(AbpSettingManagementEntityFrameworkCoreModule),
typeof(AbpPermissionManagementEntityFrameworkCoreModule),
typeof(AbpFeatureManagementEntityFrameworkCoreModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpEmailingExceptionHandlingModule),
typeof(AbpCAPEventBusModule),

2
aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/EntityFrameworkCore/BackendAdminHostMigrationsDbContext.cs

@ -1,5 +1,6 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.FeatureManagement.EntityFrameworkCore;
using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.TenantManagement.EntityFrameworkCore;
@ -18,6 +19,7 @@ namespace LINGYUN.BackendAdmin.EntityFrameworkCore
{
base.OnModelCreating(modelBuilder);
modelBuilder.ConfigureFeatureManagement();
modelBuilder.ConfigureTenantManagement();
modelBuilder.ConfigureSettingManagement();
modelBuilder.ConfigurePermissionManagement();

3
aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/LINGYUN.BackendAdminApp.Host.csproj

@ -46,6 +46,9 @@
<PackageReference Include="Volo.Abp.EntityFrameworkCore.MySQL" Version="3.1.0" />
<PackageReference Include="Volo.Abp.Account.Application" Version="3.1.0" />
<PackageReference Include="Volo.Abp.Account.HttpApi" Version="3.1.0" />
<PackageReference Include="Volo.Abp.FeatureManagement.Application" Version="3.1.0" />
<PackageReference Include="Volo.Abp.FeatureManagement.EntityFrameworkCore" Version="3.1.0" />
<PackageReference Include="Volo.Abp.FeatureManagement.HttpApi" Version="3.1.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.Identity" Version="3.1.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.IdentityServer" Version="3.1.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.HttpApi" Version="3.1.0" />

206
aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/Migrations/20200910080638_Add-abp-feature-module.Designer.cs

@ -0,0 +1,206 @@
// <auto-generated />
using System;
using LINGYUN.BackendAdmin.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.BackendAdmin.Migrations
{
[DbContext(typeof(BackendAdminHostMigrationsDbContext))]
[Migration("20200910080638_Add-abp-feature-module")]
partial class Addabpfeaturemodule
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql)
.HasAnnotation("ProductVersion", "3.1.7")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("varchar(128) CHARACTER SET utf8mb4")
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasMaxLength(64);
b.Property<string>("ProviderName")
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasMaxLength(64);
b.Property<string>("Value")
.IsRequired()
.HasColumnType("varchar(128) CHARACTER SET utf8mb4")
.HasMaxLength(128);
b.HasKey("Id");
b.HasIndex("Name", "ProviderName", "ProviderKey");
b.ToTable("AbpFeatureValues");
});
modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("varchar(128) CHARACTER SET utf8mb4")
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.IsRequired()
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasMaxLength(64);
b.Property<string>("ProviderName")
.IsRequired()
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasMaxLength(64);
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("Name", "ProviderName", "ProviderKey");
b.ToTable("AbpPermissionGrants");
});
modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("varchar(128) CHARACTER SET utf8mb4")
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasMaxLength(64);
b.Property<string>("ProviderName")
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasMaxLength(64);
b.Property<string>("Value")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(2048);
b.HasKey("Id");
b.HasIndex("Name", "ProviderName", "ProviderKey");
b.ToTable("AbpSettings");
});
modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnName("ConcurrencyStamp")
.HasColumnType("varchar(40) CHARACTER SET utf8mb4")
.HasMaxLength(40);
b.Property<DateTime>("CreationTime")
.HasColumnName("CreationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId")
.HasColumnType("char(36)");
b.Property<Guid?>("DeleterId")
.HasColumnName("DeleterId")
.HasColumnType("char(36)");
b.Property<DateTime?>("DeletionTime")
.HasColumnName("DeletionTime")
.HasColumnType("datetime(6)");
b.Property<string>("ExtraProperties")
.HasColumnName("ExtraProperties")
.HasColumnType("longtext CHARACTER SET utf8mb4");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnName("IsDeleted")
.HasColumnType("tinyint(1)")
.HasDefaultValue(false);
b.Property<DateTime?>("LastModificationTime")
.HasColumnName("LastModificationTime")
.HasColumnType("datetime(6)");
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId")
.HasColumnType("char(36)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasMaxLength(64);
b.HasKey("Id");
b.HasIndex("Name");
b.ToTable("AbpTenants");
});
modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b =>
{
b.Property<Guid>("TenantId")
.HasColumnType("char(36)");
b.Property<string>("Name")
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasMaxLength(64);
b.Property<string>("Value")
.IsRequired()
.HasColumnType("varchar(1024) CHARACTER SET utf8mb4")
.HasMaxLength(1024);
b.HasKey("TenantId", "Name");
b.ToTable("AbpTenantConnectionStrings");
});
modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b =>
{
b.HasOne("Volo.Abp.TenantManagement.Tenant", null)
.WithMany("ConnectionStrings")
.HasForeignKey("TenantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
#pragma warning restore 612, 618
}
}
}

37
aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/Migrations/20200910080638_Add-abp-feature-module.cs

@ -0,0 +1,37 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace LINGYUN.BackendAdmin.Migrations
{
public partial class Addabpfeaturemodule : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AbpFeatureValues",
columns: table => new
{
Id = table.Column<Guid>(nullable: false),
Name = table.Column<string>(maxLength: 128, nullable: false),
Value = table.Column<string>(maxLength: 128, nullable: false),
ProviderName = table.Column<string>(maxLength: 64, nullable: true),
ProviderKey = table.Column<string>(maxLength: 64, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AbpFeatureValues", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_AbpFeatureValues_Name_ProviderName_ProviderKey",
table: "AbpFeatureValues",
columns: new[] { "Name", "ProviderName", "ProviderKey" });
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AbpFeatureValues");
}
}
}

49
aspnet-core/services/admin/LINGYUN.BackendAdminApp.Host/Migrations/BackendAdminHostMigrationsDbContextModelSnapshot.cs

@ -16,12 +16,43 @@ namespace LINGYUN.BackendAdmin.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql)
.HasAnnotation("ProductVersion", "3.1.5")
.HasAnnotation("ProductVersion", "3.1.7")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("varchar(128) CHARACTER SET utf8mb4")
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasMaxLength(64);
b.Property<string>("ProviderName")
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasMaxLength(64);
b.Property<string>("Value")
.IsRequired()
.HasColumnType("varchar(128) CHARACTER SET utf8mb4")
.HasMaxLength(128);
b.HasKey("Id");
b.HasIndex("Name", "ProviderName", "ProviderKey");
b.ToTable("AbpFeatureValues");
});
modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b =>
{
b.Property<string>("Id")
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
@ -40,7 +71,7 @@ namespace LINGYUN.BackendAdmin.Migrations
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasMaxLength(64);
b.Property<string>("TenantId")
b.Property<Guid?>("TenantId")
.HasColumnName("TenantId")
.HasColumnType("char(36)");
@ -53,7 +84,7 @@ namespace LINGYUN.BackendAdmin.Migrations
modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b =>
{
b.Property<string>("Id")
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
@ -84,7 +115,7 @@ namespace LINGYUN.BackendAdmin.Migrations
modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b =>
{
b.Property<string>("Id")
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
@ -98,11 +129,11 @@ namespace LINGYUN.BackendAdmin.Migrations
.HasColumnName("CreationTime")
.HasColumnType("datetime(6)");
b.Property<string>("CreatorId")
b.Property<Guid?>("CreatorId")
.HasColumnName("CreatorId")
.HasColumnType("char(36)");
b.Property<string>("DeleterId")
b.Property<Guid?>("DeleterId")
.HasColumnName("DeleterId")
.HasColumnType("char(36)");
@ -124,7 +155,7 @@ namespace LINGYUN.BackendAdmin.Migrations
.HasColumnName("LastModificationTime")
.HasColumnType("datetime(6)");
b.Property<string>("LastModifierId")
b.Property<Guid?>("LastModifierId")
.HasColumnName("LastModifierId")
.HasColumnType("char(36)");
@ -142,7 +173,7 @@ namespace LINGYUN.BackendAdmin.Migrations
modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b =>
{
b.Property<string>("TenantId")
b.Property<Guid>("TenantId")
.HasColumnType("char(36)");
b.Property<string>("Name")

BIN
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db

Binary file not shown.

2
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs

@ -31,6 +31,7 @@ using Volo.Abp.BlobStoring.FileSystem;
using Volo.Abp.Caching;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.FeatureManagement.EntityFrameworkCore;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
@ -50,6 +51,7 @@ namespace LINGYUN.Platform
typeof(AppPlatformHttpApiModule),
typeof(AppPlatformEntityFrameworkCoreModule),
typeof(AbpAspNetCoreMultiTenancyModule),
typeof(AbpFeatureManagementEntityFrameworkCoreModule),
typeof(AbpTenantManagementEntityFrameworkCoreModule),
typeof(AbpSettingManagementEntityFrameworkCoreModule),
typeof(AbpPermissionManagementEntityFrameworkCoreModule),

1
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj

@ -42,6 +42,7 @@
<PackageReference Include="Volo.Abp.Autofac" Version="3.1.0" />
<PackageReference Include="Volo.Abp.BlobStoring.FileSystem" Version="3.1.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.MySQL" Version="3.1.0" />
<PackageReference Include="Volo.Abp.FeatureManagement.EntityFrameworkCore" Version="3.1.0" />
<PackageReference Include="Volo.Abp.TenantManagement.EntityFrameworkCore" Version="3.1.0" />
<PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="3.1.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="3.1.0" />

56
vueJs/src/api/feature-management.ts

@ -0,0 +1,56 @@
import ApiService from './serviceBase'
const serviceUrl = process.env.VUE_APP_BASE_API
export default class FeatureManagementService {
public static getFeatures(providerName: string, providerKey: string) {
let _url = '/api/feature-management/features?'
_url += 'providerName=' + providerName
_url += '&providerKey=' + providerKey
return ApiService.Get<Features>(_url, serviceUrl)
}
public static updateFeatures(providerName: string, providerKey: string, features: Features) {
let _url = '/api/feature-management/features?'
_url += 'providerName=' + providerName
_url += '&providerKey=' + providerKey
return ApiService.Put<void>(_url, features, serviceUrl)
}
}
export class Provider {
providerName!: string
providerKey!: string
}
export class ValueType {
name!: string
properties!: any
validator!: any
}
export class Feature {
name!: string
displayName?: string
value!: string
description?: string
valueType?: ValueType
depth?: number
parentName?: string
constructor(
name: string,
value: any
) {
this.name = name
this.value = value
}
}
export class Features {
features!: Feature[]
constructor() {
this.features = new Array<Feature>()
}
}

4
vueJs/src/store/modules/abp.ts

@ -29,12 +29,12 @@ class AbpConfiguration extends VuexModule implements IAbpState {
if (typeof resource !== 'object') return
Object.keys(resource).forEach(key2 => {
if (/'{|{/g.test(resource[key2])) {
resource[key2] = resource[key2].replace(/'{|{/g, '{{').replace(/}'|}/g, '}}')
resource[key2] = resource[key2].replace(/'{|{/g, '{').replace(/}'|}/g, '}')
}
})
resources[key] = resource
})
i18n.mergeLocaleMessage(twoLetterIsoLanguageName as string, resources)
i18n.mergeLocaleMessage(twoLetterIsoLanguageName, resources)
}
@Action({ rawError: true })

1
vueJs/src/utils/request.ts

@ -96,6 +96,7 @@ service.interceptors.response.use(
return response
},
(error) => {
console.log(error.response)
if (error.response.status === 401) {
UserModule.RefreshSession().then(token => {
const config = error.response.config

317
vueJs/src/views/admin/components/FeatureManagement.vue

@ -0,0 +1,317 @@
<template>
<div class="app-container">
<el-form
ref="frmFeature"
:model="features"
label-width="100px"
>
<el-tabs v-model="selectTab">
<el-tab-pane
v-for="(feature, fi) in features.features"
:key="feature.name"
:label="feature.displayName"
:name="feature.name"
>
<el-form-item
v-for="(featureChildren, fci) in feature.children"
:key="featureChildren.name"
:label="featureChildren.displayName"
:prop="'features.' + fi + '.children.' + fci + '.value'"
:rules="featureChildren.valueType.validator | inputRuleFilter(localizer)"
>
<div
v-if="featureChildren.valueType.name === 'ToggleStringValueType'"
>
<el-switch
v-if="featureChildren.valueType.validator.name === 'BOOLEAN'"
v-model="featureChildren.value"
/>
<el-input
v-else-if="featureChildren.valueType.validator.name === 'NUMERIC'"
v-model.number="featureChildren.value"
type="number"
/>
<el-input
v-else-if="featureChildren.valueType.validator.name === 'STRING'"
v-model="featureChildren.value"
type="text"
/>
</div>
<div
v-else-if="featureChildren.valueType.name === 'SELECTION'"
>
<el-select
v-model="featureChildren.value"
>
<el-option
v-for="valueItem in featureChildren.valueType.itemSource.items"
:key="valueItem.value"
:label="valueItem.displayText"
:value="valueItem.value"
/>
</el-select>
</div>
</el-form-item>
</el-tab-pane>
</el-tabs>
<el-button
type="primary"
class="confirm"
@click="onSave"
>
{{ $t('AbpFeatureManagement.Submit') }}
</el-button>
<el-button
class="cancel"
@click="onClosed"
>
{{ $t('AbpFeatureManagement.Cancel') }}
</el-button>
</el-form>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
import FeatureManagementService, { ValueType, Feature, Features } from '@/api/feature-management'
/**
* 适用于动态表单的功能节点列表
*/
class FeatureItems {
features = new Array<FeatureItem>()
}
/**
* 适用于动态表单的功能节点
*/
class FeatureItem {
/** 功能名称 */
name!: string
/** 显示名称 */
displayName?: string
/** 当前值 */
value!: any
/** 说明 */
description?: string
/** 值类型 */
valueType?: ValueType
/** 深度 */
depth?: number
/** 子节点 */
children!: FeatureItem[]
/** 构造器 */
constructor(
name: string,
value: any,
displayName?: string,
description?: string,
valueType?: ValueType,
depth?: number
) {
this.name = name
this.depth = depth
this.valueType = valueType
this.displayName = displayName
this.description = description
this.children = new Array<FeatureItem>()
if (value !== null) {
this.value = value.toLowerCase() === 'true' ? true // boolean
: !isNaN(Number(value)) ? Number(value) // number
: value
}
}
/**
* 创建子节点
* @feature 子节点
*/
public appendChildren(feature: FeatureItem) {
this.children.push(feature)
}
/**
* 获取子节点
* @name 节点名称
*/
public getChildren(name: string) {
const childrenIndex = this.children.findIndex(feature => feature.name === name)
if (childrenIndex >= 0) {
return this.children[childrenIndex]
}
return undefined
}
}
@Component({
name: 'FeatureManagement',
filters: {
/**
* 动态处理功能表单验证
* @validator 后端传递的验证规则
* @localizer 本地化method
*/
inputRuleFilter(validator: any, localizer: any) {
const featureRules: {[key: string]: any}[] = new Array<{[key: string]: any}>()
if (validator.name === 'NUMERIC') {
const ruleRang: {[key: string]: any} = {}
ruleRang.pattern = RegExp('^(' + validator.minValue + '|[1-9]d?|' + validator.maxValue + ')$')
// ruleRang.pattern = /^(1|[1-9]\d?|10)$/
// ruleRang.min = validator.minValue
// ruleRang.max = validator.maxValue
ruleRang.trigger = 'blur'
ruleRang.message = localizer('AbpFeatureManagement.ThisFieldMustBeBetween{0}And{1}', { 0: validator.minValue, 1: validator.maxValue })
featureRules.push(ruleRang)
} else if (validator.name === 'STRING') {
if (validator.allowNull && validator.allowNull.toLowerCase() === 'true') {
const ruleRequired: {[key: string]: any} = {}
ruleRequired.required = true
ruleRequired.trigger = 'blur'
ruleRequired.messahe = localizer('AbpFeatureManagement.ThisFieldIsRequired')
featureRules.push(ruleRequired)
}
const ruleString: {[key: string]: any} = {}
ruleString.min = validator.minLength
ruleString.max = validator.maxLength
ruleString.trigger = 'blur'
ruleString.message = localizer('AbpFeatureManagement.ThisFieldMustBeBetween{0}And{1}', { 0: validator.minValue, 1: validator.maxValue })
featureRules.push(ruleString)
}
return featureRules
}
},
methods: {
/**
* 本地化method
*/
localizer(name: string, values?: any[]) {
return this.$t(name, values)
}
}
})
export default class extends Vue {
/**
* 功能提供者名称
*/
@Prop({ default: '' })
private providerName!: string
/**
* 功能提供者标识
*/
@Prop({ default: '' })
private providerKey!: string
/**
* 默认选择tab选项卡
* 如果不定义的话,动态组合的表单需要手动点击一次才会显示?
*/
private selectTab = ''
/**
* 用于拼接动态表单的功能数据,需要把abp返回的数据做一次调整
*/
private features = new FeatureItems()
@Watch('providerKey', { immediate: true })
onProviderKeyChanged() {
if (this.providerKey) {
this.handleGetFeatures()
}
}
/**
* 重置表单数据
*/
public resetFeature() {
this.features = new FeatureItems()
}
/**
* 获取功能列表
*/
private handleGetFeatures() {
FeatureManagementService.getFeatures(this.providerName, this.providerKey).then(res => {
this.features = new FeatureItems()
res.features.forEach(feature => {
const featureTrue = new FeatureItem(
feature.name,
feature.value,
feature.displayName,
feature.description,
feature.valueType,
feature.depth
)
if (feature.parentName) {
const children = this.features.features.find(f => f.name === feature.parentName)
if (children) {
children.appendChildren(featureTrue)
} else {
this.features.features.push(featureTrue)
}
} else {
this.features.features.push(featureTrue)
}
})
// ?
if (this.features.features.length > 0) {
this.selectTab = this.features.features[0].name
}
})
}
/**
* 保存变更
*/
private onSave() {
if (this.features.features.length > 0) {
const frmFeature = this.$refs.frmFeature as any
frmFeature.validate((valid: boolean) => {
if (valid) {
const updateFeatures = new Features()
this.features.features.forEach(feature => {
this.getChangedFeatures(feature, updateFeatures)
})
FeatureManagementService
.updateFeatures(this.providerName, this.providerKey, updateFeatures)
.then(() => {
this.$message.success(this.$t('global.successful').toString())
this.onClosed()
})
}
})
}
}
/**
* 递归获取abp的功能接口格式数据
*/
private getChangedFeatures(feature: FeatureItem, features: Features) {
const updateFeature = new Feature(feature.name, feature.value)
features.features.push(updateFeature)
feature.children.forEach(children => {
this.getChangedFeatures(children, features)
})
}
/**
* 关闭模态窗口
*/
private onClosed() {
this.$emit('closed')
}
}
</script>
<style lang="scss" scoped>
.confirm {
width: 120px;
position: absolute;
right: 180px;
}
.cancel {
width: 120px;
position: absolute;
right: 40px;
}
</style>

41
vueJs/src/views/admin/tenants/components/TenantFeatureEditForm.vue

@ -0,0 +1,41 @@
<template>
<el-dialog
:visible="showDialog"
title="管理功能"
width="800px"
:show-close="false"
@closed="onFormClosed"
>
<feature-management
ref="featureManagement"
provider-name="T"
:provider-key="tenantId"
@closed="onFormClosed"
/>
</el-dialog>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'
import FeatureManagement from '../../components/FeatureManagement.vue'
@Component({
name: 'TenantFeatureEditForm',
components: {
FeatureManagement
}
})
export default class extends Vue {
@Prop({ default: '' })
private tenantId!: string
@Prop({ default: false })
private showDialog!: boolean
private onFormClosed() {
this.$emit('closed')
const featureManagement = this.$refs.featureManagement as FeatureManagement
featureManagement.resetFeature()
}
}
</script>

24
vueJs/src/views/admin/tenants/index.vue

@ -122,6 +122,12 @@
>
{{ $t('tenant.connectionOptions') }}
</el-dropdown-item>
<el-dropdown-item
:command="{key: 'feature', row}"
:disabled="!checkPermission(['AbpTenantManagement.Tenants.ManageFeatures'])"
>
管理功能
</el-dropdown-item>
<el-dropdown-item
divided
:command="{key: 'delete', row}"
@ -175,6 +181,12 @@
@closed="handleTenantConnectionEditFormClosed"
/>
</el-dialog>
<tenant-feature-editForm
:show-dialog="showFeatureEditFormDialog"
:tenant-id="editTenantId"
@closed="onFeatureEditFormClosed"
/>
</div>
</template>
@ -184,6 +196,7 @@ import TenantService, { TenantDto, TenantGetByPaged } from '@/api/tenant'
import { dateFormat } from '@/utils/index'
import { checkPermission } from '@/utils/permission'
import Pagination from '@/components/Pagination/index.vue'
import TenantFeatureEditForm from './components/TenantFeatureEditForm.vue'
import TenantCreateOrEditForm from './components/TenantCreateOrEditForm.vue'
import TenantEditConnectionForm from './components/TenantEditConnectionForm.vue'
@ -191,6 +204,7 @@ import TenantEditConnectionForm from './components/TenantEditConnectionForm.vue'
name: 'RoleList',
components: {
Pagination,
TenantFeatureEditForm,
TenantCreateOrEditForm,
TenantEditConnectionForm
},
@ -213,6 +227,7 @@ export default class extends Vue {
private showEditTenantConnectionDialog: boolean
private showCreateOrEditTenantDialog: boolean
private showFeatureEditFormDialog = false
constructor() {
super()
@ -245,6 +260,10 @@ export default class extends Vue {
this.editTenantId = command.row.id
this.showEditTenantConnectionDialog = true
break
case 'feature' :
this.editTenantId = command.row.id
this.showFeatureEditFormDialog = true
break
case 'delete' :
this.handleDeleteTenant(command.row.id, command.row.name)
break
@ -291,6 +310,11 @@ export default class extends Vue {
this.tenantGetPagedFilter.sorting = column.prop
}
private onFeatureEditFormClosed() {
this.showFeatureEditFormDialog = false
this.editTenantId = ''
}
private l(name: string, values?: any[] | { [key: string]: any }) {
return this.$t(name, values).toString()
}

2
vueJs/src/views/file-management/index.vue

@ -382,6 +382,8 @@ export default class extends Vue {
//
callback(size)
}
}).catch(() => {
callback(size)
})
}

Loading…
Cancel
Save