113 lines
4.3 KiB
C#
113 lines
4.3 KiB
C#
using System.Security.Claims;
|
|
using AgriculturalPlatform.Api.Data;
|
|
using AgriculturalPlatform.Api.Dtos;
|
|
using AgriculturalPlatform.Api.Models;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace AgriculturalPlatform.Api.Controllers;
|
|
|
|
/// <summary>菜单/权限管理</summary>
|
|
[ApiController]
|
|
[Route("api/menus")]
|
|
[Authorize]
|
|
public class MenusController(AppDbContext db) : ControllerBase
|
|
{
|
|
/// <summary>菜单树(全部)</summary>
|
|
[HttpGet]
|
|
public async Task<ActionResult> Tree()
|
|
{
|
|
var menus = await db.SysMenus.AsNoTracking().OrderBy(m => m.Sort).ThenBy(m => m.Id).ToListAsync();
|
|
return Ok(BuildTree(menus, null));
|
|
}
|
|
|
|
/// <summary>当前登录用户的菜单与权限</summary>
|
|
[HttpGet("my")]
|
|
public async Task<ActionResult> My()
|
|
{
|
|
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
|
if (userId is null) return Unauthorized();
|
|
|
|
// 用户角色 -> 菜单
|
|
var user = await db.Users.Include(u => u.SysRole).FirstOrDefaultAsync(u => u.Id == int.Parse(userId));
|
|
if (user is null) return Unauthorized();
|
|
|
|
int[] menuIds;
|
|
if (user.SysRole?.Code == "super_admin" || user.Role == UserRole.SuperAdmin)
|
|
{
|
|
menuIds = await db.SysMenus.Select(m => m.Id).ToArrayAsync();
|
|
}
|
|
else if (user.RoleId is int rid)
|
|
{
|
|
menuIds = await db.SysRoleMenus.Where(rm => rm.RoleId == rid).Select(rm => rm.MenuId).ToArrayAsync();
|
|
}
|
|
else
|
|
{
|
|
menuIds = Array.Empty<int>();
|
|
}
|
|
|
|
var menus = await db.SysMenus.AsNoTracking()
|
|
.Where(m => menuIds.Contains(m.Id))
|
|
.OrderBy(m => m.Sort).ThenBy(m => m.Id)
|
|
.ToListAsync();
|
|
var tree = BuildTree(menus, null);
|
|
var permissions = menus.Where(m => !string.IsNullOrWhiteSpace(m.Permission)).Select(m => m.Permission).Distinct().ToArray();
|
|
return Ok(new { menus = tree, permissions });
|
|
}
|
|
|
|
private static List<MenuDto> BuildTree(List<SysMenu> all, int? parentId)
|
|
{
|
|
return all.Where(m => m.ParentId == parentId)
|
|
.Select(m => new MenuDto(
|
|
m.Id, m.ParentId, m.Name, m.Path, m.Component, m.Icon, m.Type,
|
|
m.Permission, m.Visible, m.Sort, BuildTree(all, m.Id)))
|
|
.ToList();
|
|
}
|
|
|
|
/// <summary>新增菜单</summary>
|
|
[HttpPost]
|
|
public async Task<ActionResult> Create(MenuSaveRequest req)
|
|
{
|
|
var menu = new SysMenu
|
|
{
|
|
ParentId = req.ParentId, Name = req.Name, Path = req.Path, Component = req.Component,
|
|
Icon = req.Icon, Type = req.Type, Permission = req.Permission, Visible = req.Visible,
|
|
Sort = req.Sort, CreatedAt = DateTime.Now
|
|
};
|
|
db.SysMenus.Add(menu);
|
|
await db.SaveChangesAsync();
|
|
return Ok(new { message = "保存成功", id = menu.Id });
|
|
}
|
|
|
|
/// <summary>修改菜单</summary>
|
|
[HttpPut("{id:int}")]
|
|
public async Task<ActionResult> Update(int id, MenuSaveRequest req)
|
|
{
|
|
var menu = await db.SysMenus.FindAsync(id);
|
|
if (menu is null) return NotFound();
|
|
if (req.ParentId == id) return BadRequest(new { message = "父级不能选择自身" });
|
|
|
|
menu.ParentId = req.ParentId; menu.Name = req.Name; menu.Path = req.Path;
|
|
menu.Component = req.Component; menu.Icon = req.Icon; menu.Type = req.Type;
|
|
menu.Permission = req.Permission; menu.Visible = req.Visible; menu.Sort = req.Sort;
|
|
await db.SaveChangesAsync();
|
|
return Ok(new { message = "保存成功" });
|
|
}
|
|
|
|
/// <summary>删除菜单(有子菜单或已被角色引用时禁止删除)</summary>
|
|
[HttpDelete("{id:int}")]
|
|
public async Task<IActionResult> Delete(int id)
|
|
{
|
|
if (await db.SysMenus.AnyAsync(m => m.ParentId == id))
|
|
return BadRequest(new { message = "请先删除子菜单" });
|
|
if (await db.SysRoleMenus.AnyAsync(rm => rm.MenuId == id))
|
|
return BadRequest(new { message = "该菜单已被角色引用,请先解除关联" });
|
|
var menu = await db.SysMenus.FindAsync(id);
|
|
if (menu is null) return NotFound();
|
|
db.SysMenus.Remove(menu);
|
|
await db.SaveChangesAsync();
|
|
return Ok(new { message = "删除成功" });
|
|
}
|
|
}
|