package com.tcm.training.admin.user.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.tcm.training.admin.common.PageResponse; import com.tcm.training.admin.user.dto.RoleSaveRequest; import com.tcm.training.admin.user.entity.SysMenu; import com.tcm.training.admin.user.entity.SysRole; import com.tcm.training.admin.user.entity.SysRoleMenu; import com.tcm.training.admin.user.mapper.SysMenuMapper; import com.tcm.training.admin.user.mapper.SysRoleMapper; import com.tcm.training.admin.user.mapper.SysRoleMenuMapper; import com.tcm.training.admin.user.row.RoleDetailRow; import com.tcm.training.admin.user.row.RoleListRow; import com.tcm.training.admin.user.vo.PermissionTreeNodeVO; import com.tcm.training.admin.user.vo.RoleDetailVO; import com.tcm.training.admin.user.vo.RoleListItemVO; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; @Service public class RoleAppService { private static final String SUPER_ADMIN_CODE = "SUPER_ADMIN"; private final SysRoleMapper sysRoleMapper; private final SysMenuMapper sysMenuMapper; private final SysRoleMenuMapper sysRoleMenuMapper; public RoleAppService( SysRoleMapper sysRoleMapper, SysMenuMapper sysMenuMapper, SysRoleMenuMapper sysRoleMenuMapper ) { this.sysRoleMapper = sysRoleMapper; this.sysMenuMapper = sysMenuMapper; this.sysRoleMenuMapper = sysRoleMenuMapper; } public PageResponse page(int page, int pageSize, String roleName) { IPage records = sysRoleMapper.selectRolePage(new Page(page, pageSize), roleName); List list = new ArrayList(); for (RoleListRow row : records.getRecords()) { RoleListItemVO item = new RoleListItemVO(); item.setId(row.getId()); item.setRoleName(row.getRoleName()); item.setAccountCount(row.getAccountCount() == null ? 0L : row.getAccountCount()); item.setCreatedAt(row.getCreatedAt()); item.setRemark(row.getRemark()); list.add(item); } return PageResponse.of(list, records.getTotal(), records.getCurrent(), records.getSize()); } public RoleDetailVO detail(Long id) { RoleDetailRow row = sysRoleMapper.selectRoleDetail(id); if (row == null) { throw new IllegalArgumentException("角色不存在"); } RoleDetailVO vo = new RoleDetailVO(); vo.setId(row.getId()); vo.setRoleName(row.getRoleName()); vo.setRemark(row.getRemark()); vo.setAccountCount(row.getAccountCount() == null ? 0L : row.getAccountCount()); vo.setCreatedAt(row.getCreatedAt()); vo.setUpdatedAt(row.getUpdatedAt()); vo.setPermissionIds(sysRoleMapper.selectPermissionIdsByRoleId(id)); return vo; } public List permissionTree() { List menus = sysMenuMapper.selectList(new LambdaQueryWrapper() .eq(SysMenu::getDeleted, 0) .eq(SysMenu::getStatus, 1) .orderByAsc(SysMenu::getSort, SysMenu::getId)); Map nodeMap = new LinkedHashMap(); List roots = new ArrayList(); for (SysMenu menu : menus) { PermissionTreeNodeVO node = new PermissionTreeNodeVO(); node.setId(menu.getId()); node.setParentId(menu.getParentId()); node.setName(menu.getName()); node.setType(menu.getType()); node.setPermissionKey(menu.getPermissionKey()); nodeMap.put(node.getId(), node); } for (SysMenu menu : menus) { PermissionTreeNodeVO node = nodeMap.get(menu.getId()); PermissionTreeNodeVO parent = nodeMap.get(menu.getParentId()); if (parent == null || menu.getParentId() == null || menu.getParentId() == 0L) { roots.add(node); } else { parent.getChildren().add(node); } } return roots; } @Transactional public RoleDetailVO create(RoleSaveRequest req) { String roleName = req.getRoleName().trim(); ensureRoleNameUnique(roleName, null); List permissionIds = normalizePermissionIds(req.getPermissionIds()); validatePermissionIds(permissionIds); SysRole role = new SysRole(); role.setRoleName(roleName); role.setRoleCode(generateRoleCode()); role.setRemark(normalizeRemark(req.getRemark())); role.setStatus(1); role.setDeleted(0); role.setCreatedAt(LocalDateTime.now()); role.setUpdatedAt(LocalDateTime.now()); sysRoleMapper.insert(role); saveRoleMenus(role.getId(), permissionIds); return detail(role.getId()); } @Transactional public RoleDetailVO update(Long id, RoleSaveRequest req) { SysRole role = requireRole(id); String roleName = req.getRoleName().trim(); ensureRoleNameUnique(roleName, id); List permissionIds = normalizePermissionIds(req.getPermissionIds()); validatePermissionIds(permissionIds); role.setRoleName(roleName); role.setRemark(normalizeRemark(req.getRemark())); role.setUpdatedAt(LocalDateTime.now()); sysRoleMapper.updateById(role); saveRoleMenus(id, permissionIds); return detail(id); } @Transactional public void delete(Long id) { SysRole role = requireRole(id); if (SUPER_ADMIN_CODE.equals(role.getRoleCode())) { throw new IllegalArgumentException("超级管理员角色不允许删除"); } long bindCount = sysRoleMapper.countAccountBindingsByRoleId(id); if (bindCount > 0) { throw new IllegalArgumentException("该角色已关联帐号,暂不允许删除"); } role.setStatus(0); role.setUpdatedAt(LocalDateTime.now()); sysRoleMapper.updateById(role); sysRoleMapper.deleteById(id); sysRoleMenuMapper.delete(new LambdaQueryWrapper() .eq(SysRoleMenu::getRoleId, id)); } private SysRole requireRole(Long id) { SysRole role = sysRoleMapper.selectOne(new LambdaQueryWrapper() .eq(SysRole::getId, id) .eq(SysRole::getDeleted, 0) .last("limit 1")); if (role == null) { throw new IllegalArgumentException("角色不存在"); } return role; } private void ensureRoleNameUnique(String roleName, Long excludeId) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper() .eq(SysRole::getRoleName, roleName) .eq(SysRole::getDeleted, 0); if (excludeId != null) { wrapper.ne(SysRole::getId, excludeId); } SysRole exists = sysRoleMapper.selectOne(wrapper.last("limit 1")); if (exists != null) { throw new IllegalArgumentException("角色名称已存在"); } } private List normalizePermissionIds(List permissionIds) { Set idSet = new LinkedHashSet(); if (permissionIds != null) { for (Long permissionId : permissionIds) { if (permissionId != null) { idSet.add(permissionId); } } } return new ArrayList(idSet); } private void validatePermissionIds(List permissionIds) { if (permissionIds.isEmpty()) { throw new IllegalArgumentException("操作权限不能为空"); } List menus = sysMenuMapper.selectList(new LambdaQueryWrapper() .in(SysMenu::getId, permissionIds) .eq(SysMenu::getDeleted, 0) .eq(SysMenu::getStatus, 1)); if (menus.size() != permissionIds.size()) { throw new IllegalArgumentException("存在无效的操作权限"); } } private void saveRoleMenus(Long roleId, List permissionIds) { sysRoleMenuMapper.delete(new LambdaQueryWrapper() .eq(SysRoleMenu::getRoleId, roleId)); LocalDateTime now = LocalDateTime.now(); for (Long permissionId : permissionIds) { SysRoleMenu relation = new SysRoleMenu(); relation.setRoleId(roleId); relation.setMenuId(permissionId); relation.setCreatedAt(now); sysRoleMenuMapper.insert(relation); } } private String normalizeRemark(String remark) { if (remark == null) { return null; } String trimmed = remark.trim(); return trimmed.isEmpty() ? null : trimmed; } private String generateRoleCode() { for (int i = 0; i < 10; i++) { String code = "ROLE_" + UUID.randomUUID().toString().replace("-", "") .substring(0, 12).toUpperCase(); SysRole exists = sysRoleMapper.selectOne(new LambdaQueryWrapper() .eq(SysRole::getRoleCode, code) .last("limit 1")); if (exists == null) { return code; } } throw new IllegalStateException("角色编码生成失败"); } }