import { Injectable, NotFoundException } from '@nestjs/common'; import { PrismaService } from '../prisma/prisma.service'; import { CreateMenuDto } from './dto/create-menu.dto'; import { UpdateMenuDto } from './dto/update-menu.dto'; import { AuthService } from '../auth/auth.service'; @Injectable() export class MenusService { constructor( private prisma: PrismaService, private authService: AuthService, ) {} async create(createMenuDto: CreateMenuDto) { return this.prisma.menu.create({ data: createMenuDto, }); } async findAll() { return this.prisma.menu.findMany({ where: { parentId: null, }, include: { children: { orderBy: { sort: 'asc', }, }, }, orderBy: { sort: 'asc', }, }); } async findOne(id: number) { const menu = await this.prisma.menu.findUnique({ where: { id }, include: { children: true, parent: true, }, }); if (!menu) { throw new NotFoundException('菜单不存在'); } return menu; } async update(id: number, updateMenuDto: UpdateMenuDto) { return this.prisma.menu.update({ where: { id }, data: updateMenuDto, }); } async remove(id: number) { return this.prisma.menu.delete({ where: { id }, }); } /** * 获取当前用户的菜单(根据权限过滤) * @param userId 用户ID * @param tenantId 租户ID * @returns 过滤后的菜单树 */ async findUserMenus(userId: number, tenantId: number) { // 获取用户的所有权限 const userPermissions = await this.authService.getUserPermissions(userId); // 获取租户分配的菜单ID const tenantMenus = await this.prisma.tenantMenu.findMany({ where: { tenantId }, }); const menuIds = tenantMenus.map((tm) => tm.menuId); if (menuIds.length === 0) { return []; } // 获取租户分配的所有菜单(包括父菜单) const allMenus = await this.prisma.menu.findMany({ where: { OR: [ { id: { in: menuIds } }, { children: { some: { id: { in: menuIds } } } }, ], validState: 1, // 只获取有效的菜单 }, orderBy: { sort: 'asc', }, }); // 构建树形结构 const buildTree = (menus: any[], parentId: number | null = null): any[] => { return menus .filter((menu) => menu.parentId === parentId) .map((menu) => ({ ...menu, children: buildTree(menus, menu.id), })); }; // 先构建树 const menuTree = buildTree(allMenus); // 过滤菜单:如果菜单有permission字段,检查用户是否有该权限;如果没有permission字段,则显示 const filterMenus = (menus: any[]): any[] => { return menus .filter((menu) => { // 如果菜单没有设置权限要求,则显示 if (!menu.permission) { return true; } // 如果设置了权限要求,检查用户是否有该权限 return userPermissions.includes(menu.permission); }) .map((menu) => { const filtered = { ...menu }; // 递归过滤子菜单 if (menu.children && menu.children.length > 0) { filtered.children = filterMenus(menu.children); } return filtered; }); }; // 过滤菜单树 const filteredTree = filterMenus(menuTree); // 移除没有子菜单且没有path的父菜单(空菜单) const removeEmptyParents = (menus: any[]): any[] => { return menus .map((menu) => { const hasChildren = menu.children && menu.children.length > 0; const hasPath = menu.path && menu.path.trim() !== ''; // 如果有子菜单,递归处理 if (hasChildren) { const processedChildren = removeEmptyParents(menu.children); // 如果处理后还有子菜单,保留此菜单 if (processedChildren.length > 0) { return { ...menu, children: processedChildren, }; } // 如果处理后没有子菜单,但有path,保留此菜单(作为叶子节点) if (hasPath) { return { ...menu, children: [], }; } // 既没有子菜单也没有path,移除 return null; } // 叶子节点,保留 return menu; }) .filter((menu) => menu !== null); }; return removeEmptyParents(filteredTree); } }