committed by
GitHub
54 changed files with 9921 additions and 9235 deletions
File diff suppressed because it is too large
@ -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); |
|||
} |
|||
} |
|||
|
|||
@ -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; } |
|||
} |
|||
} |
|||
|
|||
@ -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; } |
|||
} |
|||
} |
|||
|
|||
@ -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; } |
|||
} |
|||
} |
|||
|
|||
@ -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; } |
|||
} |
|||
} |
|||
|
|||
@ -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; } |
|||
} |
|||
} |
|||
|
|||
@ -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; } |
|||
} |
|||
} |
|||
|
|||
@ -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; } |
|||
} |
|||
} |
|||
|
|||
@ -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; } |
|||
} |
|||
} |
|||
|
|||
@ -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; } |
|||
} |
|||
} |
|||
|
|||
@ -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(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -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)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -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!" |
|||
} |
|||
} |
|||
@ -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} 的布局!" |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
namespace LINGYUN.Platform.Routes |
|||
{ |
|||
public static class LayoutConsts |
|||
{ |
|||
public static int MaxFrameworkLength { get; set; } = 64; |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -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); |
|||
} |
|||
} |
|||
|
|||
@ -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); |
|||
} |
|||
} |
|||
|
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -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 |
|||
); |
|||
} |
|||
} |
|||
|
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -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 |
|||
); |
|||
} |
|||
} |
|||
|
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -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(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -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(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -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 |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
|
|||
File diff suppressed because it is too large
@ -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; |
|||
} |
|||
} |
|||
} |
|||
@ -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)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -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> |
|||
|
|||
@ -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
|
|||
} |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -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 = '' |
|||
} |
|||
|
|||
@ -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 = '' |
|||
} |
|||
|
|||
@ -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>() |
|||
} |
|||
|
|||
@ -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) |
|||
|
|||
@ -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> |
|||
|
|||
@ -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> |
|||
|
|||
@ -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> |
|||
|
|||
@ -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> |
|||
|
|||
@ -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> |
|||
|
|||
@ -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> |
|||
|
|||
@ -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> |
|||
|
|||
@ -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> |
|||
|
|||
@ -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…
Reference in new issue