import { Provide, Inject } from "@midwayjs/core"; import { InjectRepository } from "@midwayjs/sequelize"; import SysRole from "../entity/sysRole.entity"; import SysUserRole from "../entity/sysUserRole.entity"; import SysRoleMenu from "../entity/sysRoleMenu.entity"; import SysMenu from "../entity/sysMenu.entity"; import { Op } from "sequelize"; @Provide() export class RoleService { @InjectRepository(SysRole) roleModel!: typeof SysRole; @InjectRepository(SysUserRole) userRoleModel!: typeof SysUserRole; @InjectRepository(SysRoleMenu) roleMenuModel!: typeof SysRoleMenu; @InjectRepository(SysMenu) menuModel!: typeof SysMenu; async list(query: { page?: number; pageSize?: number; keyword?: string; }): Promise { const page = query.page || 1; const pageSize = query.pageSize || 10; const offset = (page - 1) * pageSize; const whereClause: any = {}; if (query.keyword) { whereClause[Op.or] = [ { roleCode: { [Op.like]: `%${query.keyword}%` } }, { roleName: { [Op.like]: `%${query.keyword}%` } }, ]; } const { count, rows } = await this.roleModel.findAndCountAll({ where: whereClause, attributes: ["id", "roleCode", "roleName", "description", "sortOrder"], offset, limit: pageSize, order: [["sort_order", "ASC"], ["created_at", "DESC"]], }); for (const role of rows) { const userCount = await this.userRoleModel.count({ where: { roleId: role.id }, }); (role as any).setDataValue("userCount", userCount); } return { code: 200, message: "获取角色列表成功", data: { list: rows, total: count, page, pageSize, }, }; } async getAllRoles(): Promise { const roles = await this.roleModel.findAll({ order: [["sort_order", "ASC"], ["created_at", "DESC"]], }); return { code: 200, message: "获取所有角色成功", data: roles, }; } async detail(id: string): Promise { const role = await this.roleModel.findByPk(Number(id)); if (!role) { return { code: 404, message: "角色不存在", data: null, }; } const userCount = await this.userRoleModel.count({ where: { roleId: role.id }, }); (role as any).setDataValue("userCount", userCount); return { code: 200, message: "获取角色详情成功", data: role, }; } async create(data: any): Promise { const { roleCode, roleName, description, sortOrder = 0 } = data; const existingRole = await this.roleModel.findOne({ where: { roleCode }, }); if (existingRole) { return { code: 400, message: "角色编码已存在", data: null, }; } const role = await this.roleModel.create({ roleCode, roleName, description, sort_order: sortOrder, }); return { code: 200, message: "创建角色成功", data: role, }; } async update(id: string, data: any): Promise { const role = await this.roleModel.findByPk(Number(id)); if (!role) { return { code: 404, message: "角色不存在", data: null, }; } if (data.roleCode && data.roleCode !== role.roleCode) { const existingRole = await this.roleModel.findOne({ where: { roleCode: data.roleCode }, }); if (existingRole) { return { code: 400, message: "角色编码已存在", data: null, }; } } const updateData: any = {}; if (data.roleCode !== undefined) updateData.roleCode = data.roleCode; if (data.roleName !== undefined) updateData.roleName = data.roleName; if (data.description !== undefined) updateData.description = data.description; if (data.sortOrder !== undefined) updateData.sort_order = data.sortOrder; await role.update(updateData); return { code: 200, message: "更新角色成功", data: role, }; } async delete(id: string): Promise { const role = await this.roleModel.findByPk(Number(id)); if (!role) { return { code: 404, message: "角色不存在", data: null, }; } const userCount = await this.userRoleModel.count({ where: { roleId: Number(id) }, }); if (userCount > 0) { return { code: 400, message: `该角色下有${userCount}个用户,无法删除`, data: null, }; } await this.roleMenuModel.destroy({ where: { roleId: Number(id) }, }); await role.destroy(); return { code: 200, message: "删除角色成功", data: null, }; } async getMenus(roleId: number): Promise { const role = await this.roleModel.findByPk(roleId); if (!role) { return { code: 404, message: "角色不存在", data: null, }; } const roleMenus = await this.roleMenuModel.findAll({ where: { roleId }, }); const assignedMenuIds = roleMenus.map(rm => rm.menuId); const menus = await this.menuModel.findAll({ where: { menuType: { [Op.in]: [1, 2] } }, order: [["sort_order", "ASC"], ["id", "ASC"]], }); const menuTree = this.buildMenuTree( menus.map(m => m.toJSON()), assignedMenuIds ); return { code: 200, message: "获取角色菜单成功", data: { menuTree, menuIds: assignedMenuIds, }, }; } async updateMenus(roleId: number, menuIds: number[]): Promise { const role = await this.roleModel.findByPk(roleId); if (!role) { return { code: 404, message: "角色不存在", data: null, }; } await this.roleMenuModel.destroy({ where: { roleId }, }); if (menuIds && menuIds.length > 0) { const roleMenus = menuIds.map(menuId => ({ roleId, menuId, })); await this.roleMenuModel.bulkCreate(roleMenus); } return { code: 200, message: "菜单更新成功", data: null, }; } private buildMenuTree(menus: any[], checkedIds: number[]): any[] { const nodeMap = new Map(); const menuIdSet = new Set(menus.map(m => m.id)); const tree: any[] = []; for (const menu of menus) { nodeMap.set(menu.id, { ...menu, children: [], checked: checkedIds.includes(menu.id), }); } for (const menu of menus) { const node = nodeMap.get(menu.id)!; const parent = menu.parentId ? nodeMap.get(menu.parentId) : undefined; // 仅当父节点为一级节点时挂为其子节点,保证输出两级树; // 父节点不在列表或父节点本身是二级节点时,提升为一级节点 if (parent && !menuIdSet.has(parent.parentId)) { parent.children.push(node); } else { tree.push(node); } } // 一级节点已在查询时按 sort_order 排序,此处对子节点排序 for (const node of tree) { node.children.sort((a: any, b: any) => a.sortOrder - b.sortOrder); } return tree; } }