Browse Source

Merge pull request #1189 from colinin/optimize-menu-management

feat(platform): 优化用户角色多框架菜单管理
pull/1211/head
yx lin 1 year ago
committed by GitHub
parent
commit
b02f812c15
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Datas/Dto/DataCreateDto.cs
  2. 9
      aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/RoleMenuInput.cs
  3. 7
      aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/RoleMenuStartupInput.cs
  4. 10
      aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/UserMenuInput.cs
  5. 8
      aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/UserMenuStartupInput.cs
  6. 20
      aspnet-core/modules/platform/LINGYUN.Platform.Application/LINGYUN/Platform/Menus/MenuAppService.cs
  7. 3
      aspnet-core/modules/platform/LINGYUN.Platform.Domain.Shared/LINGYUN/Platform/Localization/Resources/en.json
  8. 7
      aspnet-core/modules/platform/LINGYUN.Platform.Domain.Shared/LINGYUN/Platform/Localization/Resources/zh-Hans.json
  9. 4
      aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/IRoleMenuRepository.cs
  10. 4
      aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/IUserMenuRepository.cs
  11. 20
      aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/MenuManager.cs
  12. 34
      aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/Menus/EfCoreRoleMenuRepository.cs
  13. 28
      aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/Menus/EfCoreUserMenuRepository.cs

2
aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Datas/Dto/DataCreateDto.cs

@ -1,8 +1,10 @@
using System; using System;
using System.ComponentModel;
namespace LINGYUN.Platform.Datas; namespace LINGYUN.Platform.Datas;
public class DataCreateDto : DataCreateOrUpdateDto public class DataCreateDto : DataCreateOrUpdateDto
{ {
[DisplayName("DisplayName:ParentData")]
public Guid? ParentId { get; set; } public Guid? ParentId { get; set; }
} }

9
aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/RoleMenuInput.cs

@ -1,6 +1,8 @@
using System; using LINGYUN.Platform.Routes;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
namespace LINGYUN.Platform.Menus; namespace LINGYUN.Platform.Menus;
@ -10,6 +12,11 @@ public class RoleMenuInput
[StringLength(80)] [StringLength(80)]
public string RoleName { get; set; } public string RoleName { get; set; }
[DynamicStringLength(typeof(LayoutConsts), nameof(LayoutConsts.MaxFrameworkLength))]
public string Framework { get; set; }
public Guid? StartupMenuId { get; set; }
[Required] [Required]
public List<Guid> MenuIds { get; set; } = new List<Guid>(); public List<Guid> MenuIds { get; set; } = new List<Guid>();
} }

7
aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/RoleMenuStartupInput.cs

@ -1,4 +1,6 @@
using System.ComponentModel.DataAnnotations; using LINGYUN.Platform.Routes;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
namespace LINGYUN.Platform.Menus; namespace LINGYUN.Platform.Menus;
@ -7,4 +9,7 @@ public class RoleMenuStartupInput
[Required] [Required]
[StringLength(80)] [StringLength(80)]
public string RoleName { get; set; } public string RoleName { get; set; }
[DynamicStringLength(typeof(LayoutConsts), nameof(LayoutConsts.MaxFrameworkLength))]
public string Framework { get; set; }
} }

10
aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/UserMenuInput.cs

@ -1,6 +1,8 @@
using System; using LINGYUN.Platform.Routes;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
namespace LINGYUN.Platform.Menus; namespace LINGYUN.Platform.Menus;
@ -9,6 +11,12 @@ public class UserMenuInput
[Required] [Required]
public Guid UserId { get; set; } public Guid UserId { get; set; }
[DynamicStringLength(typeof(LayoutConsts), nameof(LayoutConsts.MaxFrameworkLength))]
public string Framework { get; set; }
public Guid? StartupMenuId { get; set; }
[Required] [Required]
public List<Guid> MenuIds { get; set; } = new List<Guid>(); public List<Guid> MenuIds { get; set; } = new List<Guid>();
} }

8
aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/UserMenuStartupInput.cs

