Browse Source

Merge pull request #281 from colinin/4.3

Use a data dictionary instead of a **PlatformType**
pull/287/head
cKey 5 years ago
committed by GitHub
parent
commit
d9e9ab691f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3531
      aspnet-core/database/ApiGateway-Init.sql
  2. 50
      aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Datas/IDataAppService.cs
  3. 29
      aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Layouts/Dto/GetLayoutListInput.cs
  4. 25
      aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Layouts/Dto/LayoutCreateDto.cs
  5. 56
      aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Layouts/Dto/LayoutCreateOrUpdateDto.cs
  6. 34
      aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Layouts/Dto/LayoutDto.cs
  7. 18
      aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/GetMenuInput.cs
  8. 4
      aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/MenuDto.cs
  9. 43
      aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/MenuGetAllInput.cs
  10. 29
      aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/MenuGetByRoleInput.cs
  11. 33
      aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/MenuGetByUserInput.cs
  12. 39
      aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/MenuGetListInput.cs
  13. 389
      aspnet-core/modules/platform/LINGYUN.Platform.Application/LINGYUN/Platform/Datas/DataAppService.cs
  14. 245
      aspnet-core/modules/platform/LINGYUN.Platform.Application/LINGYUN/Platform/Layouts/LayoutAppService.cs
  15. 479
      aspnet-core/modules/platform/LINGYUN.Platform.Application/LINGYUN/Platform/Menus/MenuAppService.cs
  16. 113
      aspnet-core/modules/platform/LINGYUN.Platform.Domain.Shared/LINGYUN/Platform/Localization/Resources/en.json
  17. 113
      aspnet-core/modules/platform/LINGYUN.Platform.Domain.Shared/LINGYUN/Platform/Localization/Resources/zh-Hans.json
  18. 7
      aspnet-core/modules/platform/LINGYUN.Platform.Domain.Shared/LINGYUN/Platform/Routes/LayoutConsts.cs
  19. 248
      aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/Data.cs
  20. 118
      aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/DataDictionaryDataSeeder.cs
  21. 187
      aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/DataItem.cs
  22. 37
      aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/IDataDictionaryDataSeeder.cs
  23. 76
      aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Layouts/ILayoutRepository.cs
  24. 78
      aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Layouts/Layout.cs
  25. 226
      aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/IMenuRepository.cs
  26. 134
      aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/Menu.cs
  27. 482
      aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/MenuManager.cs
  28. 100
      aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Routes/IRouteDataSeeder.cs
  29. 300
      aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Routes/RouteDataSeeder.cs
  30. 507
      aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/EntityFrameworkCore/PlatformDbContextModelBuilderExtensions.cs
  31. 160
      aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/Layouts/EfCoreLayoutRepository.cs
  32. 504
      aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/Menus/EfCoreMenuRepository.cs
  33. 175
      aspnet-core/modules/platform/LINGYUN.Platform.HttpApi/LINGYUN/Platform/Datas/DataController.cs
  34. 256
      aspnet-core/modules/platform/LINGYUN.Platform.HttpApi/LINGYUN/Platform/Menus/MenuController.cs
  35. 1887
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/DataSeeder/ElementAdminDataSeedContributor.cs
  36. 291
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/DataSeeder/VbenAdminDataSeedContributor.cs
  37. 556
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/EventBus/Handlers/TenantSynchronizer.cs
  38. 148
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj
  39. 665
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/Migrations/20210621020117_Rename-Route-Field-PlantType-To-Framework.Designer.cs
  40. 81
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/Migrations/20210621020117_Rename-Route-Field-PlantType-To-Framework.cs
  41. 1302
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/Migrations/PlatformHttpApiHostMigrationsDbContextModelSnapshot.cs
  42. 237
      vueJs/src/api/data-dictionary.ts
  43. 186
      vueJs/src/api/layout.ts
  44. 245
      vueJs/src/api/menu.ts
  45. 283
      vueJs/src/store/modules/permission.ts
  46. 408
      vueJs/src/views/admin/data-dictionary/components/DataDictionaryTree.vue
  47. 358
      vueJs/src/views/admin/roles/components/ManageRoleMenuDialog.vue
  48. 716
      vueJs/src/views/admin/roles/index.vue
  49. 358
      vueJs/src/views/admin/users/components/ManageUserMenuDialog.vue
  50. 746
      vueJs/src/views/admin/users/index.vue
  51. 555
      vueJs/src/views/container/layouts/components/CreateOrUpdateLayoutDialog.vue
  52. 486
      vueJs/src/views/container/layouts/index.vue
  53. 583
      vueJs/src/views/container/menus/index.vue
  54. 240
      vueJs/vue.config.js

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

File diff suppressed because it is too large

50
aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Datas/IDataAppService.cs

@ -1,24 +1,26 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace LINGYUN.Platform.Datas
{
public interface IDataAppService :
ICrudAppService<
DataDto,
Guid,
GetDataListInput,
DataCreateDto,
DataUpdateDto>
{
Task<ListResultDto<DataDto>> GetAllAsync();
Task CreateItemAsync(Guid id, DataItemCreateDto input);
Task UpdateItemAsync(Guid id, string name, DataItemUpdateDto input);
Task DeleteItemAsync(Guid id, string name);
}
}
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace LINGYUN.Platform.Datas
{
public interface IDataAppService :
ICrudAppService<
DataDto,
Guid,
GetDataListInput,
DataCreateDto,
DataUpdateDto>
{
Task<DataDto> GetAsync(string name);
Task<ListResultDto<DataDto>> GetAllAsync();
Task CreateItemAsync(Guid id, DataItemCreateDto input);
Task UpdateItemAsync(Guid id, string name, DataItemUpdateDto input);
Task DeleteItemAsync(Guid id, string name);
}
}

29
aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Layouts/Dto/GetLayoutListInput.cs

@ -1,13 +1,16 @@
using Volo.Abp.Application.Dtos;
namespace LINGYUN.Platform.Layouts
{
public class GetLayoutListInput : PagedAndSortedResultRequestDto
{
public string Filter { get; set; }
public bool Reverse { get; set; }
public PlatformType? PlatformType { get; set; }
}
}
using LINGYUN.Platform.Routes;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Validation;
namespace LINGYUN.Platform.Layouts
{
public class GetLayoutListInput : PagedAndSortedResultRequestDto
{
public string Filter { get; set; }
public bool Reverse { get; set; }
[DynamicStringLength(typeof(LayoutConsts), nameof(LayoutConsts.MaxFrameworkLength))]
public string Framework { get; set; }
}
}

25
aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Layouts/Dto/LayoutCreateDto.cs

@ -1,9 +1,16 @@
using System;
namespace LINGYUN.Platform.Layouts
{
public class LayoutCreateDto : LayoutCreateOrUpdateDto
{
public Guid DataId { get; set; }
}
}
using LINGYUN.Platform.Routes;
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
namespace LINGYUN.Platform.Layouts
{
public class LayoutCreateDto : LayoutCreateOrUpdateDto
{
public Guid DataId { get; set; }
[Required]
[DynamicStringLength(typeof(LayoutConsts), nameof(LayoutConsts.MaxFrameworkLength))]
public string Framework { get; set; }
}
}

56
aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Layouts/Dto/LayoutCreateOrUpdateDto.cs

@ -1,29 +1,27 @@
using LINGYUN.Platform.Routes;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
namespace LINGYUN.Platform.Layouts
{
public class LayoutCreateOrUpdateDto
{
[Required]
[DynamicStringLength(typeof(RouteConsts), nameof(RouteConsts.MaxNameLength))]
public string Name { get; set; }
[Required]
[DynamicStringLength(typeof(RouteConsts), nameof(RouteConsts.MaxDisplayNameLength))]
public string DisplayName { get; set; }
[DynamicStringLength(typeof(RouteConsts), nameof(RouteConsts.MaxDescriptionLength))]
public string Description { get; set; }
[Required]
[DynamicStringLength(typeof(RouteConsts), nameof(RouteConsts.MaxPathLength))]
public string Path { get; set; }
[DynamicStringLength(typeof(RouteConsts), nameof(RouteConsts.MaxRedirectLength))]
public string Redirect { get; set; }
public PlatformType PlatformType { get; set; }
}
}
using LINGYUN.Platform.Routes;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
namespace LINGYUN.Platform.Layouts
{
public class LayoutCreateOrUpdateDto
{
[Required]
[DynamicStringLength(typeof(RouteConsts), nameof(RouteConsts.MaxNameLength))]
public string Name { get; set; }
[Required]
[DynamicStringLength(typeof(RouteConsts), nameof(RouteConsts.MaxDisplayNameLength))]
public string DisplayName { get; set; }
[DynamicStringLength(typeof(RouteConsts), nameof(RouteConsts.MaxDescriptionLength))]
public string Description { get; set; }
[Required]
[DynamicStringLength(typeof(RouteConsts), nameof(RouteConsts.MaxPathLength))]
public string Path { get; set; }
[DynamicStringLength(typeof(RouteConsts), nameof(RouteConsts.MaxRedirectLength))]
public string Redirect { get; set; }
}
}

34
aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Layouts/Dto/LayoutDto.cs

@ -1,17 +1,17 @@
using LINGYUN.Platform.Routes;
using System;
namespace LINGYUN.Platform.Layouts
{
public class LayoutDto : RouteDto
{
/// <summary>
/// 所属平台
/// </summary>
public PlatformType PlatformType { get; set; }
/// <summary>
/// 约定的Meta采用哪种数据字典,主要是约束路由必须字段的一致性
/// </summary>
public Guid DataId { get; set; }
}
}
using LINGYUN.Platform.Routes;
using System;
namespace LINGYUN.Platform.Layouts
{
public class LayoutDto : RouteDto
{
/// <summary>
/// 框架
/// </summary>
public string Framework { get; set; }
/// <summary>
/// 约定的Meta采用哪种数据字典,主要是约束路由必须字段的一致性
/// </summary>
public Guid DataId { get; set; }
}
}

18
aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/GetMenuInput.cs

@ -1,7 +1,11 @@
namespace LINGYUN.Platform.Menus
{
public class GetMenuInput
{
public PlatformType PlatformType { get; set; }
}
}
using LINGYUN.Platform.Routes;
using Volo.Abp.Validation;
namespace LINGYUN.Platform.Menus
{
public class GetMenuInput
{
[DynamicStringLength(typeof(LayoutConsts), nameof(LayoutConsts.MaxFrameworkLength))]
public string Framework { get; set; }
}
}

4
aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/MenuDto.cs

@ -15,9 +15,9 @@ namespace LINGYUN.Platform.Menus
/// </summary>
public string Component { get; set; }
/// <summary>
/// 所属平台
/// 框架
/// </summary>
public PlatformType PlatformType { get; set; }
public string Framework { get; set; }
/// <summary>
/// 父节点
/// </summary>

43
aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/MenuGetAllInput.cs

@ -1,20 +1,23 @@
using System;
using Volo.Abp.Application.Dtos;
namespace LINGYUN.Platform.Menus
{
public class MenuGetAllInput : ISortedResultRequest
{
public PlatformType? PlatformType { get; set; }
public string Filter { get; set; }
public bool Reverse { get; set; }
public Guid? ParentId { get; set; }
public string Sorting { get; set; }
public Guid? LayoutId { get; set; }
}
}
using LINGYUN.Platform.Routes;
using System;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Validation;
namespace LINGYUN.Platform.Menus
{
public class MenuGetAllInput : ISortedResultRequest
{
[DynamicStringLength(typeof(LayoutConsts), nameof(LayoutConsts.MaxFrameworkLength))]
public string Framework { get; set; }
public string Filter { get; set; }
public bool Reverse { get; set; }
public Guid? ParentId { get; set; }
public string Sorting { get; set; }
public Guid? LayoutId { get; set; }
}
}

29
aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/MenuGetByRoleInput.cs

@ -1,13 +1,16 @@
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Platform.Menus
{
public class MenuGetByRoleInput
{
[Required]
[StringLength(80)]
public string Role { get; set; }
public PlatformType PlatformType { get; set; }
}
}
using LINGYUN.Platform.Routes;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
namespace LINGYUN.Platform.Menus
{
public class MenuGetByRoleInput
{
[Required]
[StringLength(80)]
public string Role { get; set; }
[DynamicStringLength(typeof(LayoutConsts), nameof(LayoutConsts.MaxFrameworkLength))]
public string Framework { get; set; }
}
}

33
aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/MenuGetByUserInput.cs

@ -1,15 +1,18 @@
using System;
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Platform.Menus
{
public class MenuGetByUserInput
{
[Required]
public Guid UserId { get; set; }
public string[] Roles { get; set; } = new string[0];
public PlatformType PlatformType { get; set; }
}
}
using LINGYUN.Platform.Routes;
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
namespace LINGYUN.Platform.Menus
{
public class MenuGetByUserInput
{
[Required]
public Guid UserId { get; set; }
public string[] Roles { get; set; } = new string[0];
[DynamicStringLength(typeof(LayoutConsts), nameof(LayoutConsts.MaxFrameworkLength))]
public string Framework { get; set; }
}
}

39
aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/MenuGetListInput.cs

@ -1,18 +1,21 @@
using System;
using Volo.Abp.Application.Dtos;
namespace LINGYUN.Platform.Menus
{
public class MenuGetListInput : PagedAndSortedResultRequestDto
{
public PlatformType? PlatformType { get; set; }
public string Filter { get; set; }
public bool Reverse { get; set; }
public Guid? ParentId { get; set; }
public Guid? LayoutId { get; set; }
}
}
using LINGYUN.Platform.Routes;
using System;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Validation;
namespace LINGYUN.Platform.Menus
{
public class MenuGetListInput : PagedAndSortedResultRequestDto
{
[DynamicStringLength(typeof(LayoutConsts), nameof(LayoutConsts.MaxFrameworkLength))]
public string Framework { get; set; }
public string Filter { get; set; }
public bool Reverse { get; set; }
public Guid? ParentId { get; set; }
public Guid? LayoutId { get; set; }
}
}

389
aspnet-core/modules/platform/LINGYUN.Platform.Application/LINGYUN/Platform/Datas/DataAppService.cs

@ -1,191 +1,198 @@
using LINGYUN.Platform.Permissions;
using LINGYUN.Platform.Utils;
using Microsoft.AspNetCore.Authorization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
namespace LINGYUN.Platform.Datas
{
[Authorize(PlatformPermissions.DataDictionary.Default)]
public class DataAppService : PlatformApplicationServiceBase, IDataAppService
{
protected IDataRepository DataRepository { get; }
public DataAppService(
IDataRepository dataRepository)
{
DataRepository = dataRepository;
}
[Authorize(PlatformPermissions.DataDictionary.Create)]
public virtual async Task<DataDto> CreateAsync(DataCreateDto input)
{
var data = await DataRepository.FindByNameAsync(input.Name);
if (data != null)
{
throw new UserFriendlyException("指定名称的数据字典已经存在!");
}
string code = string.Empty;
var children = await DataRepository.GetChildrenAsync(input.ParentId);
if (children.Any())
{
var lastChildren = children.OrderBy(x => x.Code).FirstOrDefault();
code = CodeNumberGenerator.CalculateNextCode(lastChildren.Code);
}
else
{
var parentData = input.ParentId != null
? await DataRepository.GetAsync(input.ParentId.Value)
: null;
code = CodeNumberGenerator.AppendCode(parentData?.Code, CodeNumberGenerator.CreateCode(1));
}
data = new Data(
GuidGenerator.Create(),
input.Name,
code,
input.DisplayName,
input.Description,
input.ParentId,
CurrentTenant.Id
);
data = await DataRepository.InsertAsync(data);
await CurrentUnitOfWork.SaveChangesAsync();
return ObjectMapper.Map<Data, DataDto>(data);
}
[Authorize(PlatformPermissions.DataDictionary.Delete)]
public virtual async Task DeleteAsync(Guid id)
{
var data = await DataRepository.GetAsync(id);
var children = await DataRepository.GetChildrenAsync(data.Id);
if (children.Any())
{
throw new UserFriendlyException("当前数据字典存在子节点,无法删除!");
}
await DataRepository.DeleteAsync(data);
}
public virtual async Task<DataDto> GetAsync(Guid id)
{
var data = await DataRepository.GetAsync(id);
return ObjectMapper.Map<Data, DataDto>(data);
}
public virtual async Task<ListResultDto<DataDto>> GetAllAsync()
{
var datas = await DataRepository.GetListAsync(includeDetails: false);
return new ListResultDto<DataDto>(
ObjectMapper.Map<List<Data>, List<DataDto>>(datas));
}
public virtual async Task<PagedResultDto<DataDto>> GetListAsync(GetDataListInput input)
{
var count = await DataRepository.GetCountAsync(input.Filter);
var datas = await DataRepository.GetPagedListAsync(
input.Filter, input.Sorting,
false, input.SkipCount, input.MaxResultCount);
return new PagedResultDto<DataDto>(count,
ObjectMapper.Map<List<Data>, List<DataDto>>(datas));
}
[Authorize(PlatformPermissions.DataDictionary.Update)]
public virtual async Task<DataDto> UpdateAsync(Guid id, DataUpdateDto input)
{
var data = await DataRepository.GetAsync(id);
if (!string.Equals(data.Name, input.Name, StringComparison.InvariantCultureIgnoreCase))
{
data.Name = input.Name;
}
if (!string.Equals(data.DisplayName, input.DisplayName, StringComparison.InvariantCultureIgnoreCase))
{
data.DisplayName = input.DisplayName;
}
if (!string.Equals(data.Description, input.Description, StringComparison.InvariantCultureIgnoreCase))
{
data.Description = input.Description;
}
data = await DataRepository.UpdateAsync(data);
await CurrentUnitOfWork.SaveChangesAsync();
return ObjectMapper.Map<Data, DataDto>(data);
}
[Authorize(PlatformPermissions.DataDictionary.ManageItems)]
public virtual async Task UpdateItemAsync(Guid id, string name, DataItemUpdateDto input)
{
var data = await DataRepository.GetAsync(id);
var dataItem = data.FindItem(name);
if (dataItem == null)
{
throw new UserFriendlyException($"不存在名为 {name} 的数据字典项!");
}
if (!string.Equals(dataItem.DefaultValue, input.DefaultValue, StringComparison.InvariantCultureIgnoreCase))
{
dataItem.DefaultValue = input.DefaultValue;
}
if (!string.Equals(dataItem.DisplayName, input.DisplayName, StringComparison.InvariantCultureIgnoreCase))
{
dataItem.DisplayName = input.DisplayName;
}
if (!string.Equals(dataItem.Description, input.Description, StringComparison.InvariantCultureIgnoreCase))
{
dataItem.Description = input.Description;
}
dataItem.AllowBeNull = input.AllowBeNull;
data = await DataRepository.UpdateAsync(data);
await CurrentUnitOfWork.SaveChangesAsync();
}
[Authorize(PlatformPermissions.DataDictionary.ManageItems)]
public virtual async Task CreateItemAsync(Guid id, DataItemCreateDto input)
{
var data = await DataRepository.GetAsync(id);
var dataItem = data.FindItem(input.Name);
if (dataItem != null)
{
throw new UserFriendlyException($"已经存在名为 {input.Name} 的数据字典项!");
}
data.AddItem(
GuidGenerator,
input.Name,
input.DisplayName,
input.DefaultValue,
input.ValueType,
input.Description,
input.AllowBeNull);
await DataRepository.UpdateAsync(data);
await CurrentUnitOfWork.SaveChangesAsync();
}
[Authorize(PlatformPermissions.DataDictionary.ManageItems)]
public virtual async Task DeleteItemAsync(Guid id, string name)
{
var data = await DataRepository.GetAsync(id);
data.RemoveItem(name);
await DataRepository.UpdateAsync(data);
await CurrentUnitOfWork.SaveChangesAsync();
}
}
}
using LINGYUN.Platform.Permissions;
using LINGYUN.Platform.Utils;
using Microsoft.AspNetCore.Authorization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
namespace LINGYUN.Platform.Datas
{
[Authorize(PlatformPermissions.DataDictionary.Default)]
public class DataAppService : PlatformApplicationServiceBase, IDataAppService
{
protected IDataRepository DataRepository { get; }
public DataAppService(
IDataRepository dataRepository)
{
DataRepository = dataRepository;
}
[Authorize(PlatformPermissions.DataDictionary.Create)]
public virtual async Task<DataDto> CreateAsync(DataCreateDto input)
{
var data = await DataRepository.FindByNameAsync(input.Name);
if (data != null)
{
throw new UserFriendlyException(L["DuplicateData", input.Name]);
}
string code = string.Empty;
var children = await DataRepository.GetChildrenAsync(input.ParentId);
if (children.Any())
{
var lastChildren = children.OrderBy(x => x.Code).FirstOrDefault();
code = CodeNumberGenerator.CalculateNextCode(lastChildren.Code);
}
else
{
var parentData = input.ParentId != null
? await DataRepository.GetAsync(input.ParentId.Value)
: null;
code = CodeNumberGenerator.AppendCode(parentData?.Code, CodeNumberGenerator.CreateCode(1));
}
data = new Data(
GuidGenerator.Create(),
input.Name,
code,
input.DisplayName,
input.Description,
input.ParentId,
CurrentTenant.Id
);
data = await DataRepository.InsertAsync(data);
await CurrentUnitOfWork.SaveChangesAsync();
return ObjectMapper.Map<Data, DataDto>(data);
}
[Authorize(PlatformPermissions.DataDictionary.Delete)]
public virtual async Task DeleteAsync(Guid id)
{
var data = await DataRepository.GetAsync(id);
var children = await DataRepository.GetChildrenAsync(data.Id);
if (children.Any())
{
throw new UserFriendlyException(L["UnableRemoveHasChildNode"]);
}
await DataRepository.DeleteAsync(data);
}
public virtual async Task<DataDto> GetAsync(string name)
{
var data = await DataRepository.FindByNameAsync(name);
return ObjectMapper.Map<Data, DataDto>(data);
}
public virtual async Task<DataDto> GetAsync(Guid id)
{
var data = await DataRepository.GetAsync(id);
return ObjectMapper.Map<Data, DataDto>(data);
}
public virtual async Task<ListResultDto<DataDto>> GetAllAsync()
{
var datas = await DataRepository.GetListAsync(includeDetails: false);
return new ListResultDto<DataDto>(
ObjectMapper.Map<List<Data>, List<DataDto>>(datas));
}
public virtual async Task<PagedResultDto<DataDto>> GetListAsync(GetDataListInput input)
{
var count = await DataRepository.GetCountAsync(input.Filter);
var datas = await DataRepository.GetPagedListAsync(
input.Filter, input.Sorting,
false, input.SkipCount, input.MaxResultCount);
return new PagedResultDto<DataDto>(count,
ObjectMapper.Map<List<Data>, List<DataDto>>(datas));
}
[Authorize(PlatformPermissions.DataDictionary.Update)]
public virtual async Task<DataDto> UpdateAsync(Guid id, DataUpdateDto input)
{
var data = await DataRepository.GetAsync(id);
if (!string.Equals(data.Name, input.Name, StringComparison.InvariantCultureIgnoreCase))
{
data.Name = input.Name;
}
if (!string.Equals(data.DisplayName, input.DisplayName, StringComparison.InvariantCultureIgnoreCase))
{
data.DisplayName = input.DisplayName;
}
if (!string.Equals(data.Description, input.Description, StringComparison.InvariantCultureIgnoreCase))
{
data.Description = input.Description;
}
data = await DataRepository.UpdateAsync(data);
await CurrentUnitOfWork.SaveChangesAsync();
return ObjectMapper.Map<Data, DataDto>(data);
}
[Authorize(PlatformPermissions.DataDictionary.ManageItems)]
public virtual async Task UpdateItemAsync(Guid id, string name, DataItemUpdateDto input)
{
var data = await DataRepository.GetAsync(id);
var dataItem = data.FindItem(name);
if (dataItem == null)
{
throw new UserFriendlyException(L["DataItemNotFound", name]);
}
if (!string.Equals(dataItem.DefaultValue, input.DefaultValue, StringComparison.InvariantCultureIgnoreCase))
{
dataItem.DefaultValue = input.DefaultValue;
}
if (!string.Equals(dataItem.DisplayName, input.DisplayName, StringComparison.InvariantCultureIgnoreCase))
{
dataItem.DisplayName = input.DisplayName;
}
if (!string.Equals(dataItem.Description, input.Description, StringComparison.InvariantCultureIgnoreCase))
{
dataItem.Description = input.Description;
}
dataItem.AllowBeNull = input.AllowBeNull;
await DataRepository.UpdateAsync(data);
await CurrentUnitOfWork.SaveChangesAsync();
}
[Authorize(PlatformPermissions.DataDictionary.ManageItems)]
public virtual async Task CreateItemAsync(Guid id, DataItemCreateDto input)
{
var data = await DataRepository.GetAsync(id);
var dataItem = data.FindItem(input.Name);
if (dataItem != null)
{
throw new UserFriendlyException(L["DuplicateDataItem", input.Name]);
}
data.AddItem(
GuidGenerator,
input.Name,
input.DisplayName,
input.DefaultValue,
input.ValueType,
input.Description,
input.AllowBeNull);
await DataRepository.UpdateAsync(data);
await CurrentUnitOfWork.SaveChangesAsync();
}
[Authorize(PlatformPermissions.DataDictionary.ManageItems)]
public virtual async Task DeleteItemAsync(Guid id, string name)
{
var data = await DataRepository.GetAsync(id);
data.RemoveItem(name);
await DataRepository.UpdateAsync(data);
await CurrentUnitOfWork.SaveChangesAsync();
}
}
}

245
aspnet-core/modules/platform/LINGYUN.Platform.Application/LINGYUN/Platform/Layouts/LayoutAppService.cs

@ -1,124 +1,121 @@
using LINGYUN.Platform.Datas;
using LINGYUN.Platform.Permissions;
using LINGYUN.Platform.Routes;
using LINGYUN.Platform.Utils;
using Microsoft.AspNetCore.Authorization;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
namespace LINGYUN.Platform.Layouts
{
[Authorize(PlatformPermissions.Layout.Default)]
public class LayoutAppService : PlatformApplicationServiceBase, ILayoutAppService
{
protected ILayoutRepository LayoutRepository { get; }
public LayoutAppService(
ILayoutRepository layoutRepository)
{
LayoutRepository = layoutRepository;
}
[Authorize(PlatformPermissions.Layout.Create)]
public virtual async Task<LayoutDto> CreateAsync(LayoutCreateDto input)
{
var layout = await LayoutRepository.FindByNameAsync(input.Name);
if (layout != null)
{
throw new UserFriendlyException($"已经存在名为 {input.Name} 的布局!");
}
layout = new Layout(
GuidGenerator.Create(),
input.Path,
input.Name,
input.DisplayName,
input.DataId,
input.PlatformType,
input.Redirect,
input.Description,
CurrentTenant.Id);
layout = await LayoutRepository.InsertAsync(layout);
await CurrentUnitOfWork.SaveChangesAsync();
return ObjectMapper.Map<Layout, LayoutDto>(layout);
}
[Authorize(PlatformPermissions.Layout.Delete)]
public virtual async Task DeleteAsync(Guid id)
{
var layout = await LayoutRepository.GetAsync(id);
//if (await LayoutRepository.AnyMenuAsync(layout.Id))
//{
// throw new UserFriendlyException($"不能删除存在菜单的布局!");
//}
await LayoutRepository.DeleteAsync(layout);
await CurrentUnitOfWork.SaveChangesAsync();
}
public virtual async Task<LayoutDto> GetAsync(Guid id)
{
var layout = await LayoutRepository.GetAsync(id);
return ObjectMapper.Map<Layout, LayoutDto>(layout);
}
public virtual async Task<ListResultDto<LayoutDto>> GetAllListAsync()
{
var layouts = await LayoutRepository.GetListAsync();
return new ListResultDto<LayoutDto>(
ObjectMapper.Map<List<Layout>, List<LayoutDto>>(layouts));
}
public virtual async Task<PagedResultDto<LayoutDto>> GetListAsync(GetLayoutListInput input)
{
var count = await LayoutRepository.GetCountAsync(input.PlatformType, input.Filter);
var layouts = await LayoutRepository.GetPagedListAsync(
input.PlatformType, input.Filter,
input.Sorting, input.Reverse, false,
input.SkipCount, input.MaxResultCount);
return new PagedResultDto<LayoutDto>(count,
ObjectMapper.Map<List<Layout>, List<LayoutDto>>(layouts));
}
[Authorize(PlatformPermissions.Layout.Update)]
public virtual async Task<LayoutDto> UpdateAsync(Guid id, LayoutUpdateDto input)
{
var layout = await LayoutRepository.GetAsync(id);
if (!string.Equals(layout.Name, input.Name, StringComparison.InvariantCultureIgnoreCase))
{
layout.Name = input.Name;
}
if (!string.Equals(layout.DisplayName, input.DisplayName, StringComparison.InvariantCultureIgnoreCase))
{
layout.DisplayName = input.DisplayName;
}
if (!string.Equals(layout.Description, input.Description, StringComparison.InvariantCultureIgnoreCase))
{
layout.Description = input.Description;
}
if (!string.Equals(layout.Path, input.Path, StringComparison.InvariantCultureIgnoreCase))
{
layout.Path = input.Path;
}
if (!string.Equals(layout.Redirect, input.Redirect, StringComparison.InvariantCultureIgnoreCase))
{
layout.Redirect = input.Redirect;
}
layout = await LayoutRepository.UpdateAsync(layout);
await CurrentUnitOfWork.SaveChangesAsync();
return ObjectMapper.Map<Layout, LayoutDto>(layout);
}
}
}
using LINGYUN.Platform.Permissions;
using Microsoft.AspNetCore.Authorization;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
namespace LINGYUN.Platform.Layouts
{
[Authorize(PlatformPermissions.Layout.Default)]
public class LayoutAppService : PlatformApplicationServiceBase, ILayoutAppService
{
protected ILayoutRepository LayoutRepository { get; }
public LayoutAppService(
ILayoutRepository layoutRepository)
{
LayoutRepository = layoutRepository;
}
[Authorize(PlatformPermissions.Layout.Create)]
public virtual async Task<LayoutDto> CreateAsync(LayoutCreateDto input)
{
var layout = await LayoutRepository.FindByNameAsync(input.Name);
if (layout != null)
{
throw new UserFriendlyException(L["DuplicateLayout", input.Name]);
}
layout = new Layout(
GuidGenerator.Create(),
input.Path,
input.Name,
input.DisplayName,
input.DataId,
input.Framework,
input.Redirect,
input.Description,
CurrentTenant.Id);
layout = await LayoutRepository.InsertAsync(layout);
await CurrentUnitOfWork.SaveChangesAsync();
return ObjectMapper.Map<Layout, LayoutDto>(layout);
}
[Authorize(PlatformPermissions.Layout.Delete)]
public virtual async Task DeleteAsync(Guid id)
{
var layout = await LayoutRepository.GetAsync(id);
//if (await LayoutRepository.AnyMenuAsync(layout.Id))
//{
// throw new UserFriendlyException($"不能删除存在菜单的布局!");
//}
await LayoutRepository.DeleteAsync(layout);
await CurrentUnitOfWork.SaveChangesAsync();
}
public virtual async Task<LayoutDto> GetAsync(Guid id)
{
var layout = await LayoutRepository.GetAsync(id);
return ObjectMapper.Map<Layout, LayoutDto>(layout);
}
public virtual async Task<ListResultDto<LayoutDto>> GetAllListAsync()
{
var layouts = await LayoutRepository.GetListAsync();
return new ListResultDto<LayoutDto>(
ObjectMapper.Map<List<Layout>, List<LayoutDto>>(layouts));
}
public virtual async Task<PagedResultDto<LayoutDto>> GetListAsync(GetLayoutListInput input)
{
var count = await LayoutRepository.GetCountAsync(input.Framework, input.Filter);
var layouts = await LayoutRepository.GetPagedListAsync(
input.Framework, input.Filter,
input.Sorting, input.Reverse, false,
input.SkipCount, input.MaxResultCount);
return new PagedResultDto<LayoutDto>(count,
ObjectMapper.Map<List<Layout>, List<LayoutDto>>(layouts));
}
[Authorize(PlatformPermissions.Layout.Update)]
public virtual async Task<LayoutDto> UpdateAsync(Guid id, LayoutUpdateDto input)
{
var layout = await LayoutRepository.GetAsync(id);
if (!string.Equals(layout.Name, input.Name, StringComparison.InvariantCultureIgnoreCase))
{
layout.Name = input.Name;
}
if (!string.Equals(layout.DisplayName, input.DisplayName, StringComparison.InvariantCultureIgnoreCase))
{
layout.DisplayName = input.DisplayName;
}
if (!string.Equals(layout.Description, input.Description, StringComparison.InvariantCultureIgnoreCase))
{
layout.Description = input.Description;
}
if (!string.Equals(layout.Path, input.Path, StringComparison.InvariantCultureIgnoreCase))
{
layout.Path = input.Path;
}
if (!string.Equals(layout.Redirect, input.Redirect, StringComparison.InvariantCultureIgnoreCase))
{
layout.Redirect = input.Redirect;
}
layout = await LayoutRepository.UpdateAsync(layout);
await CurrentUnitOfWork.SaveChangesAsync();
return ObjectMapper.Map<Layout, LayoutDto>(layout);
}
}
}

479
aspnet-core/modules/platform/LINGYUN.Platform.Application/LINGYUN/Platform/Menus/MenuAppService.cs

@ -1,240 +1,239 @@
using LINGYUN.Platform.Datas;
using LINGYUN.Platform.Layouts;
using LINGYUN.Platform.Permissions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Data;
using Volo.Abp.Users;
namespace LINGYUN.Platform.Menus
{
[Authorize]
public class MenuAppService : PlatformApplicationServiceBase, IMenuAppService
{
protected DataItemMappingOptions DataItemMapping { get; }
protected MenuManager MenuManager { get; }
protected IMenuRepository MenuRepository { get; }
protected IDataRepository DataRepository { get; }
protected ILayoutRepository LayoutRepository { get; }
public MenuAppService(
MenuManager menuManager,
IMenuRepository menuRepository,
IDataRepository dataRepository,
ILayoutRepository layoutRepository,
IOptions<DataItemMappingOptions> options)
{
MenuManager = menuManager;
MenuRepository = menuRepository;
DataRepository = dataRepository;
LayoutRepository = layoutRepository;
DataItemMapping = options.Value;
}
public virtual async Task<ListResultDto<MenuDto>> GetCurrentUserMenuListAsync(GetMenuInput input)
{
var myMenus = await MenuRepository.GetUserMenusAsync(
CurrentUser.GetId(),
CurrentUser.Roles,
input.PlatformType);
return new ListResultDto<MenuDto>(
ObjectMapper.Map<List<Menu>, List<MenuDto>>(myMenus));
}
[Authorize(PlatformPermissions.Menu.Default)]
public virtual async Task<MenuDto> GetAsync(Guid id)
{
var menu = await MenuRepository.GetAsync(id);
return ObjectMapper.Map<Menu, MenuDto>(menu);
}
[Authorize(PlatformPermissions.Menu.Default)]
public virtual async Task<ListResultDto<MenuDto>> GetAllAsync(MenuGetAllInput input)
{
var menus = await MenuRepository.GetAllAsync(
input.Filter, input.Sorting, input.Reverse,
input.PlatformType, input.ParentId, input.LayoutId);
return new ListResultDto<MenuDto>(
ObjectMapper.Map<List<Menu>, List<MenuDto>>(menus));
}
[Authorize(PlatformPermissions.Menu.Default)]
public virtual async Task<PagedResultDto<MenuDto>> GetListAsync(MenuGetListInput input)
{
var count = await MenuRepository.GetCountAsync(input.Filter, input.PlatformType, input.ParentId, input.LayoutId);
var menus = await MenuRepository.GetListAsync(
input.Filter, input.Sorting, input.Reverse,
input.PlatformType, input.ParentId, input.LayoutId,
input.SkipCount, input.MaxResultCount);
return new PagedResultDto<MenuDto>(count,
ObjectMapper.Map<List<Menu>, List<MenuDto>>(menus));
}
[Authorize(PlatformPermissions.Menu.Create)]
public virtual async Task<MenuDto> CreateAsync(MenuCreateDto input)
{
var layout = await LayoutRepository.GetAsync(input.LayoutId);
var data = await DataRepository.GetAsync(layout.DataId);
var menu = await MenuManager.CreateAsync(
GuidGenerator.Create(),
layout.Id,
input.Path,
input.Name,
input.Component,
input.DisplayName,
input.Redirect,
input.Description,
layout.PlatformType,
input.ParentId,
CurrentTenant.Id,
input.IsPublic);
// 利用布局约定的数据字典来校验必须的路由元数据,元数据的加入是为了适配多端路由
foreach (var dataItem in data.Items)
{
if (!input.Meta.TryGetValue(dataItem.Name, out object meta))
{
if (!dataItem.AllowBeNull)
{
throw new BusinessException(PlatformErrorCodes.MenuMissingMetadata)
.WithData("Name", dataItem.DisplayName)
.WithData("DataName", data.DisplayName);
}
// 是否需要设定默认值
menu.SetProperty(dataItem.Name, dataItem.DefaultValue);
}
else
{
// 需要检查参数是否有效
menu.SetProperty(dataItem.Name, DataItemMapping.MapToString(dataItem.ValueType, meta));
}
}
await CurrentUnitOfWork.SaveChangesAsync();
return ObjectMapper.Map<Menu, MenuDto>(menu);
}
[Authorize(PlatformPermissions.Menu.Update)]
public virtual async Task<MenuDto> UpdateAsync(Guid id, MenuUpdateDto input)
{
var menu = await MenuRepository.GetAsync(id);
// 利用布局约定的数据字典来校验必须的路由元数据,元数据的加入是为了适配多端路由
var layout = await LayoutRepository.GetAsync(menu.LayoutId);
var data = await DataRepository.GetAsync(layout.DataId);
foreach (var dataItem in data.Items)
{
if (!input.Meta.TryGetValue(dataItem.Name, out object meta))
{
if (!dataItem.AllowBeNull)
{
throw new BusinessException(PlatformErrorCodes.MenuMissingMetadata)
.WithData("Name", dataItem.DisplayName)
.WithData("DataName", data.DisplayName);
}
// 是否需要设定默认值?
menu.SetProperty(dataItem.Name, dataItem.DefaultValue);
}
else
{
// 与现有的数据做对比
var menuMeta = menu.GetProperty(dataItem.Name);
if (menuMeta != null && menuMeta.Equals(meta))
{
continue;
}
// 需要检查参数是否有效
menu.SetProperty(dataItem.Name, DataItemMapping.MapToString(dataItem.ValueType, meta));
}
}
if (!string.Equals(menu.Name, input.Name, StringComparison.InvariantCultureIgnoreCase))
{
menu.Name = input.Name;
}
if (!string.Equals(menu.DisplayName, input.DisplayName, StringComparison.InvariantCultureIgnoreCase))
{
menu.DisplayName = input.DisplayName;
}
if (!string.Equals(menu.Description, input.Description, StringComparison.InvariantCultureIgnoreCase))
{
menu.Description = input.Description;
}
if (!string.Equals(menu.Path, input.Path, StringComparison.InvariantCultureIgnoreCase))
{
menu.Path = input.Path;
}
if (!string.Equals(menu.Redirect, input.Redirect, StringComparison.InvariantCultureIgnoreCase))
{
menu.Redirect = input.Redirect;
}
if (!string.Equals(menu.Component, input.Component, StringComparison.InvariantCultureIgnoreCase))
{
menu.Component = input.Component;
}
menu.IsPublic = input.IsPublic;
await MenuManager.UpdateAsync(menu);
await CurrentUnitOfWork.SaveChangesAsync();
return ObjectMapper.Map<Menu, MenuDto>(menu);
}
[Authorize(PlatformPermissions.Menu.Delete)]
public virtual async Task DeleteAsync(Guid id)
{
var childrens = await MenuRepository.GetChildrenAsync(id);
if (childrens.Any())
{
throw new BusinessException(PlatformErrorCodes.DeleteMenuHaveChildren);
}
var menu = await MenuRepository.GetAsync(id);
await MenuRepository.DeleteAsync(menu);
}
[Authorize(PlatformPermissions.Menu.ManageUsers)]
public virtual async Task<ListResultDto<MenuDto>> GetUserMenuListAsync(MenuGetByUserInput input)
{
var menus = await MenuRepository.GetUserMenusAsync(input.UserId, input.Roles, input.PlatformType);
return new ListResultDto<MenuDto>(
ObjectMapper.Map<List<Menu>, List<MenuDto>>(menus));
}
[Authorize(PlatformPermissions.Menu.ManageUsers)]
public virtual async Task SetUserMenusAsync(UserMenuInput input)
{
await MenuManager.SetUserMenusAsync(input.UserId, input.MenuIds);
}
[Authorize(PlatformPermissions.Menu.ManageRoles)]
public virtual async Task SetRoleMenusAsync(RoleMenuInput input)
{
await MenuManager.SetRoleMenusAsync(input.RoleName, input.MenuIds);
}
[Authorize(PlatformPermissions.Menu.ManageRoles)]
public virtual async Task<ListResultDto<MenuDto>> GetRoleMenuListAsync(MenuGetByRoleInput input)
{
var menus = await MenuRepository.GetRoleMenusAsync(new string[] { input.Role }, input.PlatformType);
return new ListResultDto<MenuDto>(
ObjectMapper.Map<List<Menu>, List<MenuDto>>(menus));
}
}
}
using LINGYUN.Platform.Datas;
using LINGYUN.Platform.Layouts;
using LINGYUN.Platform.Permissions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Data;
using Volo.Abp.Users;
namespace LINGYUN.Platform.Menus
{
[Authorize]
public class MenuAppService : PlatformApplicationServiceBase, IMenuAppService
{
protected DataItemMappingOptions DataItemMapping { get; }
protected MenuManager MenuManager { get; }
protected IMenuRepository MenuRepository { get; }
protected IDataRepository DataRepository { get; }
protected ILayoutRepository LayoutRepository { get; }
public MenuAppService(
MenuManager menuManager,
IMenuRepository menuRepository,
IDataRepository dataRepository,
ILayoutRepository layoutRepository,
IOptions<DataItemMappingOptions> options)
{
MenuManager = menuManager;
MenuRepository = menuRepository;
DataRepository = dataRepository;
LayoutRepository = layoutRepository;
DataItemMapping = options.Value;
}
public virtual async Task<ListResultDto<MenuDto>> GetCurrentUserMenuListAsync(GetMenuInput input)
{
var myMenus = await MenuRepository.GetUserMenusAsync(
CurrentUser.GetId(),
CurrentUser.Roles,
input.Framework);
return new ListResultDto<MenuDto>(
ObjectMapper.Map<List<Menu>, List<MenuDto>>(myMenus));
}
[Authorize(PlatformPermissions.Menu.Default)]
public virtual async Task<MenuDto> GetAsync(Guid id)
{
var menu = await MenuRepository.GetAsync(id);
return ObjectMapper.Map<Menu, MenuDto>(menu);
}
[Authorize(PlatformPermissions.Menu.Default)]
public virtual async Task<ListResultDto<MenuDto>> GetAllAsync(MenuGetAllInput input)
{
var menus = await MenuRepository.GetAllAsync(
input.Filter, input.Sorting, input.Reverse,
input.Framework, input.ParentId, input.LayoutId);
return new ListResultDto<MenuDto>(
ObjectMapper.Map<List<Menu>, List<MenuDto>>(menus));
}
[Authorize(PlatformPermissions.Menu.Default)]
public virtual async Task<PagedResultDto<MenuDto>> GetListAsync(MenuGetListInput input)
{
var count = await MenuRepository.GetCountAsync(input.Filter, input.Framework, input.ParentId, input.LayoutId);
var menus = await MenuRepository.GetListAsync(
input.Filter, input.Sorting, input.Reverse,
input.Framework, input.ParentId, input.LayoutId,
input.SkipCount, input.MaxResultCount);
return new PagedResultDto<MenuDto>(count,
ObjectMapper.Map<List<Menu>, List<MenuDto>>(menus));
}
[Authorize(PlatformPermissions.Menu.Create)]
public virtual async Task<MenuDto> CreateAsync(MenuCreateDto input)
{
var layout = await LayoutRepository.GetAsync(input.LayoutId);
var data = await DataRepository.GetAsync(layout.DataId);
var menu = await MenuManager.CreateAsync(
layout,
GuidGenerator.Create(),
input.Path,
input.Name,
input.Component,
input.DisplayName,
input.Redirect,
input.Description,
input.ParentId,
CurrentTenant.Id,
input.IsPublic);
// 利用布局约定的数据字典来校验必须的路由元数据,元数据的加入是为了适配多端路由
foreach (var dataItem in data.Items)
{
if (!input.Meta.TryGetValue(dataItem.Name, out object meta))
{
if (!dataItem.AllowBeNull)
{
throw new BusinessException(PlatformErrorCodes.MenuMissingMetadata)
.WithData("Name", dataItem.DisplayName)
.WithData("DataName", data.DisplayName);
}
// 是否需要设定默认值
menu.SetProperty(dataItem.Name, dataItem.DefaultValue);
}
else
{
// 需要检查参数是否有效
menu.SetProperty(dataItem.Name, DataItemMapping.MapToString(dataItem.ValueType, meta));
}
}
await CurrentUnitOfWork.SaveChangesAsync();
return ObjectMapper.Map<Menu, MenuDto>(menu);
}
[Authorize(PlatformPermissions.Menu.Update)]
public virtual async Task<MenuDto> UpdateAsync(Guid id, MenuUpdateDto input)
{
var menu = await MenuRepository.GetAsync(id);
// 利用布局约定的数据字典来校验必须的路由元数据,元数据的加入是为了适配多端路由
var layout = await LayoutRepository.GetAsync(menu.LayoutId);
var data = await DataRepository.GetAsync(layout.DataId);
foreach (var dataItem in data.Items)
{
if (!input.Meta.TryGetValue(dataItem.Name, out object meta))
{
if (!dataItem.AllowBeNull)
{
throw new BusinessException(PlatformErrorCodes.MenuMissingMetadata)
.WithData("Name", dataItem.DisplayName)
.WithData("DataName", data.DisplayName);
}
// 是否需要设定默认值?
menu.SetProperty(dataItem.Name, dataItem.DefaultValue);
}
else
{
// 与现有的数据做对比
var menuMeta = menu.GetProperty(dataItem.Name);
if (menuMeta != null && menuMeta.Equals(meta))
{
continue;
}
// 需要检查参数是否有效
menu.SetProperty(dataItem.Name, DataItemMapping.MapToString(dataItem.ValueType, meta));
}
}
if (!string.Equals(menu.Name, input.Name, StringComparison.InvariantCultureIgnoreCase))
{
menu.Name = input.Name;
}
if (!string.Equals(menu.DisplayName, input.DisplayName, StringComparison.InvariantCultureIgnoreCase))
{
menu.DisplayName = input.DisplayName;
}
if (!string.Equals(menu.Description, input.Description, StringComparison.InvariantCultureIgnoreCase))
{
menu.Description = input.Description;
}
if (!string.Equals(menu.Path, input.Path, StringComparison.InvariantCultureIgnoreCase))
{
menu.Path = input.Path;
}
if (!string.Equals(menu.Redirect, input.Redirect, StringComparison.InvariantCultureIgnoreCase))
{
menu.Redirect = input.Redirect;
}
if (!string.Equals(menu.Component, input.Component, StringComparison.InvariantCultureIgnoreCase))
{
menu.Component = input.Component;
}
menu.IsPublic = input.IsPublic;
await MenuManager.UpdateAsync(menu);
await CurrentUnitOfWork.SaveChangesAsync();
return ObjectMapper.Map<Menu, MenuDto>(menu);
}
[Authorize(PlatformPermissions.Menu.Delete)]
public virtual async Task DeleteAsync(Guid id)
{
var childrens = await MenuRepository.GetChildrenAsync(id);
if (childrens.Any())
{
throw new BusinessException(PlatformErrorCodes.DeleteMenuHaveChildren);
}
var menu = await MenuRepository.GetAsync(id);
await MenuRepository.DeleteAsync(menu);
}
[Authorize(PlatformPermissions.Menu.ManageUsers)]
public virtual async Task<ListResultDto<MenuDto>> GetUserMenuListAsync(MenuGetByUserInput input)
{
var menus = await MenuRepository.GetUserMenusAsync(input.UserId, input.Roles, input.Framework);
return new ListResultDto<MenuDto>(
ObjectMapper.Map<List<Menu>, List<MenuDto>>(menus));
}
[Authorize(PlatformPermissions.Menu.ManageUsers)]
public virtual async Task SetUserMenusAsync(UserMenuInput input)
{
await MenuManager.SetUserMenusAsync(input.UserId, input.MenuIds);
}
[Authorize(PlatformPermissions.Menu.ManageRoles)]
public virtual async Task SetRoleMenusAsync(RoleMenuInput input)
{
await MenuManager.SetRoleMenusAsync(input.RoleName, input.MenuIds);
}
[Authorize(PlatformPermissions.Menu.ManageRoles)]
public virtual async Task<ListResultDto<MenuDto>> GetRoleMenuListAsync(MenuGetByRoleInput input)
{
var menus = await MenuRepository.GetRoleMenusAsync(new string[] { input.Role }, input.Framework);
return new ListResultDto<MenuDto>(
ObjectMapper.Map<List<Menu>, List<MenuDto>>(menus));
}
}
}

113
aspnet-core/modules/platform/LINGYUN.Platform.Domain.Shared/LINGYUN/Platform/Localization/Resources/en.json

@ -1,55 +1,60 @@
{
"culture": "en",
"texts": {
"Platform:01404": "File not found, name: {FileName}, version:{FileVersion}!",
"Platform:02001": "The same menu exists in the sibling directory: {Name}!",
"Platform:02002": "You are not allowed to delete menu nodes when there are other submenus!",
"Platform:02003": "The menu level has reached the specified maximum: {Depth}!",
"Platform:02101": "The menu metadata is missing the necessary element :{Name}, which is defined in the data dictionary :{DataName}!",
"Platform:03001": "The metadata format does not match!",
"UploadFileSizeBeyondLimit": "Upload file size cannot exceed {0} MB!",
"NotAllowedFileExtensionName": "Not allowed file extension: {0}!",
"DisplayName:VersionFileLimitLength": "File limit size",
"Description:VersionFileLimitLength": "Limit size of uploaded file in MB",
"DisplayName:AllowVersionFileExtensions": "File extension",
"Description:AllowVersionFileExtensions": "List of allowed extensions to upload files, with multiple extensions separated by, don't need a notation",
"DisplayName:Menus": "Menus",
"DisplayName:Name": "Name",
"DisplayName:Code": "Code",
"DisplayName:IsPublic": "Is Public",
"DisplayName:DisplayName": "Display Name",
"DisplayName:Description": "Description",
"DisplayName:AllowBeNull": "Allow Be Null",
"DisplayName:DefaultValue": "Default Value",
"DisplayName:ValueType": "Value Type",
"DisplayName:Path": "Path",
"DisplayName:Redirect": "Redirect",
"DisplayName:Meta": "Meta",
"DisplayName:Component": "Component",
"DisplayName:Filter": "Filter",
"DisplayName:PlatformType": "Platform Type",
"DisplayName:SecrchMenu": "Secrch Menu",
"DisplayName:SecrchLayout": "Secrch Layout",
"DisplayName:Layout": "Layout",
"DisplayName:Basic": "Basic",
"DisplayName:DataDictionary": "Data Dictionary",
"Layout:AddNew": "Add New",
"Layout:Edit": "Edit",
"Layout:EditByName": "Edit Layout - {0}",
"Layout:Delete": "Delete Layout",
"Menu:AddNew": "Add New",
"Menu:AddChildren": "Add Children",
"Menu:Edit": "Edit",
"Menu:EditByName": "Edit Menu - {0}",
"Menu:Delete": "Delete Menu",
"Menu:Manage": "Manage Menus",
"Data:AddNew": "Add New",
"Data:AddChildren": "Add Children",
"Data:Edit": "Edit",
"Data:Delete": "Delete Data",
"Data:AppendItem": "Append Item",
"Data:EditItem": "Edit Item",
"Data:RemoveItem": "Remove Item",
"Data:Items": "Data Items"
}
{
"culture": "en",
"texts": {
"Platform:01404": "File not found, name: {FileName}, version:{FileVersion}!",
"Platform:02001": "The same menu exists in the sibling directory: {Name}!",
"Platform:02002": "You are not allowed to delete menu nodes when there are other submenus!",
"Platform:02003": "The menu level has reached the specified maximum: {Depth}!",
"Platform:02101": "The menu metadata is missing the necessary element :{Name}, which is defined in the data dictionary :{DataName}!",
"Platform:03001": "The metadata format does not match!",
"UploadFileSizeBeyondLimit": "Upload file size cannot exceed {0} MB!",
"NotAllowedFileExtensionName": "Not allowed file extension: {0}!",
"DisplayName:VersionFileLimitLength": "File limit size",
"Description:VersionFileLimitLength": "Limit size of uploaded file in MB",
"DisplayName:AllowVersionFileExtensions": "File extension",
"Description:AllowVersionFileExtensions": "List of allowed extensions to upload files, with multiple extensions separated by, don't need a notation",
"DisplayName:Menus": "Menus",
"DisplayName:Name": "Name",
"DisplayName:Code": "Code",
"DisplayName:IsPublic": "Is Public",
"DisplayName:DisplayName": "Display Name",
"DisplayName:Description": "Description",
"DisplayName:AllowBeNull": "Allow Be Null",
"DisplayName:DefaultValue": "Default Value",
"DisplayName:ValueType": "Value Type",
"DisplayName:Path": "Path",
"DisplayName:Redirect": "Redirect",
"DisplayName:Meta": "Meta",
"DisplayName:Component": "Component",
"DisplayName:Filter": "Filter",
"DisplayName:PlatformType": "Platform Type",
"DisplayName:SecrchMenu": "Secrch Menu",
"DisplayName:SecrchLayout": "Secrch Layout",
"DisplayName:Layout": "Layout",
"DisplayName:Basic": "Basic",
"DisplayName:DataDictionary": "Data Dictionary",
"Layout:AddNew": "Add New",
"Layout:Edit": "Edit",
"Layout:EditByName": "Edit Layout - {0}",
"Layout:Delete": "Delete Layout",
"Menu:AddNew": "Add New",
"Menu:AddChildren": "Add Children",
"Menu:Edit": "Edit",
"Menu:EditByName": "Edit Menu - {0}",
"Menu:Delete": "Delete Menu",
"Menu:Manage": "Manage Menus",
"Data:AddNew": "Add New",
"Data:AddChildren": "Add Children",
"Data:Edit": "Edit",
"Data:Delete": "Delete Data",
"Data:AppendItem": "Append Item",
"Data:EditItem": "Edit Item",
"Data:RemoveItem": "Remove Item",
"Data:Items": "Data Items",
"DuplicateData": "A data dictionary named {0} already exists!",
"DuplicateDataItem": "A data dictionary entry named {0} already exists!",
"DataItemNotFound": "There is no data dictionary entry named {0}!",
"UnableRemoveHasChildNode": "Current data dictionary exists child node, cannot delete!",
"DuplicateLayout": "A layout named {0} already exists!"
}
}

113
aspnet-core/modules/platform/LINGYUN.Platform.Domain.Shared/LINGYUN/Platform/Localization/Resources/zh-Hans.json

@ -1,55 +1,60 @@
{
"culture": "zh-Hans",
"texts": {
"Platform:01404": "文件: {FileName}, 版本号: {FileVersion} 不存在!",
"Platform:02001": "同级目录下存在相同的菜单: {Name}!",
"Platform:02002": "在有其他子菜单的情况下,不允许删除菜单节点!",
"Platform:02003": "菜单层级已达到规定最大值: {Depth}!",
"Platform:02101": "菜单元数据缺少必要的元素: {Name},此选项在数据字典:{DataName} 中定义!",
"Platform:03001": "元数据格式不匹配!",
"UploadFileSizeBeyondLimit": "上传文件大小不能超过 {0} MB!",
"NotAllowedFileExtensionName": "不被允许的文件扩展名: {0}!",
"DisplayName:VersionFileLimitLength": "文件限制大小",
"Description:VersionFileLimitLength": "上传文件的限制大小,单位(MB)",
"DisplayName:AllowVersionFileExtensions": "文件扩展名",
"Description:AllowVersionFileExtensions": "允许的上传文件扩展名列表,多个扩展名以,分隔,无需输入.符号",
"DisplayName:Menus": "菜单列表",
"DisplayName:Name": "名称",
"DisplayName:Code": "编号",
"DisplayName:IsPublic": "是否公用的",
"DisplayName:DisplayName": "显示名称",
"DisplayName:Description": "说明",
"DisplayName:AllowBeNull": "允许空值",
"DisplayName:DefaultValue": "默认值",
"DisplayName:ValueType": "值类型",
"DisplayName:Path": "路径",
"DisplayName:Redirect": "重定向路径",
"DisplayName:Meta": "元数据",
"DisplayName:Component": "组件",
"DisplayName:Filter": "筛选",
"DisplayName:PlatformType": "平台类型",
"DisplayName:SecrchMenu": "查询菜单",
"DisplayName:SecrchLayout": "查询布局",
"DisplayName:Layout": "布局",
"DisplayName:Basic": "基础信息",
"DisplayName:DataDictionary": "数据字典",
"Layout:AddNew": "添加新布局",
"Layout:Edit": "编辑布局",
"Layout:EditByName": "编辑布局 - {0}",
"Layout:Delete": "删除布局",
"Menu:AddNew": "添加新菜单",
"Menu:AddChildren": "添加子菜单",
"Menu:Edit": "编辑菜单",
"Menu:EditByName": "编辑菜单 - {0}",
"Menu:Delete": "删除菜单",
"Menu:Manage": "管理菜单",
"Data:AddNew": "添加新字典",
"Data:AddChildren": "添加下级字典",
"Data:Edit": "编辑字典",
"Data:Delete": "删除字典",
"Data:AppendItem": "添加项目",
"Data:EditItem": "编辑项目",
"Data:RemoveItem": "删除项目",
"Data:Items": "字典项目"
}
{
"culture": "zh-Hans",
"texts": {
"Platform:01404": "文件: {FileName}, 版本号: {FileVersion} 不存在!",
"Platform:02001": "同级目录下存在相同的菜单: {Name}!",
"Platform:02002": "在有其他子菜单的情况下,不允许删除菜单节点!",
"Platform:02003": "菜单层级已达到规定最大值: {Depth}!",
"Platform:02101": "菜单元数据缺少必要的元素: {Name},此选项在数据字典:{DataName} 中定义!",
"Platform:03001": "元数据格式不匹配!",
"UploadFileSizeBeyondLimit": "上传文件大小不能超过 {0} MB!",
"NotAllowedFileExtensionName": "不被允许的文件扩展名: {0}!",
"DisplayName:VersionFileLimitLength": "文件限制大小",
"Description:VersionFileLimitLength": "上传文件的限制大小,单位(MB)",
"DisplayName:AllowVersionFileExtensions": "文件扩展名",
"Description:AllowVersionFileExtensions": "允许的上传文件扩展名列表,多个扩展名以,分隔,无需输入.符号",
"DisplayName:Menus": "菜单列表",
"DisplayName:Name": "名称",
"DisplayName:Code": "编号",
"DisplayName:IsPublic": "是否公用的",
"DisplayName:DisplayName": "显示名称",
"DisplayName:Description": "说明",
"DisplayName:AllowBeNull": "允许空值",
"DisplayName:DefaultValue": "默认值",
"DisplayName:ValueType": "值类型",
"DisplayName:Path": "路径",
"DisplayName:Redirect": "重定向路径",
"DisplayName:Meta": "元数据",
"DisplayName:Component": "组件",
"DisplayName:Filter": "筛选",
"DisplayName:PlatformType": "平台类型",
"DisplayName:SecrchMenu": "查询菜单",
"DisplayName:SecrchLayout": "查询布局",
"DisplayName:Layout": "布局",
"DisplayName:Basic": "基础信息",
"DisplayName:DataDictionary": "数据字典",
"Layout:AddNew": "添加新布局",
"Layout:Edit": "编辑布局",
"Layout:EditByName": "编辑布局 - {0}",
"Layout:Delete": "删除布局",
"Menu:AddNew": "添加新菜单",
"Menu:AddChildren": "添加子菜单",
"Menu:Edit": "编辑菜单",
"Menu:EditByName": "编辑菜单 - {0}",
"Menu:Delete": "删除菜单",
"Menu:Manage": "管理菜单",
"Data:AddNew": "添加新字典",
"Data:AddChildren": "添加下级字典",
"Data:Edit": "编辑字典",
"Data:Delete": "删除字典",
"Data:AppendItem": "添加项目",
"Data:EditItem": "编辑项目",
"Data:RemoveItem": "删除项目",
"Data:Items": "字典项目",
"DuplicateData": "已经存在名为 {0} 的数据字典!",
"DuplicateDataItem": "已经存在名为 {0} 的数据字典项!",
"DataItemNotFound": "不存在名为 {0} 的数据字典项!",
"UnableRemoveHasChildNode": "当前数据字典存在子节点,无法删除!",
"DuplicateLayout": "已经存在名为 {0} 的布局!"
}
}

7
aspnet-core/modules/platform/LINGYUN.Platform.Domain.Shared/LINGYUN/Platform/Routes/LayoutConsts.cs

@ -0,0 +1,7 @@
namespace LINGYUN.Platform.Routes
{
public static class LayoutConsts
{
public static int MaxFrameworkLength { get; set; } = 64;
}
}

248
aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/Data.cs

@ -1,121 +1,127 @@
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Platform.Datas
{
/// <summary>
/// 数据字典
/// </summary>
public class Data : FullAuditedAggregateRoot<Guid>, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
public virtual string Name { get; set; }
public virtual string Code { get; set; }
public virtual string DisplayName { get; set; }
public virtual string Description { get; set; }
public virtual Guid? ParentId { get; set; }
public virtual ICollection<DataItem> Items { get; protected set; }
protected Data()
{
Items = new Collection<DataItem>();
}
public Data(
[NotNull] Guid id,
[NotNull] string name,
[NotNull] string code,
[NotNull] string displayName,
string description = "",
Guid? parentId = null,
Guid? tenantId = null)
{
Check.NotNull(id, nameof(id));
Check.NotNullOrWhiteSpace(name, nameof(name));
Check.NotNullOrWhiteSpace(code, nameof(code));
Check.NotNullOrWhiteSpace(displayName, nameof(displayName));
Id = id;
Name = name;
Code = code;
DisplayName = displayName;
Description = description;
ParentId = parentId;
TenantId = tenantId;
CreationTime = DateTime.Now;
Items = new Collection<DataItem>();
}
public Data AddItem(
[NotNull] IGuidGenerator guidGenerator,
[NotNull] string name,
[NotNull] string displayName,
[CanBeNull] string defaultValue,
ValueType valueType = ValueType.String,
string description = "",
bool allowBeNull = true)
{
Check.NotNull(guidGenerator, nameof(guidGenerator));
Check.NotNull(name, nameof(name));
Check.NotNull(displayName, nameof(displayName));
if (!IsInItem(name))
{
var dataItem = new DataItem(
guidGenerator.Create(),
Id,
name,
displayName,
defaultValue,
valueType,
description,
allowBeNull,
TenantId
);
Items.Add(dataItem);
}
return this;
}
public DataItem FindItem(string name)
{
return Items.FirstOrDefault(item => item.Name == name);
}
public DataItem FindItem(Guid id)
{
return Items.FirstOrDefault(item => item.Id == id);
}
public bool RemoveItem(string name)
{
if (IsInItem(name))
{
Items.RemoveAll(item => item.Name == name);
return true;
}
return false;
}
public bool IsInItem(string name)
{
return Items.Any(item => item.Name == name);
}
}
}
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Platform.Datas
{
/// <summary>
/// 数据字典
/// </summary>
public class Data : FullAuditedAggregateRoot<Guid>, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
public virtual string Name { get; set; }
public virtual string Code { get; set; }
public virtual string DisplayName { get; set; }
public virtual string Description { get; set; }
public virtual Guid? ParentId { get; set; }
public virtual bool IsStatic { get; set; }
public virtual ICollection<DataItem> Items { get; protected set; }
protected Data()
{
Items = new Collection<DataItem>();
}
public Data(
[NotNull] Guid id,
[NotNull] string name,
[NotNull] string code,
[NotNull] string displayName,
string description = "",
Guid? parentId = null,
Guid? tenantId = null)
{
Check.NotNull(id, nameof(id));
Check.NotNullOrWhiteSpace(name, nameof(name));
Check.NotNullOrWhiteSpace(code, nameof(code));
Check.NotNullOrWhiteSpace(displayName, nameof(displayName));
Id = id;
Name = name;
Code = code;
DisplayName = displayName;
Description = description;
ParentId = parentId;
TenantId = tenantId;
CreationTime = DateTime.Now;
Items = new Collection<DataItem>();
}
public Data AddItem(
[NotNull] IGuidGenerator guidGenerator,
[NotNull] string name,
[NotNull] string displayName,
[CanBeNull] string defaultValue,
ValueType valueType = ValueType.String,
string description = "",
bool allowBeNull = true,
bool isStatic = false)
{
Check.NotNull(guidGenerator, nameof(guidGenerator));
Check.NotNull(name, nameof(name));
Check.NotNull(displayName, nameof(displayName));
if (!IsInItem(name))
{
var dataItem = new DataItem(
guidGenerator.Create(),
Id,
name,
displayName,
defaultValue,
valueType,
description,
allowBeNull,
TenantId
)
{
IsStatic = isStatic
};
Items.Add(dataItem);
}
return this;
}
public DataItem FindItem(string name)
{
return Items.FirstOrDefault(item => item.Name == name);
}
public DataItem FindItem(Guid id)
{
return Items.FirstOrDefault(item => item.Id == id);
}
public bool RemoveItem(string name)
{
if (IsInItem(name))
{
Items.RemoveAll(item => item.Name == name);
return true;
}
return false;
}
public bool IsInItem(string name)
{
return Items.Any(item => item.Name == name);
}
}
}

118
aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/DataDictionaryDataSeeder.cs

@ -1,57 +1,61 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Platform.Datas
{
public class DataDictionaryDataSeeder : IDataDictionaryDataSeeder, ITransientDependency
{
protected ICurrentTenant CurrentTenant { get; }
protected IGuidGenerator GuidGenerator { get; }
protected IDataRepository DataRepository { get; }
public DataDictionaryDataSeeder(
ICurrentTenant currentTenant,
IGuidGenerator guidGenerator,
IDataRepository dataRepository)
{
CurrentTenant = currentTenant;
GuidGenerator = guidGenerator;
DataRepository = dataRepository;
}
public virtual async Task<Data> SeedAsync(
string name,
string code,
string displayName,
string description = "",
Guid? parentId = null,
Guid? tenantId = null,
CancellationToken cancellationToken = default)
{
using (CurrentTenant.Change(tenantId))
{
var data = await DataRepository.FindByNameAsync(name, cancellationToken: cancellationToken);
if (data == null)
{
data = new Data(
GuidGenerator.Create(),
name,
code,
displayName,
description,
parentId,
tenantId);
data = await DataRepository.InsertAsync(data);
}
return data;
}
}
}
}
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Platform.Datas
{
public class DataDictionaryDataSeeder : IDataDictionaryDataSeeder, ITransientDependency
{
protected ICurrentTenant CurrentTenant { get; }
protected IGuidGenerator GuidGenerator { get; }
protected IDataRepository DataRepository { get; }
public DataDictionaryDataSeeder(
ICurrentTenant currentTenant,
IGuidGenerator guidGenerator,
IDataRepository dataRepository)
{
CurrentTenant = currentTenant;
GuidGenerator = guidGenerator;
DataRepository = dataRepository;
}
public virtual async Task<Data> SeedAsync(
string name,
string code,
string displayName,
string description = "",
Guid? parentId = null,
Guid? tenantId = null,
bool isStatic = false,
CancellationToken cancellationToken = default)
{
using (CurrentTenant.Change(tenantId))
{
var data = await DataRepository.FindByNameAsync(name, cancellationToken: cancellationToken);
if (data == null)
{
data = new Data(
GuidGenerator.Create(),
name,
code,
displayName,
description,
parentId,
tenantId)
{
IsStatic = isStatic
};
data = await DataRepository.InsertAsync(data, true);
}
return data;
}
}
}
}

187
aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/DataItem.cs

@ -1,93 +1,94 @@
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Platform.Datas
{
public class DataItem : FullAuditedAggregateRoot<Guid>, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
public virtual string Name { get; protected set; }
public virtual string DisplayName { get; set; }
public virtual string DefaultValue { get; set; }
public virtual string Description { get; set; }
public virtual bool AllowBeNull { get; set; }
public virtual ValueType ValueType { get; protected set; }
public virtual Guid DataId { get; protected set; }
protected DataItem() { }
public DataItem(
[NotNull] Guid id,
[NotNull] Guid dataId,
[NotNull] string name,
[NotNull] string displayName,
[CanBeNull] string defaultValue = null,
ValueType valueType = ValueType.String,
string description = "",
bool allowBeNull = true,
Guid? tenantId = null)
{
Check.NotNull(id, nameof(id));
Check.NotNull(dataId, nameof(dataId));
Check.NotNullOrWhiteSpace(name, nameof(name));
Check.NotNullOrWhiteSpace(displayName, nameof(displayName));
Id = id;
Name = name;
DefaultValue = defaultValue ?? SetDefaultValue();
ValueType = valueType;
DisplayName = displayName;
AllowBeNull = allowBeNull;
DataId = dataId;
TenantId = tenantId;
Description = description;
}
public string SetDefaultValue()
{
switch (ValueType)
{
case ValueType.Array:
DefaultValue = "";// 当数据类型为数组对象时,需要前端来做转换了,约定的分隔符为英文逗号
break;
case ValueType.Boolean:
DefaultValue = "false";
break;
case ValueType.Date:
DefaultValue = !AllowBeNull ? DateTime.Now.ToString("yyyy-MM-dd") : "";
break;
case ValueType.DateTime:
if (!AllowBeNull)
{
DefaultValue = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); // TODO: 以当前时间作为默认值?
}
DefaultValue = !AllowBeNull ? DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") : "";
break;
case ValueType.Numeic:
DefaultValue = "0";
break;
case ValueType.Object:
DefaultValue = "{}";
break;
default:
case ValueType.String:
DefaultValue = "";
break;
}
return DefaultValue;
}
}
}
using JetBrains.Annotations;
using System;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Platform.Datas
{
public class DataItem : FullAuditedAggregateRoot<Guid>, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
public virtual string Name { get; protected set; }
public virtual string DisplayName { get; set; }
public virtual string DefaultValue { get; set; }
public virtual string Description { get; set; }
public virtual bool AllowBeNull { get; set; }
public virtual bool IsStatic { get; set; }
public virtual ValueType ValueType { get; protected set; }
public virtual Guid DataId { get; protected set; }
protected DataItem() { }
internal DataItem(
[NotNull] Guid id,
[NotNull] Guid dataId,
[NotNull] string name,
[NotNull] string displayName,
[CanBeNull] string defaultValue = null,
ValueType valueType = ValueType.String,
string description = "",
bool allowBeNull = true,
Guid? tenantId = null)
{
Check.NotNull(id, nameof(id));
Check.NotNull(dataId, nameof(dataId));
Check.NotNullOrWhiteSpace(name, nameof(name));
Check.NotNullOrWhiteSpace(displayName, nameof(displayName));
Id = id;
Name = name;
DefaultValue = defaultValue ?? SetDefaultValue();
ValueType = valueType;
DisplayName = displayName;
AllowBeNull = allowBeNull;
DataId = dataId;
TenantId = tenantId;
Description = description;
}
public string SetDefaultValue()
{
switch (ValueType)
{
case ValueType.Array:
DefaultValue = "";// 当数据类型为数组对象时,需要前端来做转换了,约定的分隔符为英文逗号
break;
case ValueType.Boolean:
DefaultValue = "false";
break;
case ValueType.Date:
DefaultValue = !AllowBeNull ? DateTime.Now.ToString("yyyy-MM-dd") : "";
break;
case ValueType.DateTime:
if (!AllowBeNull)
{
DefaultValue = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); // TODO: 以当前时间作为默认值?
}
DefaultValue = !AllowBeNull ? DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") : "";
break;
case ValueType.Numeic:
DefaultValue = "0";
break;
case ValueType.Object:
DefaultValue = "{}";
break;
default:
case ValueType.String:
DefaultValue = "";
break;
}
return DefaultValue;
}
}
}

37
aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/IDataDictionaryDataSeeder.cs

@ -1,18 +1,19 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Platform.Datas
{
public interface IDataDictionaryDataSeeder
{
Task<Data> SeedAsync(
string name,
string code,
string displayName,
string description = "",
Guid? parentId = null,
Guid? tenantId = null,
CancellationToken cancellationToken = default);
}
}
using System;
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Platform.Datas
{
public interface IDataDictionaryDataSeeder
{
Task<Data> SeedAsync(
string name,
string code,
string displayName,
string description = "",
Guid? parentId = null,
Guid? tenantId = null,
bool isStatic = false,
CancellationToken cancellationToken = default);
}
}

76
aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Layouts/ILayoutRepository.cs

@ -1,38 +1,38 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace LINGYUN.Platform.Layouts
{
public interface ILayoutRepository : IBasicRepository<Layout, Guid>
{
/// <summary>
/// 根据名称查询布局
/// </summary>
/// <param name="name"></param>
/// <param name="includeDetails"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<Layout> FindByNameAsync(
string name,
bool includeDetails = true,
CancellationToken cancellationToken = default);
Task<int> GetCountAsync(
PlatformType? platformType = null,
string filter = "",
CancellationToken cancellationToken = default);
Task<List<Layout>> GetPagedListAsync(
PlatformType? platformType = null,
string filter = "",
string sorting = nameof(Layout.Name),
bool reverse = false,
bool includeDetails = false,
int skipCount = 0,
int maxResultCount = 10,
CancellationToken cancellationToken = default);
}
}
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace LINGYUN.Platform.Layouts
{
public interface ILayoutRepository : IBasicRepository<Layout, Guid>
{
/// <summary>
/// 根据名称查询布局
/// </summary>
/// <param name="name"></param>
/// <param name="includeDetails"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<Layout> FindByNameAsync(
string name,
bool includeDetails = true,
CancellationToken cancellationToken = default);
Task<int> GetCountAsync(
string framework = "",
string filter = "",
CancellationToken cancellationToken = default);
Task<List<Layout>> GetPagedListAsync(
string framework = "",
string filter = "",
string sorting = nameof(Layout.Name),
bool reverse = false,
bool includeDetails = false,
int skipCount = 0,
int maxResultCount = 10,
CancellationToken cancellationToken = default);
}
}

78
aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Layouts/Layout.cs

@ -1,39 +1,39 @@
using JetBrains.Annotations;
using LINGYUN.Platform.Routes;
using System;
namespace LINGYUN.Platform.Layouts
{
/// <summary>
/// 布局视图实体
/// </summary>
public class Layout : Route
{
/// <summary>
/// 所属平台
/// </summary>
public virtual PlatformType PlatformType { get; protected set; }
/// <summary>
/// 约定的Meta采用哪种数据字典,主要是约束路由必须字段的一致性
/// </summary>
public virtual Guid DataId { get; protected set; }
protected Layout() { }
public Layout(
[NotNull] Guid id,
[NotNull] string path,
[NotNull] string name,
[NotNull] string displayName,
[NotNull] Guid dataId,
[NotNull] PlatformType platformType = PlatformType.None,
[CanBeNull] string redirect = "",
[CanBeNull] string description = "",
[CanBeNull] Guid? tenantId = null)
: base(id, path, name, displayName, redirect, description, tenantId)
{
DataId = dataId;
PlatformType = platformType;
}
}
}
using JetBrains.Annotations;
using LINGYUN.Platform.Routes;
using System;
namespace LINGYUN.Platform.Layouts
{
/// <summary>
/// 布局视图实体
/// </summary>
public class Layout : Route
{
/// <summary>
/// 框架
/// </summary>
public virtual string Framework { get; protected set; }
/// <summary>
/// 约定的Meta采用哪种数据字典,主要是约束路由必须字段的一致性
/// </summary>
public virtual Guid DataId { get; protected set; }
protected Layout() { }
public Layout(
[NotNull] Guid id,
[NotNull] string path,
[NotNull] string name,
[NotNull] string displayName,
[NotNull] Guid dataId,
[NotNull] string framework,
[CanBeNull] string redirect = "",
[CanBeNull] string description = "",
[CanBeNull] Guid? tenantId = null)
: base(id, path, name, displayName, redirect, description, tenantId)
{
DataId = dataId;
Framework = framework;
}
}
}

226
aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/IMenuRepository.cs

@ -1,113 +1,113 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace LINGYUN.Platform.Menus
{
public interface IMenuRepository : IBasicRepository<Menu, Guid>
{
/// <summary>
/// 根据名称查询菜单
/// </summary>
/// <param name="menuName"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<Menu> FindByNameAsync(
string menuName,
CancellationToken cancellationToken = default);
/// <summary>
/// 查询主菜单,每一个布局页创建的时候都要创建路径为 / 的主菜单
/// </summary>
/// <param name="platformType"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<Menu> FindMainAsync(
PlatformType platformType = PlatformType.None,
CancellationToken cancellationToken = default);
/// <summary>
/// 获取子节点
/// </summary>
/// <param name="parentId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<List<Menu>> GetChildrenAsync(
Guid? parentId,
CancellationToken cancellationToken = default
);
/// <summary>
/// 通过父菜单编码查询子菜单
/// </summary>
/// <param name="code"></param>
/// <param name="parentId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<List<Menu>> GetAllChildrenWithParentCodeAsync(
string code,
Guid? parentId,
CancellationToken cancellationToken = default
);
/// <summary>
/// 查找用户可访问菜单
/// </summary>
/// <param name="userId">用户标识</param>
/// <param name="roles">角色列表</param>
/// <param name="platformType">平台类型</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<List<Menu>> GetUserMenusAsync(
Guid userId,
string[] roles,
PlatformType platformType = PlatformType.None,
CancellationToken cancellationToken = default);
/// <summary>
/// 查找角色可访问菜单
/// </summary>
/// <param name="roles">角色列表</param>
/// <param name="platformType">平台类型</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<List<Menu>> GetRoleMenusAsync(
string[] roles,
PlatformType platformType = PlatformType.None,
CancellationToken cancellationToken = default);
Task<int> GetCountAsync(
string filter = "",
PlatformType? platformType = null,
Guid? parentId = null,
Guid? layoutId = null,
CancellationToken cancellationToken = default);
Task<List<Menu>> GetListAsync(
string filter = "",
string sorting = nameof(Menu.Code),
bool reverse = false,
PlatformType? platformType = null,
Guid? parentId = null,
Guid? layoutId = null,
int skipCount = 0,
int maxResultCount = 10,
CancellationToken cancellationToken = default);
Task<List<Menu>> GetAllAsync(
string filter = "",
string sorting = nameof(Menu.Code),
bool reverse = false,
PlatformType? platformType = null,
Guid? parentId = null,
Guid? layoutId = null,
CancellationToken cancellationToken = default);
Task RemoveAllRolesAsync(
Menu menu,
CancellationToken cancellationToken = default
);
Task RemoveAllMembersAsync(
Menu menu,
CancellationToken cancellationToken = default
);
}
}
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace LINGYUN.Platform.Menus
{
public interface IMenuRepository : IBasicRepository<Menu, Guid>
{
/// <summary>
/// 根据名称查询菜单
/// </summary>
/// <param name="menuName"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<Menu> FindByNameAsync(
string menuName,
CancellationToken cancellationToken = default);
/// <summary>
/// 查询主菜单,每一个布局页创建的时候都要创建路径为 / 的主菜单
/// </summary>
/// <param name="platformType"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<Menu> FindMainAsync(
string framework = "",
CancellationToken cancellationToken = default);
/// <summary>
/// 获取子节点
/// </summary>
/// <param name="parentId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<List<Menu>> GetChildrenAsync(
Guid? parentId,
CancellationToken cancellationToken = default
);
/// <summary>
/// 通过父菜单编码查询子菜单
/// </summary>
/// <param name="code"></param>
/// <param name="parentId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<List<Menu>> GetAllChildrenWithParentCodeAsync(
string code,
Guid? parentId,
CancellationToken cancellationToken = default
);
/// <summary>
/// 查找用户可访问菜单
/// </summary>
/// <param name="userId">用户标识</param>
/// <param name="roles">角色列表</param>
/// <param name="platformType">平台类型</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<List<Menu>> GetUserMenusAsync(
Guid userId,
string[] roles,
string framework = "",
CancellationToken cancellationToken = default);
/// <summary>
/// 查找角色可访问菜单
/// </summary>
/// <param name="roles">角色列表</param>
/// <param name="platformType">平台类型</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<List<Menu>> GetRoleMenusAsync(
string[] roles,
string framework = "",
CancellationToken cancellationToken = default);
Task<int> GetCountAsync(
string filter = "",
string framework = "",
Guid? parentId = null,
Guid? layoutId = null,
CancellationToken cancellationToken = default);
Task<List<Menu>> GetListAsync(
string filter = "",
string sorting = nameof(Menu.Code),
bool reverse = false,
string framework = "",
Guid? parentId = null,
Guid? layoutId = null,
int skipCount = 0,
int maxResultCount = 10,
CancellationToken cancellationToken = default);
Task<List<Menu>> GetAllAsync(
string filter = "",
string sorting = nameof(Menu.Code),
bool reverse = false,
string framework = "",
Guid? parentId = null,
Guid? layoutId = null,
CancellationToken cancellationToken = default);
Task RemoveAllRolesAsync(
Menu menu,
CancellationToken cancellationToken = default
);
Task RemoveAllMembersAsync(
Menu menu,
CancellationToken cancellationToken = default
);
}
}

134
aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/Menu.cs

@ -1,67 +1,67 @@
using JetBrains.Annotations;
using LINGYUN.Platform.Routes;
using System;
using Volo.Abp;
namespace LINGYUN.Platform.Menus
{
/// <summary>
/// 菜单
/// </summary>
public class Menu : Route
{
/// <summary>
/// 所属平台
/// </summary>
public virtual PlatformType PlatformType { get; set; }
/// <summary>
/// 菜单编号
/// </summary>
public virtual string Code { get; set; }
/// <summary>
/// 菜单布局页,Layout的路径
/// </summary>
public virtual string Component { get; set; }
/// <summary>
/// 所属的父菜单
/// </summary>
public virtual Guid? ParentId { get; set; }
/// <summary>
/// 所属布局标识
/// </summary>
public virtual Guid LayoutId { get; set; }
/// <summary>
/// 公共菜单
/// </summary>
public virtual bool IsPublic { get; set; }
protected Menu()
{
}
public Menu(
[NotNull] Guid id,
[NotNull] Guid layoutId,
[NotNull] string path,
[NotNull] string name,
[NotNull] string code,
[NotNull] string component,
[NotNull] string displayName,
string redirect = "",
string description = "",
PlatformType platformType = PlatformType.None,
Guid? parentId = null,
Guid? tenantId = null)
: base(id, path, name, displayName, redirect, description, tenantId)
{
Check.NotNullOrWhiteSpace(code, nameof(code));
LayoutId = layoutId;
Code = code;
Component = component;// 下属的一级菜单的Component应该是布局页, 例如vue-admin中的 component: Layout, 其他前端框架雷同, 此处应传递布局页的路径让前端import
PlatformType = platformType;
ParentId = parentId;
IsPublic = false;
}
}
}
using JetBrains.Annotations;
using LINGYUN.Platform.Routes;
using System;
using Volo.Abp;
namespace LINGYUN.Platform.Menus
{
/// <summary>
/// 菜单
/// </summary>
public class Menu : Route
{
/// <summary>
/// 框架
/// </summary>
public virtual string Framework { get; set; }
/// <summary>
/// 菜单编号
/// </summary>
public virtual string Code { get; set; }
/// <summary>
/// 菜单布局页,Layout的路径
/// </summary>
public virtual string Component { get; set; }
/// <summary>
/// 所属的父菜单
/// </summary>
public virtual Guid? ParentId { get; set; }
/// <summary>
/// 所属布局标识
/// </summary>
public virtual Guid LayoutId { get; set; }
/// <summary>
/// 公共菜单
/// </summary>
public virtual bool IsPublic { get; set; }
protected Menu()
{
}
public Menu(
[NotNull] Guid id,
[NotNull] Guid layoutId,
[NotNull] string path,
[NotNull] string name,
[NotNull] string code,
[NotNull] string component,
[NotNull] string displayName,
[NotNull] string framework,
string redirect = "",
string description = "",
Guid? parentId = null,
Guid? tenantId = null)
: base(id, path, name, displayName, redirect, description, tenantId)
{
Check.NotNullOrWhiteSpace(code, nameof(code));
LayoutId = layoutId;
Code = code;
Component = component;// 下属的一级菜单的Component应该是布局页, 例如vue-admin中的 component: Layout, 其他前端框架雷同, 此处应传递布局页的路径让前端import
Framework = framework;
ParentId = parentId;
IsPublic = false;
}
}
}

482
aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/MenuManager.cs

@ -1,241 +1,241 @@
using LINGYUN.Platform.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Domain.Services;
using Volo.Abp.Uow;
namespace LINGYUN.Platform.Menus
{
public class MenuManager : DomainService
{
protected IUnitOfWorkManager UnitOfWorkManager => LazyServiceProvider.LazyGetRequiredService<IUnitOfWorkManager>();
protected IMenuRepository MenuRepository { get; }
protected IUserMenuRepository UserMenuRepository { get; }
protected IRoleMenuRepository RoleMenuRepository { get; }
public MenuManager(
IMenuRepository menuRepository,
IUserMenuRepository userMenuRepository,
IRoleMenuRepository roleMenuRepository)
{
MenuRepository = menuRepository;
UserMenuRepository = userMenuRepository;
RoleMenuRepository = roleMenuRepository;
}
[UnitOfWork]
public virtual async Task<Menu> CreateAsync(
Guid id,
Guid layoutId,
string path,
string name,
string component,
string displayName,
string redirect = "",
string description = "",
PlatformType platformType = PlatformType.None,
Guid? parentId = null,
Guid? tenantId = null,
bool isPublic = false)
{
var code = await GetNextChildCodeAsync(parentId);
if (code.Length > MenuConsts.MaxCodeLength)
{
throw new BusinessException(PlatformErrorCodes.MenuAchieveMaxDepth)
.WithData("Depth", MenuConsts.MaxDepth);
}
var menu = new Menu(
id,
layoutId,
path,
name,
code,
component,
displayName,
redirect,
description,
platformType,
parentId,
tenantId)
{
IsPublic = isPublic
};
await ValidateMenuAsync(menu);
await MenuRepository.InsertAsync(menu);
return menu;
}
[UnitOfWork]
public virtual async Task UpdateAsync(Menu menu)
{
await ValidateMenuAsync(menu);
await MenuRepository.UpdateAsync(menu);
}
[UnitOfWork]
public virtual async Task DeleteAsync(Guid id)
{
var children = await FindChildrenAsync(id, true);
foreach (var child in children)
{
await MenuRepository.RemoveAllMembersAsync(child);
await MenuRepository.RemoveAllRolesAsync(child);
await MenuRepository.DeleteAsync(child);
}
var menu = await MenuRepository.GetAsync(id);
await MenuRepository.RemoveAllMembersAsync(menu);
await MenuRepository.RemoveAllRolesAsync(menu);
await MenuRepository.DeleteAsync(id);
}
[UnitOfWork]
public virtual async Task MoveAsync(Guid id, Guid? parentId)
{
var menu = await MenuRepository.GetAsync(id);
if (menu.ParentId == parentId)
{
return;
}
var children = await FindChildrenAsync(id, true);
var oldCode = menu.Code;
menu.Code = await GetNextChildCodeAsync(parentId);
menu.ParentId = parentId;
await ValidateMenuAsync(menu);
foreach (var child in children)
{
child.Code = CodeNumberGenerator.AppendCode(menu.Code, CodeNumberGenerator.GetRelativeCode(child.Code, oldCode));
}
}
public virtual async Task<bool> UserHasInMenuAsync(Guid userId, string menuName)
{
var menu = await MenuRepository.FindByNameAsync(menuName);
return false;
}
public virtual async Task SetUserMenusAsync(Guid userId, IEnumerable<Guid> menuIds)
{
using (var unitOfWork = UnitOfWorkManager.Begin())
{
var userMenus = await UserMenuRepository.GetListByUserIdAsync(userId);
// 移除不存在的菜单
// TODO: 升级框架版本解决未能删除不需要菜单的问题
// userMenus.RemoveAll(x => !menuIds.Contains(x.MenuId));
var dels = userMenus.Where(x => !menuIds.Contains(x.MenuId));
if (dels.Any())
{
await UserMenuRepository.DeleteManyAsync(dels);
}
var adds = menuIds.Where(menuId => !userMenus.Any(x => x.MenuId == menuId));
if (adds.Any())
{
var addInMenus = adds.Select(menuId => new UserMenu(GuidGenerator.Create(), menuId, userId, CurrentTenant.Id));
await UserMenuRepository.InsertAsync(addInMenus);
}
await unitOfWork.SaveChangesAsync();
}
}
public virtual async Task SetRoleMenusAsync(string roleName, IEnumerable<Guid> menuIds)
{
using (var unitOfWork = UnitOfWorkManager.Begin())
{
var roleMenus = await RoleMenuRepository.GetListByRoleNameAsync(roleName);
// 移除不存在的菜单
// TODO: 升级框架版本解决未能删除不需要菜单的问题
// roleMenus.RemoveAll(x => !menuIds.Contains(x.MenuId));
var dels = roleMenus.Where(x => !menuIds.Contains(x.MenuId));
if (dels.Any())
{
await RoleMenuRepository.DeleteManyAsync(dels);
}
var adds = menuIds.Where(menuId => !roleMenus.Any(x => x.MenuId == menuId));
if (adds.Any())
{
var addInMenus = adds.Select(menuId => new RoleMenu(GuidGenerator.Create(), menuId, roleName, CurrentTenant.Id));
await RoleMenuRepository.InsertAsync(addInMenus);
}
await unitOfWork.SaveChangesAsync();
}
}
public virtual async Task<string> GetNextChildCodeAsync(Guid? parentId)
{
var lastChild = await GetLastChildOrNullAsync(parentId);
if (lastChild != null)
{
return CodeNumberGenerator.CalculateNextCode(lastChild.Code);
}
var parentCode = parentId != null
? await GetCodeOrDefaultAsync(parentId.Value)
: null;
return CodeNumberGenerator.AppendCode(
parentCode,
CodeNumberGenerator.CreateCode(1)
);
}
public virtual async Task<Menu> GetLastChildOrNullAsync(Guid? parentId)
{
var children = await MenuRepository.GetChildrenAsync(parentId);
return children.OrderBy(c => c.Code).LastOrDefault();
}
public async Task<List<Menu>> FindChildrenAsync(Guid? parentId, bool recursive = false)
{
if (!recursive)
{
return await MenuRepository.GetChildrenAsync(parentId);
}
if (!parentId.HasValue)
{
return await MenuRepository.GetListAsync(includeDetails: true);
}
var code = await GetCodeOrDefaultAsync(parentId.Value);
return await MenuRepository.GetAllChildrenWithParentCodeAsync(code, parentId);
}
public virtual async Task<string> GetCodeOrDefaultAsync(Guid id)
{
var menu = await MenuRepository.GetAsync(id);
return menu?.Code;
}
protected virtual async Task ValidateMenuAsync(Menu menu)
{
var siblings = (await FindChildrenAsync(menu.ParentId))
.Where(x => x.Id != menu.Id)
.ToList();
if (siblings.Any(x => x.Name == menu.Name))
{
throw new BusinessException(PlatformErrorCodes.DuplicateMenu)
.WithData("Name", menu.Name);
}
}
}
}
using LINGYUN.Platform.Layouts;
using LINGYUN.Platform.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Domain.Services;
using Volo.Abp.Uow;
namespace LINGYUN.Platform.Menus
{
public class MenuManager : DomainService
{
protected IUnitOfWorkManager UnitOfWorkManager => LazyServiceProvider.LazyGetRequiredService<IUnitOfWorkManager>();
protected IMenuRepository MenuRepository { get; }
protected IUserMenuRepository UserMenuRepository { get; }
protected IRoleMenuRepository RoleMenuRepository { get; }
public MenuManager(
IMenuRepository menuRepository,
IUserMenuRepository userMenuRepository,
IRoleMenuRepository roleMenuRepository)
{
MenuRepository = menuRepository;
UserMenuRepository = userMenuRepository;
RoleMenuRepository = roleMenuRepository;
}
[UnitOfWork]
public virtual async Task<Menu> CreateAsync(
Layout layout,
Guid id,
string path,
string name,
string component,
string displayName,
string redirect = "",
string description = "",
Guid? parentId = null,
Guid? tenantId = null,
bool isPublic = false)
{
var code = await GetNextChildCodeAsync(parentId);
if (code.Length > MenuConsts.MaxCodeLength)
{
throw new BusinessException(PlatformErrorCodes.MenuAchieveMaxDepth)
.WithData("Depth", MenuConsts.MaxDepth);
}
var menu = new Menu(
id,
layout.Id,
path,
name,
code,
component,
displayName,
layout.Framework,
redirect,
description,
parentId,
tenantId)
{
IsPublic = isPublic
};
await ValidateMenuAsync(menu);
await MenuRepository.InsertAsync(menu);
return menu;
}
[UnitOfWork]
public virtual async Task UpdateAsync(Menu menu)
{
await ValidateMenuAsync(menu);
await MenuRepository.UpdateAsync(menu);
}
[UnitOfWork]
public virtual async Task DeleteAsync(Guid id)
{
var children = await FindChildrenAsync(id, true);
foreach (var child in children)
{
await MenuRepository.RemoveAllMembersAsync(child);
await MenuRepository.RemoveAllRolesAsync(child);
await MenuRepository.DeleteAsync(child);
}
var menu = await MenuRepository.GetAsync(id);
await MenuRepository.RemoveAllMembersAsync(menu);
await MenuRepository.RemoveAllRolesAsync(menu);
await MenuRepository.DeleteAsync(id);
}
[UnitOfWork]
public virtual async Task MoveAsync(Guid id, Guid? parentId)
{
var menu = await MenuRepository.GetAsync(id);
if (menu.ParentId == parentId)
{
return;
}
var children = await FindChildrenAsync(id, true);
var oldCode = menu.Code;
menu.Code = await GetNextChildCodeAsync(parentId);
menu.ParentId = parentId;
await ValidateMenuAsync(menu);
foreach (var child in children)
{
child.Code = CodeNumberGenerator.AppendCode(menu.Code, CodeNumberGenerator.GetRelativeCode(child.Code, oldCode));
}
}
public virtual async Task<bool> UserHasInMenuAsync(Guid userId, string menuName)
{
var menu = await MenuRepository.FindByNameAsync(menuName);
return false;
}
public virtual async Task SetUserMenusAsync(Guid userId, IEnumerable<Guid> menuIds)
{
using (var unitOfWork = UnitOfWorkManager.Begin())
{
var userMenus = await UserMenuRepository.GetListByUserIdAsync(userId);
// 移除不存在的菜单
// TODO: 升级框架版本解决未能删除不需要菜单的问题
// userMenus.RemoveAll(x => !menuIds.Contains(x.MenuId));
var dels = userMenus.Where(x => !menuIds.Contains(x.MenuId));
if (dels.Any())
{
await UserMenuRepository.DeleteManyAsync(dels);
}
var adds = menuIds.Where(menuId => !userMenus.Any(x => x.MenuId == menuId));
if (adds.Any())
{
var addInMenus = adds.Select(menuId => new UserMenu(GuidGenerator.Create(), menuId, userId, CurrentTenant.Id));
await UserMenuRepository.InsertAsync(addInMenus);
}
await unitOfWork.SaveChangesAsync();
}
}
public virtual async Task SetRoleMenusAsync(string roleName, IEnumerable<Guid> menuIds)
{
using (var unitOfWork = UnitOfWorkManager.Begin())
{
var roleMenus = await RoleMenuRepository.GetListByRoleNameAsync(roleName);
// 移除不存在的菜单
// TODO: 升级框架版本解决未能删除不需要菜单的问题
// roleMenus.RemoveAll(x => !menuIds.Contains(x.MenuId));
var dels = roleMenus.Where(x => !menuIds.Contains(x.MenuId));
if (dels.Any())
{
await RoleMenuRepository.DeleteManyAsync(dels);
}
var adds = menuIds.Where(menuId => !roleMenus.Any(x => x.MenuId == menuId));
if (adds.Any())
{
var addInMenus = adds.Select(menuId => new RoleMenu(GuidGenerator.Create(), menuId, roleName, CurrentTenant.Id));
await RoleMenuRepository.InsertAsync(addInMenus);
}
await unitOfWork.SaveChangesAsync();
}
}
public virtual async Task<string> GetNextChildCodeAsync(Guid? parentId)
{
var lastChild = await GetLastChildOrNullAsync(parentId);
if (lastChild != null)
{
return CodeNumberGenerator.CalculateNextCode(lastChild.Code);
}
var parentCode = parentId != null
? await GetCodeOrDefaultAsync(parentId.Value)
: null;
return CodeNumberGenerator.AppendCode(
parentCode,
CodeNumberGenerator.CreateCode(1)
);
}
public virtual async Task<Menu> GetLastChildOrNullAsync(Guid? parentId)
{
var children = await MenuRepository.GetChildrenAsync(parentId);
return children.OrderBy(c => c.Code).LastOrDefault();
}
public async Task<List<Menu>> FindChildrenAsync(Guid? parentId, bool recursive = false)
{
if (!recursive)
{
return await MenuRepository.GetChildrenAsync(parentId);
}
if (!parentId.HasValue)
{
return await MenuRepository.GetListAsync(includeDetails: true);
}
var code = await GetCodeOrDefaultAsync(parentId.Value);
return await MenuRepository.GetAllChildrenWithParentCodeAsync(code, parentId);
}
public virtual async Task<string> GetCodeOrDefaultAsync(Guid id)
{
var menu = await MenuRepository.GetAsync(id);
return menu?.Code;
}
protected virtual async Task ValidateMenuAsync(Menu menu)
{
var siblings = (await FindChildrenAsync(menu.ParentId))
.Where(x => x.Id != menu.Id)
.ToList();
if (siblings.Any(x => x.Name == menu.Name))
{
throw new BusinessException(PlatformErrorCodes.DuplicateMenu)
.WithData("Name", menu.Name);
}
}
}
}

100
aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Routes/IRouteDataSeeder.cs

@ -1,50 +1,50 @@
using LINGYUN.Platform.Layouts;
using LINGYUN.Platform.Menus;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Platform.Routes
{
public interface IRouteDataSeeder
{
Task<Layout> SeedLayoutAsync(
string name,
string path,
string displayName,
Guid dataId,
PlatformType platformType = PlatformType.None,
string redirect = "",
string description = "",
Guid? tenantId = null,
CancellationToken cancellationToken = default);
Task<Menu> SeedMenuAsync(
Layout layout,
string name,
string path,
string code,
string component,
string displayName,
string redirect = "",
string description = "",
Guid? parentId = null,
Guid? tenantId = null,
bool isPublic = false,
CancellationToken cancellationToken = default);
Task SeedUserMenuAsync(
Guid userId,
Menu menu,
Guid? tenantId = null,
CancellationToken cancellationToken = default
);
Task SeedRoleMenuAsync(
string roleName,
Menu menu,
Guid? tenantId = null,
CancellationToken cancellationToken = default
);
}
}
using LINGYUN.Platform.Layouts;
using LINGYUN.Platform.Menus;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Platform.Routes
{
public interface IRouteDataSeeder
{
Task<Layout> SeedLayoutAsync(
string name,
string path,
string displayName,
Guid dataId,
string framework,
string redirect = "",
string description = "",
Guid? tenantId = null,
CancellationToken cancellationToken = default);
Task<Menu> SeedMenuAsync(
Layout layout,
string name,
string path,
string code,
string component,
string displayName,
string redirect = "",
string description = "",
Guid? parentId = null,
Guid? tenantId = null,
bool isPublic = false,
CancellationToken cancellationToken = default);
Task SeedUserMenuAsync(
Guid userId,
Menu menu,
Guid? tenantId = null,
CancellationToken cancellationToken = default
);
Task SeedRoleMenuAsync(
string roleName,
Menu menu,
Guid? tenantId = null,
CancellationToken cancellationToken = default
);
}
}

300
aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Routes/RouteDataSeeder.cs

@ -1,150 +1,150 @@
using LINGYUN.Platform.Layouts;
using LINGYUN.Platform.Menus;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
namespace LINGYUN.Platform.Routes
{
public class RouteDataSeeder : IRouteDataSeeder, ITransientDependency
{
protected IGuidGenerator GuidGenerator { get; }
protected ILayoutRepository LayoutRepository { get; }
protected IMenuRepository MenuRepository { get; }
protected IUserMenuRepository UserMenuRepository { get; }
protected IRoleMenuRepository RoleMenuRepository { get; }
public RouteDataSeeder(
IGuidGenerator guidGenerator,
IMenuRepository menuRepository,
ILayoutRepository layoutRepository,
IUserMenuRepository userMenuRepository,
IRoleMenuRepository roleMenuRepository)
{
GuidGenerator = guidGenerator;
MenuRepository = menuRepository;
LayoutRepository = layoutRepository;
UserMenuRepository = userMenuRepository;
RoleMenuRepository = roleMenuRepository;
}
public virtual async Task<Layout> SeedLayoutAsync(
string name,
string path,
string displayName,
Guid dataId,
PlatformType platformType = PlatformType.None,
string redirect = "",
string description = "",
Guid? tenantId = null,
CancellationToken cancellationToken = default)
{
var layout = await LayoutRepository.FindByNameAsync(name, cancellationToken: cancellationToken);
if (layout == null)
{
layout = new Layout(
GuidGenerator.Create(),
path,
name,
displayName,
dataId,
platformType,
redirect,
description,
tenantId);
layout = await LayoutRepository.InsertAsync(layout, cancellationToken: cancellationToken);
}
return layout;
}
public virtual async Task<Menu> SeedMenuAsync(
Layout layout,
string name,
string path,
string code,
string component,
string displayName,
string redirect = "",
string description = "",
Guid? parentId = null,
Guid? tenantId = null,
bool isPublic = false,
CancellationToken cancellationToken = default)
{
if (parentId.HasValue)
{
var children = await MenuRepository.GetChildrenAsync(parentId);
var childMenu = children.FirstOrDefault(x => x.Name == name);
if (childMenu != null)
{
return childMenu;
}
}
var menu = await MenuRepository.FindByNameAsync(name, cancellationToken: cancellationToken);
if (menu == null)
{
menu = new Menu(
GuidGenerator.Create(),
layout.Id,
path,
name,
code,
component,
displayName,
redirect,
description,
layout.PlatformType,
parentId,
tenantId)
{
IsPublic = isPublic
};
menu = await MenuRepository.InsertAsync(menu, cancellationToken: cancellationToken);
}
return menu;
}
public virtual async Task SeedRoleMenuAsync(
string roleName,
Menu menu,
Guid? tenantId = null,
CancellationToken cancellationToken = default)
{
if (! await RoleMenuRepository.RoleHasInMenuAsync(roleName, menu.Name, cancellationToken))
{
var roleMenu = new RoleMenu(GuidGenerator.Create(), menu.Id, roleName, tenantId);
await RoleMenuRepository.InsertAsync(roleMenu);
var childrens = await MenuRepository.GetChildrenAsync(menu.Id);
foreach (var children in childrens)
{
await SeedRoleMenuAsync(roleName, children, tenantId, cancellationToken);
}
}
}
public virtual async Task SeedUserMenuAsync(
Guid userId,
Menu menu,
Guid? tenantId = null,
CancellationToken cancellationToken = default)
{
if (!await UserMenuRepository.UserHasInMenuAsync(userId, menu.Name, cancellationToken))
{
var userMenu = new UserMenu(GuidGenerator.Create(), menu.Id, userId, tenantId);
await UserMenuRepository.InsertAsync(userMenu);
var childrens = await MenuRepository.GetChildrenAsync(menu.Id);
foreach (var children in childrens)
{
await SeedUserMenuAsync(userId, children, tenantId, cancellationToken);
}
}
}
}
}
using LINGYUN.Platform.Layouts;
using LINGYUN.Platform.Menus;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
namespace LINGYUN.Platform.Routes
{
public class RouteDataSeeder : IRouteDataSeeder, ITransientDependency
{
protected IGuidGenerator GuidGenerator { get; }
protected ILayoutRepository LayoutRepository { get; }
protected IMenuRepository MenuRepository { get; }
protected IUserMenuRepository UserMenuRepository { get; }
protected IRoleMenuRepository RoleMenuRepository { get; }
public RouteDataSeeder(
IGuidGenerator guidGenerator,
IMenuRepository menuRepository,
ILayoutRepository layoutRepository,
IUserMenuRepository userMenuRepository,
IRoleMenuRepository roleMenuRepository)
{
GuidGenerator = guidGenerator;
MenuRepository = menuRepository;
LayoutRepository = layoutRepository;
UserMenuRepository = userMenuRepository;
RoleMenuRepository = roleMenuRepository;
}
public virtual async Task<Layout> SeedLayoutAsync(
string name,
string path,
string displayName,
Guid dataId,
string framework,
string redirect = "",
string description = "",
Guid? tenantId = null,
CancellationToken cancellationToken = default)
{
var layout = await LayoutRepository.FindByNameAsync(name, cancellationToken: cancellationToken);
if (layout == null)
{
layout = new Layout(
GuidGenerator.Create(),
path,
name,
displayName,
dataId,
framework,
redirect,
description,
tenantId);
layout = await LayoutRepository.InsertAsync(layout, cancellationToken: cancellationToken);
}
return layout;
}
public virtual async Task<Menu> SeedMenuAsync(
Layout layout,
string name,
string path,
string code,
string component,
string displayName,
string redirect = "",
string description = "",
Guid? parentId = null,
Guid? tenantId = null,
bool isPublic = false,
CancellationToken cancellationToken = default)
{
if (parentId.HasValue)
{
var children = await MenuRepository.GetChildrenAsync(parentId);
var childMenu = children.FirstOrDefault(x => x.Name == name);
if (childMenu != null)
{
return childMenu;
}
}
var menu = await MenuRepository.FindByNameAsync(name, cancellationToken: cancellationToken);
if (menu == null)
{
menu = new Menu(
GuidGenerator.Create(),
layout.Id,
path,
name,
code,
component,
displayName,
layout.Framework,
redirect,
description,
parentId,
tenantId)
{
IsPublic = isPublic
};
menu = await MenuRepository.InsertAsync(menu, cancellationToken: cancellationToken);
}
return menu;
}
public virtual async Task SeedRoleMenuAsync(
string roleName,
Menu menu,
Guid? tenantId = null,
CancellationToken cancellationToken = default)
{
if (! await RoleMenuRepository.RoleHasInMenuAsync(roleName, menu.Name, cancellationToken))
{
var roleMenu = new RoleMenu(GuidGenerator.Create(), menu.Id, roleName, tenantId);
await RoleMenuRepository.InsertAsync(roleMenu);
var childrens = await MenuRepository.GetChildrenAsync(menu.Id);
foreach (var children in childrens)
{
await SeedRoleMenuAsync(roleName, children, tenantId, cancellationToken);
}
}
}
public virtual async Task SeedUserMenuAsync(
Guid userId,
Menu menu,
Guid? tenantId = null,
CancellationToken cancellationToken = default)
{
if (!await UserMenuRepository.UserHasInMenuAsync(userId, menu.Name, cancellationToken))
{
var userMenu = new UserMenu(GuidGenerator.Create(), menu.Id, userId, tenantId);
await UserMenuRepository.InsertAsync(userMenu);
var childrens = await MenuRepository.GetChildrenAsync(menu.Id);
foreach (var children in childrens)
{
await SeedUserMenuAsync(userId, children, tenantId, cancellationToken);
}
}
}
}
}

507
aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/EntityFrameworkCore/PlatformDbContextModelBuilderExtensions.cs

@ -1,249 +1,258 @@
using JetBrains.Annotations;
using LINGYUN.Platform.Datas;
using LINGYUN.Platform.Layouts;
using LINGYUN.Platform.Menus;
using LINGYUN.Platform.Routes;
using LINGYUN.Platform.Versions;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System;
using Volo.Abp;
using Volo.Abp.EntityFrameworkCore.Modeling;
namespace LINGYUN.Platform.EntityFrameworkCore
{
public static class PlatformDbContextModelBuilderExtensions
{
public static void ConfigurePlatform(
this ModelBuilder builder,
Action<PlatformModelBuilderConfigurationOptions> optionsAction = null)
{
Check.NotNull(builder, nameof(builder));
var options = new PlatformModelBuilderConfigurationOptions(
PlatformDbProperties.DbTablePrefix,
PlatformDbProperties.DbSchema
);
optionsAction?.Invoke(options);
builder.Entity<Layout>(b =>
{
b.ToTable(options.TablePrefix + "Layouts", options.Schema);
b.ConfigureRoute();
});
builder.Entity<Menu>(b =>
{
b.ToTable(options.TablePrefix + "Menus", options.Schema);
b.ConfigureRoute();
b.Property(p => p.Component)
.HasMaxLength(MenuConsts.MaxComponentLength)
.HasColumnName(nameof(Menu.Component))
.IsRequired();
b.Property(p => p.Code)
.HasMaxLength(MenuConsts.MaxCodeLength)
.HasColumnName(nameof(Menu.Code))
.IsRequired();
});
builder.Entity<RoleMenu>(x =>
{
x.ToTable(options.TablePrefix + "RoleMenus");
x.Property(p => p.RoleName)
.IsRequired()
.HasMaxLength(RoleRouteConsts.MaxRoleNameLength)
.HasColumnName(nameof(RoleMenu.RoleName));
x.ConfigureByConvention();
x.HasIndex(i => new { i.RoleName, i.MenuId });
});
builder.Entity<UserMenu>(x =>
{
x.ToTable(options.TablePrefix + "UserMenus");
x.ConfigureByConvention();
x.HasIndex(i => new { i.UserId, i.MenuId });
});
builder.Entity<Data>(x =>
{
x.ToTable(options.TablePrefix + "Datas");
x.Property(p => p.Code)
.HasMaxLength(DataConsts.MaxCodeLength)
.HasColumnName(nameof(Data.Code))
.IsRequired();
x.Property(p => p.Name)
.HasMaxLength(DataConsts.MaxNameLength)
.HasColumnName(nameof(Data.Name))
.IsRequired();
x.Property(p => p.DisplayName)
.HasMaxLength(DataConsts.MaxDisplayNameLength)
.HasColumnName(nameof(Data.DisplayName))
.IsRequired();
x.Property(p => p.Description)
.HasMaxLength(DataConsts.MaxDescriptionLength)
.HasColumnName(nameof(Data.Description));
x.ConfigureByConvention();
x.HasMany(p => p.Items)
.WithOne()
.HasForeignKey(fk => fk.DataId)
.IsRequired();
x.HasIndex(i => new { i.Name });
});
builder.Entity<DataItem>(x =>
{
x.ToTable(options.TablePrefix + "DataItems");
x.Property(p => p.DefaultValue)
.HasMaxLength(DataItemConsts.MaxValueLength)
.HasColumnName(nameof(DataItem.DefaultValue));
x.Property(p => p.Name)
.HasMaxLength(DataItemConsts.MaxNameLength)
.HasColumnName(nameof(DataItem.Name))
.IsRequired();
x.Property(p => p.DisplayName)
.HasMaxLength(DataItemConsts.MaxDisplayNameLength)
.HasColumnName(nameof(DataItem.DisplayName))
.IsRequired();
x.Property(p => p.Description)
.HasMaxLength(DataItemConsts.MaxDescriptionLength)
.HasColumnName(nameof(DataItem.Description));
x.Property(p => p.AllowBeNull).HasDefaultValue(true);
x.ConfigureByConvention();
x.HasIndex(i => new { i.Name });
});
builder.Entity<AppVersion>(x =>
{
x.ToTable(options.TablePrefix + "Version", options.Schema);
x.Property(p => p.Title)
.IsRequired()
.HasColumnName(nameof(AppVersion.Title))
.HasMaxLength(AppVersionConsts.MaxTitleLength);
x.Property(p => p.Version)
.IsRequired()
.HasColumnName(nameof(AppVersion.Version))
.HasMaxLength(AppVersionConsts.MaxVersionLength);
x.Property(p => p.Description)
.HasColumnName(nameof(AppVersion.Description))
.HasMaxLength(AppVersionConsts.MaxDescriptionLength);
x.ConfigureByConvention();
x.HasIndex(i => i.Version);
x.HasMany(p => p.Files)
.WithOne(q => q.AppVersion)
.HasPrincipalKey(pk => pk.Id)
.HasForeignKey(fk => fk.AppVersionId)
.OnDelete(DeleteBehavior.Cascade);
});
builder.Entity<VersionFile>(x =>
{
x.ToTable(options.TablePrefix + "VersionFile", options.Schema);
x.Property(p => p.Name)
.IsRequired()
.HasColumnName(nameof(VersionFile.Name))
.HasMaxLength(VersionFileConsts.MaxNameLength);
x.Property(p => p.SHA256)
.IsRequired()
.HasColumnName(nameof(VersionFile.SHA256))
.HasMaxLength(VersionFileConsts.MaxSHA256Length);
x.Property(p => p.Version)
.IsRequired()
.HasColumnName(nameof(VersionFile.Version))
.HasMaxLength(VersionFileConsts.MaxVersionLength);
x.Property(p => p.Path)
.HasColumnName(nameof(VersionFile.Path))
.HasMaxLength(VersionFileConsts.MaxPathLength);
x.ConfigureAudited();
x.ConfigureMultiTenant();
x.HasIndex(i => new { i.Path, i.Name, i.Version }).IsUnique();
});
}
public static EntityTypeBuilder<TRoute> ConfigureRoute<TRoute>(
this EntityTypeBuilder<TRoute> builder)
where TRoute : Route
{
builder
.Property(p => p.DisplayName)
.HasMaxLength(RouteConsts.MaxDisplayNameLength)
.HasColumnName(nameof(Route.DisplayName))
.IsRequired();
builder
.Property(p => p.Name)
.HasMaxLength(RouteConsts.MaxNameLength)
.HasColumnName(nameof(Route.Name))
.IsRequired();
builder
.Property(p => p.Path)
.HasMaxLength(RouteConsts.MaxPathLength)
.HasColumnName(nameof(Route.Path));
builder
.Property(p => p.Redirect)
.HasMaxLength(RouteConsts.MaxRedirectLength)
.HasColumnName(nameof(Route.Redirect));
builder.ConfigureByConvention();
return builder;
}
public static OwnedNavigationBuilder<TEntity, TRoute> ConfigureRoute<TEntity, TRoute>(
[NotNull] this OwnedNavigationBuilder<TEntity, TRoute> builder,
[CanBeNull] string tablePrefix = "",
[CanBeNull] string schema = null)
where TEntity : class
where TRoute : Route
{
builder.ToTable(tablePrefix + "Routes", schema);
builder
.Property(p => p.DisplayName)
.HasMaxLength(RouteConsts.MaxDisplayNameLength)
.HasColumnName(nameof(Route.DisplayName))
.IsRequired();
builder
.Property(p => p.Name)
.HasMaxLength(RouteConsts.MaxNameLength)
.HasColumnName(nameof(Route.Name))
.IsRequired();
builder
.Property(p => p.Path)
.HasMaxLength(RouteConsts.MaxPathLength)
.HasColumnName(nameof(Route.Path));
builder
.Property(p => p.Redirect)
.HasMaxLength(RouteConsts.MaxRedirectLength)
.HasColumnName(nameof(Route.Redirect));
return builder;
}
}
}
using JetBrains.Annotations;
using LINGYUN.Platform.Datas;
using LINGYUN.Platform.Layouts;
using LINGYUN.Platform.Menus;
using LINGYUN.Platform.Routes;
using LINGYUN.Platform.Versions;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System;
using Volo.Abp;
using Volo.Abp.EntityFrameworkCore.Modeling;
namespace LINGYUN.Platform.EntityFrameworkCore
{
public static class PlatformDbContextModelBuilderExtensions
{
public static void ConfigurePlatform(
this ModelBuilder builder,
Action<PlatformModelBuilderConfigurationOptions> optionsAction = null)
{
Check.NotNull(builder, nameof(builder));
var options = new PlatformModelBuilderConfigurationOptions(
PlatformDbProperties.DbTablePrefix,
PlatformDbProperties.DbSchema
);
optionsAction?.Invoke(options);
builder.Entity<Layout>(b =>
{
b.ToTable(options.TablePrefix + "Layouts", options.Schema);
b.Property(p => p.Framework)
.HasMaxLength(LayoutConsts.MaxFrameworkLength)
.HasColumnName(nameof(Layout.Framework))
.IsRequired();
b.ConfigureRoute();
});
builder.Entity<Menu>(b =>
{
b.ToTable(options.TablePrefix + "Menus", options.Schema);
b.ConfigureRoute();
b.Property(p => p.Framework)
.HasMaxLength(LayoutConsts.MaxFrameworkLength)
.HasColumnName(nameof(Menu.Framework))
.IsRequired();
b.Property(p => p.Component)
.HasMaxLength(MenuConsts.MaxComponentLength)
.HasColumnName(nameof(Menu.Component))
.IsRequired();
b.Property(p => p.Code)
.HasMaxLength(MenuConsts.MaxCodeLength)
.HasColumnName(nameof(Menu.Code))
.IsRequired();
});
builder.Entity<RoleMenu>(x =>
{
x.ToTable(options.TablePrefix + "RoleMenus");
x.Property(p => p.RoleName)
.IsRequired()
.HasMaxLength(RoleRouteConsts.MaxRoleNameLength)
.HasColumnName(nameof(RoleMenu.RoleName));
x.ConfigureByConvention();
x.HasIndex(i => new { i.RoleName, i.MenuId });
});
builder.Entity<UserMenu>(x =>
{
x.ToTable(options.TablePrefix + "UserMenus");
x.ConfigureByConvention();
x.HasIndex(i => new { i.UserId, i.MenuId });
});
builder.Entity<Data>(x =>
{
x.ToTable(options.TablePrefix + "Datas");
x.Property(p => p.Code)
.HasMaxLength(DataConsts.MaxCodeLength)
.HasColumnName(nameof(Data.Code))
.IsRequired();
x.Property(p => p.Name)
.HasMaxLength(DataConsts.MaxNameLength)
.HasColumnName(nameof(Data.Name))
.IsRequired();
x.Property(p => p.DisplayName)
.HasMaxLength(DataConsts.MaxDisplayNameLength)
.HasColumnName(nameof(Data.DisplayName))
.IsRequired();
x.Property(p => p.Description)
.HasMaxLength(DataConsts.MaxDescriptionLength)
.HasColumnName(nameof(Data.Description));
x.ConfigureByConvention();
x.HasMany(p => p.Items)
.WithOne()
.HasForeignKey(fk => fk.DataId)
.IsRequired();
x.HasIndex(i => new { i.Name });
});
builder.Entity<DataItem>(x =>
{
x.ToTable(options.TablePrefix + "DataItems");
x.Property(p => p.DefaultValue)
.HasMaxLength(DataItemConsts.MaxValueLength)
.HasColumnName(nameof(DataItem.DefaultValue));
x.Property(p => p.Name)
.HasMaxLength(DataItemConsts.MaxNameLength)
.HasColumnName(nameof(DataItem.Name))
.IsRequired();
x.Property(p => p.DisplayName)
.HasMaxLength(DataItemConsts.MaxDisplayNameLength)
.HasColumnName(nameof(DataItem.DisplayName))
.IsRequired();
x.Property(p => p.Description)
.HasMaxLength(DataItemConsts.MaxDescriptionLength)
.HasColumnName(nameof(DataItem.Description));
x.Property(p => p.AllowBeNull).HasDefaultValue(true);
x.ConfigureByConvention();
x.HasIndex(i => new { i.Name });
});
builder.Entity<AppVersion>(x =>
{
x.ToTable(options.TablePrefix + "Version", options.Schema);
x.Property(p => p.Title)
.IsRequired()
.HasColumnName(nameof(AppVersion.Title))
.HasMaxLength(AppVersionConsts.MaxTitleLength);
x.Property(p => p.Version)
.IsRequired()
.HasColumnName(nameof(AppVersion.Version))
.HasMaxLength(AppVersionConsts.MaxVersionLength);
x.Property(p => p.Description)
.HasColumnName(nameof(AppVersion.Description))
.HasMaxLength(AppVersionConsts.MaxDescriptionLength);
x.ConfigureByConvention();
x.HasIndex(i => i.Version);
x.HasMany(p => p.Files)
.WithOne(q => q.AppVersion)
.HasPrincipalKey(pk => pk.Id)
.HasForeignKey(fk => fk.AppVersionId)
.OnDelete(DeleteBehavior.Cascade);
});
builder.Entity<VersionFile>(x =>
{
x.ToTable(options.TablePrefix + "VersionFile", options.Schema);
x.Property(p => p.Name)
.IsRequired()
.HasColumnName(nameof(VersionFile.Name))
.HasMaxLength(VersionFileConsts.MaxNameLength);
x.Property(p => p.SHA256)
.IsRequired()
.HasColumnName(nameof(VersionFile.SHA256))
.HasMaxLength(VersionFileConsts.MaxSHA256Length);
x.Property(p => p.Version)
.IsRequired()
.HasColumnName(nameof(VersionFile.Version))
.HasMaxLength(VersionFileConsts.MaxVersionLength);
x.Property(p => p.Path)
.HasColumnName(nameof(VersionFile.Path))
.HasMaxLength(VersionFileConsts.MaxPathLength);
x.ConfigureAudited();
x.ConfigureMultiTenant();
x.HasIndex(i => new { i.Path, i.Name, i.Version }).IsUnique();
});
}
public static EntityTypeBuilder<TRoute> ConfigureRoute<TRoute>(
this EntityTypeBuilder<TRoute> builder)
where TRoute : Route
{
builder
.Property(p => p.DisplayName)
.HasMaxLength(RouteConsts.MaxDisplayNameLength)
.HasColumnName(nameof(Route.DisplayName))
.IsRequired();
builder
.Property(p => p.Name)
.HasMaxLength(RouteConsts.MaxNameLength)
.HasColumnName(nameof(Route.Name))
.IsRequired();
builder
.Property(p => p.Path)
.HasMaxLength(RouteConsts.MaxPathLength)
.HasColumnName(nameof(Route.Path));
builder
.Property(p => p.Redirect)
.HasMaxLength(RouteConsts.MaxRedirectLength)
.HasColumnName(nameof(Route.Redirect));
builder.ConfigureByConvention();
return builder;
}
public static OwnedNavigationBuilder<TEntity, TRoute> ConfigureRoute<TEntity, TRoute>(
[NotNull] this OwnedNavigationBuilder<TEntity, TRoute> builder,
[CanBeNull] string tablePrefix = "",
[CanBeNull] string schema = null)
where TEntity : class
where TRoute : Route
{
builder.ToTable(tablePrefix + "Routes", schema);
builder
.Property(p => p.DisplayName)
.HasMaxLength(RouteConsts.MaxDisplayNameLength)
.HasColumnName(nameof(Route.DisplayName))
.IsRequired();
builder
.Property(p => p.Name)
.HasMaxLength(RouteConsts.MaxNameLength)
.HasColumnName(nameof(Route.Name))
.IsRequired();
builder
.Property(p => p.Path)
.HasMaxLength(RouteConsts.MaxPathLength)
.HasColumnName(nameof(Route.Path));
builder
.Property(p => p.Redirect)
.HasMaxLength(RouteConsts.MaxRedirectLength)
.HasColumnName(nameof(Route.Redirect));
return builder;
}
}
}

160
aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/Layouts/EfCoreLayoutRepository.cs

@ -1,80 +1,80 @@
using LINGYUN.Platform.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.Platform.Layouts
{
public class EfCoreLayoutRepository : EfCoreRepository<PlatformDbContext, Layout, Guid>, ILayoutRepository
{
public EfCoreLayoutRepository(IDbContextProvider<PlatformDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public virtual async Task<Layout> FindByNameAsync(
string name,
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.IncludeDetails(includeDetails)
.Where(x => x.Name == name)
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<int> GetCountAsync(
PlatformType? platformType = null,
string filter = "",
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.WhereIf(platformType.HasValue, x => x.PlatformType == platformType.Value)
.WhereIf(!filter.IsNullOrWhiteSpace(), x =>
x.Name.Contains(filter) || x.DisplayName.Contains(filter) ||
x.Description.Contains(filter) || x.Redirect.Contains(filter))
.CountAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Layout>> GetPagedListAsync(
PlatformType? platformType = null,
string filter = "",
string sorting = nameof(Layout.Name),
bool reverse = false,
bool includeDetails = false,
int skipCount = 0,
int maxResultCount = 10,
CancellationToken cancellationToken = default)
{
sorting ??= nameof(Layout.Name);
sorting = reverse ? sorting + " DESC" : sorting;
return await (await GetDbSetAsync())
.IncludeDetails(includeDetails)
.WhereIf(platformType.HasValue, x => x.PlatformType == platformType.Value)
.WhereIf(!filter.IsNullOrWhiteSpace(), x =>
x.Name.Contains(filter) || x.DisplayName.Contains(filter) ||
x.Description.Contains(filter) || x.Redirect.Contains(filter))
.OrderBy(sorting)
.PageBy(skipCount, maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public override async Task<IQueryable<Layout>> WithDetailsAsync()
{
return (await GetQueryableAsync()).IncludeDetails();
}
[System.Obsolete("将在abp框架移除之后删除")]
public override IQueryable<Layout> WithDetails()
{
return GetQueryable().IncludeDetails();
}
}
}
using LINGYUN.Platform.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.Platform.Layouts
{
public class EfCoreLayoutRepository : EfCoreRepository<PlatformDbContext, Layout, Guid>, ILayoutRepository
{
public EfCoreLayoutRepository(IDbContextProvider<PlatformDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public virtual async Task<Layout> FindByNameAsync(
string name,
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.IncludeDetails(includeDetails)
.Where(x => x.Name == name)
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<int> GetCountAsync(
string framework = "",
string filter = "",
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.WhereIf(!framework.IsNullOrWhiteSpace(), x => x.Framework.Equals(framework))
.WhereIf(!filter.IsNullOrWhiteSpace(), x =>
x.Name.Contains(filter) || x.DisplayName.Contains(filter) ||
x.Description.Contains(filter) || x.Redirect.Contains(filter))
.CountAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Layout>> GetPagedListAsync(
string framework = "",
string filter = "",
string sorting = nameof(Layout.Name),
bool reverse = false,
bool includeDetails = false,
int skipCount = 0,
int maxResultCount = 10,
CancellationToken cancellationToken = default)
{
sorting ??= nameof(Layout.Name);
sorting = reverse ? sorting + " DESC" : sorting;
return await (await GetDbSetAsync())
.IncludeDetails(includeDetails)
.WhereIf(!framework.IsNullOrWhiteSpace(), x => x.Framework.Equals(framework))
.WhereIf(!filter.IsNullOrWhiteSpace(), x =>
x.Name.Contains(filter) || x.DisplayName.Contains(filter) ||
x.Description.Contains(filter) || x.Redirect.Contains(filter))
.OrderBy(sorting)
.PageBy(skipCount, maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public override async Task<IQueryable<Layout>> WithDetailsAsync()
{
return (await GetQueryableAsync()).IncludeDetails();
}
[System.Obsolete("将在abp框架移除之后删除")]
public override IQueryable<Layout> WithDetails()
{
return GetQueryable().IncludeDetails();
}
}
}

504
aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/Menus/EfCoreMenuRepository.cs

@ -1,252 +1,252 @@
using LINGYUN.Platform.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.Platform.Menus
{
public class EfCoreMenuRepository : EfCoreRepository<PlatformDbContext, Menu, Guid>, IMenuRepository
{
public EfCoreMenuRepository(
IDbContextProvider<PlatformDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public virtual async Task<bool> UserHasInMenuAsync(
Guid userId,
string menuName,
CancellationToken cancellationToken = default)
{
var menuQuery = (await GetDbSetAsync()).Where(x => x.Name == menuName);
return await (from menu in menuQuery
join userMenu in (await GetDbContextAsync()).Set<UserMenu>()
on menu.Id equals userMenu.MenuId
select userMenu)
.AnyAsync(x => x.UserId == userId, GetCancellationToken(cancellationToken));
}
public virtual async Task<bool> RoleHasInMenuAsync(
string roleName,
string menuName,
CancellationToken cancellationToken = default)
{
var menuQuery = (await GetDbSetAsync()).Where(x => x.Name == menuName);
return await (from menu in menuQuery
join roleMenu in (await GetDbContextAsync()).Set<RoleMenu>()
on menu.Id equals roleMenu.MenuId
select roleMenu)
.AnyAsync(x => x.RoleName == roleName, GetCancellationToken(cancellationToken));
}
public virtual async Task<Menu> FindByNameAsync(
string menuName,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.Where(x => x.Name == menuName)
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<Menu> FindMainAsync(
PlatformType platformType = PlatformType.None,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.Where(menu => menu.PlatformType.HasFlag(platformType) && menu.Path == "/")
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Menu>> GetRoleMenusAsync(
string[] roles,
PlatformType platformType = PlatformType.None,
CancellationToken cancellationToken = default)
{
var menuQuery = (await GetDbSetAsync())
.Where(menu => menu.PlatformType.HasFlag(platformType));
var roleMenuQuery = (await GetDbContextAsync()).Set<RoleMenu>()
.Where(menu => roles.Contains(menu.RoleName));
return await (from menu in menuQuery
join roleMenu in roleMenuQuery
on menu.Id equals roleMenu.MenuId
select menu)
.Union(menuQuery.Where(x => x.IsPublic))
.Distinct()
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Menu>> GetUserMenusAsync(
Guid userId,
string[] roles,
PlatformType platformType = PlatformType.None,
CancellationToken cancellationToken = default)
{
var menuQuery = (await GetDbSetAsync())
.Where(menu => menu.PlatformType.HasFlag(platformType));
var dbContext = await GetDbContextAsync();
var userMenuQuery = from userMenu in dbContext.Set<UserMenu>()
join menu in menuQuery
on userMenu.MenuId equals menu.Id
where userMenu.UserId == userId
select menu;
if (roles != null && roles.Length > 0)
{
var roleMenuQuery = from roleMenu in dbContext.Set<RoleMenu>()
join menu in menuQuery
on roleMenu.MenuId equals menu.Id
where roles.Contains(roleMenu.RoleName)
select menu; ;
return await userMenuQuery
.Union(roleMenuQuery)
.Union(menuQuery.Where(x => x.IsPublic))
.Distinct()
.ToListAsync(GetCancellationToken(cancellationToken));
}
return await userMenuQuery
.Union(menuQuery.Where(x => x.IsPublic))
.Distinct()
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Menu>> GetChildrenAsync(
Guid? parentId,
CancellationToken cancellationToken = default
)
{
return await (await GetDbSetAsync())
.Where(x => x.ParentId == parentId)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Menu>> GetAllChildrenWithParentCodeAsync(
string code,
Guid? parentId,
CancellationToken cancellationToken = default
)
{
return await (await GetDbSetAsync())
.Where(x => x.Code.StartsWith(code) && x.Id != parentId.Value)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Menu>> GetAllAsync(
string filter = "",
string sorting = nameof(Menu.Code),
bool reverse = false,
PlatformType? platformType = null,
Guid? parentId = null,
Guid? layoutId = null,
CancellationToken cancellationToken = default)
{
sorting ??= nameof(Menu.Code);
sorting = reverse ? sorting + " DESC" : sorting;
return await (await GetDbSetAsync())
.WhereIf(parentId.HasValue, x => x.ParentId == parentId)
.WhereIf(layoutId.HasValue, x => x.LayoutId == layoutId)
.WhereIf(platformType.HasValue, menu => menu.PlatformType.HasFlag(platformType.Value))
.WhereIf(!filter.IsNullOrWhiteSpace(), menu =>
menu.Path.Contains(filter) || menu.Name.Contains(filter) ||
menu.DisplayName.Contains(filter) || menu.Description.Contains(filter) ||
menu.Redirect.Contains(filter))
.OrderBy(sorting)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<int> GetCountAsync(
string filter = "",
PlatformType? platformType = null,
Guid? parentId = null,
Guid? layoutId = null,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.WhereIf(parentId.HasValue, x => x.ParentId == parentId)
.WhereIf(layoutId.HasValue, x => x.LayoutId == layoutId)
.WhereIf(platformType.HasValue, menu => menu.PlatformType.HasFlag(platformType.Value))
.WhereIf(!filter.IsNullOrWhiteSpace(), menu =>
menu.Path.Contains(filter) || menu.Name.Contains(filter) ||
menu.DisplayName.Contains(filter) || menu.Description.Contains(filter) ||
menu.Redirect.Contains(filter))
.CountAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Menu>> GetListAsync(
string filter = "",
string sorting = nameof(Menu.Code),
bool reverse = false,
PlatformType? platformType = null,
Guid? parentId = null,
Guid? layoutId = null,
int skipCount = 0,
int maxResultCount = 10,
CancellationToken cancellationToken = default)
{
sorting ??= nameof(Menu.Code);
sorting = reverse ? sorting + " DESC" : sorting;
return await (await GetDbSetAsync())
.WhereIf(parentId.HasValue, x => x.ParentId == parentId)
.WhereIf(layoutId.HasValue, x => x.LayoutId == layoutId)
.WhereIf(platformType.HasValue, menu => menu.PlatformType.HasFlag(platformType.Value))
.WhereIf(!filter.IsNullOrWhiteSpace(), menu =>
menu.Path.Contains(filter) || menu.Name.Contains(filter) ||
menu.DisplayName.Contains(filter) || menu.Description.Contains(filter) ||
menu.Redirect.Contains(filter))
.OrderBy(sorting)
.PageBy(skipCount, maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task RemoveAllRolesAsync(
Menu menu,
CancellationToken cancellationToken = default
)
{
var dbContext = await GetDbContextAsync();
var rolesQuery = await dbContext.Set<RoleMenu>()
.Where(q => q.MenuId == menu.Id)
.ToListAsync(GetCancellationToken(cancellationToken));
dbContext.Set<RoleMenu>().RemoveRange(rolesQuery);
}
public virtual async Task RemoveAllMembersAsync(
Menu menu,
CancellationToken cancellationToken = default
)
{
var dbContext = await GetDbContextAsync();
var membersQuery = await dbContext.Set<UserMenu>()
.Where(q => q.MenuId == menu.Id)
.ToListAsync(GetCancellationToken(cancellationToken));
dbContext.Set<UserMenu>().RemoveRange(membersQuery);
}
public override async Task<IQueryable<Menu>> WithDetailsAsync()
{
return (await GetQueryableAsync()).IncludeDetails();
}
[System.Obsolete("将在abp框架移除之后删除")]
public override IQueryable<Menu> WithDetails()
{
return GetQueryable().IncludeDetails();
}
}
}
using LINGYUN.Platform.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.Platform.Menus
{
public class EfCoreMenuRepository : EfCoreRepository<PlatformDbContext, Menu, Guid>, IMenuRepository
{
public EfCoreMenuRepository(
IDbContextProvider<PlatformDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public virtual async Task<bool> UserHasInMenuAsync(
Guid userId,
string menuName,
CancellationToken cancellationToken = default)
{
var menuQuery = (await GetDbSetAsync()).Where(x => x.Name == menuName);
return await (from menu in menuQuery
join userMenu in (await GetDbContextAsync()).Set<UserMenu>()
on menu.Id equals userMenu.MenuId
select userMenu)
.AnyAsync(x => x.UserId == userId, GetCancellationToken(cancellationToken));
}
public virtual async Task<bool> RoleHasInMenuAsync(
string roleName,
string menuName,
CancellationToken cancellationToken = default)
{
var menuQuery = (await GetDbSetAsync()).Where(x => x.Name == menuName);
return await (from menu in menuQuery
join roleMenu in (await GetDbContextAsync()).Set<RoleMenu>()
on menu.Id equals roleMenu.MenuId
select roleMenu)
.AnyAsync(x => x.RoleName == roleName, GetCancellationToken(cancellationToken));
}
public virtual async Task<Menu> FindByNameAsync(
string menuName,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.Where(x => x.Name == menuName)
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<Menu> FindMainAsync(
string framework = "",
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.Where(menu => menu.Framework.Equals(framework) && menu.Path == "/")
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Menu>> GetRoleMenusAsync(
string[] roles,
string framework = "",
CancellationToken cancellationToken = default)
{
var menuQuery = (await GetDbSetAsync())
.Where(menu => menu.Framework.Equals(framework));
var roleMenuQuery = (await GetDbContextAsync()).Set<RoleMenu>()
.Where(menu => roles.Contains(menu.RoleName));
return await (from menu in menuQuery
join roleMenu in roleMenuQuery
on menu.Id equals roleMenu.MenuId
select menu)
.Union(menuQuery.Where(x => x.IsPublic))
.Distinct()
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Menu>> GetUserMenusAsync(
Guid userId,
string[] roles,
string framework = "",
CancellationToken cancellationToken = default)
{
var menuQuery = (await GetDbSetAsync())
.Where(menu => menu.Framework.Equals(framework));
var dbContext = await GetDbContextAsync();
var userMenuQuery = from userMenu in dbContext.Set<UserMenu>()
join menu in menuQuery
on userMenu.MenuId equals menu.Id
where userMenu.UserId == userId
select menu;
if (roles != null && roles.Length > 0)
{
var roleMenuQuery = from roleMenu in dbContext.Set<RoleMenu>()
join menu in menuQuery
on roleMenu.MenuId equals menu.Id
where roles.Contains(roleMenu.RoleName)
select menu; ;
return await userMenuQuery
.Union(roleMenuQuery)
.Union(menuQuery.Where(x => x.IsPublic))
.Distinct()
.ToListAsync(GetCancellationToken(cancellationToken));
}
return await userMenuQuery
.Union(menuQuery.Where(x => x.IsPublic))
.Distinct()
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Menu>> GetChildrenAsync(
Guid? parentId,
CancellationToken cancellationToken = default
)
{
return await (await GetDbSetAsync())
.Where(x => x.ParentId == parentId)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Menu>> GetAllChildrenWithParentCodeAsync(
string code,
Guid? parentId,
CancellationToken cancellationToken = default
)
{
return await (await GetDbSetAsync())
.Where(x => x.Code.StartsWith(code) && x.Id != parentId.Value)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Menu>> GetAllAsync(
string filter = "",
string sorting = nameof(Menu.Code),
bool reverse = false,
string framework = "",
Guid? parentId = null,
Guid? layoutId = null,
CancellationToken cancellationToken = default)
{
sorting ??= nameof(Menu.Code);
sorting = reverse ? sorting + " DESC" : sorting;
return await (await GetDbSetAsync())
.WhereIf(parentId.HasValue, x => x.ParentId == parentId)
.WhereIf(layoutId.HasValue, x => x.LayoutId == layoutId)
.WhereIf(!framework.IsNullOrWhiteSpace(), menu => menu.Framework.Equals(framework))
.WhereIf(!filter.IsNullOrWhiteSpace(), menu =>
menu.Path.Contains(filter) || menu.Name.Contains(filter) ||
menu.DisplayName.Contains(filter) || menu.Description.Contains(filter) ||
menu.Redirect.Contains(filter))
.OrderBy(sorting)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<int> GetCountAsync(
string filter = "",
string framework = "",
Guid? parentId = null,
Guid? layoutId = null,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.WhereIf(parentId.HasValue, x => x.ParentId == parentId)
.WhereIf(layoutId.HasValue, x => x.LayoutId == layoutId)
.WhereIf(!framework.IsNullOrWhiteSpace(), menu => menu.Framework.Equals(framework))
.WhereIf(!filter.IsNullOrWhiteSpace(), menu =>
menu.Path.Contains(filter) || menu.Name.Contains(filter) ||
menu.DisplayName.Contains(filter) || menu.Description.Contains(filter) ||
menu.Redirect.Contains(filter))
.CountAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Menu>> GetListAsync(
string filter = "",
string sorting = nameof(Menu.Code),
bool reverse = false,
string framework = "",
Guid? parentId = null,
Guid? layoutId = null,
int skipCount = 0,
int maxResultCount = 10,
CancellationToken cancellationToken = default)
{
sorting ??= nameof(Menu.Code);
sorting = reverse ? sorting + " DESC" : sorting;
return await (await GetDbSetAsync())
.WhereIf(parentId.HasValue, x => x.ParentId == parentId)
.WhereIf(layoutId.HasValue, x => x.LayoutId == layoutId)
.WhereIf(!framework.IsNullOrWhiteSpace(), menu => menu.Framework.Equals(framework))
.WhereIf(!filter.IsNullOrWhiteSpace(), menu =>
menu.Path.Contains(filter) || menu.Name.Contains(filter) ||
menu.DisplayName.Contains(filter) || menu.Description.Contains(filter) ||
menu.Redirect.Contains(filter))
.OrderBy(sorting)
.PageBy(skipCount, maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task RemoveAllRolesAsync(
Menu menu,
CancellationToken cancellationToken = default
)
{
var dbContext = await GetDbContextAsync();
var rolesQuery = await dbContext.Set<RoleMenu>()
.Where(q => q.MenuId == menu.Id)
.ToListAsync(GetCancellationToken(cancellationToken));
dbContext.Set<RoleMenu>().RemoveRange(rolesQuery);
}
public virtual async Task RemoveAllMembersAsync(
Menu menu,
CancellationToken cancellationToken = default
)
{
var dbContext = await GetDbContextAsync();
var membersQuery = await dbContext.Set<UserMenu>()
.Where(q => q.MenuId == menu.Id)
.ToListAsync(GetCancellationToken(cancellationToken));
dbContext.Set<UserMenu>().RemoveRange(membersQuery);
}
public override async Task<IQueryable<Menu>> WithDetailsAsync()
{
return (await GetQueryableAsync()).IncludeDetails();
}
[System.Obsolete("将在abp框架移除之后删除")]
public override IQueryable<Menu> WithDetails()
{
return GetQueryable().IncludeDetails();
}
}
}

175
aspnet-core/modules/platform/LINGYUN.Platform.HttpApi/LINGYUN/Platform/Datas/DataController.cs

@ -1,84 +1,91 @@
using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.AspNetCore.Mvc;
namespace LINGYUN.Platform.Datas
{
[RemoteService(Name = PlatformRemoteServiceConsts.RemoteServiceName)]
[Area("platform")]
[Route("api/platform/datas")]
public class DataController : AbpController, IDataAppService
{
protected IDataAppService DataAppService { get; }
public DataController(
IDataAppService dataAppService)
{
DataAppService = dataAppService;
}
[HttpPost]
public virtual async Task<DataDto> CreateAsync(DataCreateDto input)
{
return await DataAppService.CreateAsync(input);
}
[HttpPost]
[Route("{id}/items")]
public virtual async Task CreateItemAsync(Guid id, DataItemCreateDto input)
{
await DataAppService.CreateItemAsync(id, input);
}
[HttpDelete]
[Route("{id}")]
public virtual async Task DeleteAsync(Guid id)
{
await DataAppService.DeleteAsync(id);
}
[HttpDelete]
[Route("{id}/items/{name}")]
public virtual async Task DeleteItemAsync(Guid id, string name)
{
await DataAppService.DeleteItemAsync(id, name);
}
[HttpGet]
[Route("{id}")]
public virtual async Task<DataDto> GetAsync(Guid id)
{
return await DataAppService.GetAsync(id);
}
[HttpGet]
[Route("all")]
public virtual async Task<ListResultDto<DataDto>> GetAllAsync()
{
return await DataAppService.GetAllAsync();
}
[HttpGet]
public virtual async Task<PagedResultDto<DataDto>> GetListAsync(GetDataListInput input)
{
return await DataAppService.GetListAsync(input);
}
[HttpPut]
[Route("{id}")]
public virtual async Task<DataDto> UpdateAsync(Guid id, DataUpdateDto input)
{
return await DataAppService.UpdateAsync(id, input);
}
[HttpPut]
[Route("{id}/items/{name}")]
public virtual async Task UpdateItemAsync(Guid id, string name, DataItemUpdateDto input)
{
await DataAppService.UpdateItemAsync(id, name, input);
}
}
}
using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.AspNetCore.Mvc;
namespace LINGYUN.Platform.Datas
{
[RemoteService(Name = PlatformRemoteServiceConsts.RemoteServiceName)]
[Area("platform")]
[Route("api/platform/datas")]
public class DataController : AbpController, IDataAppService
{
protected IDataAppService DataAppService { get; }
public DataController(
IDataAppService dataAppService)
{
DataAppService = dataAppService;
}
[HttpPost]
public virtual async Task<DataDto> CreateAsync(DataCreateDto input)
{
return await DataAppService.CreateAsync(input);
}
[HttpPost]
[Route("{id}/items")]
public virtual async Task CreateItemAsync(Guid id, DataItemCreateDto input)
{
await DataAppService.CreateItemAsync(id, input);
}
[HttpDelete]
[Route("{id}")]
public virtual async Task DeleteAsync(Guid id)
{
await DataAppService.DeleteAsync(id);
}
[HttpDelete]
[Route("{id}/items/{name}")]
public virtual async Task DeleteItemAsync(Guid id, string name)
{
await DataAppService.DeleteItemAsync(id, name);
}
[HttpGet]
[Route("by-name/{name}")]
public virtual async Task<DataDto> GetAsync(string name)
{
return await DataAppService.GetAsync(name);
}
[HttpGet]
[Route("{id}")]
public virtual async Task<DataDto> GetAsync(Guid id)
{
return await DataAppService.GetAsync(id);
}
[HttpGet]
[Route("all")]
public virtual async Task<ListResultDto<DataDto>> GetAllAsync()
{
return await DataAppService.GetAllAsync();
}
[HttpGet]
public virtual async Task<PagedResultDto<DataDto>> GetListAsync(GetDataListInput input)
{
return await DataAppService.GetListAsync(input);
}
[HttpPut]
[Route("{id}")]
public virtual async Task<DataDto> UpdateAsync(Guid id, DataUpdateDto input)
{
return await DataAppService.UpdateAsync(id, input);
}
[HttpPut]
[Route("{id}/items/{name}")]
public virtual async Task UpdateItemAsync(Guid id, string name, DataItemUpdateDto input)
{
await DataAppService.UpdateItemAsync(id, name, input);
}
}
}

256
aspnet-core/modules/platform/LINGYUN.Platform.HttpApi/LINGYUN/Platform/Menus/MenuController.cs

@ -1,128 +1,128 @@
using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Identity;
namespace LINGYUN.Platform.Menus
{
[RemoteService(Name = PlatformRemoteServiceConsts.RemoteServiceName)]
[Area("platform")]
[Route("api/platform/menus")]
public class MenuController : AbpController, IMenuAppService
{
protected IMenuAppService MenuAppService { get; }
protected IUserRoleFinder UserRoleFinder { get; }
public MenuController(
IMenuAppService menuAppService,
IUserRoleFinder userRoleFinder)
{
MenuAppService = menuAppService;
UserRoleFinder = userRoleFinder;
}
[HttpGet]
[Route("by-current-user")]
public virtual async Task<ListResultDto<MenuDto>> GetCurrentUserMenuListAsync(GetMenuInput input)
{
return await MenuAppService.GetCurrentUserMenuListAsync(input);
}
[HttpGet]
[Route("{id}")]
public virtual async Task<MenuDto> GetAsync(Guid id)
{
return await MenuAppService.GetAsync(id);
}
[HttpGet]
[Route("all")]
public virtual async Task<ListResultDto<MenuDto>> GetAllAsync(MenuGetAllInput input)
{
return await MenuAppService.GetAllAsync(input);
}
[HttpGet]
public virtual async Task<PagedResultDto<MenuDto>> GetListAsync(MenuGetListInput input)
{
return await MenuAppService.GetListAsync(input);
}
[HttpPost]
public virtual async Task<MenuDto> CreateAsync(MenuCreateDto input)
{
return await MenuAppService.CreateAsync(input);
}
[HttpPut]
[Route("{id}")]
public virtual async Task<MenuDto> UpdateAsync(Guid id, MenuUpdateDto input)
{
return await MenuAppService.UpdateAsync(id, input);
}
[HttpDelete]
[Route("{id}")]
public virtual async Task DeleteAsync(Guid id)
{
await MenuAppService.DeleteAsync(id);
}
[HttpPut]
[Route("by-user")]
public virtual async Task SetUserMenusAsync(UserMenuInput input)
{
await MenuAppService.SetUserMenusAsync(input);
}
[HttpGet]
[Route("by-user")]
public virtual async Task<ListResultDto<MenuDto>> GetUserMenuListAsync(MenuGetByUserInput input)
{
return await MenuAppService.GetUserMenuListAsync(input);
}
[HttpGet]
[Route("by-user/{userId}/{platformType}")]
public virtual async Task<ListResultDto<MenuDto>> GetUserMenuListAsync(Guid userId, PlatformType platformType)
{
var userRoles = await UserRoleFinder.GetRolesAsync(userId);
var getMenuByUser = new MenuGetByUserInput
{
UserId = userId,
Roles = userRoles,
PlatformType = platformType
};
return await MenuAppService.GetUserMenuListAsync(getMenuByUser);
}
[HttpPut]
[Route("by-role")]
public virtual async Task SetRoleMenusAsync(RoleMenuInput input)
{
await MenuAppService.SetRoleMenusAsync(input);
}
[HttpGet]
[Route("by-role")]
public virtual async Task<ListResultDto<MenuDto>> GetRoleMenuListAsync(MenuGetByRoleInput input)
{
return await MenuAppService.GetRoleMenuListAsync(input);
}
[HttpGet]
[Route("by-role/{role}/{platformType}")]
public virtual async Task<ListResultDto<MenuDto>> GetRoleMenuListAsync(string role, PlatformType platformType)
{
return await MenuAppService.GetRoleMenuListAsync(new MenuGetByRoleInput
{
Role = role,
PlatformType = platformType
});
}
}
}
using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Identity;
namespace LINGYUN.Platform.Menus
{
[RemoteService(Name = PlatformRemoteServiceConsts.RemoteServiceName)]
[Area("platform")]
[Route("api/platform/menus")]
public class MenuController : AbpController, IMenuAppService
{
protected IMenuAppService MenuAppService { get; }
protected IUserRoleFinder UserRoleFinder { get; }
public MenuController(
IMenuAppService menuAppService,
IUserRoleFinder userRoleFinder)
{
MenuAppService = menuAppService;
UserRoleFinder = userRoleFinder;
}
[HttpGet]
[Route("by-current-user")]
public virtual async Task<ListResultDto<MenuDto>> GetCurrentUserMenuListAsync(GetMenuInput input)
{
return await MenuAppService.GetCurrentUserMenuListAsync(input);
}
[HttpGet]
[Route("{id}")]
public virtual async Task<MenuDto> GetAsync(Guid id)
{
return await MenuAppService.GetAsync(id);
}
[HttpGet]
[Route("all")]
public virtual async Task<ListResultDto<MenuDto>> GetAllAsync(MenuGetAllInput input)
{
return await MenuAppService.GetAllAsync(input);
}
[HttpGet]
public virtual async Task<PagedResultDto<MenuDto>> GetListAsync(MenuGetListInput input)
{
return await MenuAppService.GetListAsync(input);
}
[HttpPost]
public virtual async Task<MenuDto> CreateAsync(MenuCreateDto input)
{
return await MenuAppService.CreateAsync(input);
}
[HttpPut]
[Route("{id}")]
public virtual async Task<MenuDto> UpdateAsync(Guid id, MenuUpdateDto input)
{
return await MenuAppService.UpdateAsync(id, input);
}
[HttpDelete]
[Route("{id}")]
public virtual async Task DeleteAsync(Guid id)
{
await MenuAppService.DeleteAsync(id);
}
[HttpPut]
[Route("by-user")]
public virtual async Task SetUserMenusAsync(UserMenuInput input)
{
await MenuAppService.SetUserMenusAsync(input);
}
[HttpGet]
[Route("by-user")]
public virtual async Task<ListResultDto<MenuDto>> GetUserMenuListAsync(MenuGetByUserInput input)
{
return await MenuAppService.GetUserMenuListAsync(input);
}
[HttpGet]
[Route("by-user/{userId}/{framework}")]
public virtual async Task<ListResultDto<MenuDto>> GetUserMenuListAsync(Guid userId, string framework)
{
var userRoles = await UserRoleFinder.GetRolesAsync(userId);
var getMenuByUser = new MenuGetByUserInput
{
UserId = userId,
Roles = userRoles,
Framework = framework
};
return await MenuAppService.GetUserMenuListAsync(getMenuByUser);
}
[HttpPut]
[Route("by-role")]
public virtual async Task SetRoleMenusAsync(RoleMenuInput input)
{
await MenuAppService.SetRoleMenusAsync(input);
}
[HttpGet]
[Route("by-role")]
public virtual async Task<ListResultDto<MenuDto>> GetRoleMenuListAsync(MenuGetByRoleInput input)
{
return await MenuAppService.GetRoleMenuListAsync(input);
}
[HttpGet]
[Route("by-role/{role}/{framework}")]
public virtual async Task<ListResultDto<MenuDto>> GetRoleMenuListAsync(string role, string framework)
{
return await MenuAppService.GetRoleMenuListAsync(new MenuGetByRoleInput
{
Role = role,
Framework = framework
});
}
}
}

1887
aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/PlatformDataSeedContributor.cs → aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/DataSeeder/ElementAdminDataSeedContributor.cs

File diff suppressed because it is too large

291
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/DataSeeder/VbenAdminDataSeedContributor.cs

@ -0,0 +1,291 @@
using LINGYUN.Platform.Datas;
using LINGYUN.Platform.Layouts;
using LINGYUN.Platform.Menus;
using LINGYUN.Platform.Routes;
using LINGYUN.Platform.Utils;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Platform.DataSeeder
{
public class VbenAdminDataSeedContributor : IDataSeedContributor, ITransientDependency
{
protected ICurrentTenant CurrentTenant { get; }
protected IGuidGenerator GuidGenerator { get; }
protected IRouteDataSeeder RouteDataSeeder { get; }
protected IDataDictionaryDataSeeder DataDictionaryDataSeeder { get; }
protected IMenuRepository MenuRepository { get; }
protected ILayoutRepository LayoutRepository { get; }
public VbenAdminDataSeedContributor(
ICurrentTenant currentTenant,
IRouteDataSeeder routeDataSeeder,
IMenuRepository menuRepository,
ILayoutRepository layoutRepository,
IGuidGenerator guidGenerator,
IDataDictionaryDataSeeder dataDictionaryDataSeeder)
{
CurrentTenant = currentTenant;
GuidGenerator = guidGenerator;
RouteDataSeeder = routeDataSeeder;
MenuRepository = menuRepository;
LayoutRepository = layoutRepository;
DataDictionaryDataSeeder = dataDictionaryDataSeeder;
}
public virtual async Task SeedAsync(DataSeedContext context)
{
using (CurrentTenant.Change(context.TenantId))
{
var uiDataItem = await SeedUIFrameworkDataAsync(context.TenantId);
var layoutData = await SeedLayoutDataAsync(context.TenantId);
var layout = await SeedDefaultLayoutAsync(layoutData, uiDataItem);
}
}
private async Task<DataItem> SeedUIFrameworkDataAsync(Guid? tenantId)
{
var data = await DataDictionaryDataSeeder
.SeedAsync(
"UI Framewark",
CodeNumberGenerator.CreateCode(2),
"UI框架",
"UI Framewark",
null,
tenantId,
true);
data.AddItem(
GuidGenerator,
"Vue Vben Admin",
"Vue Vben Admin",
"Vue Vben Admin",
Datas.ValueType.String,
"Vue Vben Admin",
isStatic: true);
return data.FindItem("Vue Vben Admin");
}
private async Task<Layout> SeedDefaultLayoutAsync(Data data, DataItem uiDataItem)
{
var layout = await RouteDataSeeder.SeedLayoutAsync(
"Vben Admin Layout",
"LAYOUT", // 路由层面已经处理好了,只需要传递LAYOUT可自动引用布局
"Vben Admin Layout",
data.Id,
uiDataItem.Name,
"",
"Vben Admin Layout",
data.TenantId
);
return layout;
}
private async Task<Data> SeedLayoutDataAsync(Guid? tenantId)
{
var data = await DataDictionaryDataSeeder
.SeedAsync(
"Vben Admin Layout",
CodeNumberGenerator.CreateCode(3),
"Vben Admin布局约束",
"Vben Admin Layout Meta Dictionary",
null,
tenantId,
true);
data.AddItem(
GuidGenerator,
"hideMenu",
"不在菜单显示",
"false",
Datas.ValueType.Boolean,
"当前路由不在菜单显示",
isStatic: true);
data.AddItem(
GuidGenerator,
"icon",
"图标",
"",
Datas.ValueType.String,
"图标,也是菜单图标",
isStatic: true);
data.AddItem(
GuidGenerator,
"currentActiveMenu",
"当前激活的菜单",
"",
Datas.ValueType.String,
"用于配置详情页时左侧激活的菜单路径",
isStatic: true);
data.AddItem(
GuidGenerator,
"ignoreKeepAlive",
"KeepAlive缓存",
"false",
Datas.ValueType.Boolean,
"是否忽略KeepAlive缓存",
isStatic: true);
data.AddItem(
GuidGenerator,
"frameSrc",
"IFrame地址",
"",
Datas.ValueType.String,
"内嵌iframe的地址",
isStatic: true);
data.AddItem(
GuidGenerator,
"transitionName",
"路由切换动画",
"",
Datas.ValueType.String,
"指定该路由切换的动画名",
isStatic: true);
data.AddItem(
GuidGenerator,
"roles",
"可以访问的角色",
"",
Datas.ValueType.Array,
"可以访问的角色,只在权限模式为Role的时候有效",
isStatic: true);
data.AddItem(
GuidGenerator,
"title",
"路由标题",
"",
Datas.ValueType.String,
"路由title 一般必填",
false,
isStatic: true);
data.AddItem(
GuidGenerator,
"carryParam",
"在tab页显示",
"false",
Datas.ValueType.Boolean,
"如果该路由会携带参数,且需要在tab页上面显示。则需要设置为true",
isStatic: true);
data.AddItem(
GuidGenerator,
"hideBreadcrumb",
"隐藏面包屑",
"false",
Datas.ValueType.Boolean,
"隐藏该路由在面包屑上面的显示",
isStatic: true);
data.AddItem(
GuidGenerator,
"ignoreAuth",
"忽略权限",
"false",
Datas.ValueType.Boolean,
"是否忽略权限,只在权限模式为Role的时候有效",
isStatic: true);
data.AddItem(
GuidGenerator,
"hideChildrenInMenu",
"隐藏所有子菜单",
"false",
Datas.ValueType.Boolean,
"隐藏所有子菜单",
isStatic: true);
data.AddItem(
GuidGenerator,
"hideTab",
"不在标签页显示",
"false",
Datas.ValueType.Boolean,
"当前路由不在标签页显示",
isStatic: true);
data.AddItem(
GuidGenerator,
"affix",
"固定标签页",
"false",
Datas.ValueType.Boolean,
"是否固定标签页",
isStatic: true);
data.AddItem(
GuidGenerator,
"frameFormat",
"格式化IFrame",
"false",
Datas.ValueType.Boolean,
"扩展的格式化frame,{token}: 在打开的iframe页面传递token请求头");
return data;
}
private async Task<Menu> SeedMenuAsync(
Layout layout,
Data data,
string name,
string path,
string code,
string component,
string displayName,
string redirect = "",
string description = "",
Guid? parentId = null,
Guid? tenantId = null,
Dictionary<string, object> meta = null,
string[] roles = null,
Guid[] users = null,
bool isPublic = false
)
{
var menu = await RouteDataSeeder.SeedMenuAsync(
layout,
name,
path,
code,
component,
displayName,
redirect,
description,
parentId,
tenantId,
isPublic
);
foreach (var item in data.Items)
{
menu.SetProperty(item.Name, item.DefaultValue);
}
if (meta != null)
{
foreach (var item in meta)
{
menu.SetProperty(item.Key, item.Value);
}
}
if (roles != null)
{
foreach (var role in roles)
{
await RouteDataSeeder.SeedRoleMenuAsync(role, menu, tenantId);
}
}
if (users != null)
{
foreach (var user in users)
{
await RouteDataSeeder.SeedUserMenuAsync(user, menu, tenantId);
}
}
return menu;
}
}
}

556
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/EventBus/Handlers/TenantSynchronizer.cs

@ -1,525 +1,31 @@
using LINGYUN.Abp.MultiTenancy;
using LINGYUN.Platform.Datas;
using LINGYUN.Platform.Layouts;
using LINGYUN.Platform.Menus;
using LINGYUN.Platform.Routes;
using LINGYUN.Platform.Utils;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Platform.EventBus.Handlers
{
public class TenantSynchronizer :
IDistributedEventHandler<CreateEventData>,
ITransientDependency
{
protected ICurrentTenant CurrentTenant { get; }
protected IGuidGenerator GuidGenerator { get; }
protected IRouteDataSeeder RouteDataSeeder { get; }
protected IDataDictionaryDataSeeder DataDictionaryDataSeeder { get; }
protected IMenuRepository MenuRepository { get; }
protected ILayoutRepository LayoutRepository { get; }
public TenantSynchronizer(
ICurrentTenant currentTenant,
IRouteDataSeeder routeDataSeeder,
IMenuRepository menuRepository,
ILayoutRepository layoutRepository,
IGuidGenerator guidGenerator,
IDataDictionaryDataSeeder dataDictionaryDataSeeder)
{
CurrentTenant = currentTenant;
GuidGenerator = guidGenerator;
RouteDataSeeder = routeDataSeeder;
MenuRepository = menuRepository;
LayoutRepository = layoutRepository;
DataDictionaryDataSeeder = dataDictionaryDataSeeder;
}
/// <summary>
/// 租户创建之后需要预置租户平台数据
/// </summary>
/// <param name="eventData"></param>
/// <returns></returns>
public virtual async Task HandleEventAsync(CreateEventData eventData)
{
using (CurrentTenant.Change(eventData.Id))
{
var data = await SeedDefaultDataDictionaryAsync(eventData.Id);
// 预置
var layout = await SeedDefaultLayoutAsync(data);
// 首页
await SeedHomeMenuAsync(layout, data);
// 管理菜单预置菜单数据
await SeedAdminMenuAsync(layout, data);
// 审计日志菜单数据
await SeedAuditingMenuAsync(layout, data);
// 布局容器预置菜单数据
await SeedContainerMenuAsync(layout, data);
}
}
/// <summary>
/// 租户删除之后删除租户平台数据
/// TODO: 不应删除用户数据
/// </summary>
/// <param name="eventData"></param>
/// <returns></returns>
//public virtual async Task HandleEventAsync(DeleteEventData eventData)
//{
// //await MenuRepository.GetAllAsync();
//}
private async Task<Data> SeedDefaultDataDictionaryAsync(Guid? tenantId)
{
var data = await DataDictionaryDataSeeder
.SeedAsync(
"Layout",
CodeNumberGenerator.CreateCode(1),
"Vue Admin Layout Meta Dictionary",
"Vue Admin Layout Meta Dictionary",
null,
tenantId);
data.AddItem(
GuidGenerator,
"roles", // TODO: 是否需要把这一项写入到预置数据?
"roles",
"",
Datas.ValueType.Array,
"will control the page roles (allow setting multiple roles)");
data.AddItem(
GuidGenerator,
"title",
"title",
"component",
Datas.ValueType.String,
"the name showed in subMenu and breadcrumb (recommend set)");
data.AddItem(
GuidGenerator,
"icon",
"icon",
"icon",
Datas.ValueType.String,
"the icon showed in the sidebar");
data.AddItem(
GuidGenerator,
"hidden",
"hidden",
"false",
Datas.ValueType.Boolean,
"if true, this route will not show in the sidebar (default is false)");
data.AddItem(
GuidGenerator,
"alwaysShow",
"alwaysShow",
"false",
Datas.ValueType.Boolean,
"if true, will always show the root menu (default is false)");
data.AddItem(
GuidGenerator,
"breadcrumb",
"breadcrumb",
"true",
Datas.ValueType.Boolean,
"if false, the item will be hidden in breadcrumb (default is true)");
data.AddItem(
GuidGenerator,
"noCache",
"noCache",
"false",
Datas.ValueType.Boolean,
"if true, the page will not be cached (default is false)");
data.AddItem(
GuidGenerator,
"affix",
"affix",
"false",
Datas.ValueType.Boolean,
"if true, the tag will affix in the tags-view");
data.AddItem(
GuidGenerator,
"activeMenu",
"activeMenu",
"",
Datas.ValueType.String,
"if set path, the sidebar will highlight the path you set");
return data;
}
private async Task<Layout> SeedDefaultLayoutAsync(Data data)
{
var layout = await RouteDataSeeder.SeedLayoutAsync(
"Layout",
"layout/index.vue",
"Vue Admin Layout",
data.Id,
PlatformType.WebMvvm, // 针对当前的vue管理页
"",
"Vue Admin Layout",
data.TenantId
);
return layout;
}
private async Task SeedHomeMenuAsync(Layout layout, Data data)
{
var adminMenu = await SeedMenuAsync(
layout,
data,
"home",
"/",
CodeNumberGenerator.CreateCode(1),
layout.Path,
"Home",
"/dashboard",
"Home",
null,
layout.TenantId,
new Dictionary<string, object>()
{
{ "title", "home" },
{ "icon", "home" },
{ "alwaysShow", true }
},
// isPublic: true,
isPublic: false); // 首页应该是共有的页面
await SeedMenuAsync(
layout,
data,
"dashboard",
"dashboard",
CodeNumberGenerator.AppendCode(adminMenu.Code, CodeNumberGenerator.CreateCode(1)),
"views/dashboard/index.vue",
"Dashboard",
"",
"Dashboard",
adminMenu.Id,
layout.TenantId,
new Dictionary<string, object>()
{
{ "title", "dashboard" },
{ "icon", "dashboard" }
},
isPublic: false);
}
private async Task SeedAdminMenuAsync(Layout layout, Data data)
{
var adminMenu = await SeedMenuAsync(
layout,
data,
"admin",
"/admin",
CodeNumberGenerator.CreateCode(2),
layout.Path,
"Admin",
"",
"Admin",
null,
layout.TenantId,
new Dictionary<string, object>()
{
{ "title", "admin" },
{ "icon", "admin" },
{ "alwaysShow", true }
},
new string[] { "admin" });
await SeedMenuAsync(
layout,
data,
"roles",
"roles",
CodeNumberGenerator.AppendCode(adminMenu.Code, CodeNumberGenerator.CreateCode(1)),
"views/admin/roles/index.vue",
"Manage Roles",
"",
"Manage Roles",
adminMenu.Id,
layout.TenantId,
new Dictionary<string, object>()
{
{ "title", "roles" },
{ "icon", "role" },
{ "roles", new string[] { "AbpIdentity.Roles" } }
},
new string[] { "admin" });
await SeedMenuAsync(
layout,
data,
"users",
"users",
CodeNumberGenerator.AppendCode(adminMenu.Code, CodeNumberGenerator.CreateCode(2)),
"views/admin/users/index.vue",
"Manage Users",
"",
"Manage Users",
adminMenu.Id,
layout.TenantId,
new Dictionary<string, object>()
{
{ "title", "users" },
{ "icon", "users" },
{ "roles", new string[] { "AbpIdentity.Users" } }
},
new string[] { "admin" });
await SeedMenuAsync(
layout,
data,
"organization-unit",
"organization-unit",
CodeNumberGenerator.AppendCode(adminMenu.Code, CodeNumberGenerator.CreateCode(3)),
"views/admin/organization-unit/index.vue",
"Manage Organization Units",
"",
"Manage Organization Units",
adminMenu.Id,
layout.TenantId,
new Dictionary<string, object>()
{
{ "title", "organization-unit" },
{ "icon", "organization-unit" },
{ "roles", new string[] { "AbpIdentity.OrganizationUnits" } }
},
new string[] { "admin" });
await SeedMenuAsync(
layout,
data,
"data-dictionary",
"data-dictionary",
CodeNumberGenerator.AppendCode(adminMenu.Code, CodeNumberGenerator.CreateCode(5)),
"views/admin/data-dictionary/index.vue",
"Manage Data Dictionarys",
"",
"Manage Data Dictionarys",
adminMenu.Id,
layout.TenantId,
new Dictionary<string, object>()
{
{ "title", "data-dictionary" },
{ "icon", "data-dictionary" },
{ "roles", new string[] { "Platform.DataDictionary" } }
},
new string[] { "admin" });
await SeedMenuAsync(
layout,
data,
"settings",
"settings",
CodeNumberGenerator.AppendCode(adminMenu.Code, CodeNumberGenerator.CreateCode(6)),
"views/admin/settings/index.vue",
"Manage Settings",
"",
"Manage Settings",
adminMenu.Id,
layout.TenantId,
new Dictionary<string, object>()
{
{ "title", "settings" },
{ "icon", "settings" },
{ "roles", new string[] { "AbpSettingManagement.Settings" } }
},
new string[] { "admin" });
}
private async Task SeedAuditingMenuAsync(Layout layout, Data data)
{
var auditingMenu = await SeedMenuAsync(
layout,
data,
"auditing",
"/auditing",
CodeNumberGenerator.CreateCode(5),
layout.Path,
"Auditing",
"",
"Auditing",
null,
layout.TenantId,
new Dictionary<string, object>()
{
{ "title", "auditing" },
{ "icon", "auditing" },
{ "alwaysShow", true },
{ "roles", new string[]{ "AbpAuditing.AuditLog", "AbpAuditing.SecurityLog" } }
},
new string[] { "admin" });
await SeedMenuAsync(
layout,
data,
"audit-log",
"audit-log",
CodeNumberGenerator.AppendCode(auditingMenu.Code, CodeNumberGenerator.CreateCode(1)),
"views/admin/auditing/audit-log/index.vue",
"Manage AuditLog",
"",
"Manage AuditLog",
auditingMenu.Id,
layout.TenantId,
new Dictionary<string, object>()
{
{ "title", "audit-log" },
{ "icon", "audit-log" },
{ "roles", new string[]{ "AbpAuditing.AuditLog" } }
},
new string[] { "admin" });
await SeedMenuAsync(
layout,
data,
"security-log",
"security-log",
CodeNumberGenerator.AppendCode(auditingMenu.Code, CodeNumberGenerator.CreateCode(2)),
"views/admin/auditing/security-log/index.vue",
"Manage SecurityLog",
"",
"Manage SecurityLog",
auditingMenu.Id,
layout.TenantId,
new Dictionary<string, object>()
{
{ "title", "security-log" },
{ "icon", "security-log" },
{ "roles", new string[]{ "AbpAuditing.SecurityLog" } }
},
new string[] { "admin" });
}
private async Task SeedContainerMenuAsync(Layout layout, Data data)
{
var containerRoot = await SeedMenuAsync(
layout,
data,
"container",
"/container",
CodeNumberGenerator.CreateCode(6),
layout.Path,
"Container",
"",
"Manage Container",
null,
layout.TenantId,
new Dictionary<string, object>()
{
{ "title", "container" },
{ "icon", "container" },
{ "alwaysShow", true }
},
new string[] { "admin" });
await SeedMenuAsync(
layout,
data,
"layouts",
"layouts",
CodeNumberGenerator.AppendCode(containerRoot.Code, CodeNumberGenerator.CreateCode(1)),
"views/container/layouts/index.vue",
"Manage Layouts",
"",
"Manage Layouts",
containerRoot.Id,
containerRoot.TenantId,
new Dictionary<string, object>()
{
{ "title", "layouts" },
{ "icon", "layout" }
},
new string[] { "admin" });
await SeedMenuAsync(
layout,
data,
"menus",
"menus",
CodeNumberGenerator.AppendCode(containerRoot.Code, CodeNumberGenerator.CreateCode(2)),
"views/container/menus/index.vue",
"Manage Menus",
"",
"Manage Menus",
containerRoot.Id,
containerRoot.TenantId,
new Dictionary<string, object>()
{
{ "title", "menus" },
{ "icon", "menu" }
},
new string[] { "admin" });
}
private async Task<Menu> SeedMenuAsync(
Layout layout,
Data data,
string name,
string path,
string code,
string component,
string displayName,
string redirect = "",
string description = "",
Guid? parentId = null,
Guid? tenantId = null,
Dictionary<string, object> meta = null,
string[] roles = null,
Guid[] users = null,
bool isPublic = false
)
{
var menu = await RouteDataSeeder.SeedMenuAsync(
layout,
name,
path,
code,
component,
displayName,
redirect,
description,
parentId,
tenantId,
isPublic
);
foreach (var item in data.Items)
{
menu.SetProperty(item.Name, item.DefaultValue);
}
if (meta != null)
{
foreach (var item in meta)
{
menu.SetProperty(item.Key, item.Value);
}
}
if (roles != null)
{
foreach (var role in roles)
{
await RouteDataSeeder.SeedRoleMenuAsync(role, menu, tenantId);
}
}
if (users != null)
{
foreach (var user in users)
{
await RouteDataSeeder.SeedUserMenuAsync(user, menu, tenantId);
}
}
return menu;
}
}
}
using LINGYUN.Abp.MultiTenancy;
using System.Threading.Tasks;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
namespace LINGYUN.Platform.EventBus.Handlers
{
public class TenantSynchronizer :
IDistributedEventHandler<CreateEventData>,
ITransientDependency
{
protected IDataSeeder DataSeeder { get; }
public TenantSynchronizer(IDataSeeder dataSeeder)
{
DataSeeder = dataSeeder;
}
/// <summary>
/// 租户创建之后需要预置种子数据
/// </summary>
/// <param name="eventData"></param>
/// <returns></returns>
public virtual async Task HandleEventAsync(CreateEventData eventData)
{
await DataSeeder.SeedAsync(
new DataSeedContext(eventData.Id));
}
}
}

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

@ -1,74 +1,74 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace>LINGYUN.Platform</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Remove="%2a%2a\**" />
<Content Remove="%2a%2a\**" />
<EmbeddedResource Remove="%2a%2a\**" />
<None Remove="%2a%2a\**" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Migrations\20200723131720_Add-Platform-Module.cs" />
<Compile Remove="Migrations\20200723131720_Add-Platform-Module.Designer.cs" />
<Compile Remove="Migrations\20200908021207_Upgrade-abp-3.1.0.cs" />
<Compile Remove="Migrations\20200908021207_Upgrade-abp-3.1.0.Designer.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="DotNetCore.CAP.Dashboard" Version="5.1.0" />
<PackageReference Include="DotNetCore.CAP.MySql" Version="5.1.0" />
<PackageReference Include="DotNetCore.CAP.RabbitMQ" Version="5.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.*">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="5.0.*" />
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
<PackageReference Include="Serilog.Enrichers.Assembly" Version="2.0.0" />
<PackageReference Include="Serilog.Enrichers.Process" Version="2.0.1" />
<PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="4.3.0" />
<PackageReference Include="Volo.Abp.AspNetCore.MultiTenancy" Version="4.3.0" />
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="4.3.0" />
<PackageReference Include="Volo.Abp.Autofac" Version="4.3.0" />
<PackageReference Include="Volo.Abp.BlobStoring.FileSystem" Version="4.3.0" />
<PackageReference Include="Volo.Abp.Identity.HttpApi.Client" Version="4.3.0" />
<PackageReference Include="Volo.Abp.Http.Client.IdentityModel.Web" Version="4.3.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.MySQL" Version="4.3.0" />
<PackageReference Include="Volo.Abp.AuditLogging.EntityFrameworkCore" Version="4.3.0" />
<PackageReference Include="Volo.Abp.FeatureManagement.EntityFrameworkCore" Version="4.3.0" />
<PackageReference Include="Volo.Abp.TenantManagement.EntityFrameworkCore" Version="4.3.0" />
<PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="4.3.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="4.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.AspNetCore.HttpOverrides\LINGYUN.Abp.AspNetCore.HttpOverrides.csproj" />
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.csproj" />
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.ExceptionHandling.Emailing\LINGYUN.Abp.ExceptionHandling.Emailing.csproj" />
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.Features.LimitValidation.Redis.Client\LINGYUN.Abp.Features.LimitValidation.Redis.Client.csproj" />
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.Notifications\LINGYUN.Abp.Notifications.csproj" />
<ProjectReference Include="..\..\..\modules\features\LINGYUN.Abp.Features.Client\LINGYUN.Abp.Features.Client.csproj" />
<ProjectReference Include="..\..\..\modules\lt\LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore\LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\modules\oss-management\LINGYUN.Abp.OssManagement.Aliyun\LINGYUN.Abp.OssManagement.Aliyun.csproj" />
<ProjectReference Include="..\..\..\modules\oss-management\LINGYUN.Abp.OssManagement.Application\LINGYUN.Abp.OssManagement.Application.csproj" />
<ProjectReference Include="..\..\..\modules\oss-management\LINGYUN.Abp.OssManagement.FileSystem.ImageSharp\LINGYUN.Abp.OssManagement.FileSystem.ImageSharp.csproj" />
<ProjectReference Include="..\..\..\modules\oss-management\LINGYUN.Abp.OssManagement.FileSystem\LINGYUN.Abp.OssManagement.FileSystem.csproj" />
<ProjectReference Include="..\..\..\modules\oss-management\LINGYUN.Abp.OssManagement.HttpApi\LINGYUN.Abp.OssManagement.HttpApi.csproj" />
<ProjectReference Include="..\..\..\modules\oss-management\LINGYUN.Abp.OssManagement.SettingManagement\LINGYUN.Abp.OssManagement.SettingManagement.csproj" />
<ProjectReference Include="..\..\..\modules\platform\LINGYUN.Platform.Application\LINGYUN.Platform.Application.csproj" />
<ProjectReference Include="..\..\..\modules\platform\LINGYUN.Platform.EntityFrameworkCore\LINGYUN.Platform.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\modules\platform\LINGYUN.Platform.HttpApi\LINGYUN.Platform.HttpApi.csproj" />
<ProjectReference Include="..\..\..\modules\tenants\LINGYUN.Abp.MultiTenancy.DbFinder\LINGYUN.Abp.MultiTenancy.DbFinder.csproj" />
<ProjectReference Include="..\..\..\modules\tenants\LINGYUN.Abp.MultiTenancy\LINGYUN.Abp.MultiTenancy.csproj" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace>LINGYUN.Platform</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Remove="%2a%2a\**" />
<Content Remove="%2a%2a\**" />
<EmbeddedResource Remove="%2a%2a\**" />
<None Remove="%2a%2a\**" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Migrations\20200723131720_Add-Platform-Module.cs" />
<Compile Remove="Migrations\20200723131720_Add-Platform-Module.Designer.cs" />
<Compile Remove="Migrations\20200908021207_Upgrade-abp-3.1.0.cs" />
<Compile Remove="Migrations\20200908021207_Upgrade-abp-3.1.0.Designer.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="DotNetCore.CAP.Dashboard" Version="5.1.0" />
<PackageReference Include="DotNetCore.CAP.MySql" Version="5.1.0" />
<PackageReference Include="DotNetCore.CAP.RabbitMQ" Version="5.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.*">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="5.0.*" />
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
<PackageReference Include="Serilog.Enrichers.Assembly" Version="2.0.0" />
<PackageReference Include="Serilog.Enrichers.Process" Version="2.0.1" />
<PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="4.3.0" />
<PackageReference Include="Volo.Abp.AspNetCore.MultiTenancy" Version="4.3.0" />
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="4.3.0" />
<PackageReference Include="Volo.Abp.Autofac" Version="4.3.0" />
<PackageReference Include="Volo.Abp.BlobStoring.FileSystem" Version="4.3.0" />
<PackageReference Include="Volo.Abp.Identity.HttpApi.Client" Version="4.3.0" />
<PackageReference Include="Volo.Abp.Http.Client.IdentityModel.Web" Version="4.3.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.MySQL" Version="4.3.0" />
<PackageReference Include="Volo.Abp.AuditLogging.EntityFrameworkCore" Version="4.3.0" />
<PackageReference Include="Volo.Abp.FeatureManagement.EntityFrameworkCore" Version="4.3.0" />
<PackageReference Include="Volo.Abp.TenantManagement.EntityFrameworkCore" Version="4.3.0" />
<PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="4.3.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="4.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.AspNetCore.HttpOverrides\LINGYUN.Abp.AspNetCore.HttpOverrides.csproj" />
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.csproj" />
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.ExceptionHandling.Emailing\LINGYUN.Abp.ExceptionHandling.Emailing.csproj" />
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.Features.LimitValidation.Redis.Client\LINGYUN.Abp.Features.LimitValidation.Redis.Client.csproj" />
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.Notifications\LINGYUN.Abp.Notifications.csproj" />
<ProjectReference Include="..\..\..\modules\features\LINGYUN.Abp.Features.Client\LINGYUN.Abp.Features.Client.csproj" />
<ProjectReference Include="..\..\..\modules\lt\LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore\LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\modules\oss-management\LINGYUN.Abp.OssManagement.Aliyun\LINGYUN.Abp.OssManagement.Aliyun.csproj" />
<ProjectReference Include="..\..\..\modules\oss-management\LINGYUN.Abp.OssManagement.Application\LINGYUN.Abp.OssManagement.Application.csproj" />
<ProjectReference Include="..\..\..\modules\oss-management\LINGYUN.Abp.OssManagement.FileSystem.ImageSharp\LINGYUN.Abp.OssManagement.FileSystem.ImageSharp.csproj" />
<ProjectReference Include="..\..\..\modules\oss-management\LINGYUN.Abp.OssManagement.FileSystem\LINGYUN.Abp.OssManagement.FileSystem.csproj" />
<ProjectReference Include="..\..\..\modules\oss-management\LINGYUN.Abp.OssManagement.HttpApi\LINGYUN.Abp.OssManagement.HttpApi.csproj" />
<ProjectReference Include="..\..\..\modules\oss-management\LINGYUN.Abp.OssManagement.SettingManagement\LINGYUN.Abp.OssManagement.SettingManagement.csproj" />
<ProjectReference Include="..\..\..\modules\platform\LINGYUN.Platform.Application\LINGYUN.Platform.Application.csproj" />
<ProjectReference Include="..\..\..\modules\platform\LINGYUN.Platform.EntityFrameworkCore\LINGYUN.Platform.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\modules\platform\LINGYUN.Platform.HttpApi\LINGYUN.Platform.HttpApi.csproj" />
<ProjectReference Include="..\..\..\modules\tenants\LINGYUN.Abp.MultiTenancy.DbFinder\LINGYUN.Abp.MultiTenancy.DbFinder.csproj" />
<ProjectReference Include="..\..\..\modules\tenants\LINGYUN.Abp.MultiTenancy\LINGYUN.Abp.MultiTenancy.csproj" />
</ItemGroup>
</Project>

665
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/Migrations/20210621020117_Rename-Route-Field-PlantType-To-Framework.Designer.cs

@ -0,0 +1,665 @@
// <auto-generated />
using System;
using LINGYUN.Platform.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.Platform.Migrations
{
[DbContext(typeof(PlatformHttpApiHostMigrationsDbContext))]
[Migration("20210621020117_Rename-Route-Field-PlantType-To-Framework")]
partial class RenameRouteFieldPlantTypeToFramework
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql)
.HasAnnotation("Relational:MaxIdentifierLength", 64)
.HasAnnotation("ProductVersion", "5.0.7");
modelBuilder.Entity("LINGYUN.Platform.Datas.Data", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(1024)
.HasColumnType("varchar(1024) CHARACTER SET utf8mb4")
.HasColumnName("Code");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("varchar(40) CHARACTER SET utf8mb4")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("char(36)")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime(6)")
.HasColumnName("DeletionTime");
b.Property<string>("Description")
.HasMaxLength(1024)
.HasColumnType("varchar(1024) CHARACTER SET utf8mb4")
.HasColumnName("Description");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("varchar(128) CHARACTER SET utf8mb4")
.HasColumnName("DisplayName");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<bool>("IsStatic")
.HasColumnType("tinyint(1)");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("varchar(30) CHARACTER SET utf8mb4")
.HasColumnName("Name");
b.Property<Guid?>("ParentId")
.HasColumnType("char(36)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("Name");
b.ToTable("AppPlatformDatas");
});
modelBuilder.Entity("LINGYUN.Platform.Datas.DataItem", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<bool>("AllowBeNull")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasDefaultValue(true);
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("varchar(40) CHARACTER SET utf8mb4")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<Guid>("DataId")
.HasColumnType("char(36)");
b.Property<string>("DefaultValue")
.HasMaxLength(128)
.HasColumnType("varchar(128) CHARACTER SET utf8mb4")
.HasColumnName("DefaultValue");
b.Property<Guid?>("DeleterId")
.HasColumnType("char(36)")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime(6)")
.HasColumnName("DeletionTime");
b.Property<string>("Description")
.HasMaxLength(1024)
.HasColumnType("varchar(1024) CHARACTER SET utf8mb4")
.HasColumnName("Description");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("varchar(128) CHARACTER SET utf8mb4")
.HasColumnName("DisplayName");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<bool>("IsStatic")
.HasColumnType("tinyint(1)");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("varchar(30) CHARACTER SET utf8mb4")
.HasColumnName("Name");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<int>("ValueType")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("DataId");
b.HasIndex("Name");
b.ToTable("AppPlatformDataItems");
});
modelBuilder.Entity("LINGYUN.Platform.Layouts.Layout", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("varchar(40) CHARACTER SET utf8mb4")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<Guid>("DataId")
.HasColumnType("char(36)");
b.Property<Guid?>("DeleterId")
.HasColumnType("char(36)")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime(6)")
.HasColumnName("DeletionTime");
b.Property<string>("Description")
.HasColumnType("longtext CHARACTER SET utf8mb4");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("varchar(128) CHARACTER SET utf8mb4")
.HasColumnName("DisplayName");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasColumnName("ExtraProperties");
b.Property<string>("Framework")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasColumnName("Framework");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasColumnName("Name");
b.Property<string>("Path")
.HasMaxLength(255)
.HasColumnType("varchar(255) CHARACTER SET utf8mb4")
.HasColumnName("Path");
b.Property<string>("Redirect")
.HasMaxLength(255)
.HasColumnType("varchar(255) CHARACTER SET utf8mb4")
.HasColumnName("Redirect");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.HasKey("Id");
b.ToTable("AppPlatformLayouts");
});
modelBuilder.Entity("LINGYUN.Platform.Menus.Menu", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(23)
.HasColumnType("varchar(23) CHARACTER SET utf8mb4")
.HasColumnName("Code");
b.Property<string>("Component")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("varchar(255) CHARACTER SET utf8mb4")
.HasColumnName("Component");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("varchar(40) CHARACTER SET utf8mb4")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("char(36)")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime(6)")
.HasColumnName("DeletionTime");
b.Property<string>("Description")
.HasColumnType("longtext CHARACTER SET utf8mb4");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("varchar(128) CHARACTER SET utf8mb4")
.HasColumnName("DisplayName");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasColumnName("ExtraProperties");
b.Property<string>("Framework")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasColumnName("Framework");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<bool>("IsPublic")
.HasColumnType("tinyint(1)");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<Guid>("LayoutId")
.HasColumnType("char(36)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("varchar(64) CHARACTER SET utf8mb4")
.HasColumnName("Name");
b.Property<Guid?>("ParentId")
.HasColumnType("char(36)");
b.Property<string>("Path")
.HasMaxLength(255)
.HasColumnType("varchar(255) CHARACTER SET utf8mb4")
.HasColumnName("Path");
b.Property<string>("Redirect")
.HasMaxLength(255)
.HasColumnType("varchar(255) CHARACTER SET utf8mb4")
.HasColumnName("Redirect");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.HasKey("Id");
b.ToTable("AppPlatformMenus");
});
modelBuilder.Entity("LINGYUN.Platform.Menus.RoleMenu", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<Guid>("MenuId")
.HasColumnType("char(36)");
b.Property<string>("RoleName")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("varchar(256) CHARACTER SET utf8mb4")
.HasColumnName("RoleName");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("RoleName", "MenuId");
b.ToTable("AppPlatformRoleMenus");
});
modelBuilder.Entity("LINGYUN.Platform.Menus.UserMenu", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<Guid>("MenuId")
.HasColumnType("char(36)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<Guid>("UserId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("UserId", "MenuId");
b.ToTable("AppPlatformUserMenus");
});
modelBuilder.Entity("LINGYUN.Platform.Versions.AppVersion", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("varchar(40) CHARACTER SET utf8mb4")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("char(36)")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime(6)")
.HasColumnName("DeletionTime");
b.Property<string>("Description")
.HasMaxLength(2048)
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasColumnName("Description");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<int>("PlatformType")
.HasColumnType("int");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("varchar(50) CHARACTER SET utf8mb4")
.HasColumnName("Title");
b.Property<string>("Version")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20) CHARACTER SET utf8mb4")
.HasColumnName("Version");
b.HasKey("Id");
b.HasIndex("Version");
b.ToTable("AppPlatformVersion");
});
modelBuilder.Entity("LINGYUN.Platform.Versions.VersionFile", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<Guid>("AppVersionId")
.HasColumnType("char(36)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<int>("DownloadCount")
.HasColumnType("int");
b.Property<int>("FileType")
.HasColumnType("int");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("varchar(255) CHARACTER SET utf8mb4")
.HasColumnName("Name");
b.Property<string>("Path")
.HasMaxLength(255)
.HasColumnType("varchar(255) CHARACTER SET utf8mb4")
.HasColumnName("Path");
b.Property<string>("SHA256")
.IsRequired()
.HasMaxLength(65)
.HasColumnType("varchar(65) CHARACTER SET utf8mb4")
.HasColumnName("SHA256");
b.Property<long>("Size")
.HasColumnType("bigint");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<string>("Version")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20) CHARACTER SET utf8mb4")
.HasColumnName("Version");
b.HasKey("Id");
b.HasIndex("AppVersionId");
b.HasIndex("Path", "Name", "Version")
.IsUnique();
b.ToTable("AppPlatformVersionFile");
});
modelBuilder.Entity("LINGYUN.Platform.Datas.DataItem", b =>
{
b.HasOne("LINGYUN.Platform.Datas.Data", null)
.WithMany("Items")
.HasForeignKey("DataId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("LINGYUN.Platform.Versions.VersionFile", b =>
{
b.HasOne("LINGYUN.Platform.Versions.AppVersion", "AppVersion")
.WithMany("Files")
.HasForeignKey("AppVersionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("AppVersion");
});
modelBuilder.Entity("LINGYUN.Platform.Datas.Data", b =>
{
b.Navigation("Items");
});
modelBuilder.Entity("LINGYUN.Platform.Versions.AppVersion", b =>
{
b.Navigation("Files");
});
#pragma warning restore 612, 618
}
}
}

81
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/Migrations/20210621020117_Rename-Route-Field-PlantType-To-Framework.cs

@ -0,0 +1,81 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace LINGYUN.Platform.Migrations
{
public partial class RenameRouteFieldPlantTypeToFramework : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "PlatformType",
table: "AppPlatformMenus");
migrationBuilder.DropColumn(
name: "PlatformType",
table: "AppPlatformLayouts");
migrationBuilder.AddColumn<string>(
name: "Framework",
table: "AppPlatformMenus",
type: "varchar(64) CHARACTER SET utf8mb4",
maxLength: 64,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "Framework",
table: "AppPlatformLayouts",
type: "varchar(64) CHARACTER SET utf8mb4",
maxLength: 64,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<bool>(
name: "IsStatic",
table: "AppPlatformDatas",
type: "tinyint(1)",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<bool>(
name: "IsStatic",
table: "AppPlatformDataItems",
type: "tinyint(1)",
nullable: false,
defaultValue: false);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Framework",
table: "AppPlatformMenus");
migrationBuilder.DropColumn(
name: "Framework",
table: "AppPlatformLayouts");
migrationBuilder.DropColumn(
name: "IsStatic",
table: "AppPlatformDatas");
migrationBuilder.DropColumn(
name: "IsStatic",
table: "AppPlatformDataItems");
migrationBuilder.AddColumn<int>(
name: "PlatformType",
table: "AppPlatformMenus",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<int>(
name: "PlatformType",
table: "AppPlatformLayouts",
type: "int",
nullable: false,
defaultValue: 0);
}
}
}

1302
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/Migrations/PlatformHttpApiHostMigrationsDbContextModelSnapshot.cs

File diff suppressed because it is too large

237
vueJs/src/api/data-dictionary.ts

@ -1,116 +1,121 @@
import ApiService from './serviceBase'
import { urlStringify } from '@/utils/index'
import { ListResultDto, PagedResultDto, PagedAndSortedResultRequestDto } from './types'
const sourceUrl = '/api/platform/datas'
/** 远程服务地址 */
const serviceUrl = process.env.VUE_APP_BASE_API
/** 数据字典api接口 */
export default class DataDictionaryService {
public static get(id: string) {
const _url = sourceUrl + '/' + id
return ApiService.Get<Data>(_url, serviceUrl)
}
public static getList(payload: GetDataByPaged) {
const _url = sourceUrl + '?' + urlStringify(payload)
return ApiService.Get<PagedResultDto<Data >>(_url, serviceUrl)
}
public static getAll() {
const _url = sourceUrl + '/all'
return ApiService.Get<ListResultDto<Data >>(_url, serviceUrl)
}
public static create(payload: DataCreate) {
return ApiService.Post<Data>(sourceUrl, payload, serviceUrl)
}
public static update(id: string, payload: DataUpdate) {
const _url = sourceUrl + '/' + id
return ApiService.Put<Data>(_url, payload, serviceUrl)
}
public static delete(id: string) {
const _url = sourceUrl + '/' + id
return ApiService.Delete(_url, serviceUrl)
}
public static appendItem(id: string, payload: DataItemCreate) {
const _url = sourceUrl + '/' + id + '/items'
return ApiService.Post<Data>(_url, payload, serviceUrl)
}
public static updateItem(id: string, name: string, payload: DataItemUpdate) {
const _url = sourceUrl + '/' + id + '/items/' + name
return ApiService.Put<Data>(_url, payload, serviceUrl)
}
public static removeItem(id: string, name: string) {
const _url = sourceUrl + '/' + id + '/items/' + name
return ApiService.Delete(_url, serviceUrl)
}
}
export enum ValueType {
String = 0,
Numeic = 1,
Boolean = 2,
Date = 3,
DateTime = 4,
Array = 5,
Object = 6
}
export class DataItem {
id!: string
name!: string
defaultValue!: string
displayName!: string
description?: string
allowBeNull!: boolean
valueType!: ValueType
}
export class Data {
id!: string
name!: string
code!: string
displayName!: string
description?: string
parentId?: string
items = new Array<DataItem>()
}
export class GetDataByPaged extends PagedAndSortedResultRequestDto {
filter = ''
}
export class DataCreateOrUpdate {
name = ''
displayName = ''
description? = ''
}
export class DataCreate extends DataCreateOrUpdate {
parentId?: string
}
export class DataUpdate extends DataCreateOrUpdate {
}
export class DataItemCreateOrUpdate {
defaultValue = ''
displayName = ''
description? = ''
allowBeNull = true
valueType = ValueType.String
}
export class DataItemUpdate extends DataItemCreateOrUpdate {
}
export class DataItemCreate extends DataItemCreateOrUpdate {
name = ''
}
import ApiService from './serviceBase'
import { urlStringify } from '@/utils/index'
import { ListResultDto, PagedResultDto, PagedAndSortedResultRequestDto } from './types'
const sourceUrl = '/api/platform/datas'
/** 远程服务地址 */
const serviceUrl = process.env.VUE_APP_BASE_API
/** 数据字典api接口 */
export default class DataDictionaryService {
public static get(id: string) {
const _url = sourceUrl + '/' + id
return ApiService.Get<Data>(_url, serviceUrl)
}
public static getByName(name: string) {
const _url = sourceUrl + '/by-name/' + name
return ApiService.Get<Data>(_url, serviceUrl)
}
public static getList(payload: GetDataByPaged) {
const _url = sourceUrl + '?' + urlStringify(payload)
return ApiService.Get<PagedResultDto<Data >>(_url, serviceUrl)
}
public static getAll() {
const _url = sourceUrl + '/all'
return ApiService.Get<ListResultDto<Data >>(_url, serviceUrl)
}
public static create(payload: DataCreate) {
return ApiService.Post<Data>(sourceUrl, payload, serviceUrl)
}
public static update(id: string, payload: DataUpdate) {
const _url = sourceUrl + '/' + id
return ApiService.Put<Data>(_url, payload, serviceUrl)
}
public static delete(id: string) {
const _url = sourceUrl + '/' + id
return ApiService.Delete(_url, serviceUrl)
}
public static appendItem(id: string, payload: DataItemCreate) {
const _url = sourceUrl + '/' + id + '/items'
return ApiService.Post<Data>(_url, payload, serviceUrl)
}
public static updateItem(id: string, name: string, payload: DataItemUpdate) {
const _url = sourceUrl + '/' + id + '/items/' + name
return ApiService.Put<Data>(_url, payload, serviceUrl)
}
public static removeItem(id: string, name: string) {
const _url = sourceUrl + '/' + id + '/items/' + name
return ApiService.Delete(_url, serviceUrl)
}
}
export enum ValueType {
String = 0,
Numeic = 1,
Boolean = 2,
Date = 3,
DateTime = 4,
Array = 5,
Object = 6
}
export class DataItem {
id!: string
name!: string
defaultValue!: string
displayName!: string
description?: string
allowBeNull!: boolean
valueType!: ValueType
}
export class Data {
id!: string
name!: string
code!: string
displayName!: string
description?: string
parentId?: string
items = new Array<DataItem>()
}
export class GetDataByPaged extends PagedAndSortedResultRequestDto {
filter = ''
}
export class DataCreateOrUpdate {
name = ''
displayName = ''
description? = ''
}
export class DataCreate extends DataCreateOrUpdate {
parentId?: string
}
export class DataUpdate extends DataCreateOrUpdate {
}
export class DataItemCreateOrUpdate {
defaultValue = ''
displayName = ''
description? = ''
allowBeNull = true
valueType = ValueType.String
}
export class DataItemUpdate extends DataItemCreateOrUpdate {
}
export class DataItemCreate extends DataItemCreateOrUpdate {
name = ''
}

186
vueJs/src/api/layout.ts

@ -1,109 +1,77 @@
import ApiService from './serviceBase'
import { urlStringify } from '@/utils/index'
import { ListResultDto, PagedResultDto, PagedAndSortedResultRequestDto } from './types'
const sourceUrl = '/api/platform/layouts'
/** 远程服务地址 */
const serviceUrl = process.env.VUE_APP_BASE_API
/** 路由相关pi接口 */
export default class LayoutService {
public static get(id: string) {
const _url = sourceUrl + '/' + id
return ApiService.Get<Layout>(_url, serviceUrl)
}
public static getAllList() {
const _url = sourceUrl + '/all'
return ApiService.Get<ListResultDto<Layout >>(_url, serviceUrl)
}
public static getList(payload: GetLayoutByPaged) {
const _url = sourceUrl + '?' + urlStringify(payload)
return ApiService.Get<PagedResultDto<Layout >>(_url, serviceUrl)
}
public static create(payload: LayoutCreate) {
return ApiService.Post<Layout>(sourceUrl, payload, serviceUrl)
}
public static update(id: string, payload: LayoutUpdate) {
const _url = sourceUrl + '/' + id
return ApiService.Put<Layout>(_url, payload, serviceUrl)
}
public static delete(id: string) {
const _url = sourceUrl + '/' + id
return ApiService.Delete(_url, serviceUrl)
}
}
export enum PlatformType {
None = 0,
WinCe = 2,
WinForm = 4,
Desktop = WinCe | WinForm,
WebForm = 8,
WebMvc = 16,
WebMvvm = 32,
Web = WebForm | WebMvc | WebMvvm,
Android = 64,
iOS = 128,
Mobile = Android | iOS,
MiniProgram = 256,
All = Desktop | Web | Mobile | MiniProgram
}
export const PlatformTypes = [
{ key: 'None', value: PlatformType.None },
{ key: 'WinCe', value: PlatformType.WinCe },
{ key: 'WinForm', value: PlatformType.WinForm },
{ key: 'Desktop', value: PlatformType.Desktop },
{ key: 'WebForm', value: PlatformType.WebForm },
{ key: 'WebMvc', value: PlatformType.WebMvc },
{ key: 'WebMvvm', value: PlatformType.WebMvvm },
{ key: 'Web', value: PlatformType.Web },
{ key: 'Android', value: PlatformType.Android },
{ key: 'iOS', value: PlatformType.iOS },
{ key: 'Mobile', value: PlatformType.Mobile },
{ key: 'MiniProgram', value: PlatformType.MiniProgram },
{ key: 'All', value: PlatformType.All }
]
export class Route {
id!: string
name!: string
path!: string
displayName!: string
description?: string
redirect?: string
meta: {[key: string]: any} = {}
}
export class Layout extends Route {
platformType!: PlatformType
dataId!: string
}
export class LayoutCreateOrUpdate {
name!: string
path!: string
displayName!: string
description?: string
redirect?: string
platformType!: PlatformType
}
export class LayoutCreate extends LayoutCreateOrUpdate {
dataId!: string
}
export class LayoutUpdate extends LayoutCreateOrUpdate {
}
export class GetLayoutByPaged extends PagedAndSortedResultRequestDto {
filter = ''
reverse = false
platformType?: PlatformType | null
}
import ApiService from './serviceBase'
import { urlStringify } from '@/utils/index'
import { ListResultDto, PagedResultDto, PagedAndSortedResultRequestDto } from './types'
const sourceUrl = '/api/platform/layouts'
/** 远程服务地址 */
const serviceUrl = process.env.VUE_APP_BASE_API
/** 路由相关pi接口 */
export default class LayoutService {
public static get(id: string) {
const _url = sourceUrl + '/' + id
return ApiService.Get<Layout>(_url, serviceUrl)
}
public static getAllList() {
const _url = sourceUrl + '/all'
return ApiService.Get<ListResultDto<Layout >>(_url, serviceUrl)
}
public static getList(payload: GetLayoutByPaged) {
const _url = sourceUrl + '?' + urlStringify(payload)
return ApiService.Get<PagedResultDto<Layout >>(_url, serviceUrl)
}
public static create(payload: LayoutCreate) {
return ApiService.Post<Layout>(sourceUrl, payload, serviceUrl)
}
public static update(id: string, payload: LayoutUpdate) {
const _url = sourceUrl + '/' + id
return ApiService.Put<Layout>(_url, payload, serviceUrl)
}
public static delete(id: string) {
const _url = sourceUrl + '/' + id
return ApiService.Delete(_url, serviceUrl)
}
}
export class Route {
id!: string
name!: string
path!: string
displayName!: string
description?: string
redirect?: string
meta: {[key: string]: any} = {}
}
export class Layout extends Route {
framework!: string
dataId!: string
}
export class LayoutCreateOrUpdate {
name!: string
path!: string
displayName!: string
description?: string
redirect?: string
}
export class LayoutCreate extends LayoutCreateOrUpdate {
dataId!: string
framework!: string
}
export class LayoutUpdate extends LayoutCreateOrUpdate {
}
export class GetLayoutByPaged extends PagedAndSortedResultRequestDto {
filter = ''
reverse = false
framework = ''
}

245
vueJs/src/api/menu.ts

@ -1,123 +1,122 @@
import ApiService from './serviceBase'
import { Route, PlatformType } from './layout'
import { urlStringify } from '@/utils/index'
import { ISortedResultRequest, PagedResultDto, PagedAndSortedResultRequestDto, ListResultDto } from './types'
const sourceUrl = '/api/platform/menus'
/** 远程服务地址 */
const serviceUrl = process.env.VUE_APP_BASE_API
/** 路由相关pi接口 */
export default class MenuService {
public static get(id: string) {
const _url = sourceUrl + '/' + id
return ApiService.Get<Menu>(_url, serviceUrl)
}
public static getAll(payload: GetAllMenu) {
const _url = sourceUrl + '/all?' + urlStringify(payload)
return ApiService.Get<ListResultDto<Menu>>(_url, serviceUrl)
}
public static getList(payload: GetMenuByPaged) {
const _url = sourceUrl + '?' + urlStringify(payload)
return ApiService.Get<PagedResultDto<Menu>>(_url, serviceUrl)
}
public static getMyMenuList(platformType: PlatformType) {
const _url = sourceUrl + '/by-current-user?platformType=' + platformType
return ApiService.Get<ListResultDto<Menu>>(_url, serviceUrl)
}
public static getRoleMenuList(role: string, platformType: PlatformType) {
const _url = sourceUrl + `/by-role/${role}/${platformType}`
return ApiService.Get<ListResultDto<Menu>>(_url, serviceUrl)
}
public static getUserMenuList(userId: string, platformType: PlatformType) {
const _url = sourceUrl + `/by-user/${userId}/${platformType}`
return ApiService.Get<ListResultDto<Menu>>(_url, serviceUrl)
}
public static create(payload: MenuCreate) {
return ApiService.Post<Menu>(sourceUrl, payload, serviceUrl)
}
public static update(id: string, payload: MenuUpdate) {
const _url = sourceUrl + '/' + id
return ApiService.Put<Menu>(_url, payload, serviceUrl)
}
public static delete(id: string) {
const _url = sourceUrl + '/' + id
return ApiService.Delete(_url, serviceUrl)
}
public static setRoleMenu(payload: RoleMenu) {
const _url = sourceUrl + '/by-role'
return ApiService.Put<void>(_url, payload, serviceUrl)
}
public static setUserMenu(payload: UserMenu) {
const _url = sourceUrl + '/by-user'
return ApiService.Put<void>(_url, payload, serviceUrl)
}
}
export class MenuCreateOrUpdate {
name!: string
path!: string
component!: string
displayName!: string
description?: string
redirect?: string
isPublic!: boolean
platformType!: PlatformType
meta: {[key: string]: any} = {}
}
export class MenuCreate extends MenuCreateOrUpdate {
layoutId!: string
parentId?: string
}
export class MenuUpdate extends MenuCreateOrUpdate {
}
export class GetAllMenu implements ISortedResultRequest {
filter = ''
sorting = ''
reverse = false
parentId?: string
layoutId?: string
platformType?: PlatformType
}
export class GetMenuByPaged extends PagedAndSortedResultRequestDto {
filter = ''
reverse = false
layoutId?: string
parentId?: string
platformType?: PlatformType
}
export class Menu extends Route {
code!: string
layoutId!: string
component!: string
platformType!: PlatformType
parentId?: string
isPublic!: boolean
children = new Array<Menu>()
}
export class RoleMenu {
roleName!: string
menuIds = new Array<string>()
}
export class UserMenu {
userId!: string
menuIds = new Array<string>()
}
import ApiService from './serviceBase'
import { Route } from './layout'
import { urlStringify } from '@/utils/index'
import { ISortedResultRequest, PagedResultDto, PagedAndSortedResultRequestDto, ListResultDto } from './types'
const sourceUrl = '/api/platform/menus'
/** 远程服务地址 */
const serviceUrl = process.env.VUE_APP_BASE_API
/** 路由相关pi接口 */
export default class MenuService {
public static get(id: string) {
const _url = sourceUrl + '/' + id
return ApiService.Get<Menu>(_url, serviceUrl)
}
public static getAll(payload: GetAllMenu) {
const _url = sourceUrl + '/all?' + urlStringify(payload)
return ApiService.Get<ListResultDto<Menu>>(_url, serviceUrl)
}
public static getList(payload: GetMenuByPaged) {
const _url = sourceUrl + '?' + urlStringify(payload)
return ApiService.Get<PagedResultDto<Menu>>(_url, serviceUrl)
}
public static getMyMenuList(framework: string) {
const _url = sourceUrl + '/by-current-user?framework=' + framework
return ApiService.Get<ListResultDto<Menu>>(_url, serviceUrl)
}
public static getRoleMenuList(role: string, framework: string) {
const _url = sourceUrl + `/by-role/${role}/${framework}`
return ApiService.Get<ListResultDto<Menu>>(_url, serviceUrl)
}
public static getUserMenuList(userId: string, framework: string) {
const _url = sourceUrl + `/by-user/${userId}/${framework}`
return ApiService.Get<ListResultDto<Menu>>(_url, serviceUrl)
}
public static create(payload: MenuCreate) {
return ApiService.Post<Menu>(sourceUrl, payload, serviceUrl)
}
public static update(id: string, payload: MenuUpdate) {
const _url = sourceUrl + '/' + id
return ApiService.Put<Menu>(_url, payload, serviceUrl)
}
public static delete(id: string) {
const _url = sourceUrl + '/' + id
return ApiService.Delete(_url, serviceUrl)
}
public static setRoleMenu(payload: RoleMenu) {
const _url = sourceUrl + '/by-role'
return ApiService.Put<void>(_url, payload, serviceUrl)
}
public static setUserMenu(payload: UserMenu) {
const _url = sourceUrl + '/by-user'
return ApiService.Put<void>(_url, payload, serviceUrl)
}
}
export class MenuCreateOrUpdate {
name!: string
path!: string
component!: string
displayName!: string
description?: string
redirect?: string
isPublic!: boolean
meta: {[key: string]: any} = {}
}
export class MenuCreate extends MenuCreateOrUpdate {
layoutId!: string
parentId?: string
}
export class MenuUpdate extends MenuCreateOrUpdate {
}
export class GetAllMenu implements ISortedResultRequest {
filter = ''
sorting = ''
reverse = false
parentId?: string
layoutId?: string
framework = ''
}
export class GetMenuByPaged extends PagedAndSortedResultRequestDto {
filter = ''
reverse = false
layoutId?: string
parentId?: string
framework = ''
}
export class Menu extends Route {
code!: string
layoutId!: string
component!: string
framework = ''
parentId?: string
isPublic!: boolean
children = new Array<Menu>()
}
export class RoleMenu {
roleName!: string
menuIds = new Array<string>()
}
export class UserMenu {
userId!: string
menuIds = new Array<string>()
}

283
vueJs/src/store/modules/permission.ts

@ -1,142 +1,141 @@
import { VuexModule, Module, Mutation, Action, getModule } from 'vuex-module-decorators'
import { RouteConfig } from 'vue-router'
// eslint-disable-next-line
import { asyncRoutes, constantRoutes } from '@/router'
import store from '@/store'
import { AbpModule } from '@/store/modules/abp'
import MenuService, { Menu } from '@/api/menu'
import { PlatformType } from '@/api/layout'
import { generateTree } from '@/utils'
const mapMetaBoolean = (key: string, meta: any) => {
return typeof meta[key] === 'boolean' ? meta[key] : meta[key] === 'true'
}
const mapMetaArray = (key: string, meta: any) => {
return Array.isArray(meta[key]) ? meta[key] : String(meta[key]).split(',')
}
const hasPermission = (roles: string[], route: RouteConfig) => {
if (route.meta && route.meta.roles) {
return roles.some(role => route.meta.roles.includes(role))
} else {
return true
}
}
export const filterAsyncRoutes = (routes: RouteConfig[], roles: string[]) => {
const res: RouteConfig[] = []
routes.forEach(route => {
const r = { ...route }
if (hasPermission(roles, r)) {
if (r.children) {
r.children = filterAsyncRoutes(r.children, roles)
}
res.push(r)
}
})
return res
}
const filterDynamicRoutes = (menus: Menu[]) => {
const res: RouteConfig[] = []
menus.forEach(menu => {
const r: RouteConfig = {
path: menu.path,
name: menu.name,
redirect: menu.redirect,
// meta自行转换
meta: {
activeMenu: menu.meta.activeMenu,
affix: mapMetaBoolean('affix', menu.meta), // 需要转换为正确的bool类型
noCache: mapMetaBoolean('noCache', menu.meta),
breadcrumb: mapMetaBoolean('breadcrumb', menu.meta),
alwaysShow: mapMetaBoolean('alwaysShow', menu.meta),
hidden: mapMetaBoolean('hidden', menu.meta),
icon: menu.meta.icon,
title: menu.meta.title,
displayName: menu.displayName,
roles: mapMetaArray('roles', menu.meta) // 需要转换为正确的array类型
},
component: resolve => require([`@/${menu.component}`], resolve) // 需要这种格式才可以正确加载动态路由
}
if (menu.children && menu.children.length > 0) {
r.children = filterDynamicRoutes(menu.children)
}
res.push(r)
})
return res
}
export interface IPermissionState {
routes: RouteConfig[]
dynamicRoutes: RouteConfig[]
}
@Module({ dynamic: true, store, name: 'permission' })
class Permission extends VuexModule implements IPermissionState {
public routes: RouteConfig[] = []
public dynamicRoutes: RouteConfig[] = []
public authorizedPermissions: string[] = []
@Mutation
private SET_ROUTES(routes: RouteConfig[]) {
this.routes = constantRoutes.concat(routes)
this.dynamicRoutes = routes
}
@Mutation
private SET_AUTHPERMISSIONS(permissions: Array<string>) {
this.authorizedPermissions = permissions
}
@Action
public async RefreshPermissions() {
const authPermissions = new Array<string>()
const grantedPolicies = AbpModule.configuration.auth.grantedPolicies
if (grantedPolicies) {
Object.keys(grantedPolicies).forEach(key => {
if (grantedPolicies[key]) {
authPermissions.push(key)
}
})
}
if (authPermissions.length === 0) {
// 防止没有任何权限无限刷新页面
this.SET_AUTHPERMISSIONS(['guest'])
} else {
this.SET_AUTHPERMISSIONS(authPermissions)
}
}
@Action
public async GenerateRoutes() {
await this.RefreshPermissions() // 保留授权
// 没必要再针对admin角色授权,改成全部后台授权
// if (this.authorizedPermissions.includes('admin')) {
// accessedRoutes = asyncRoutes
// } else {
// accessedRoutes = filterAsyncRoutes(asyncRoutes, this.authorizedPermissions)
// }
// 取消注释用来启用后端动态路由配置
const { items } = await MenuService.getMyMenuList(PlatformType.WebMvvm)
const dynamicRoutes = filterDynamicRoutes(generateTree(items))
this.SET_ROUTES(dynamicRoutes)
// 取消注释用来启用前端动态路由配置
// const accessedRoutes = filterAsyncRoutes(asyncRoutes, this.authorizedPermissions)
// this.SET_ROUTES(accessedRoutes)
}
@Action ResetPermissions() {
this.SET_AUTHPERMISSIONS([])
}
@Action ResetRoutes() {
this.SET_ROUTES([])
}
}
export const PermissionModule = getModule(Permission)
import { VuexModule, Module, Mutation, Action, getModule } from 'vuex-module-decorators'
import { RouteConfig } from 'vue-router'
// eslint-disable-next-line
import { asyncRoutes, constantRoutes } from '@/router'
import store from '@/store'
import { AbpModule } from '@/store/modules/abp'
import MenuService, { Menu } from '@/api/menu'
import { generateTree } from '@/utils'
const mapMetaBoolean = (key: string, meta: any) => {
return typeof meta[key] === 'boolean' ? meta[key] : meta[key] === 'true'
}
const mapMetaArray = (key: string, meta: any) => {
return Array.isArray(meta[key]) ? meta[key] : String(meta[key]).split(',')
}
const hasPermission = (roles: string[], route: RouteConfig) => {
if (route.meta && route.meta.roles) {
return roles.some(role => route.meta.roles.includes(role))
} else {
return true
}
}
export const filterAsyncRoutes = (routes: RouteConfig[], roles: string[]) => {
const res: RouteConfig[] = []
routes.forEach(route => {
const r = { ...route }
if (hasPermission(roles, r)) {
if (r.children) {
r.children = filterAsyncRoutes(r.children, roles)
}
res.push(r)
}
})
return res
}
const filterDynamicRoutes = (menus: Menu[]) => {
const res: RouteConfig[] = []
menus.forEach(menu => {
const r: RouteConfig = {
path: menu.path,
name: menu.name,
redirect: menu.redirect,
// meta自行转换
meta: {
activeMenu: menu.meta.activeMenu,
affix: mapMetaBoolean('affix', menu.meta), // 需要转换为正确的bool类型
noCache: mapMetaBoolean('noCache', menu.meta),
breadcrumb: mapMetaBoolean('breadcrumb', menu.meta),
alwaysShow: mapMetaBoolean('alwaysShow', menu.meta),
hidden: mapMetaBoolean('hidden', menu.meta),
icon: menu.meta.icon,
title: menu.meta.title,
displayName: menu.displayName,
roles: mapMetaArray('roles', menu.meta) // 需要转换为正确的array类型
},
component: resolve => require([`@/${menu.component}`], resolve) // 需要这种格式才可以正确加载动态路由
}
if (menu.children && menu.children.length > 0) {
r.children = filterDynamicRoutes(menu.children)
}
res.push(r)
})
return res
}
export interface IPermissionState {
routes: RouteConfig[]
dynamicRoutes: RouteConfig[]
}
@Module({ dynamic: true, store, name: 'permission' })
class Permission extends VuexModule implements IPermissionState {
public routes: RouteConfig[] = []
public dynamicRoutes: RouteConfig[] = []
public authorizedPermissions: string[] = []
@Mutation
private SET_ROUTES(routes: RouteConfig[]) {
this.routes = constantRoutes.concat(routes)
this.dynamicRoutes = routes
}
@Mutation
private SET_AUTHPERMISSIONS(permissions: Array<string>) {
this.authorizedPermissions = permissions
}
@Action
public async RefreshPermissions() {
const authPermissions = new Array<string>()
const grantedPolicies = AbpModule.configuration.auth.grantedPolicies
if (grantedPolicies) {
Object.keys(grantedPolicies).forEach(key => {
if (grantedPolicies[key]) {
authPermissions.push(key)
}
})
}
if (authPermissions.length === 0) {
// 防止没有任何权限无限刷新页面
this.SET_AUTHPERMISSIONS(['guest'])
} else {
this.SET_AUTHPERMISSIONS(authPermissions)
}
}
@Action
public async GenerateRoutes() {
await this.RefreshPermissions() // 保留授权
// 没必要再针对admin角色授权,改成全部后台授权
// if (this.authorizedPermissions.includes('admin')) {
// accessedRoutes = asyncRoutes
// } else {
// accessedRoutes = filterAsyncRoutes(asyncRoutes, this.authorizedPermissions)
// }
// 取消注释用来启用后端动态路由配置
const { items } = await MenuService.getMyMenuList('Vue Element Admin')
const dynamicRoutes = filterDynamicRoutes(generateTree(items))
this.SET_ROUTES(dynamicRoutes)
// 取消注释用来启用前端动态路由配置
// const accessedRoutes = filterAsyncRoutes(asyncRoutes, this.authorizedPermissions)
// this.SET_ROUTES(accessedRoutes)
}
@Action ResetPermissions() {
this.SET_AUTHPERMISSIONS([])
}
@Action ResetRoutes() {
this.SET_ROUTES([])
}
}
export const PermissionModule = getModule(Permission)

408
vueJs/src/views/admin/data-dictionary/components/DataDictionaryTree.vue

@ -1,205 +1,203 @@
<template>
<div>
<el-card class="box-card">
<div
slot="header"
class="clearfix"
>
<span>{{ $t('AppPlatform.DisplayName:DataDictionary') }}</span>
<el-button
style="float: right;"
type="primary"
icon="ivu-icon ivu-icon-md-add"
@click="handleEditData('')"
>
{{ $t('AppPlatform.Data:AddNew') }}
</el-button>
</div>
<div>
<el-tree
ref="dataTree"
node-key="id"
:props="dataProps"
:data="datas"
draggable
highlight-current
default-expand-all
:expand-on-click-node="false"
icon-class="el-icon-arrow-right"
:allow-drag="handleAllowDrag"
:allow-drop="handleAllowDrop"
@node-drop="handleNodeDroped"
@node-click="handleNodeClick"
@node-contextmenu="onContextMenu"
/>
</div>
</el-card>
<create-or-update-data-dialog
:is-edit="isEditData"
:title="editDataTitle"
:show-dialog="showDataDialog"
:data-id="editDataId"
@closed="onDataDialogClosed"
/>
</div>
</template>
<script lang="ts">
import { checkPermission } from '@/utils/permission'
import { generateTree } from '@/utils/index'
import { Component, Mixins, Vue } from 'vue-property-decorator'
import LocalizationMiXin from '@/mixins/LocalizationMiXin'
import DataDictionaryService, { Data } from '@/api/data-dictionary'
import CreateOrUpdateDataDialog from './CreateOrUpdateDataDialog.vue'
const $contextmenu = Vue.prototype.$contextmenu
@Component({
name: 'DataDictionaryTree',
components: {
CreateOrUpdateDataDialog
},
data() {
return {
dataProps: {
label: 'displayName',
children: 'children'
}
}
}
})
export default class DataDictionaryTree extends Mixins(LocalizationMiXin) {
private showDataDialog = false
private isEditData = false
private editDataId = ''
private editDataTitle = ''
private datas = []
private currentEditNode = {}
mounted() {
this.handleGetDatas()
}
private handleGetDatas() {
DataDictionaryService
.getAll()
.then(res => {
this.datas = generateTree(res.items)
})
}
private onContextMenu(event: any, data: Data) {
$contextmenu({
items: [
{
label: this.l('AppPlatform.Data:Edit'),
icon: 'el-icon-edit',
disabled: !checkPermission(['Platform.DataDictionary.Update']),
onClick: () => {
this.handleEditData(data.id)
}
},
{
label: this.l('AppPlatform.Data:AddNew'),
icon: 'ivu-icon ivu-icon-md-add',
disabled: !checkPermission(['Platform.DataDictionary.Create']),
onClick: () => {
this.handleEditData('')
}
},
{
label: this.l('AppPlatform.Data:AppendItem'),
disabled: !checkPermission(['Platform.DataDictionary.ManageItems']),
onClick: () => {
this.$emit('onDataChecked', data.id)
this.$events.emit('onCreateNewDataItem')
}
},
{
label: this.l('AppPlatform.Data:Delete'),
icon: 'el-icon-delete',
disabled: !checkPermission(['Platform.DataDictionary.Delete']),
onClick: () => {
this.$confirm(this.l('AppPlatform.Data:WillDelete', { 0: data.displayName }),
this.l('AppPlatform.AreYouSure'), {
callback: (action) => {
if (action === 'confirm') {
DataDictionaryService
.delete(data.id)
.then(() => {
this.handleGetDatas()
})
}
}
})
}
}
],
event,
customClass: 'context-menu',
zIndex: 2,
minWidth: 150
})
}
private onDataDialogClosed(changed: boolean) {
this.showDataDialog = false
if (changed) {
this.handleGetDatas()
}
}
private handleEditData(dataId: string) {
this.editDataTitle = this.l('AppPlatform.Data:AddNew')
this.isEditData = false
if (dataId) {
this.editDataId = dataId
this.isEditData = true
this.editDataTitle = this.l('AppPlatform.Data:Edit')
} else {
this.editDataId = ''
}
this.showDataDialog = true
}
private handleAllowDrag(draggingNode: any) {
return draggingNode.data.parentId !== undefined && draggingNode.data.parentId !== null
}
private handleAllowDrop(draggingNode: any, dropNode: any) {
console.log(dropNode)
}
private handleNodeDroped(draggingNode: any, dropNode: any) {
console.log(dropNode)
}
private handleNodeClick(data: any) {
if (data.id !== undefined) {
this.$emit('onDataChecked', data.id)
}
}
}
</script>
<style lang="scss" scoped>
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
.el-dropdown-link {
cursor: pointer;
color: #409EFF;
}
.el-icon-arrow-down {
font-size: 12px;
}
</style>
<template>
<div>
<el-card class="box-card">
<div
slot="header"
class="clearfix"
>
<span>{{ $t('AppPlatform.DisplayName:DataDictionary') }}</span>
<el-button
style="float: right;"
type="primary"
icon="ivu-icon ivu-icon-md-add"
@click="handleEditData(null)"
>
{{ $t('AppPlatform.Data:AddNew') }}
</el-button>
</div>
<div>
<el-tree
ref="dataTree"
node-key="id"
:props="dataProps"
:data="datas"
draggable
highlight-current
default-expand-all
:expand-on-click-node="false"
icon-class="el-icon-arrow-right"
:allow-drag="handleAllowDrag"
:allow-drop="handleAllowDrop"
@node-drop="handleNodeDroped"
@node-click="handleNodeClick"
@node-contextmenu="onContextMenu"
/>
</div>
</el-card>
<create-or-update-data-dialog
:is-edit="isEditData"
:title="editDataTitle"
:show-dialog="showDataDialog"
:data-id="editDataId"
@closed="onDataDialogClosed"
/>
</div>
</template>
<script lang="ts">
import { checkPermission } from '@/utils/permission'
import { generateTree } from '@/utils/index'
import { Component, Mixins, Vue } from 'vue-property-decorator'
import LocalizationMiXin from '@/mixins/LocalizationMiXin'
import DataDictionaryService, { Data } from '@/api/data-dictionary'
import CreateOrUpdateDataDialog from './CreateOrUpdateDataDialog.vue'
const $contextmenu = Vue.prototype.$contextmenu
@Component({
name: 'DataDictionaryTree',
components: {
CreateOrUpdateDataDialog
},
data() {
return {
dataProps: {
label: 'displayName',
children: 'children'
}
}
}
})
export default class DataDictionaryTree extends Mixins(LocalizationMiXin) {
private showDataDialog = false
private isEditData = false
private editDataId: string | null = ''
private editDataTitle = ''
private datas = []
private currentEditNode = {}
mounted() {
this.handleGetDatas()
}
private handleGetDatas() {
DataDictionaryService
.getAll()
.then(res => {
this.datas = generateTree(res.items)
})
}
private onContextMenu(event: any, data: Data) {
$contextmenu({
items: [
{
label: this.l('AppPlatform.Data:Edit'),
icon: 'el-icon-edit',
disabled: !checkPermission(['Platform.DataDictionary.Update']),
onClick: () => {
this.handleEditData(data.id)
}
},
{
label: this.l('AppPlatform.Data:AddNew'),
icon: 'ivu-icon ivu-icon-md-add',
disabled: !checkPermission(['Platform.DataDictionary.Create']),
onClick: () => {
this.handleEditData(null)
}
},
{
label: this.l('AppPlatform.Data:AppendItem'),
disabled: !checkPermission(['Platform.DataDictionary.ManageItems']),
onClick: () => {
this.$emit('onDataChecked', data.id)
this.$events.emit('onCreateNewDataItem')
}
},
{
label: this.l('AppPlatform.Data:Delete'),
icon: 'el-icon-delete',
disabled: !checkPermission(['Platform.DataDictionary.Delete']),
onClick: () => {
this.$confirm(this.l('AppPlatform.Data:WillDelete', { 0: data.displayName }),
this.l('AppPlatform.AreYouSure'), {
callback: (action) => {
if (action === 'confirm') {
DataDictionaryService
.delete(data.id)
.then(() => {
this.handleGetDatas()
})
}
}
})
}
}
],
event,
customClass: 'context-menu',
zIndex: 2,
minWidth: 150
})
}
private onDataDialogClosed(changed: boolean) {
this.showDataDialog = false
if (changed) {
this.handleGetDatas()
}
}
private handleEditData(dataId: string | null) {
this.editDataTitle = this.l('AppPlatform.Data:AddNew')
this.isEditData = false
this.editDataId = dataId
if (dataId) {
this.isEditData = true
this.editDataTitle = this.l('AppPlatform.Data:Edit')
}
this.showDataDialog = true
}
private handleAllowDrag(draggingNode: any) {
return draggingNode.data.parentId !== undefined && draggingNode.data.parentId !== null
}
private handleAllowDrop(draggingNode: any, dropNode: any) {
console.log(dropNode)
}
private handleNodeDroped(draggingNode: any, dropNode: any) {
console.log(dropNode)
}
private handleNodeClick(data: any) {
if (data.id !== undefined) {
this.$emit('onDataChecked', data.id)
}
}
}
</script>
<style lang="scss" scoped>
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
.el-dropdown-link {
cursor: pointer;
color: #409EFF;
}
.el-icon-arrow-down {
font-size: 12px;
}
</style>

358
vueJs/src/views/admin/roles/components/ManageRoleMenuDialog.vue

@ -1,173 +1,185 @@
<template>
<el-dialog
v-el-draggable-dialog
width="800px"
:title="$t('AppPlatform.Menu:Manage')"
:visible="showDialog"
custom-class="modal-form"
:close-on-click-modal="false"
:close-on-press-escape="false"
:show-close="false"
@close="onFormClosed"
>
<el-form>
<el-card>
<el-form-item
label-width="120px"
:label="$t('AppPlatform.DisplayName:PlatformType')"
>
<el-select
v-model="getMenuQuery.platformType"
style="width: 100%;"
class="filter-item"
clearable
:placeholder="$t('pleaseSelectBy', {name: $t('AppPlatform.DisplayName:PlatformType')})"
@change="onPlatformTypeChanged"
>
<el-option
v-for="item in platformTypes"
:key="item.key"
:label="item.key"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item
label-width="120px"
:label="$t('AppPlatform.DisplayName:Menus')"
>
<el-tree
ref="roleMenuTree"
show-checkbox
:check-strictly="true"
node-key="id"
:data="menus"
:props="menuProps"
:default-checked-keys="roleMenuIds"
/>
</el-form-item>
</el-card>
<el-form-item>
<el-button
class="cancel"
type="info"
style="width:100px"
@click="onFormClosed"
>
{{ $t('AbpUi.Cancel') }}
</el-button>
<el-button
class="confirm"
type="primary"
style="width:100px"
icon="el-icon-check"
:loading="confirmButtonBusy"
@click="onSave"
>
{{ confirmButtonTitle }}
</el-button>
</el-form-item>
</el-form>
</el-dialog>
</template>
<script lang="ts">
import { Component, Mixins, Prop, Watch } from 'vue-property-decorator'
import LocalizationMiXin from '@/mixins/LocalizationMiXin'
import MenuService, { Menu, GetAllMenu, RoleMenu } from '@/api/menu'
import { generateTree } from '@/utils'
import { PlatformType, PlatformTypes } from '@/api/layout'
import { Tree } from 'element-ui'
@Component({
name: 'ManageRoleMenuDialog'
})
export default class ManageRoleMenuDialog extends Mixins(LocalizationMiXin) {
@Prop({ default: false })
private showDialog!: boolean
@Prop({ default: '' })
private roleName!: string
private menus = new Array<Menu>()
private roleMenuIds = new Array<string>()
private getMenuQuery = new GetAllMenu()
private platformTypes = PlatformTypes
private confirmButtonBusy = false
private menuProps = {
children: 'children',
label: 'displayName'
}
get confirmButtonTitle() {
if (this.confirmButtonBusy) {
return this.$t('AbpUi.SavingWithThreeDot')
}
return this.$t('AbpUi.Save')
}
@Watch('showDialog', { immediate: true })
private onShowDialogChanged() {
this.handleGetRoleMenus()
}
private onPlatformTypeChanged() {
this.handleGetMenus()
this.handleGetRoleMenus()
}
private handleGetMenus() {
MenuService
.getAll(this.getMenuQuery)
.then(res => {
this.menus = generateTree(res.items)
})
}
private handleGetRoleMenus() {
if (this.showDialog && this.roleName) {
MenuService
.getRoleMenuList(this.roleName, this.getMenuQuery.platformType || PlatformType.None)
.then(res => {
this.roleMenuIds = res.items.map(item => item.id)
})
} else {
this.roleMenuIds.length = 0
}
}
private onSave() {
const roleMenuTree = this.$refs.roleMenuTree as Tree
const roleMenu = new RoleMenu()
roleMenu.roleName = this.roleName
roleMenu.menuIds = roleMenuTree.getCheckedKeys()
MenuService
.setRoleMenu(roleMenu)
.then(() => {
this.$message.success(this.l('successful'))
this.onFormClosed()
})
}
private onFormClosed() {
this.$nextTick(() => {
const tree = this.$refs.roleMenuTree as Tree
tree.setCheckedKeys([])
})
this.$emit('closed')
}
}
</script>
<style lang="scss" scoped>
.confirm {
position: absolute;
margin-top: 10px;
right: 0px;
}
.cancel {
position: absolute;
margin-top: 10px;
right: 120px;
}
</style>
<template>
<el-dialog
v-el-draggable-dialog
width="800px"
:title="$t('AppPlatform.Menu:Manage')"
:visible="showDialog"
custom-class="modal-form"
:close-on-click-modal="false"
:close-on-press-escape="false"
:show-close="false"
@close="onFormClosed"
>
<el-form>
<el-card>
<el-form-item
label-width="120px"
:label="$t('AppPlatform.DisplayName:UIFramework')"
>
<el-select
v-model="getMenuQuery.framework"
style="width: 100%;"
class="filter-item"
clearable
:placeholder="$t('pleaseSelectBy', {name: $t('AppPlatform.DisplayName:UIFramework')})"
@change="onFrameworksChanged"
>
<el-option
v-for="framework in uiFrameworks"
:key="framework"
:label="framework"
:value="framework"
/>
</el-select>
</el-form-item>
<el-form-item
label-width="120px"
:label="$t('AppPlatform.DisplayName:Menus')"
>
<el-tree
ref="roleMenuTree"
show-checkbox
:check-strictly="true"
node-key="id"
:data="menus"
:props="menuProps"
:default-checked-keys="roleMenuIds"
/>
</el-form-item>
</el-card>
<el-form-item>
<el-button
class="cancel"
type="info"
style="width:100px"
@click="onFormClosed"
>
{{ $t('AbpUi.Cancel') }}
</el-button>
<el-button
class="confirm"
type="primary"
style="width:100px"
icon="el-icon-check"
:loading="confirmButtonBusy"
@click="onSave"
>
{{ confirmButtonTitle }}
</el-button>
</el-form-item>
</el-form>
</el-dialog>
</template>
<script lang="ts">
import { Component, Mixins, Prop, Watch } from 'vue-property-decorator'
import LocalizationMiXin from '@/mixins/LocalizationMiXin'
import DataService from '@/api/data-dictionary'
import MenuService, { Menu, GetAllMenu, RoleMenu } from '@/api/menu'
import { generateTree } from '@/utils'
import { Tree } from 'element-ui'
@Component({
name: 'ManageRoleMenuDialog'
})
export default class ManageRoleMenuDialog extends Mixins(LocalizationMiXin) {
@Prop({ default: false })
private showDialog!: boolean
@Prop({ default: '' })
private roleName!: string
private menus = new Array<Menu>()
private roleMenuIds = new Array<string>()
private getMenuQuery = new GetAllMenu()
private uiFrameworks: string[] = []
private confirmButtonBusy = false
private menuProps = {
children: 'children',
label: 'displayName'
}
get confirmButtonTitle() {
if (this.confirmButtonBusy) {
return this.$t('AbpUi.SavingWithThreeDot')
}
return this.$t('AbpUi.Save')
}
@Watch('showDialog', { immediate: true })
private onShowDialogChanged() {
this.handleGetRoleMenus()
}
monted() {
this.getUIFrameworks()
}
private onFrameworksChanged() {
this.handleGetMenus()
this.handleGetRoleMenus()
}
private getUIFrameworks() {
DataService
.getByName('UI Framewark')
.then(res => {
this.uiFrameworks = res.items.map(item => item.name)
})
}
private handleGetMenus() {
MenuService
.getAll(this.getMenuQuery)
.then(res => {
this.menus = generateTree(res.items)
})
}
private handleGetRoleMenus() {
if (this.showDialog && this.roleName) {
MenuService
.getRoleMenuList(this.roleName, this.getMenuQuery.framework)
.then(res => {
this.roleMenuIds = res.items.map(item => item.id)
})
} else {
this.roleMenuIds.length = 0
}
}
private onSave() {
const roleMenuTree = this.$refs.roleMenuTree as Tree
const roleMenu = new RoleMenu()
roleMenu.roleName = this.roleName
roleMenu.menuIds = roleMenuTree.getCheckedKeys()
MenuService
.setRoleMenu(roleMenu)
.then(() => {
this.$message.success(this.l('successful'))
this.onFormClosed()
})
}
private onFormClosed() {
this.$nextTick(() => {
const tree = this.$refs.roleMenuTree as Tree
tree.setCheckedKeys([])
})
this.$emit('closed')
}
}
</script>
<style lang="scss" scoped>
.confirm {
position: absolute;
margin-top: 10px;
right: 0px;
}
.cancel {
position: absolute;
margin-top: 10px;
right: 120px;
}
</style>

716
vueJs/src/views/admin/roles/index.vue

@ -1,358 +1,358 @@
<template>
<div class="app-container">
<div class="filter-container">
<el-button
class="filter-item"
style="margin-left: 10px; text-alignt"
type="primary"
@click="refreshPagedData"
>
{{ $t('roles.refreshList') }}
</el-button>
<el-button
class="filter-item"
type="primary"
:disabled="!checkPermission(['AbpIdentity.Roles.Create'])"
@click="handleCreateRole"
>
{{ $t('roles.createRole') }}
</el-button>
</div>
<el-table
v-loading="dataLoading"
row-key="id"
:data="dataList"
border
fit
highlight-current-row
style="width: 100%;"
size="small"
>
<el-table-column
:label="$t('roles.id')"
prop="id"
sortable
width="300px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.id }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('roles.name')"
prop="name"
sortable
width="350px"
min-width="350px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.name }}</span>
<el-tag
v-if="row.isDefault"
type="success"
>
{{ $t('roles.isDefault') }}
</el-tag>
</template>
</el-table-column>
<el-table-column
:label="$t('roles.isPublic')"
prop="isPublic"
width="200px"
align="center"
>
<template slot-scope="{row}">
<el-tag
:type="row.isPublic ? 'success' : 'warning'"
>
{{ row.isPublic ? $t('roles.isPublic') : $t('roles.isPrivate') }}
</el-tag>
</template>
</el-table-column>
<el-table-column
:label="$t('roles.type')"
prop="isStatic"
width="200px"
align="center"
>
<template slot-scope="{row}">
<el-tag
:type="row.isStatic ? 'info' : 'success'"
>
{{ row.isStatic ? $t('roles.system') : $t('roles.custom') }}
</el-tag>
</template>
</el-table-column>
<el-table-column
:label="$t('roles.operaActions')"
align="center"
width="250px"
min-width="250px"
>
<template slot-scope="{row}">
<el-button
:disabled="!checkPermission(['AbpIdentity.Roles.Update'])"
size="mini"
type="primary"
@click="handleEditRole(row)"
>
{{ $t('roles.updateRole') }}
</el-button>
<el-dropdown
class="options"
@command="handleCommand"
>
<el-button
v-permission="['AbpIdentity.Roles']"
size="mini"
type="info"
>
{{ $t('roles.otherOpera') }}<i class="el-icon-arrow-down el-icon--right" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
:command="{key: 'claim', row}"
:disabled="!checkPermission(['AbpIdentity.Roles.ManageClaims'])"
>
{{ $t('AbpIdentity.ManageClaim') }}
</el-dropdown-item>
<el-dropdown-item
:command="{key: 'menu', row}"
:disabled="!checkPermission(['Platform.Menu.ManageRoles'])"
>
{{ $t('AppPlatform.Menu:Manage') }}
</el-dropdown-item>
<el-dropdown-item
:command="{key: 'permission', row}"
:disabled="!checkPermission(['AbpIdentity.Roles.ManagePermissions'])"
>
{{ $t('AbpIdentity.Permissions') }}
</el-dropdown-item>
<el-dropdown-item
:command="row.isDefault ? {key: 'unDefault', row} : {key: 'default', row}"
:disabled="row.isStatic || !checkPermission(['AbpIdentity.Roles.Update'])"
>
{{ row.isDefault ? $t('roles.unSetDefault') : $t('roles.setDefault') }}
</el-dropdown-item>
<el-dropdown-item
divided
:command="{key: 'delete', row}"
:disabled="row.isStatic || !checkPermission(['AbpIdentity.Roles.Delete'])"
>
{{ $t('roles.deleteRole') }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<pagination
v-show="dataTotal>0"
:total="dataTotal"
:page.sync="currentPage"
:limit.sync="pageSize"
@pagination="refreshPagedData"
/>
<role-edit-form
:show-dialog="showEditDialog"
:role-id="editRoleId"
@closed="onEditRoleFormClosed"
/>
<role-create-form
:show-dialog="showCreateDialog"
@closed="onCreateDialogClosed"
/>
<role-claim-create-or-update-form
:show-dialog="showClaimDialog"
:role-id="editRoleId"
@closed="onClaimDialogClosed"
/>
<manage-role-menu-dialog
:show-dialog="showManageRoleMenuDialog"
:role-name="editRoleName"
@closed="showManageRoleMenuDialog=false"
/>
<permission-form
provider-name="R"
:provider-key="editRoleName"
:readonly="!checkPermission(['AbpIdentity.Roles.ManagePermissions'])"
:show-dialog="showPermissionDialog"
@closed="onPermissionDialogClosed"
/>
</div>
</template>
<script lang="ts">
import { abpPagerFormat } from '@/utils'
import DataListMiXin from '@/mixins/DataListMiXin'
import Component, { mixins } from 'vue-class-component'
import RoleService, { RoleDto, UpdateRoleDto, RoleGetPagedDto } from '@/api/roles'
import { checkPermission } from '@/utils/permission'
import Pagination from '@/components/Pagination/index.vue'
import PermissionForm from '@/components/PermissionForm/index.vue'
import RoleEditForm from './components/RoleEditForm.vue'
import RoleCreateForm from './components/RoleCreateForm.vue'
import ManageRoleMenuDialog from './components/ManageRoleMenuDialog.vue'
import RoleClaimCreateOrUpdateForm from './components/RoleClaimCreateOrUpdateForm.vue'
@Component({
name: 'RoleList',
components: {
PermissionForm,
Pagination,
RoleEditForm,
RoleCreateForm,
ManageRoleMenuDialog,
RoleClaimCreateOrUpdateForm
},
methods: {
checkPermission
}
})
export default class extends mixins(DataListMiXin) {
private showEditDialog = false
private showManageRoleMenuDialog = false
private editRoleId = ''
private showClaimDialog = false
private showCreateDialog = false
private editRoleName = ''
private showPermissionDialog = false
public dataFilter = new RoleGetPagedDto()
mounted() {
this.refreshPagedData()
}
protected processDataFilter() {
this.dataFilter.skipCount = abpPagerFormat(this.currentPage, this.pageSize)
}
/** 获取角色权限列表 */
protected getPagedList(filter: any) {
return RoleService.getRoles(filter)
}
/** 响应角色行操作事件 */
private handleCommand(command: {key: string, row: RoleDto}) {
switch (command.key) {
case 'claim' :
this.handleShowCliamDialog(command.row)
break
case 'permission' :
this.handleShowPermissionDialog(command.row)
break
case 'default' :
this.handleSetDefaultRole(command.row, true)
break
case 'unDefault' :
this.handleSetDefaultRole(command.row, false)
break
case 'delete' :
this.handleDeleteRole(command.row)
break
case 'menu' :
this.editRoleName = command.row.name
this.showManageRoleMenuDialog = true
break
default: break
}
}
/** 新建角色 */
private handleCreateRole() {
this.showCreateDialog = true
}
private handleEditRole(role: RoleDto) {
this.editRoleId = role.id
this.showEditDialog = true
}
private handleShowCliamDialog(row: RoleDto) {
this.editRoleId = row.id
this.showClaimDialog = true
}
private handleShowPermissionDialog(row: RoleDto) {
this.editRoleName = row.name
this.showPermissionDialog = true
}
private onPermissionDialogClosed() {
this.showPermissionDialog = false
}
private onClaimDialogClosed() {
this.showClaimDialog = false
}
private onCreateDialogClosed(changed: boolean) {
this.showCreateDialog = false
if (changed) {
this.refreshPagedData()
}
}
/** 设置默认角色 */
private handleSetDefaultRole(role: RoleDto, setDefault: boolean) {
// console.log('handleSetDefaultRole:' + role.id)
const setDefaultRoleDto = new UpdateRoleDto()
setDefaultRoleDto.name = role.name
setDefaultRoleDto.isDefault = setDefault
setDefaultRoleDto.concurrencyStamp = role.concurrencyStamp
RoleService.updateRole(role.id, setDefaultRoleDto).then(role => {
this.$message.success(this.l('roles.roleHasBeenSetDefault', { name: role.name }))
this.refreshPagedData()
})
}
/** 删除角色 */
private handleDeleteRole(role: RoleDto) {
this.$confirm(this.l('roles.delNotRecoverData'),
this.l('roles.whetherDeleteRole', { name: role.name }), {
callback: (action) => {
if (action === 'confirm') {
RoleService.deleteRole(role.id).then(() => {
this.$message.success(this.l('roles.roleHasBeenDeleted', { name: role.name }))
this.refreshPagedData()
})
}
}
})
}
private onEditRoleFormClosed(changed: boolean) {
this.showEditDialog = false
if (changed) {
this.refreshPagedData()
}
}
}
</script>
<style lang="scss" scoped>
.roleItem {
width: 40px;
}
.options {
vertical-align: top;
margin-left: 20px;
}
.el-dropdown + .el-dropdown {
margin-left: 15px;
}
.el-icon-arrow-down {
font-size: 12px;
}
</style>
<template>
<div class="app-container">
<div class="filter-container">
<el-button
class="filter-item"
style="margin-left: 10px;"
type="primary"
@click="refreshPagedData"
>
{{ $t('roles.refreshList') }}
</el-button>
<el-button
class="filter-item"
type="primary"
:disabled="!checkPermission(['AbpIdentity.Roles.Create'])"
@click="handleCreateRole"
>
{{ $t('roles.createRole') }}
</el-button>
</div>
<el-table
v-loading="dataLoading"
row-key="id"
:data="dataList"
border
fit
highlight-current-row
style="width: 100%;"
size="small"
>
<el-table-column
:label="$t('roles.id')"
prop="id"
sortable
width="300px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.id }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('roles.name')"
prop="name"
sortable
width="350px"
min-width="350px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.name }}</span>
<el-tag
v-if="row.isDefault"
type="success"
>
{{ $t('roles.isDefault') }}
</el-tag>
</template>
</el-table-column>
<el-table-column
:label="$t('roles.isPublic')"
prop="isPublic"
width="200px"
align="center"
>
<template slot-scope="{row}">
<el-tag
:type="row.isPublic ? 'success' : 'warning'"
>
{{ row.isPublic ? $t('roles.isPublic') : $t('roles.isPrivate') }}
</el-tag>
</template>
</el-table-column>
<el-table-column
:label="$t('roles.type')"
prop="isStatic"
width="200px"
align="center"
>
<template slot-scope="{row}">
<el-tag
:type="row.isStatic ? 'info' : 'success'"
>
{{ row.isStatic ? $t('roles.system') : $t('roles.custom') }}
</el-tag>
</template>
</el-table-column>
<el-table-column
:label="$t('roles.operaActions')"
align="center"
width="250px"
min-width="250px"
>
<template slot-scope="{row}">
<el-button
:disabled="!checkPermission(['AbpIdentity.Roles.Update'])"
size="mini"
type="primary"
@click="handleEditRole(row)"
>
{{ $t('roles.updateRole') }}
</el-button>
<el-dropdown
class="options"
@command="handleCommand"
>
<el-button
v-permission="['AbpIdentity.Roles']"
size="mini"
type="info"
>
{{ $t('roles.otherOpera') }}<i class="el-icon-arrow-down el-icon--right" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
:command="{key: 'claim', row}"
:disabled="!checkPermission(['AbpIdentity.Roles.ManageClaims'])"
>
{{ $t('AbpIdentity.ManageClaim') }}
</el-dropdown-item>
<el-dropdown-item
:command="{key: 'menu', row}"
:disabled="!checkPermission(['Platform.Menu.ManageRoles'])"
>
{{ $t('AppPlatform.Menu:Manage') }}
</el-dropdown-item>
<el-dropdown-item
:command="{key: 'permission', row}"
:disabled="!checkPermission(['AbpIdentity.Roles.ManagePermissions'])"
>
{{ $t('AbpIdentity.Permissions') }}
</el-dropdown-item>
<el-dropdown-item
:command="row.isDefault ? {key: 'unDefault', row} : {key: 'default', row}"
:disabled="row.isStatic || !checkPermission(['AbpIdentity.Roles.Update'])"
>
{{ row.isDefault ? $t('roles.unSetDefault') : $t('roles.setDefault') }}
</el-dropdown-item>
<el-dropdown-item
divided
:command="{key: 'delete', row}"
:disabled="row.isStatic || !checkPermission(['AbpIdentity.Roles.Delete'])"
>
{{ $t('roles.deleteRole') }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<pagination
v-show="dataTotal>0"
:total="dataTotal"
:page.sync="currentPage"
:limit.sync="pageSize"
@pagination="refreshPagedData"
/>
<role-edit-form
:show-dialog="showEditDialog"
:role-id="editRoleId"
@closed="onEditRoleFormClosed"
/>
<role-create-form
:show-dialog="showCreateDialog"
@closed="onCreateDialogClosed"
/>
<role-claim-create-or-update-form
:show-dialog="showClaimDialog"
:role-id="editRoleId"
@closed="onClaimDialogClosed"
/>
<manage-role-menu-dialog
:show-dialog="showManageRoleMenuDialog"
:role-name="editRoleName"
@closed="showManageRoleMenuDialog=false"
/>
<permission-form
provider-name="R"
:provider-key="editRoleName"
:readonly="!checkPermission(['AbpIdentity.Roles.ManagePermissions'])"
:show-dialog="showPermissionDialog"
@closed="onPermissionDialogClosed"
/>
</div>
</template>
<script lang="ts">
import { abpPagerFormat } from '@/utils'
import DataListMiXin from '@/mixins/DataListMiXin'
import Component, { mixins } from 'vue-class-component'
import RoleService, { RoleDto, UpdateRoleDto, RoleGetPagedDto } from '@/api/roles'
import { checkPermission } from '@/utils/permission'
import Pagination from '@/components/Pagination/index.vue'
import PermissionForm from '@/components/PermissionForm/index.vue'
import RoleEditForm from './components/RoleEditForm.vue'
import RoleCreateForm from './components/RoleCreateForm.vue'
import ManageRoleMenuDialog from './components/ManageRoleMenuDialog.vue'
import RoleClaimCreateOrUpdateForm from './components/RoleClaimCreateOrUpdateForm.vue'
@Component({
name: 'RoleList',
components: {
PermissionForm,
Pagination,
RoleEditForm,
RoleCreateForm,
ManageRoleMenuDialog,
RoleClaimCreateOrUpdateForm
},
methods: {
checkPermission
}
})
export default class extends mixins(DataListMiXin) {
private showEditDialog = false
private showManageRoleMenuDialog = false
private editRoleId = ''
private showClaimDialog = false
private showCreateDialog = false
private editRoleName = ''
private showPermissionDialog = false
public dataFilter = new RoleGetPagedDto()
mounted() {
this.refreshPagedData()
}
protected processDataFilter() {
this.dataFilter.skipCount = abpPagerFormat(this.currentPage, this.pageSize)
}
/** 获取角色权限列表 */
protected getPagedList(filter: any) {
return RoleService.getRoles(filter)
}
/** 响应角色行操作事件 */
private handleCommand(command: {key: string, row: RoleDto}) {
switch (command.key) {
case 'claim' :
this.handleShowCliamDialog(command.row)
break
case 'permission' :
this.handleShowPermissionDialog(command.row)
break
case 'default' :
this.handleSetDefaultRole(command.row, true)
break
case 'unDefault' :
this.handleSetDefaultRole(command.row, false)
break
case 'delete' :
this.handleDeleteRole(command.row)
break
case 'menu' :
this.editRoleName = command.row.name
this.showManageRoleMenuDialog = true
break
default: break
}
}
/** 新建角色 */
private handleCreateRole() {
this.showCreateDialog = true
}
private handleEditRole(role: RoleDto) {
this.editRoleId = role.id
this.showEditDialog = true
}
private handleShowCliamDialog(row: RoleDto) {
this.editRoleId = row.id
this.showClaimDialog = true
}
private handleShowPermissionDialog(row: RoleDto) {
this.editRoleName = row.name
this.showPermissionDialog = true
}
private onPermissionDialogClosed() {
this.showPermissionDialog = false
}
private onClaimDialogClosed() {
this.showClaimDialog = false
}
private onCreateDialogClosed(changed: boolean) {
this.showCreateDialog = false
if (changed) {
this.refreshPagedData()
}
}
/** 设置默认角色 */
private handleSetDefaultRole(role: RoleDto, setDefault: boolean) {
// console.log('handleSetDefaultRole:' + role.id)
const setDefaultRoleDto = new UpdateRoleDto()
setDefaultRoleDto.name = role.name
setDefaultRoleDto.isDefault = setDefault
setDefaultRoleDto.concurrencyStamp = role.concurrencyStamp
RoleService.updateRole(role.id, setDefaultRoleDto).then(role => {
this.$message.success(this.l('roles.roleHasBeenSetDefault', { name: role.name }))
this.refreshPagedData()
})
}
/** 删除角色 */
private handleDeleteRole(role: RoleDto) {
this.$confirm(this.l('roles.delNotRecoverData'),
this.l('roles.whetherDeleteRole', { name: role.name }), {
callback: (action) => {
if (action === 'confirm') {
RoleService.deleteRole(role.id).then(() => {
this.$message.success(this.l('roles.roleHasBeenDeleted', { name: role.name }))
this.refreshPagedData()
})
}
}
})
}
private onEditRoleFormClosed(changed: boolean) {
this.showEditDialog = false
if (changed) {
this.refreshPagedData()
}
}
}
</script>
<style lang="scss" scoped>
.roleItem {
width: 40px;
}
.options {
vertical-align: top;
margin-left: 20px;
}
.el-dropdown + .el-dropdown {
margin-left: 15px;
}
.el-icon-arrow-down {
font-size: 12px;
}
</style>

358
vueJs/src/views/admin/users/components/ManageUserMenuDialog.vue

@ -1,173 +1,185 @@
<template>
<el-dialog
v-el-draggable-dialog
width="800px"
:title="$t('AppPlatform.Menu:Manage')"
:visible="showDialog"
custom-class="modal-form"
:close-on-click-modal="false"
:close-on-press-escape="false"
:show-close="false"
@close="onFormClosed"
>
<el-form>
<el-card>
<el-form-item
label-width="120px"
:label="$t('AppPlatform.DisplayName:PlatformType')"
>
<el-select
v-model="getMenuQuery.platformType"
style="width: 100%;"
class="filter-item"
clearable
:placeholder="$t('pleaseSelectBy', {name: $t('AppPlatform.DisplayName:PlatformType')})"
@change="onPlatformTypeChanged"
>
<el-option
v-for="item in platformTypes"
:key="item.key"
:label="item.key"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item
label-width="120px"
:label="$t('AppPlatform.DisplayName:Menus')"
>
<el-tree
ref="userMenuTree"
show-checkbox
:check-strictly="true"
node-key="id"
:data="menus"
:props="menuProps"
:default-checked-keys="userMenuIds"
/>
</el-form-item>
</el-card>
<el-form-item>
<el-button
class="cancel"
type="info"
style="width:100px"
@click="onFormClosed"
>
{{ $t('AbpUi.Cancel') }}
</el-button>
<el-button
class="confirm"
type="primary"
style="width:100px"
icon="el-icon-check"
:loading="confirmButtonBusy"
@click="onSave"
>
{{ confirmButtonTitle }}
</el-button>
</el-form-item>
</el-form>
</el-dialog>
</template>
<script lang="ts">
import { Component, Mixins, Prop, Watch } from 'vue-property-decorator'
import LocalizationMiXin from '@/mixins/LocalizationMiXin'
import MenuService, { Menu, GetAllMenu, UserMenu } from '@/api/menu'
import { generateTree } from '@/utils'
import { PlatformType, PlatformTypes } from '@/api/layout'
import { Tree } from 'element-ui'
@Component({
name: 'ManageUserMenuDialog'
})
export default class ManageUserMenuDialog extends Mixins(LocalizationMiXin) {
@Prop({ default: false })
private showDialog!: boolean
@Prop({ default: '' })
private userId!: string
private menus = new Array<Menu>()
private userMenuIds = new Array<string>()
private getMenuQuery = new GetAllMenu()
private platformTypes = PlatformTypes
private confirmButtonBusy = false
private menuProps = {
children: 'children',
label: 'displayName'
}
get confirmButtonTitle() {
if (this.confirmButtonBusy) {
return this.l('AbpUi.SavingWithThreeDot')
}
return this.l('AbpUi.Save')
}
@Watch('showDialog', { immediate: true })
private onShowDialogChanged() {
this.handleGetUserMenus()
}
private onPlatformTypeChanged() {
this.handleGetMenus()
this.handleGetUserMenus()
}
private handleGetMenus() {
MenuService
.getAll(this.getMenuQuery)
.then(res => {
this.menus = generateTree(res.items)
})
}
private handleGetUserMenus() {
if (this.showDialog && this.userId) {
MenuService
.getUserMenuList(this.userId, this.getMenuQuery.platformType || PlatformType.None)
.then(res => {
this.userMenuIds = res.items.map(item => item.id)
})
} else {
this.userMenuIds.length = 0
}
}
private onSave() {
const userMenuTree = this.$refs.userMenuTree as Tree
const userMenu = new UserMenu()
userMenu.userId = this.userId
userMenu.menuIds = userMenuTree.getCheckedKeys()
MenuService
.setUserMenu(userMenu)
.then(() => {
this.$message.success(this.l('successful'))
this.onFormClosed()
})
}
private onFormClosed() {
this.$nextTick(() => {
const tree = this.$refs.userMenuTree as Tree
tree.setCheckedKeys([])
})
this.$emit('closed')
}
}
</script>
<style lang="scss" scoped>
.confirm {
position: absolute;
margin-top: 10px;
right: 0px;
}
.cancel {
position: absolute;
margin-top: 10px;
right: 120px;
}
</style>
<template>
<el-dialog
v-el-draggable-dialog
width="800px"
:title="$t('AppPlatform.Menu:Manage')"
:visible="showDialog"
custom-class="modal-form"
:close-on-click-modal="false"
:close-on-press-escape="false"
:show-close="false"
@close="onFormClosed"
>
<el-form>
<el-card>
<el-form-item
label-width="120px"
:label="$t('AppPlatform.DisplayName:UIFramework')"
>
<el-select
v-model="getMenuQuery.framework"
style="width: 100%;"
class="filter-item"
clearable
:placeholder="$t('pleaseSelectBy', {name: $t('AppPlatform.DisplayName:UIFramework')})"
@change="onFrameworkChanged"
>
<el-option
v-for="framework in uiFrameworks"
:key="framework"
:label="framework"
:value="framework"
/>
</el-select>
</el-form-item>
<el-form-item
label-width="120px"
:label="$t('AppPlatform.DisplayName:Menus')"
>
<el-tree
ref="userMenuTree"
show-checkbox
:check-strictly="true"
node-key="id"
:data="menus"
:props="menuProps"
:default-checked-keys="userMenuIds"
/>
</el-form-item>
</el-card>
<el-form-item>
<el-button
class="cancel"
type="info"
style="width:100px"
@click="onFormClosed"
>
{{ $t('AbpUi.Cancel') }}
</el-button>
<el-button
class="confirm"
type="primary"
style="width:100px"
icon="el-icon-check"
:loading="confirmButtonBusy"
@click="onSave"
>
{{ confirmButtonTitle }}
</el-button>
</el-form-item>
</el-form>
</el-dialog>
</template>
<script lang="ts">
import { Component, Mixins, Prop, Watch } from 'vue-property-decorator'
import LocalizationMiXin from '@/mixins/LocalizationMiXin'
import DataService from '@/api/data-dictionary'
import MenuService, { Menu, GetAllMenu, UserMenu } from '@/api/menu'
import { generateTree } from '@/utils'
import { Tree } from 'element-ui'
@Component({
name: 'ManageUserMenuDialog'
})
export default class ManageUserMenuDialog extends Mixins(LocalizationMiXin) {
@Prop({ default: false })
private showDialog!: boolean
@Prop({ default: '' })
private userId!: string
private menus = new Array<Menu>()
private uiFrameworks: string[] = []
private userMenuIds = new Array<string>()
private getMenuQuery = new GetAllMenu()
private confirmButtonBusy = false
private menuProps = {
children: 'children',
label: 'displayName'
}
get confirmButtonTitle() {
if (this.confirmButtonBusy) {
return this.l('AbpUi.SavingWithThreeDot')
}
return this.l('AbpUi.Save')
}
@Watch('showDialog', { immediate: true })
private onShowDialogChanged() {
this.handleGetUserMenus()
}
monted() {
this.getUIFrameworks()
}
private onFrameworkChanged() {
this.handleGetMenus()
this.handleGetUserMenus()
}
private getUIFrameworks() {
DataService
.getByName('UI Framewark')
.then(res => {
this.uiFrameworks = res.items.map(item => item.name)
})
}
private handleGetMenus() {
MenuService
.getAll(this.getMenuQuery)
.then(res => {
this.menus = generateTree(res.items)
})
}
private handleGetUserMenus() {
if (this.showDialog && this.userId) {
MenuService
.getUserMenuList(this.userId, this.getMenuQuery.framework)
.then(res => {
this.userMenuIds = res.items.map(item => item.id)
})
} else {
this.userMenuIds.length = 0
}
}
private onSave() {
const userMenuTree = this.$refs.userMenuTree as Tree
const userMenu = new UserMenu()
userMenu.userId = this.userId
userMenu.menuIds = userMenuTree.getCheckedKeys()
MenuService
.setUserMenu(userMenu)
.then(() => {
this.$message.success(this.l('successful'))
this.onFormClosed()
})
}
private onFormClosed() {
this.$nextTick(() => {
const tree = this.$refs.userMenuTree as Tree
tree.setCheckedKeys([])
})
this.$emit('closed')
}
}
</script>
<style lang="scss" scoped>
.confirm {
position: absolute;
margin-top: 10px;
right: 0px;
}
.cancel {
position: absolute;
margin-top: 10px;
right: 120px;
}
</style>

746
vueJs/src/views/admin/users/index.vue

@ -1,373 +1,373 @@
<template>
<div class="app-container">
<div class="filter-container">
<label
class="radio-label"
style="padding-left:0;"
>{{ $t('users.queryFilter') }}</label>
<el-input
v-model="dataFilter.filter"
:placeholder="$t('users.filterString')"
style="width: 250px;margin-left: 10px;"
class="filter-item"
/>
<el-button
class="filter-item"
style="margin-left: 10px; text-alignt"
type="primary"
@click="refreshPagedData"
>
{{ $t('AbpIdentity.Search') }}
</el-button>
<el-button
class="filter-item"
type="primary"
:disabled="!checkPermission(['AbpIdentity.Users.Create'])"
@click="handleShowUserDialog('')"
>
{{ $t('AbpIdentity.NewUser') }}
</el-button>
</div>
<el-table
v-loading="dataLoading"
row-key="id"
:data="dataList"
border
fit
highlight-current-row
style="width: 100%;"
@sort-change="handleSortChange"
>
<el-table-column
:label="$t('AbpIdentity.DisplayName:UserName')"
prop="userName"
sortable
width="110px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.userName }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AbpIdentity.DisplayName:Surname')"
prop="surname"
width="110px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.surname }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AbpIdentity.DisplayName:Name')"
prop="name"
width="110px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.name }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AbpIdentity.DisplayName:Email')"
prop="email"
sortable
min-width="180"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.email }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AbpIdentity.DisplayName:PhoneNumber')"
prop="phoneNumber"
width="140px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.phoneNumber }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AbpIdentity.LockoutEnd')"
prop="lockoutEnd"
sortable
width="140px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.lockoutEnd | dateTimeFilter }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AbpIdentity.CreationTime')"
prop="creationTime"
sortable
width="140px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.creationTime | dateTimeFilter }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AbpIdentity.Actions')"
align="center"
width="250px"
min-width="250px"
>
<template slot-scope="{row}">
<el-button
:disabled="!checkPermission(['AbpIdentity.Users.Update'])"
size="mini"
type="primary"
icon="el-icon-edit"
@click="handleShowUserDialog(row.id)"
>
{{ $t('AbpIdentity.Edit') }}
</el-button>
<el-dropdown
class="options"
@command="handleCommand"
>
<el-button
v-permission="['AbpIdentity.Users']"
size="mini"
type="info"
>
{{ $t('AbpIdentity.Actions') }}<i class="el-icon-arrow-down el-icon--right" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
:command="{key: 'permission', row}"
:disabled="!checkPermission(['AbpIdentity.Users.ManagePermissions'])"
>
{{ $t('AbpIdentity.Permissions') }}
</el-dropdown-item>
<el-dropdown-item
:command="{key: 'lock', row}"
:disabled="!checkPermission(['AbpIdentity.Users.Update'])"
>
{{ $t('AbpIdentity.Lock') }}
</el-dropdown-item>
<el-dropdown-item
:command="{key: 'claim', row}"
:disabled="!checkPermission(['AbpIdentity.Users.ManageClaims'])"
>
{{ $t('AbpIdentity.ManageClaim') }}
</el-dropdown-item>
<el-dropdown-item
:command="{key: 'menu', row}"
:disabled="!checkPermission(['Platform.Menu.ManageUsers'])"
>
{{ $t('AppPlatform.Menu:Manage') }}
</el-dropdown-item>
<el-dropdown-item
divided
:command="{key: 'delete', row}"
:disabled="!checkPermission(['AbpIdentity.Users.Delete'])"
>
{{ $t('AbpIdentity.Delete') }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<pagination
v-show="dataTotal>0"
:total="dataTotal"
:page.sync="currentPage"
:limit.sync="pageSize"
@pagination="refreshPagedData"
/>
<user-create-or-update-form
:show-dialog="showUserDialog"
:edit-user-id="editUserId"
@closed="onUserDialogClosed"
/>
<user-claim-create-or-update-form
:show-dialog="showClaimDialog"
:user-id="editUserId"
@closed="onClaimDialogClosed"
/>
<manage-user-menu-dialog
:show-dialog="showManageUserMenuDialog"
:user-id="editUserId"
@closed="showManageUserMenuDialog=false"
/>
<permission-form
provider-name="U"
:provider-key="editUserId"
:readonly="!allowedEditPermission"
:show-dialog="showPermissionDialog"
@closed="onPermissionDialogClosed"
/>
</div>
</template>
<script lang="ts">
import { UserModule } from '@/store/modules/user'
import DataListMiXin from '@/mixins/DataListMiXin'
import EventBusMiXin from '@/mixins/EventBusMiXin'
import Component, { mixins } from 'vue-class-component'
import UserApiService, { User, UsersGetPagedDto } from '@/api/users'
import Pagination from '@/components/Pagination/index.vue'
import PermissionForm from '@/components/PermissionForm/index.vue'
import ManageUserMenuDialog from './components/ManageUserMenuDialog.vue'
import UserCreateOrUpdateForm from './components/UserCreateOrUpdateForm.vue'
import UserClaimCreateOrUpdateForm from './components/UserClaimCreateOrUpdateForm.vue'
import { dateFormat, abpPagerFormat } from '@/utils'
import { checkPermission } from '@/utils/permission'
@Component({
name: 'UserList',
components: {
Pagination,
PermissionForm,
ManageUserMenuDialog,
UserCreateOrUpdateForm,
UserClaimCreateOrUpdateForm
},
filters: {
dateTimeFilter(datetime: string) {
const date = new Date(datetime)
return dateFormat(date, 'YYYY-mm-dd HH:MM')
}
},
methods: {
checkPermission
}
})
export default class extends mixins(DataListMiXin, EventBusMiXin) {
private editUserId = ''
public dataFilter = new UsersGetPagedDto()
private showUserDialog = false
private showClaimDialog = false
private showPermissionDialog = false
private showManageUserMenuDialog = false
get allowedEditPermission() {
return this.editUserId !== UserModule.id && checkPermission(['AbpIdentity.Users.ManagePermissions'])
}
mounted() {
this.refreshPagedData()
this.subscribe('userChanged', () => this.refreshPagedData())
}
destroyed() {
this.unSubscribe('userChanged')
}
protected processDataFilter() {
this.dataFilter.skipCount = abpPagerFormat(this.currentPage, this.pageSize)
}
/** 查询用户列表 */
protected getPagedList(filter: any) {
return UserApiService.getUsers(filter)
}
/**
* @param row 操作行数据,可以转换为 UserDataDto 对象
*/
private handleLockUser(row: any) {
console.log('handleLockUser' + row.id)
}
private handleUserProfileChanged() {
this.refreshPagedData()
}
private handleShowCliamDialog(row: User) {
this.editUserId = row.id
this.showClaimDialog = true
}
private onClaimDialogClosed() {
this.showClaimDialog = false
}
private handleShowPermissionDialog(id: string) {
this.editUserId = id
this.showPermissionDialog = true
}
private onPermissionDialogClosed() {
this.showPermissionDialog = false
}
private handleShowUserDialog(id: string) {
this.editUserId = id
this.showUserDialog = true
}
private onUserDialogClosed() {
this.showUserDialog = false
}
/** 响应更多操作命令 */
private handleCommand(command: any) {
switch (command.key) {
case 'claim' :
this.handleShowCliamDialog(command.row)
break
case 'menu' :
this.editUserId = command.row.id
this.showManageUserMenuDialog = true
break
case 'permission' :
this.handleShowPermissionDialog(command.row.id)
break
case 'lock' :
this.handleLockUser(command.row)
break
case 'delete' :
this.handleDeleteUser(command.row)
break
default: break
}
}
/** 响应删除用户事件 */
private handleDeleteUser(row: any) {
this.$confirm(this.l('AbpIdentity.UserDeletionConfirmationMessage', { 0: row.userName }),
this.l('AbpIdentity.AreYouSure'), {
callback: (action) => {
if (action === 'confirm') {
UserApiService.deleteUser(row.id).then(() => {
this.$message.success(this.l('global.successful'))
this.refreshPagedData()
})
}
}
})
}
}
</script>
<style lang="scss">
.profile {
.el-dialog__header {
background-color: dodgerblue;
}
}
.options {
vertical-align: top;
margin-left: 20px;
}
.el-icon-arrow-down {
font-size: 12px;
}
</style>
<template>
<div class="app-container">
<div class="filter-container">
<label
class="radio-label"
style="padding-left:0;"
>{{ $t('users.queryFilter') }}</label>
<el-input
v-model="dataFilter.filter"
:placeholder="$t('users.filterString')"
style="width: 250px;margin-left: 10px;"
class="filter-item"
/>
<el-button
class="filter-item"
style="margin-left: 10px;"
type="primary"
@click="refreshPagedData"
>
{{ $t('AbpIdentity.Search') }}
</el-button>
<el-button
class="filter-item"
type="primary"
:disabled="!checkPermission(['AbpIdentity.Users.Create'])"
@click="handleShowUserDialog('')"
>
{{ $t('AbpIdentity.NewUser') }}
</el-button>
</div>
<el-table
v-loading="dataLoading"
row-key="id"
:data="dataList"
border
fit
highlight-current-row
style="width: 100%;"
@sort-change="handleSortChange"
>
<el-table-column
:label="$t('AbpIdentity.DisplayName:UserName')"
prop="userName"
sortable
width="110px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.userName }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AbpIdentity.DisplayName:Surname')"
prop="surname"
width="110px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.surname }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AbpIdentity.DisplayName:Name')"
prop="name"
width="110px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.name }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AbpIdentity.DisplayName:Email')"
prop="email"
sortable
min-width="180"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.email }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AbpIdentity.DisplayName:PhoneNumber')"
prop="phoneNumber"
width="140px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.phoneNumber }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AbpIdentity.LockoutEnd')"
prop="lockoutEnd"
sortable
width="140px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.lockoutEnd | dateTimeFilter }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AbpIdentity.CreationTime')"
prop="creationTime"
sortable
width="140px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.creationTime | dateTimeFilter }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AbpIdentity.Actions')"
align="center"
width="250px"
min-width="250px"
>
<template slot-scope="{row}">
<el-button
:disabled="!checkPermission(['AbpIdentity.Users.Update'])"
size="mini"
type="primary"
icon="el-icon-edit"
@click="handleShowUserDialog(row.id)"
>
{{ $t('AbpIdentity.Edit') }}
</el-button>
<el-dropdown
class="options"
@command="handleCommand"
>
<el-button
v-permission="['AbpIdentity.Users']"
size="mini"
type="info"
>
{{ $t('AbpIdentity.Actions') }}<i class="el-icon-arrow-down el-icon--right" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
:command="{key: 'permission', row}"
:disabled="!checkPermission(['AbpIdentity.Users.ManagePermissions'])"
>
{{ $t('AbpIdentity.Permissions') }}
</el-dropdown-item>
<el-dropdown-item
:command="{key: 'lock', row}"
:disabled="!checkPermission(['AbpIdentity.Users.Update'])"
>
{{ $t('AbpIdentity.Lock') }}
</el-dropdown-item>
<el-dropdown-item
:command="{key: 'claim', row}"
:disabled="!checkPermission(['AbpIdentity.Users.ManageClaims'])"
>
{{ $t('AbpIdentity.ManageClaim') }}
</el-dropdown-item>
<el-dropdown-item
:command="{key: 'menu', row}"
:disabled="!checkPermission(['Platform.Menu.ManageUsers'])"
>
{{ $t('AppPlatform.Menu:Manage') }}
</el-dropdown-item>
<el-dropdown-item
divided
:command="{key: 'delete', row}"
:disabled="!checkPermission(['AbpIdentity.Users.Delete'])"
>
{{ $t('AbpIdentity.Delete') }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<pagination
v-show="dataTotal>0"
:total="dataTotal"
:page.sync="currentPage"
:limit.sync="pageSize"
@pagination="refreshPagedData"
/>
<user-create-or-update-form
:show-dialog="showUserDialog"
:edit-user-id="editUserId"
@closed="onUserDialogClosed"
/>
<user-claim-create-or-update-form
:show-dialog="showClaimDialog"
:user-id="editUserId"
@closed="onClaimDialogClosed"
/>
<manage-user-menu-dialog
:show-dialog="showManageUserMenuDialog"
:user-id="editUserId"
@closed="showManageUserMenuDialog=false"
/>
<permission-form
provider-name="U"
:provider-key="editUserId"
:readonly="!allowedEditPermission"
:show-dialog="showPermissionDialog"
@closed="onPermissionDialogClosed"
/>
</div>
</template>
<script lang="ts">
import { UserModule } from '@/store/modules/user'
import DataListMiXin from '@/mixins/DataListMiXin'
import EventBusMiXin from '@/mixins/EventBusMiXin'
import Component, { mixins } from 'vue-class-component'
import UserApiService, { User, UsersGetPagedDto } from '@/api/users'
import Pagination from '@/components/Pagination/index.vue'
import PermissionForm from '@/components/PermissionForm/index.vue'
import ManageUserMenuDialog from './components/ManageUserMenuDialog.vue'
import UserCreateOrUpdateForm from './components/UserCreateOrUpdateForm.vue'
import UserClaimCreateOrUpdateForm from './components/UserClaimCreateOrUpdateForm.vue'
import { dateFormat, abpPagerFormat } from '@/utils'
import { checkPermission } from '@/utils/permission'
@Component({
name: 'UserList',
components: {
Pagination,
PermissionForm,
ManageUserMenuDialog,
UserCreateOrUpdateForm,
UserClaimCreateOrUpdateForm
},
filters: {
dateTimeFilter(datetime: string) {
const date = new Date(datetime)
return dateFormat(date, 'YYYY-mm-dd HH:MM')
}
},
methods: {
checkPermission
}
})
export default class extends mixins(DataListMiXin, EventBusMiXin) {
private editUserId = ''
public dataFilter = new UsersGetPagedDto()
private showUserDialog = false
private showClaimDialog = false
private showPermissionDialog = false
private showManageUserMenuDialog = false
get allowedEditPermission() {
return this.editUserId !== UserModule.id && checkPermission(['AbpIdentity.Users.ManagePermissions'])
}
mounted() {
this.refreshPagedData()
this.subscribe('userChanged', () => this.refreshPagedData())
}
destroyed() {
this.unSubscribe('userChanged')
}
protected processDataFilter() {
this.dataFilter.skipCount = abpPagerFormat(this.currentPage, this.pageSize)
}
/** 查询用户列表 */
protected getPagedList(filter: any) {
return UserApiService.getUsers(filter)
}
/**
* @param row 操作行数据,可以转换为 UserDataDto 对象
*/
private handleLockUser(row: any) {
console.log('handleLockUser' + row.id)
}
private handleUserProfileChanged() {
this.refreshPagedData()
}
private handleShowCliamDialog(row: User) {
this.editUserId = row.id
this.showClaimDialog = true
}
private onClaimDialogClosed() {
this.showClaimDialog = false
}
private handleShowPermissionDialog(id: string) {
this.editUserId = id
this.showPermissionDialog = true
}
private onPermissionDialogClosed() {
this.showPermissionDialog = false
}
private handleShowUserDialog(id: string) {
this.editUserId = id
this.showUserDialog = true
}
private onUserDialogClosed() {
this.showUserDialog = false
}
/** 响应更多操作命令 */
private handleCommand(command: any) {
switch (command.key) {
case 'claim' :
this.handleShowCliamDialog(command.row)
break
case 'menu' :
this.editUserId = command.row.id
this.showManageUserMenuDialog = true
break
case 'permission' :
this.handleShowPermissionDialog(command.row.id)
break
case 'lock' :
this.handleLockUser(command.row)
break
case 'delete' :
this.handleDeleteUser(command.row)
break
default: break
}
}
/** 响应删除用户事件 */
private handleDeleteUser(row: any) {
this.$confirm(this.l('AbpIdentity.UserDeletionConfirmationMessage', { 0: row.userName }),
this.l('AbpIdentity.AreYouSure'), {
callback: (action) => {
if (action === 'confirm') {
UserApiService.deleteUser(row.id).then(() => {
this.$message.success(this.l('global.successful'))
this.refreshPagedData()
})
}
}
})
}
}
</script>
<style lang="scss">
.profile {
.el-dialog__header {
background-color: dodgerblue;
}
}
.options {
vertical-align: top;
margin-left: 20px;
}
.el-icon-arrow-down {
font-size: 12px;
}
</style>

555
vueJs/src/views/container/layouts/components/CreateOrUpdateLayoutDialog.vue

@ -1,276 +1,279 @@
<template>
<el-dialog
v-el-draggable-dialog
width="800px"
:visible="showDialog"
:title="title"
custom-class="modal-form"
:show-close="false"
:close-on-click-modal="false"
:close-on-press-escape="false"
@close="onFormClosed(false)"
>
<el-form
ref="formLayout"
:model="layout"
label-width="120px"
>
<el-form-item
:label="$t('AppPlatform.DisplayName:PlatformType')"
:rules="{
required: true,
message: $t('pleaseInputBy', {key: $t('AppPlatform.DisplayName:PlatformType')}),
trigger: 'blur'
}"
>
<el-select
v-model="layout.platformType"
style="width: 100%;"
class="filter-item"
clearable
:placeholder="$t('pleaseSelectBy', {name: $t('AppPlatform.DisplayName:PlatformType')})"
>
<el-option
v-for="platformType in platformTypes"
:key="platformType.key"
:label="platformType.key"
:value="platformType.value"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="!isEdit"
:label="$t('AppPlatform.DisplayName:DataDictionary')"
:rules="{
required: true
}"
>
<el-select
v-model="dataId"
style="width: 100%;"
class="filter-item"
clearable
:placeholder="$t('pleaseSelectBy', {name: $t('AppPlatform.DisplayName:DataDictionary')})"
>
<el-option
v-for="data in datas"
:key="data.name"
:label="data.displayName"
:value="data.id"
/>
</el-select>
</el-form-item>
<el-form-item
prop="name"
:label="$t(('AppPlatform.DisplayName:Name'))"
:rules="{
required: true,
message: $t('pleaseInputBy', {key: $t('AppPlatform.DisplayName:Name')}),
trigger: 'blur'
}"
>
<el-input
v-model="layout.name"
/>
</el-form-item>
<el-form-item
prop="displayName"
:label="$t(('AppPlatform.DisplayName:DisplayName'))"
:rules="{
required: true,
message: $t('pleaseInputBy', {key: $t('AppPlatform.DisplayName:DisplayName')}),
trigger: 'blur'
}"
>
<el-input
v-model="layout.displayName"
/>
</el-form-item>
<el-form-item
prop="path"
:label="$t(('AppPlatform.DisplayName:Path'))"
:rules="{
required: true,
message: $t('pleaseInputBy', {key: $t('AppPlatform.DisplayName:Path')}),
trigger: 'blur'
}"
>
<el-input
v-model="layout.path"
/>
</el-form-item>
<el-form-item
prop="redirect"
:label="$t(('AppPlatform.DisplayName:Redirect'))"
>
<el-input
v-model="layout.redirect"
/>
</el-form-item>
<el-form-item
prop="description"
:label="$t(('AppPlatform.DisplayName:Description'))"
>
<el-input
v-model="layout.description"
type="textarea"
/>
</el-form-item>
<el-form-item>
<el-button
class="cancel"
type="info"
@click="onFormClosed(false)"
>
{{ $t('AbpUi.Cancel') }}
</el-button>
<el-button
class="confirm"
type="primary"
icon="el-icon-check"
@click="onSave"
>
{{ $t('AbpUi.Save') }}
</el-button>
</el-form-item>
</el-form>
</el-dialog>
</template>
<script lang="ts">
import { Component, Mixins, Prop, Watch } from 'vue-property-decorator'
import LocalizationMiXin from '@/mixins/LocalizationMiXin'
import { Form } from 'element-ui'
import DataService, { Data } from '@/api/data-dictionary'
import LayoutService, {
Layout,
LayoutCreateOrUpdate,
LayoutCreate,
LayoutUpdate,
PlatformTypes
} from '@/api/layout'
@Component({
name: 'CreateOrUpdateLayoutDialog'
})
export default class CreateOrUpdateLayoutDialog extends Mixins(LocalizationMiXin) {
@Prop({ default: false })
private showDialog!: boolean
@Prop({ default: null })
private layoutId!: string
private layout = new Layout()
private datas = new Array<Data>()
private platformTypes = PlatformTypes
private dataId = ''
get isEdit() {
if (this.layoutId) {
return true
}
return false
}
get title() {
if (this.isEdit) {
return this.l('AppPlatform.Layout:EditByName', { 0: this.layout.displayName })
}
return this.l('AppPlatform.Layout:AddNew')
}
@Watch('showDialog')
private onShowDialogChanged() {
this.handleGetLayout()
}
mounted() {
this.handleGetDataDictionarys()
}
private handleGetDataDictionarys() {
DataService
.getAll()
.then(res => {
this.datas = res.items
})
}
private handleGetLayout() {
if (this.showDialog && this.layoutId) {
LayoutService
.get(this.layoutId)
.then(res => {
this.layout = res
})
} else {
this.layout = new Layout()
}
}
private onSave() {
const formLayout = this.$refs.formLayout as Form
formLayout
.validate(valid => {
if (valid) {
if (this.isEdit) {
const update = new LayoutUpdate()
this.updateMenuByInput(update)
LayoutService
.update(this.layoutId, update)
.then(res => {
this.layout = res
this.$message.success(this.l('successful'))
this.onFormClosed(true)
})
} else {
if (!this.dataId) {
this.$message.warning(this.l('pleaseSelectBy', { key: this.l('AppPlatform.DisplayName:DataDictionary') }))
return
}
const create = new LayoutCreate()
this.updateMenuByInput(create)
create.dataId = this.dataId
LayoutService
.create(create)
.then(res => {
this.layout = res
this.$message.success(this.l('successful'))
this.onFormClosed(true)
})
}
}
})
}
private onFormClosed(changed: boolean) {
const formLayout = this.$refs.formLayout as Form
formLayout.resetFields()
this.$emit('closed', changed)
}
private updateMenuByInput(update: LayoutCreateOrUpdate) {
update.name = this.layout.name
update.path = this.layout.path
update.displayName = this.layout.displayName
update.description = this.layout.description
update.redirect = this.layout.redirect
update.platformType = this.layout.platformType
}
}
</script>
<style scoped>
.confirm {
position: absolute;
right: 10px;
width:100px;
}
.cancel {
position: absolute;
right: 120px;
width:100px;
}
</style>
<template>
<el-dialog
v-el-draggable-dialog
width="800px"
:visible="showDialog"
:title="title"
custom-class="modal-form"
:show-close="false"
:close-on-click-modal="false"
:close-on-press-escape="false"
@close="onFormClosed(false)"
>
<el-form
ref="formLayout"
:model="layout"
label-width="120px"
>
<el-form-item
v-if="!isEdit"
prop="framework"
:label="$t('AppPlatform.DisplayName:UIFramework')"
:rules="{
required: true,
message: $t('pleaseInputBy', {key: $t('AppPlatform.DisplayName:UIFramework')}),
trigger: 'blur'
}"
>
<el-select
v-model="layout.framework"
style="width: 100%;"
class="filter-item"
clearable
:placeholder="$t('pleaseSelectBy', {name: $t('AppPlatform.DisplayName:UIFramework')})"
>
<el-option
v-for="framework in uiFrameworks"
:key="framework"
:label="framework"
:value="framework"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="!isEdit"
:label="$t('AppPlatform.DisplayName:DataDictionary')"
:rules="{
required: true
}"
>
<el-select
v-model="dataId"
style="width: 100%;"
class="filter-item"
clearable
:placeholder="$t('pleaseSelectBy', {name: $t('AppPlatform.DisplayName:DataDictionary')})"
>
<el-option
v-for="data in datas"
:key="data.name"
:label="data.displayName"
:value="data.id"
/>
</el-select>
</el-form-item>
<el-form-item
prop="name"
:label="$t(('AppPlatform.DisplayName:Name'))"
:rules="{
required: true,
message: $t('pleaseInputBy', {key: $t('AppPlatform.DisplayName:Name')}),
trigger: 'blur'
}"
>
<el-input
v-model="layout.name"
/>
</el-form-item>
<el-form-item
prop="displayName"
:label="$t(('AppPlatform.DisplayName:DisplayName'))"
:rules="{
required: true,
message: $t('pleaseInputBy', {key: $t('AppPlatform.DisplayName:DisplayName')}),
trigger: 'blur'
}"
>
<el-input
v-model="layout.displayName"
/>
</el-form-item>
<el-form-item
prop="path"
:label="$t(('AppPlatform.DisplayName:Path'))"
:rules="{
required: true,
message: $t('pleaseInputBy', {key: $t('AppPlatform.DisplayName:Path')}),
trigger: 'blur'
}"
>
<el-input
v-model="layout.path"
/>
</el-form-item>
<el-form-item
prop="redirect"
:label="$t(('AppPlatform.DisplayName:Redirect'))"
>
<el-input
v-model="layout.redirect"
/>
</el-form-item>
<el-form-item
prop="description"
:label="$t(('AppPlatform.DisplayName:Description'))"
>
<el-input
v-model="layout.description"
type="textarea"
/>
</el-form-item>
<el-form-item>
<el-button
class="cancel"
type="info"
@click="onFormClosed(false)"
>
{{ $t('AbpUi.Cancel') }}
</el-button>
<el-button
class="confirm"
type="primary"
icon="el-icon-check"
@click="onSave"
>
{{ $t('AbpUi.Save') }}
</el-button>
</el-form-item>
</el-form>
</el-dialog>
</template>
<script lang="ts">
import { Component, Mixins, Prop, Watch } from 'vue-property-decorator'
import LocalizationMiXin from '@/mixins/LocalizationMiXin'
import { Form } from 'element-ui'
import DataService, { Data } from '@/api/data-dictionary'
import LayoutService, {
Layout,
LayoutCreateOrUpdate,
LayoutCreate,
LayoutUpdate
} from '@/api/layout'
@Component({
name: 'CreateOrUpdateLayoutDialog'
})
export default class CreateOrUpdateLayoutDialog extends Mixins(LocalizationMiXin) {
@Prop({ default: false })
private showDialog!: boolean
@Prop({ default: null })
private layoutId!: string
@Prop({ default: [] })
private uiFrameworks!: string[]
private layout = new Layout()
private datas = new Array<Data>()
private dataId = ''
get isEdit() {
if (this.layoutId) {
return true
}
return false
}
get title() {
if (this.isEdit) {
return this.l('AppPlatform.Layout:EditByName', { 0: this.layout.displayName })
}
return this.l('AppPlatform.Layout:AddNew')
}
@Watch('showDialog')
private onShowDialogChanged() {
this.handleGetLayout()
}
mounted() {
this.handleGetDataDictionarys()
}
private handleGetDataDictionarys() {
DataService
.getAll()
.then(res => {
this.datas = res.items
})
}
private handleGetLayout() {
if (this.showDialog && this.layoutId) {
LayoutService
.get(this.layoutId)
.then(res => {
this.layout = res
})
} else {
this.layout = new Layout()
}
}
private onSave() {
const formLayout = this.$refs.formLayout as Form
formLayout
.validate(valid => {
if (valid) {
if (this.isEdit) {
const update = new LayoutUpdate()
this.updateMenuByInput(update)
LayoutService
.update(this.layoutId, update)
.then(res => {
this.layout = res
this.$message.success(this.l('successful'))
this.onFormClosed(true)
})
} else {
if (!this.dataId) {
this.$message.warning(this.l('pleaseSelectBy', { key: this.l('AppPlatform.DisplayName:DataDictionary') }))
return
}
const create = new LayoutCreate()
this.updateMenuByInput(create)
create.dataId = this.dataId
create.framework = this.layout.framework
LayoutService
.create(create)
.then(res => {
this.layout = res
this.$message.success(this.l('successful'))
this.onFormClosed(true)
})
}
}
})
}
private onFormClosed(changed: boolean) {
const formLayout = this.$refs.formLayout as Form
formLayout.resetFields()
this.$emit('closed', changed)
}
private updateMenuByInput(update: LayoutCreateOrUpdate) {
update.name = this.layout.name
update.path = this.layout.path
update.displayName = this.layout.displayName
update.description = this.layout.description
update.redirect = this.layout.redirect
}
}
</script>
<style scoped>
.confirm {
position: absolute;
right: 10px;
width:100px;
}
.cancel {
position: absolute;
right: 120px;
width:100px;
}
</style>

486
vueJs/src/views/container/layouts/index.vue

@ -1,237 +1,249 @@
<template>
<div class="app-container">
<div class="filter-container">
<el-form inline>
<el-form-item
label-width="100px"
:label="$t('AppPlatform.DisplayName:Filter')"
>
<el-input
v-model="dataFilter.filter"
/>
</el-form-item>
<el-form-item
label-width="100px"
:label="$t('AppPlatform.DisplayName:PlatformType')"
>
<el-select
v-model="dataFilter.platformType"
class="filter-item"
clearable
:placeholder="$t('pleaseSelectBy', {name: $t('AppPlatform.DisplayName:PlatformType')})"
>
<el-option
v-for="item in platformTypes"
:key="item.key"
:label="item.key"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-button
class="filter-item"
style="width: 150px; margin-left: 10px;"
type="primary"
@click="refreshPagedData"
>
<i class="el-icon-search" />
{{ $t('AppPlatform.DisplayName:SecrchLayout') }}
</el-button>
<el-button
class="filter-item"
style="width: 150px; margin-left: 10px;"
type="success"
@click="handleAddLayout"
>
<i class="ivu-icon ivu-icon-md-add" />
{{ $t('AppPlatform.Layout:AddNew') }}
</el-button>
</el-form>
</div>
<el-table
v-loading="dataLoading"
row-key="id"
:data="dataList"
border
fit
highlight-current-row
style="width: 100%;"
@sort-change="handleSortChange"
>
<el-table-column
:label="$t('AppPlatform.DisplayName:Name')"
prop="Name"
sortable
width="200px"
>
<template slot-scope="{row}">
<span>{{ row.name }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AppPlatform.DisplayName:Path')"
prop="path"
sortable
width="250px"
>
<template slot-scope="{row}">
<el-tag>
{{ row.path }}
</el-tag>
</template>
</el-table-column>
<el-table-column
:label="$t('AppPlatform.DisplayName:DisplayName')"
prop="displayName"
sortable
width="250px"
>
<template slot-scope="{row}">
<span>{{ row.displayName }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AppPlatform.DisplayName:Description')"
prop="description"
sortable
width="250px"
>
<template slot-scope="{row}">
<span>{{ row.description }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AppPlatform.DisplayName:Redirect')"
prop="redirect"
sortable
width="250px"
>
<template slot-scope="{row}">
<span>{{ row.redirect }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('operaActions')"
align="center"
min-width="200px"
>
<template slot-scope="{row}">
<el-button
:disabled="!checkPermission(['Platform.Layout.Update'])"
size="mini"
type="primary"
icon="el-icon-edit"
@click="handleEditLayout(row.id)"
/>
<el-button
:disabled="!checkPermission(['Platform.Layout.Delete'])"
size="mini"
type="danger"
icon="el-icon-delete"
@click="handleRemoveLayout(row)"
/>
</template>
</el-table-column>
</el-table>
<pagination
v-show="dataTotal>0"
:total="dataTotal"
:page.sync="currentPage"
:limit.sync="pageSize"
@pagination="refreshPagedData"
@sort-change="handleSortChange"
/>
<create-or-update-layout-dialog
:show-dialog="showEditDialog"
:layout-id="editLayoutId"
@closed="onLayoutEditDialogClosed"
/>
</div>
</template>
<script lang="ts">
import { dateFormat, abpPagerFormat } from '@/utils'
import { checkPermission } from '@/utils/permission'
import LayoutService, { Layout, GetLayoutByPaged, PlatformTypes } from '@/api/layout'
import DataListMiXin from '@/mixins/DataListMiXin'
import { Component, Mixins } from 'vue-property-decorator'
import Pagination from '@/components/Pagination/index.vue'
import CreateOrUpdateLayoutDialog from './components/CreateOrUpdateLayoutDialog.vue'
@Component({
name: 'Layouts',
components: {
Pagination,
CreateOrUpdateLayoutDialog
},
filters: {
dateTimeFormatFilter(dateTime: Date) {
return dateFormat(new Date(dateTime), 'YYYY-mm-dd HH:MM:SS:NS')
}
},
methods: {
checkPermission
}
})
export default class extends Mixins(DataListMiXin) {
public dataFilter = new GetLayoutByPaged()
private showEditDialog = false
private editLayoutId = ''
private platformTypes = PlatformTypes
mounted() {
this.refreshPagedData()
}
protected processDataFilter() {
this.dataFilter.skipCount = abpPagerFormat(this.currentPage, this.pageSize)
}
protected getPagedList(filter: any) {
return LayoutService.getList(filter)
}
private handleRemoveLayout(layout: Layout) {
this.$confirm(this.l('questingDeleteByMessage', { message: layout.displayName }),
this.l('AppPlatform.Layout:Delete'), {
callback: (action) => {
if (action === 'confirm') {
LayoutService
.delete(layout.id)
.then(() => {
this.$message.success(this.l('successful'))
this.refreshPagedData()
})
}
}
})
}
private handleAddLayout() {
this.editLayoutId = ''
this.showEditDialog = true
}
private handleEditLayout(id: string) {
this.editLayoutId = id
this.showEditDialog = true
}
private onLayoutEditDialogClosed(changed: boolean) {
this.showEditDialog = false
if (changed) {
this.refreshPagedData()
}
}
}
</script>
<style lang="scss" scoped>
.data-filter-collapse-title {
font-size: 15px;
}
</style>
<template>
<div class="app-container">
<div class="filter-container">
<el-form inline>
<el-form-item
label-width="100px"
:label="$t('AppPlatform.DisplayName:Filter')"
>
<el-input
v-model="dataFilter.filter"
/>
</el-form-item>
<el-form-item
label-width="100px"
:label="$t('AppPlatform.DisplayName:UIFramework')"
>
<el-select
v-model="dataFilter.framework"
class="filter-item"
clearable
:placeholder="$t('pleaseSelectBy', {name: $t('AppPlatform.DisplayName:UIFramework')})"
>
<el-option
v-for="framework in uiFrameworks"
:key="framework"
:label="framework"
:value="framework"
/>
</el-select>
</el-form-item>
<el-button
class="filter-item"
style="width: 150px; margin-left: 10px;"
type="primary"
@click="refreshPagedData"
>
<i class="el-icon-search" />
{{ $t('AppPlatform.DisplayName:SecrchLayout') }}
</el-button>
<el-button
class="filter-item"
style="width: 150px; margin-left: 10px;"
type="success"
@click="handleAddLayout"
>
<i class="ivu-icon ivu-icon-md-add" />
{{ $t('AppPlatform.Layout:AddNew') }}
</el-button>
</el-form>
</div>
<el-table
v-loading="dataLoading"
row-key="id"
:data="dataList"
border
fit
highlight-current-row
style="width: 100%;"
@sort-change="handleSortChange"
>
<el-table-column
:label="$t('AppPlatform.DisplayName:Name')"
prop="Name"
sortable
width="200px"
>
<template slot-scope="{row}">
<span>{{ row.name }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AppPlatform.DisplayName:Path')"
prop="path"
sortable
width="250px"
>
<template slot-scope="{row}">
<el-tag>
{{ row.path }}
</el-tag>
</template>
</el-table-column>
<el-table-column
:label="$t('AppPlatform.DisplayName:DisplayName')"
prop="displayName"
sortable
width="250px"
>
<template slot-scope="{row}">
<span>{{ row.displayName }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AppPlatform.DisplayName:Description')"
prop="description"
sortable
width="250px"
>
<template slot-scope="{row}">
<span>{{ row.description }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AppPlatform.DisplayName:Redirect')"
prop="redirect"
sortable
width="250px"
>
<template slot-scope="{row}">
<span>{{ row.redirect }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('operaActions')"
align="center"
min-width="200px"
>
<template slot-scope="{row}">
<el-button
:disabled="!checkPermission(['Platform.Layout.Update'])"
size="mini"
type="primary"
icon="el-icon-edit"
@click="handleEditLayout(row.id)"
/>
<el-button
:disabled="!checkPermission(['Platform.Layout.Delete'])"
size="mini"
type="danger"
icon="el-icon-delete"
@click="handleRemoveLayout(row)"
/>
</template>
</el-table-column>
</el-table>
<pagination
v-show="dataTotal>0"
:total="dataTotal"
:page.sync="currentPage"
:limit.sync="pageSize"
@pagination="refreshPagedData"
@sort-change="handleSortChange"
/>
<create-or-update-layout-dialog
:show-dialog="showEditDialog"
:layout-id="editLayoutId"
:ui-frameworks="uiFrameworks"
@closed="onLayoutEditDialogClosed"
/>
</div>
</template>
<script lang="ts">
import { dateFormat, abpPagerFormat } from '@/utils'
import { checkPermission } from '@/utils/permission'
import LayoutService, { Layout, GetLayoutByPaged } from '@/api/layout'
import DataListMiXin from '@/mixins/DataListMiXin'
import { Component, Mixins } from 'vue-property-decorator'
import Pagination from '@/components/Pagination/index.vue'
import CreateOrUpdateLayoutDialog from './components/CreateOrUpdateLayoutDialog.vue'
import DataService from '@/api/data-dictionary'
@Component({
name: 'Layouts',
components: {
Pagination,
CreateOrUpdateLayoutDialog
},
filters: {
dateTimeFormatFilter(dateTime: Date) {
return dateFormat(new Date(dateTime), 'YYYY-mm-dd HH:MM:SS:NS')
}
},
methods: {
checkPermission
}
})
export default class extends Mixins(DataListMiXin) {
public dataFilter = new GetLayoutByPaged()
private showEditDialog = false
private editLayoutId = ''
private uiFrameworks: string[] = []
mounted() {
this.refreshPagedData()
this.getUIFrameworks()
}
protected processDataFilter() {
this.dataFilter.skipCount = abpPagerFormat(this.currentPage, this.pageSize)
}
protected getPagedList(filter: any) {
return LayoutService.getList(filter)
}
private getUIFrameworks() {
DataService
.getByName('UI Framewark')
.then(res => {
this.uiFrameworks = res.items.map(item => item.name)
})
}
private handleRemoveLayout(layout: Layout) {
this.$confirm(this.l('questingDeleteByMessage', { message: layout.displayName }),
this.l('AppPlatform.Layout:Delete'), {
callback: (action) => {
if (action === 'confirm') {
LayoutService
.delete(layout.id)
.then(() => {
this.$message.success(this.l('successful'))
this.refreshPagedData()
})
}
}
})
}
private handleAddLayout() {
this.editLayoutId = ''
this.showEditDialog = true
}
private handleEditLayout(id: string) {
this.editLayoutId = id
this.showEditDialog = true
}
private onLayoutEditDialogClosed(changed: boolean) {
this.showEditDialog = false
if (changed) {
this.refreshPagedData()
}
}
}
</script>
<style lang="scss" scoped>
.data-filter-collapse-title {
font-size: 15px;
}
</style>

583
vueJs/src/views/container/menus/index.vue

@ -1,286 +1,297 @@
<template>
<div class="app-container">
<div class="filter-container">
<el-form inline>
<el-form-item
label-width="100px"
:label="$t('AppPlatform.DisplayName:Filter')"
>
<el-input
v-model="dataQueryFilter.filter"
/>
</el-form-item>
<el-form-item
label-width="100px"
:label="$t('AppPlatform.DisplayName:PlatformType')"
>
<el-select
v-model="dataQueryFilter.platformType"
class="filter-item"
clearable
:placeholder="$t('pleaseSelectBy', {name: $t('AppPlatform.DisplayName:PlatformType')})"
>
<el-option
v-for="item in platformTypes"
:key="item.key"
:label="item.key"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item
label-width="100px"
:label="$t('AppPlatform.DisplayName:Layout')"
>
<el-select
v-model="dataQueryFilter.layoutId"
class="filter-item"
clearable
:placeholder="$t('pleaseSelectBy', {name: $t('AppPlatform.DisplayName:Layout')})"
>
<el-option
v-for="layout in layouts"
:key="layout.id"
:label="layout.displayName"
:value="layout.id"
/>
</el-select>
</el-form-item>
<el-button
class="filter-item"
style="width: 150px; margin-left: 10px;"
type="primary"
@click="resetList"
>
<i class="el-icon-search" />
{{ $t('AppPlatform.DisplayName:SecrchMenu') }}
</el-button>
<el-button
class="filter-item"
style="width: 150px; margin-left: 10px;"
type="success"
@click="handleAddMenu('')"
>
<i class="ivu-icon ivu-icon-md-add" />
{{ $t('AppPlatform.Menu:AddNew') }}
</el-button>
</el-form>
</div>
<el-table
v-loading="dataLoading"
row-key="id"
:data="dataList"
border
fit
highlight-current-row
style="width: 100%;"
@sort-change="handleSortChange"
>
<el-table-column
:label="$t('AppPlatform.DisplayName:Name')"
prop="Name"
sortable
width="200px"
>
<template slot-scope="{row}">
<span>{{ row.name }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AppPlatform.DisplayName:Path')"
prop="path"
sortable
width="250px"
>
<template slot-scope="{row}">
<el-tag>
{{ row.path }}
</el-tag>
</template>
</el-table-column>
<el-table-column
:label="$t('AppPlatform.DisplayName:Component')"
prop="component"
sortable
width="250px"
>
<template slot-scope="{row}">
<el-tag>
{{ row.component }}
</el-tag>
</template>
</el-table-column>
<el-table-column
:label="$t('AppPlatform.DisplayName:DisplayName')"
prop="displayName"
sortable
width="250px"
>
<template slot-scope="{row}">
<span>{{ row.displayName }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AppPlatform.DisplayName:Description')"
prop="description"
sortable
width="250px"
>
<template slot-scope="{row}">
<span>{{ row.description }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AppPlatform.DisplayName:Redirect')"
prop="redirect"
sortable
width="180px"
>
<template slot-scope="{row}">
<span>{{ row.redirect }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('operaActions')"
align="center"
min-width="200px"
fixed="right"
>
<template slot-scope="{row}">
<el-button
:disabled="!checkPermission(['Platform.Menu.Create'])"
size="mini"
type="success"
@click="handleAddMenu(row.id)"
>
<i class="ivu-icon ivu-icon-md-add" />
</el-button>
<el-button
:disabled="!checkPermission(['Platform.Menu.Update'])"
size="mini"
type="primary"
icon="el-icon-edit"
@click="handleEditMenu(row.id)"
/>
<el-button
:disabled="!checkPermission(['Platform.Menu.Delete'])"
size="mini"
type="danger"
icon="el-icon-delete"
@click="handleRemoveMenu(row)"
/>
</template>
</el-table-column>
</el-table>
<create-or-update-menu-dialog
:show-dialog="showEditDialog"
:menu-id="editMenuId"
:parent-id="parentMenuId"
@closed="onMenuEditDialogClosed"
/>
</div>
</template>
<script lang="ts">
import { dateFormat, generateTree } from '@/utils'
import { checkPermission } from '@/utils/permission'
import LayoutService, { PlatformTypes, Layout } from '@/api/layout'
import MenuService, { Menu, GetAllMenu } from '@/api/menu'
import DataListMiXin from '@/mixins/DataListMiXin'
import Component, { mixins } from 'vue-class-component'
import Pagination from '@/components/Pagination/index.vue'
import CreateOrUpdateMenuDialog from './components/CreateOrUpdateMenuDialog.vue'
@Component({
name: 'Menus',
components: {
Pagination,
CreateOrUpdateMenuDialog
},
filters: {
dateTimeFormatFilter(dateTime: Date) {
return dateFormat(new Date(dateTime), 'YYYY-mm-dd HH:MM:SS:NS')
}
},
methods: {
checkPermission
}
})
export default class extends mixins(DataListMiXin) {
public dataQueryFilter = new GetAllMenu()
private showEditDialog = false
private editMenuId = ''
private parentMenuId = ''
private layouts = new Array<Layout>()
private platformTypes = PlatformTypes
mounted() {
this.handleGetLayouts()
this.refreshData()
}
protected refreshData() {
this.dataLoading = true
MenuService
.getAll(this.dataQueryFilter)
.then(res => {
this.dataList = generateTree(res.items)
this.onDataLoadCompleted()
})
.finally(() => {
this.dataLoading = false
})
}
private handleGetLayouts() {
LayoutService
.getAllList()
.then(res => {
this.layouts = res.items
})
}
private handleRemoveMenu(menu: Menu) {
this.$confirm(this.l('questingDeleteByMessage', { message: menu.displayName }),
this.l('AppPlatform.Menu:Delete'), {
callback: (action) => {
if (action === 'confirm') {
MenuService
.delete(menu.id)
.then(() => {
this.$message.success(this.l('successful'))
this.refreshData()
})
}
}
})
}
private handleAddMenu(parentId: string) {
this.editMenuId = ''
this.parentMenuId = parentId
this.showEditDialog = true
}
private handleEditMenu(id: string) {
this.editMenuId = id
this.showEditDialog = true
}
private onMenuEditDialogClosed(changed: boolean) {
this.showEditDialog = false
if (changed) {
this.refreshData()
}
}
}
</script>
<style lang="scss" scoped>
.data-filter-collapse-title {
font-size: 15px;
}
</style>
<template>
<div class="app-container">
<div class="filter-container">
<el-form inline>
<el-form-item
label-width="100px"
:label="$t('AppPlatform.DisplayName:Filter')"
>
<el-input
v-model="dataQueryFilter.filter"
/>
</el-form-item>
<el-form-item
label-width="100px"
:label="$t('AppPlatform.DisplayName:UIFramework')"
>
<el-select
v-model="dataQueryFilter.framework"
class="filter-item"
clearable
:placeholder="$t('pleaseSelectBy', {name: $t('AppPlatform.DisplayName:UIFramework')})"
>
<el-option
v-for="framework in uiFrameworks"
:key="framework"
:label="framework"
:value="framework"
/>
</el-select>
</el-form-item>
<el-form-item
label-width="100px"
:label="$t('AppPlatform.DisplayName:Layout')"
>
<el-select
v-model="dataQueryFilter.layoutId"
class="filter-item"
clearable
:placeholder="$t('pleaseSelectBy', {name: $t('AppPlatform.DisplayName:Layout')})"
>
<el-option
v-for="layout in layouts"
:key="layout.id"
:label="layout.displayName"
:value="layout.id"
/>
</el-select>
</el-form-item>
<el-button
class="filter-item"
style="width: 150px; margin-left: 10px;"
type="primary"
@click="resetList"
>
<i class="el-icon-search" />
{{ $t('AppPlatform.DisplayName:SecrchMenu') }}
</el-button>
<el-button
class="filter-item"
style="width: 150px; margin-left: 10px;"
type="success"
@click="handleAddMenu('')"
>
<i class="ivu-icon ivu-icon-md-add" />
{{ $t('AppPlatform.Menu:AddNew') }}
</el-button>
</el-form>
</div>
<el-table
v-loading="dataLoading"
row-key="id"
:data="dataList"
border
fit
highlight-current-row
style="width: 100%;"
@sort-change="handleSortChange"
>
<el-table-column
:label="$t('AppPlatform.DisplayName:Name')"
prop="Name"
sortable
width="200px"
>
<template slot-scope="{row}">
<span>{{ row.name }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AppPlatform.DisplayName:Path')"
prop="path"
sortable
width="250px"
>
<template slot-scope="{row}">
<el-tag>
{{ row.path }}
</el-tag>
</template>
</el-table-column>
<el-table-column
:label="$t('AppPlatform.DisplayName:Component')"
prop="component"
sortable
width="250px"
>
<template slot-scope="{row}">
<el-tag>
{{ row.component }}
</el-tag>
</template>
</el-table-column>
<el-table-column
:label="$t('AppPlatform.DisplayName:DisplayName')"
prop="displayName"
sortable
width="250px"
>
<template slot-scope="{row}">
<span>{{ row.displayName }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AppPlatform.DisplayName:Description')"
prop="description"
sortable
width="250px"
>
<template slot-scope="{row}">
<span>{{ row.description }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AppPlatform.DisplayName:Redirect')"
prop="redirect"
sortable
width="180px"
>
<template slot-scope="{row}">
<span>{{ row.redirect }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('operaActions')"
align="center"
min-width="200px"
fixed="right"
>
<template slot-scope="{row}">
<el-button
:disabled="!checkPermission(['Platform.Menu.Create'])"
size="mini"
type="success"
@click="handleAddMenu(row.id)"
>
<i class="ivu-icon ivu-icon-md-add" />
</el-button>
<el-button
:disabled="!checkPermission(['Platform.Menu.Update'])"
size="mini"
type="primary"
icon="el-icon-edit"
@click="handleEditMenu(row.id)"
/>
<el-button
:disabled="!checkPermission(['Platform.Menu.Delete'])"
size="mini"
type="danger"
icon="el-icon-delete"
@click="handleRemoveMenu(row)"
/>
</template>
</el-table-column>
</el-table>
<create-or-update-menu-dialog
:show-dialog="showEditDialog"
:menu-id="editMenuId"
:parent-id="parentMenuId"
:ui-frameworks="uiFrameworks"
@closed="onMenuEditDialogClosed"
/>
</div>
</template>
<script lang="ts">
import { dateFormat, generateTree } from '@/utils'
import { checkPermission } from '@/utils/permission'
import LayoutService, { Layout } from '@/api/layout'
import MenuService, { Menu, GetAllMenu } from '@/api/menu'
import DataService from '@/api/data-dictionary'
import DataListMiXin from '@/mixins/DataListMiXin'
import Component, { mixins } from 'vue-class-component'
import Pagination from '@/components/Pagination/index.vue'
import CreateOrUpdateMenuDialog from './components/CreateOrUpdateMenuDialog.vue'
@Component({
name: 'Menus',
components: {
Pagination,
CreateOrUpdateMenuDialog
},
filters: {
dateTimeFormatFilter(dateTime: Date) {
return dateFormat(new Date(dateTime), 'YYYY-mm-dd HH:MM:SS:NS')
}
},
methods: {
checkPermission
}
})
export default class extends mixins(DataListMiXin) {
public dataQueryFilter = new GetAllMenu()
private showEditDialog = false
private editMenuId = ''
private parentMenuId = ''
private layouts = new Array<Layout>()
private uiFrameworks: string[] = []
mounted() {
this.getUIFrameworks()
this.handleGetLayouts()
this.refreshData()
}
protected refreshData() {
this.dataLoading = true
MenuService
.getAll(this.dataQueryFilter)
.then(res => {
this.dataList = generateTree(res.items)
this.onDataLoadCompleted()
})
.finally(() => {
this.dataLoading = false
})
}
private getUIFrameworks() {
DataService
.getByName('UI Framewark')
.then(res => {
this.uiFrameworks = res.items.map(item => item.name)
})
}
private handleGetLayouts() {
LayoutService
.getAllList()
.then(res => {
this.layouts = res.items
})
}
private handleRemoveMenu(menu: Menu) {
this.$confirm(this.l('questingDeleteByMessage', { message: menu.displayName }),
this.l('AppPlatform.Menu:Delete'), {
callback: (action) => {
if (action === 'confirm') {
MenuService
.delete(menu.id)
.then(() => {
this.$message.success(this.l('successful'))
this.refreshData()
})
}
}
})
}
private handleAddMenu(parentId: string) {
this.editMenuId = ''
this.parentMenuId = parentId
this.showEditDialog = true
}
private handleEditMenu(id: string) {
this.editMenuId = id
this.showEditDialog = true
}
private onMenuEditDialogClosed(changed: boolean) {
this.showEditDialog = false
if (changed) {
this.refreshData()
}
}
}
</script>
<style lang="scss" scoped>
.data-filter-collapse-title {
font-size: 15px;
}
</style>

240
vueJs/vue.config.js

@ -1,120 +1,120 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const path = require('path')
// If your port is set to 80,
// use administrator privileges to execute the command line.
// For example, on Mac: sudo npm run / sudo yarn
const devServerPort = 9527 // TODO: get this variable from setting.ts
const name = 'Vue Typescript Admin' // TODO: get this variable from setting.ts
module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? '/' : '/vue-typescript-admin-template/',
lintOnSave: process.env.NODE_ENV === 'development',
productionSourceMap: false,
devServer: {
port: devServerPort,
open: true,
overlay: {
warnings: false,
errors: true
},
progress: false,
proxy: {
// change xxx-api/login => /mock-api/v1/login
// detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_BASE_IDENTITY_SERVER]: {
// IdentityServer4 address
target: 'http://127.0.0.1:44385',
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_IDENTITY_SERVER]: ''
}
},
[process.env.VUE_APP_SIGNALR_SERVER]: {
// api gateway address websocket protocol
target: 'ws://127.0.0.1:30000',
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_SIGNALR_SERVER]: ''
},
logLevel: 'debug'
},
[process.env.VUE_APP_BASE_API]: {
// api gateway address
target: 'http://127.0.0.1:30000',
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''
},
logLevel: 'debug'
}
}
},
pwa: {
name: name,
workboxPluginMode: 'InjectManifest',
workboxOptions: {
swSrc: path.resolve(__dirname, 'src/pwa/service-worker.js')
}
},
pluginOptions: {
'style-resources-loader': {
preProcessor: 'scss',
patterns: [
path.resolve(__dirname, 'src/styles/_variables.scss'),
path.resolve(__dirname, 'src/styles/_mixins.scss')
]
}
},
chainWebpack(config) {
// provide the app's title in webpack's name field, so that
// it can be accessed in index.html to inject the correct title.
config.set('name', name)
// https://webpack.js.org/configuration/devtool/#development
config
.when(process.env.NODE_ENV === 'development',
config => config.devtool('cheap-eval-source-map')
)
// remove vue-cli-service's progress output
config.plugins.delete('progress')
// replace with another progress output plugin to solve the this bug:
// https://github.com/vuejs/vue-cli/issues/4557
config.plugin('simple-progress-webpack-plugin')
.use(require.resolve('simple-progress-webpack-plugin'), [{
format: 'compact'
}])
config
.when(process.env.NODE_ENV !== 'development',
config => {
config
.optimization.splitChunks({
chunks: 'all',
cacheGroups: {
libs: {
name: 'chunk-libs',
test: /[\\/]node_modules[\\/]/,
priority: 10,
chunks: 'initial' // only package third parties that are initially dependent
},
elementUI: {
name: 'chunk-elementUI', // split elementUI into a single package
priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
},
commons: {
name: 'chunk-commons',
test: path.resolve(__dirname, 'src/components'),
minChunks: 3, // minimum common number
priority: 5,
reuseExistingChunk: true
}
}
})
config.optimization.runtimeChunk('single')
}
)
}
}
// eslint-disable-next-line @typescript-eslint/no-var-requires
const path = require('path')
// If your port is set to 80,
// use administrator privileges to execute the command line.
// For example, on Mac: sudo npm run / sudo yarn
const devServerPort = 9527 // TODO: get this variable from setting.ts
const name = 'Vue Typescript Admin' // TODO: get this variable from setting.ts
module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? '/' : '/vue-typescript-admin-template/',
lintOnSave: process.env.NODE_ENV === 'development',
productionSourceMap: false,
devServer: {
port: devServerPort,
open: true,
overlay: {
warnings: false,
errors: true
},
progress: false,
proxy: {
// change xxx-api/login => /mock-api/v1/login
// detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_BASE_IDENTITY_SERVER]: {
// IdentityServer4 address
target: 'http://10.21.15.28:44385',
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_IDENTITY_SERVER]: ''
}
},
[process.env.VUE_APP_SIGNALR_SERVER]: {
// api gateway address websocket protocol
target: 'ws://10.21.15.28:30000',
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_SIGNALR_SERVER]: ''
},
logLevel: 'debug'
},
[process.env.VUE_APP_BASE_API]: {
// api gateway address
target: 'http://10.21.15.28:30000',
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''
},
logLevel: 'debug'
}
}
},
pwa: {
name: name,
workboxPluginMode: 'InjectManifest',
workboxOptions: {
swSrc: path.resolve(__dirname, 'src/pwa/service-worker.js')
}
},
pluginOptions: {
'style-resources-loader': {
preProcessor: 'scss',
patterns: [
path.resolve(__dirname, 'src/styles/_variables.scss'),
path.resolve(__dirname, 'src/styles/_mixins.scss')
]
}
},
chainWebpack(config) {
// provide the app's title in webpack's name field, so that
// it can be accessed in index.html to inject the correct title.
config.set('name', name)
// https://webpack.js.org/configuration/devtool/#development
config
.when(process.env.NODE_ENV === 'development',
config => config.devtool('cheap-eval-source-map')
)
// remove vue-cli-service's progress output
config.plugins.delete('progress')
// replace with another progress output plugin to solve the this bug:
// https://github.com/vuejs/vue-cli/issues/4557
config.plugin('simple-progress-webpack-plugin')
.use(require.resolve('simple-progress-webpack-plugin'), [{
format: 'compact'
}])
config
.when(process.env.NODE_ENV !== 'development',
config => {
config
.optimization.splitChunks({
chunks: 'all',
cacheGroups: {
libs: {
name: 'chunk-libs',
test: /[\\/]node_modules[\\/]/,
priority: 10,
chunks: 'initial' // only package third parties that are initially dependent
},
elementUI: {
name: 'chunk-elementUI', // split elementUI into a single package
priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
},
commons: {
name: 'chunk-commons',
test: path.resolve(__dirname, 'src/components'),
minChunks: 3, // minimum common number
priority: 5,
reuseExistingChunk: true
}
}
})
config.optimization.runtimeChunk('single')
}
)
}
}

Loading…
Cancel
Save