造轮子之菜单管理

前面完成了基础管理的相关API,接下来就得做一个菜单管理了,用于对接管理后台前端界面。

设计菜单结构

菜单是一个多级结构,所以我们得设计一个树形的。包含自己上级和下级的属性。同时预留Permission用于做可选的权限限制。

namespace Wheel.Domain.Menus {     /// <summary>     /// 菜单     /// </summary>     public class Menu : Entity<Guid>     {         /// <summary>         /// 名称         /// </summary>         public string Name { get; set; }         /// <summary>         /// 显示名称         /// </summary>         public string DisplayName { get; set; }         /// <summary>         /// 菜单类型         /// </summary>         public MenuType MenuType { get; set; }         /// <summary>         /// 菜单路径         /// </summary>         public string? Path { get; set; }         /// <summary>         /// 权限名称         /// </summary>         public string? Permission { get; set; }         /// <summary>         /// 图标         /// </summary>         public string? Icon { get; set; }         /// <summary>         /// 排序         /// </summary>         public int Sort { get; set; }         /// <summary>         /// 上级菜单Id         /// </summary>         public virtual Guid? ParentId { get; set; }         /// <summary>         /// 上级菜单         /// </summary>         public virtual Menu? Parent { get; set; }         /// <summary>         /// 子菜单         /// </summary>         public virtual List<Menu> Children { get; set; }     } }  

然后菜单和角色关联。创建RoleMenu表。

namespace Wheel.Domain.Menus {     public class RoleMenu     {         public virtual string RoleId { get; set; }         public virtual Role Role { get; set; }         public virtual Guid MenuId { get; set; }         public virtual Menu Menu { get; set; }     } } 

修改DbContext

接下来还是老套路,修改WheelDbContext
添加代码:

#region Menu public DbSet<Menu> Menus { get; set; } public DbSet<RoleMenu> RoleMenus { get; set; } #endregion 
protected override void OnModelCreating(ModelBuilder builder) {     base.OnModelCreating(builder);      ConfigureIdentity(builder);     ConfigureLocalization(builder);     ConfigurePermissionGrants(builder);     ConfigureMenus(builder); } 
void ConfigureMenus(ModelBuilder builder) {     builder.Entity<Menu>(b =>     {         b.HasKey(o => o.Id);         b.Property(o => o.Permission).HasMaxLength(128);         b.Property(o => o.Path).HasMaxLength(128);         b.Property(o => o.Name).HasMaxLength(128);         b.Property(o => o.Icon).HasMaxLength(128);         b.Property(o => o.DisplayName).HasMaxLength(128);         b.HasMany(o => o.Children).WithOne(o => o.Parent);         b.HasIndex(o => o.ParentId);     });     builder.Entity<RoleMenu>(b =>     {         b.HasKey(o => new { o.MenuId, o.RoleId });         b.Property(o => o.RoleId).HasMaxLength(36);     }); } 

然后执行数据库迁移命令即可完成表创建。

实现菜单管理

接下来就可以来实现我们的菜单管理相关功能了。

实现MenuAppService

IMenuAppService

namespace Wheel.Services.Menus {     public interface IMenuAppService : ITransientDependency     {         Task<R> Create(CreateOrUpdateMenuDto dto);         Task<R> Update(Guid id, CreateOrUpdateMenuDto dto);         Task<R> Delete(Guid id);         Task<R<MenuDto>> GetById(Guid id);         Task<R<List<MenuDto>>> GetList();         Task<R<List<MenuDto>>> GetRoleMenuList(string roleId);         Task<R<List<AntdMenuDto>>> GetCurrentMenu();         Task<R> UpdateRoleMenu(string roleId, UpdateRoleMenuDto dto);     } } 

MenuAppService

namespace Wheel.Services.Menus {     public class MenuAppService : WheelServiceBase, IMenuAppService     {         private readonly IBasicRepository<Menu, Guid> _menuRepository;         private readonly IBasicRepository<Role, string> _roleRepository;         private readonly IBasicRepository<RoleMenu> _roleMenuRepository;          public MenuAppService(IBasicRepository<Menu, Guid> menuRepository)         {             _menuRepository = menuRepository;         }          public async Task<R> Create(CreateOrUpdateMenuDto dto)         {             var menu = Mapper.Map<Menu>(dto);             menu.Id = GuidGenerator.Create();             await _menuRepository.InsertAsync(menu, true);             return new R();         }          public async Task<R> Update(Guid id,CreateOrUpdateMenuDto dto)         {             var menu = await _menuRepository.FindAsync(id);             if(menu != null)              {                 Mapper.Map(dto, menu);                 await _menuRepository.UpdateAsync(menu, true);             }             return new R();         }         public async Task<R> Delete(Guid id)         {             await _menuRepository.DeleteAsync(id, true);             return new R();         }         public async Task<R<MenuDto>> GetById(Guid id)         {             var menu = await _menuRepository.FindAsync(id);              var dto = Mapper.Map<MenuDto>(menu);             return new R<MenuDto>(dto);         }         public async Task<R<List<MenuDto>>> GetList()         {             var items = await _menuRepository.GetListAsync(                 a => a.ParentId == null,                 propertySelectors: a=>a.Children                 );             items.ForEach(a => a.Children = a.Children.OrderBy(b => b.Sort).ToList());             items = items.OrderBy(a => a.Sort).ToList();             var resultItems = Mapper.Map<List<MenuDto>>(items);             return new R<List<MenuDto>>(resultItems);         }         public async Task<R> UpdateRoleMenu(string roleId, UpdateRoleMenuDto dto)         {             using (var uow = await UnitOfWork.BeginTransactionAsync())             {                 if (await _roleMenuRepository.AnyAsync(a => a.RoleId == roleId))                 {                     await _roleMenuRepository.DeleteAsync(a => a.RoleId == roleId);                 }                 if(dto.MenuIds.Any())                 {                     var roleMenus = dto.MenuIds.Select(a => new RoleMenu { RoleId = roleId, MenuId = a });                     await _roleMenuRepository.InsertManyAsync(roleMenus.ToList());                 }                 await uow.CommitAsync();             }             return new R();         }         public async Task<R<List<MenuDto>>> GetRoleMenuList(string roleId)         {             var items = await _roleMenuRepository.SelectListAsync(a => a.RoleId == roleId && a.Menu.ParentId == null, a => a.Menu, propertySelectors: a => a.Menu.Children);             items.ForEach(a => a.Children = a.Children.OrderBy(b => b.Sort).ToList());             items = items.OrderBy(a => a.Sort).ToList();             var resultItems = Mapper.Map<List<MenuDto>>(items);             return new R<List<MenuDto>>(resultItems);         }          public async Task<R<List<AntdMenuDto>>> GetCurrentMenu()         {             if (CurrentUser.IsInRoles("admin"))             {                 var menus = await _menuRepository.GetListAsync(a => a.ParentId == null);                 return new R<List<AntdMenuDto>>(MaptoAntdMenu(menus));             }             else             {                 var roleIds = await _roleRepository.SelectListAsync(a => CurrentUser.Roles.Contains(a.Name), a => a.Id);                 var menus = await _roleMenuRepository.SelectListAsync(a => roleIds.Contains(a.RoleId) && a.Menu.ParentId == null, a => a.Menu, propertySelectors: a => a.Menu.Children);                  return new R<List<AntdMenuDto>>(MaptoAntdMenu(menus.DistinctBy(a=>a.Id).ToList()));             }         }          private List<AntdMenuDto> MaptoAntdMenu(List<Menu> menus)         {             return menus.OrderBy(m => m.Sort).Select(m =>             {                 var result = new AntdMenuDto                 {                     Name = m.Name,                     Icon = m.Icon,                     Path = m.Path,                     Access = m.Permission                 };                 if(m.Children != null && m.Children.Count > 0)                 {                     result.Children = MaptoAntdMenu(m.Children);                 }                 return result;             }).ToList();         }     } } 

实现MenuController

namespace Wheel.Controllers {     /// <summary>     /// 菜单管理     /// </summary>     [Route("api/[controller]")]     [ApiController]     public class MenuController : WheelControllerBase     {         private readonly IMenuAppService _menuAppService;          public MenuController(IMenuAppService menuAppService)         {             _menuAppService = menuAppService;         }         /// <summary>         /// 新增菜单         /// </summary>         /// <param name="dto"></param>         /// <returns></returns>         [HttpPost()]         public Task<R> Create(CreateOrUpdateMenuDto dto)         {             return _menuAppService.Create(dto);         }         /// <summary>         /// 删除菜单         /// </summary>         /// <param name="id"></param>         /// <returns></returns>         [HttpDelete("{id}")]         public Task<R> Delete(Guid id)         {             return _menuAppService.Delete(id);         }         /// <summary>         /// 获取单个菜单详情         /// </summary>         /// <param name="id"></param>         /// <returns></returns>         [HttpGet("{id}")]         public Task<R<MenuDto>> GetById(Guid id)         {             return _menuAppService.GetById(id);         }         /// <summary>         /// 查询菜单列表         /// </summary>         /// <returns></returns>         [HttpGet]         public Task<R<List<MenuDto>>> GetList()         {             return _menuAppService.GetList();         }         /// <summary>         /// 修改菜单         /// </summary>         /// <param name="id"></param>         /// <param name="dto"></param>         /// <returns></returns>         [HttpPut("{id}")]         public Task<R> Update(Guid id, CreateOrUpdateMenuDto dto)         {             return _menuAppService.Update(id, dto);         }         /// <summary>         /// 修改角色菜单         /// </summary>         /// <param name="roleId"></param>         /// <param name="dto"></param>         /// <returns></returns>         [HttpPut("role/{roleId}")]         public Task<R> UpdateRoleMenu(string roleId, UpdateRoleMenuDto dto)         {             return _menuAppService.UpdateRoleMenu(roleId, dto);         }         /// <summary>         /// 获取角色菜单列表         /// </summary>         /// <param name="roleId"></param>         /// <returns></returns>         [HttpGet("role/{roleId}")]         public Task<R<List<MenuDto>>> GetRoleMenuList(string roleId)         {             return _menuAppService.GetRoleMenuList(roleId);         }     } } 

就这样我们就完成了菜单管理相关的API功能,包含菜单的增删查改和角色菜单绑定功能。
到这里我们最基础的后台管理功能API基本开发完成。

轮子仓库地址https://github.com/Wheel-Framework/Wheel
欢迎进群催更。

造轮子之菜单管理

发表评论

评论已关闭。

相关文章