@ -1,8 +1,14 @@
using System; using LINGYUN.Platform.Routes;
using System;
using Volo.Abp.Validation;
namespace LINGYUN.Platform.Menus; namespace LINGYUN.Platform.Menus;
public class UserMenuStartupInput public class UserMenuStartupInput
{ {
public Guid UserId { get; set; } public Guid UserId { get; set; }
[DynamicStringLength(typeof(LayoutConsts), nameof(LayoutConsts.MaxFrameworkLength))]
public string Framework { get; set; }
} }

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

@ -52,12 +52,12 @@ public class MenuAppService : PlatformApplicationServiceBase, IMenuAppService
var menus = ObjectMapper.Map<List<Menu>, List<MenuDto>>(myMenus); var menus = ObjectMapper.Map<List<Menu>, List<MenuDto>>(myMenus);
var startupMenu = await UserMenuRepository.GetStartupMenuAsync( var startupMenu = await UserMenuRepository.FindStartupMenuAsync(
CurrentUser.GetId()); CurrentUser.GetId());
if (startupMenu == null && CurrentUser.Roles.Any()) if (startupMenu == null && CurrentUser.Roles.Any())
{ {
startupMenu = await RoleMenuRepository.GetStartupMenuAsync(CurrentUser.Roles); startupMenu = await RoleMenuRepository.FindStartupMenuAsync(CurrentUser.Roles);
} }
if (startupMenu != null) if (startupMenu != null)
@ -240,11 +240,11 @@ public class MenuAppService : PlatformApplicationServiceBase, IMenuAppService
var menuDtos = ObjectMapper.Map<List<Menu>, List<MenuDto>>(menus); var menuDtos = ObjectMapper.Map<List<Menu>, List<MenuDto>>(menus);
var startupMenu = await UserMenuRepository.GetStartupMenuAsync(input.UserId); var startupMenu = await UserMenuRepository.FindStartupMenuAsync(input.UserId, input.Framework);
if (startupMenu == null) if (startupMenu == null)
{ {
startupMenu = await RoleMenuRepository.GetStartupMenuAsync(input.Roles); startupMenu = await RoleMenuRepository.FindStartupMenuAsync(input.Roles, input.Framework);
} }
if (startupMenu != null) if (startupMenu != null)
@ -263,25 +263,27 @@ public class MenuAppService : PlatformApplicationServiceBase, IMenuAppService
[Authorize(PlatformPermissions.Menu.ManageUsers)] [Authorize(PlatformPermissions.Menu.ManageUsers)]
public async virtual Task SetUserMenusAsync(UserMenuInput input) public async virtual Task SetUserMenusAsync(UserMenuInput input)
{ {
await MenuManager.SetUserMenusAsync(input.UserId, input.MenuIds); await MenuManager.SetUserMenusAsync(input.UserId, input.MenuIds, input.Framework);
await MenuManager.SetUserStartupMenuAsync(input.UserId, input.StartupMenuId, input.Framework);
} }
[Authorize(PlatformPermissions.Menu.ManageUsers)] [Authorize(PlatformPermissions.Menu.ManageUsers)]
public async virtual Task SetUserStartupAsync(Guid id, UserMenuStartupInput input) public async virtual Task SetUserStartupAsync(Guid id, UserMenuStartupInput input)
{ {
await MenuManager.SetUserStartupMenuAsync(input.UserId, id); await MenuManager.SetUserStartupMenuAsync(input.UserId, id, input.Framework);
} }
[Authorize(PlatformPermissions.Menu.ManageRoles)] [Authorize(PlatformPermissions.Menu.ManageRoles)]
public async virtual Task SetRoleMenusAsync(RoleMenuInput input) public async virtual Task SetRoleMenusAsync(RoleMenuInput input)
{ {
await MenuManager.SetRoleMenusAsync(input.RoleName, input.MenuIds); await MenuManager.SetRoleMenusAsync(input.RoleName, input.MenuIds, input.Framework);
await MenuManager.SetRoleStartupMenuAsync(input.RoleName, input.StartupMenuId, input.Framework);
} }
[Authorize(PlatformPermissions.Menu.ManageRoles)] [Authorize(PlatformPermissions.Menu.ManageRoles)]
public async virtual Task SetRoleStartupAsync(Guid id, RoleMenuStartupInput input) public async virtual Task SetRoleStartupAsync(Guid id, RoleMenuStartupInput input)
{ {
await MenuManager.SetRoleStartupMenuAsync(input.RoleName, id); await MenuManager.SetRoleStartupMenuAsync(input.RoleName, id, input.Framework);
} }
[Authorize(PlatformPermissions.Menu.ManageRoles)] [Authorize(PlatformPermissions.Menu.ManageRoles)]
@ -291,7 +293,7 @@ public class MenuAppService : PlatformApplicationServiceBase, IMenuAppService
var menuDtos = ObjectMapper.Map<List<Menu>, List<MenuDto>>(menus); var menuDtos = ObjectMapper.Map<List<Menu>, List<MenuDto>>(menus);
var startupMenu = await RoleMenuRepository.GetStartupMenuAsync(new string[] { input.Role }); var startupMenu = await RoleMenuRepository.FindStartupMenuAsync(new string[] { input.Role }, input.Framework);
if (startupMenu != null) if (startupMenu != null)
{ {

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

@ -76,6 +76,9 @@
"DisplayName:BlobName": "Blob Name", "DisplayName:BlobName": "Blob Name",
"DisplayName:Key": "Key", "DisplayName:Key": "Key",
"DisplayName:Value": "Value", "DisplayName:Value": "Value",
"DisplayName:ParentData": "Parent Data",
"DisplayName:ParentMenu": "Parent Menu",
"DisplayName:LayoutConstraint": "Layout Constraint",
"MailPriority:Normal": "Normal", "MailPriority:Normal": "Normal",
"MailPriority:Low": "Low", "MailPriority:Low": "Low",
"MailPriority:High": "High", "MailPriority:High": "High",

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

@ -76,6 +76,9 @@
"DisplayName:BlobName": "存储名称", "DisplayName:BlobName": "存储名称",
"DisplayName:Key": "键名", "DisplayName:Key": "键名",
"DisplayName:Value": "键值", "DisplayName:Value": "键值",
"DisplayName:ParentData": "上级字典",
"DisplayName:ParentMenu": "上级菜单",
"DisplayName:LayoutConstraint": "布局约束",
"MailPriority:Normal": "普通", "MailPriority:Normal": "普通",
"MailPriority:Low": "低", "MailPriority:Low": "低",
"MailPriority:High": "高", "MailPriority:High": "高",
@ -115,6 +118,8 @@
"SmsMessages": "短信消息", "SmsMessages": "短信消息",
"SendMessage": "发送消息", "SendMessage": "发送消息",
"MessageWillBeReSendWarningMessage": "将重新发送选择的消息.", "MessageWillBeReSendWarningMessage": "将重新发送选择的消息.",
"SuccessfullySent": "发送成功,请稍后在消息中心查看状态!" "SuccessfullySent": "发送成功,请稍后在消息中心查看状态!",
"PreStep": "上一步",
"NextStep": "下一步"
} }
} }

