library-picturebook-activity/backend/src/menus/menus.service.ts

175 lines
4.6 KiB
TypeScript
Raw Normal View History

2025-11-23 14:04:20 +08:00
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);
}
}