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; /// 菜单/权限管理 [ApiController] [Route("api/menus")] [Authorize] public class MenusController(AppDbContext db) : ControllerBase { /// 菜单树(全部) [HttpGet] public async Task Tree() { var menus = await db.SysMenus.AsNoTracking().OrderBy(m => m.Sort).ThenBy(m => m.Id).ToListAsync(); return Ok(BuildTree(menus, null)); } /// 当前登录用户的菜单与权限 [HttpGet("my")] public async Task 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(); } 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 BuildTree(List 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(); } /// 新增菜单 [HttpPost] public async Task 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 }); } /// 修改菜单 [HttpPut("{id:int}")] public async Task 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 = "保存成功" }); } /// 删除菜单(有子菜单或已被角色引用时禁止删除) [HttpDelete("{id:int}")] public async Task 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 = "删除成功" }); } }