4
aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/IRoleMenuRepository.cs

@ -22,9 +22,11 @@ public interface IRoleMenuRepository : IBasicRepository<RoleMenu, Guid>
Task<List<RoleMenu>> GetListByRoleNameAsync( Task<List<RoleMenu>> GetListByRoleNameAsync(
string roleName, string roleName,
string framework = null,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
Task<Menu> GetStartupMenuAsync( Task<Menu> FindStartupMenuAsync(
IEnumerable<string> roleNames, IEnumerable<string> roleNames,
string framework = null,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
} }

4
aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Menus/IUserMenuRepository.cs

@ -22,9 +22,11 @@ public interface IUserMenuRepository : IBasicRepository<UserMenu, Guid>
Task<List<UserMenu>> GetListByUserIdAsync( Task<List<UserMenu>> GetListByUserIdAsync(
Guid userId, Guid userId,
string framework = null,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
Task<Menu> GetStartupMenuAsync( Task<Menu> FindStartupMenuAsync(
Guid userId, Guid userId,
string framework = null,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
} }

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

@ -126,16 +126,16 @@ public class MenuManager : DomainService
return false; return false;
} }
public async virtual Task SetUserStartupMenuAsync(Guid userId, Guid menuId) public async virtual Task SetUserStartupMenuAsync(Guid userId, Guid? menuId = null, string framework = null)
{ {
using (var unitOfWork = UnitOfWorkManager.Begin()) using (var unitOfWork = UnitOfWorkManager.Begin())
{ {
var userMenus = await UserMenuRepository.GetListByUserIdAsync(userId); var userMenus = await UserMenuRepository.GetListByUserIdAsync(userId, framework);
foreach (var menu in userMenus) foreach (var menu in userMenus)
{ {
menu.Startup = false; menu.Startup = false;
if (menu.MenuId.Equals(menuId)) if (menuId.HasValue && menu.MenuId.Equals(menuId))
{ {
menu.Startup = true; menu.Startup = true;
} }
@ -147,11 +147,11 @@ public class MenuManager : DomainService
} }
} }
public async virtual Task SetUserMenusAsync(Guid userId, IEnumerable<Guid> menuIds) public async virtual Task SetUserMenusAsync(Guid userId, IEnumerable<Guid> menuIds, string framework = null)
{ {
using (var unitOfWork = UnitOfWorkManager.Begin()) using (var unitOfWork = UnitOfWorkManager.Begin())
{ {
var userMenus = await UserMenuRepository.GetListByUserIdAsync(userId); var userMenus = await UserMenuRepository.GetListByUserIdAsync(userId, framework);
// 移除不存在的菜单 // 移除不存在的菜单
// TODO: 升级框架版本解决未能删除不需要菜单的问题 // TODO: 升级框架版本解决未能删除不需要菜单的问题
@ -173,16 +173,16 @@ public class MenuManager : DomainService
} }
} }
public async virtual Task SetRoleStartupMenuAsync(string roleName, Guid menuId) public async virtual Task SetRoleStartupMenuAsync(string roleName, Guid? menuId = null, string framework = null)
{ {
using (var unitOfWork = UnitOfWorkManager.Begin()) using (var unitOfWork = UnitOfWorkManager.Begin())
{ {
var roleMenus = await RoleMenuRepository.GetListByRoleNameAsync(roleName); var roleMenus = await RoleMenuRepository.GetListByRoleNameAsync(roleName, framework);
foreach (var menu in roleMenus) foreach (var menu in roleMenus)
{ {
menu.Startup = false; menu.Startup = false;
if (menu.MenuId.Equals(menuId)) if (menuId.HasValue && menu.MenuId.Equals(menuId))
{ {
menu.Startup = true; menu.Startup = true;
} }
@ -194,11 +194,11 @@ public class MenuManager : DomainService
} }
} }
public async virtual Task SetRoleMenusAsync(string roleName, IEnumerable<Guid> menuIds) public async virtual Task SetRoleMenusAsync(string roleName, IEnumerable<Guid> menuIds, string framework = null)
{ {
using (var unitOfWork = UnitOfWorkManager.Begin()) using (var unitOfWork = UnitOfWorkManager.Begin())
{ {
var roleMenus = await RoleMenuRepository.GetListByRoleNameAsync(roleName); var roleMenus = await RoleMenuRepository.GetListByRoleNameAsync(roleName, framework);
// 移除不存在的菜单 // 移除不存在的菜单
// TODO: 升级框架版本解决未能删除不需要菜单的问题 // TODO: 升级框架版本解决未能删除不需要菜单的问题

34
aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/Menus/EfCoreRoleMenuRepository.cs

@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
@ -18,10 +19,31 @@ public class EfCoreRoleMenuRepository : EfCoreRepository<PlatformDbContext, Role
{ {
} }
public async virtual Task<List<RoleMenu>> GetListByRoleNameAsync(string roleName, CancellationToken cancellationToken = default) public async virtual Task<List<RoleMenu>> GetListByRoleNameAsync(
string roleName,
string framework = null,
CancellationToken cancellationToken = default)
{ {
return await (await GetDbSetAsync()).Where(x => x.RoleName.Equals(roleName)) var dbContext = await GetDbContextAsync();
.ToListAsync(GetCancellationToken(cancellationToken));
var menus = dbContext.Set<Menu>();
var roleMenus = dbContext.Set<RoleMenu>().Where(x => x.RoleName == roleName);
IQueryable<RoleMenu> queryable;
if (!framework.IsNullOrWhiteSpace())
{
queryable = from menu in menus
join roleMenu in roleMenus
on menu.Id equals roleMenu.MenuId
where menu.Framework == framework
select roleMenu;
}
else
{
queryable = roleMenus;
}
return await queryable.ToListAsync(GetCancellationToken(cancellationToken));
} }
public async virtual Task<bool> RoleHasInMenuAsync( public async virtual Task<bool> RoleHasInMenuAsync(
@ -40,8 +62,9 @@ public class EfCoreRoleMenuRepository : EfCoreRepository<PlatformDbContext, Role
GetCancellationToken(cancellationToken)); GetCancellationToken(cancellationToken));
} }
public async virtual Task<Menu> GetStartupMenuAsync( public async virtual Task<Menu> FindStartupMenuAsync(
IEnumerable<string> roleNames, IEnumerable<string> roleNames,
string framework = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
var dbContext = await GetDbContextAsync(); var dbContext = await GetDbContextAsync();
@ -54,6 +77,7 @@ public class EfCoreRoleMenuRepository : EfCoreRepository<PlatformDbContext, Role
join menu in dbContext.Set<Menu>() join menu in dbContext.Set<Menu>()
on roleMenu.MenuId equals menu.Id on roleMenu.MenuId equals menu.Id
select menu) select menu)
.WhereIf(!framework.IsNullOrWhiteSpace(), x => x.Framework == framework)
.OrderByDescending(x => x.CreationTime) .OrderByDescending(x => x.CreationTime)
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); .FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
} }

28
aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/Menus/EfCoreUserMenuRepository.cs

@ -37,15 +37,34 @@ public class EfCoreUserMenuRepository : EfCoreRepository<PlatformDbContext, User
public async virtual Task<List<UserMenu>> GetListByUserIdAsync( public async virtual Task<List<UserMenu>> GetListByUserIdAsync(
Guid userId, Guid userId,
string framework = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
var dbSet = await GetDbSetAsync(); var dbContext = await GetDbContextAsync();
return await dbSet.Where(x => x.UserId.Equals(userId))
.ToListAsync(GetCancellationToken(cancellationToken)); var menus = dbContext.Set<Menu>();
var userMenus = dbContext.Set<UserMenu>().Where(x => x.UserId == userId);
IQueryable<UserMenu> queryable;
if (!framework.IsNullOrWhiteSpace())
{
queryable = from menu in menus
join userMenu in userMenus
on menu.Id equals userMenu.MenuId
where menu.Framework == framework
select userMenu;
}
else
{
queryable = userMenus;
}
return await queryable.ToListAsync(GetCancellationToken(cancellationToken));
} }
public async virtual Task<Menu> GetStartupMenuAsync( public async virtual Task<Menu> FindStartupMenuAsync(
Guid userId, Guid userId,
string framework = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
var dbContext = await GetDbContextAsync(); var dbContext = await GetDbContextAsync();
@ -58,6 +77,7 @@ public class EfCoreUserMenuRepository : EfCoreRepository<PlatformDbContext, User
join menu in dbContext.Set<Menu>() join menu in dbContext.Set<Menu>()
on userMenu.MenuId equals menu.Id on userMenu.MenuId equals menu.Id
select menu) select menu)
.WhereIf(!framework.IsNullOrWhiteSpace(), x => x.Framework == framework)
.OrderByDescending(x => x.CreationTime) .OrderByDescending(x => x.CreationTime)
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); .FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
} }

Loading…
Cancel
Save