| | |
| | | package com.xiaopeng.account.service.impl; |
| | | |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.xiaopeng.account.mapper.SysRoleMapper; |
| | | import com.xiaopeng.account.model.dto.SysRoleAddDTO; |
| | | import com.xiaopeng.account.model.dto.SysRoleEditDTO; |
| | | import com.xiaopeng.account.model.query.SysRolePageQuery; |
| | | import com.xiaopeng.account.model.vo.SysMenuVO; |
| | | import com.xiaopeng.account.model.vo.SysRoleDetailVO; |
| | | import com.xiaopeng.account.model.vo.SysRolePageVO; |
| | | import com.xiaopeng.account.service.ISysGroupMenuService; |
| | | import com.xiaopeng.account.service.ISysRoleService; |
| | | import com.xiaopeng.account.service.ISysUserRoleService; |
| | | import com.xiaopeng.api.feignClient.operation.SysMenuClient; |
| | | import com.xiaopeng.api.model.account.SysRole; |
| | | import com.xiaopeng.api.model.account.SysUserRole; |
| | | import com.xiaopeng.api.model.operation.SysMenu; |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import com.xiaopeng.common.core.exception.ServiceException; |
| | | import com.xiaopeng.common.core.utils.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import com.xiaopeng.common.core.web.page.PageInfo; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import java.util.HashSet; |
| | | import java.util.Set; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | * @author mitao |
| | | * @since 2026-02-03 |
| | | */ |
| | | @Slf4j |
| | | @Service |
| | | @RequiredArgsConstructor(onConstructor_ = @Lazy) |
| | | public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService { |
| | | |
| | | @Autowired |
| | | private ISysUserRoleService userRoleService; |
| | | private final ISysUserRoleService userRoleService; |
| | | |
| | | private final ISysGroupMenuService groupMenuService; |
| | | |
| | | private final SysMenuClient sysMenuClient; |
| | | |
| | | /** |
| | | * 根据角色ID查询权限组ID |
| | |
| | | |
| | | return roles; |
| | | } |
| | | |
| | | /** |
| | | * 新增角色 |
| | | * |
| | | * @param dto 新增角色请求 |
| | | */ |
| | | @Override |
| | | public void addRole(SysRoleAddDTO dto) { |
| | | // 校验角色名称唯一性 |
| | | if (!checkRoleNameUnique(dto.getRoleName(), null)) { |
| | | throw new ServiceException("角色名称已存在"); |
| | | } |
| | | |
| | | // 创建角色实体 |
| | | SysRole role = new SysRole(); |
| | | role.setGroupId(dto.getGroupId()); |
| | | role.setRoleName(dto.getRoleName()); |
| | | role.setRemarks(dto.getRemarks()); |
| | | |
| | | // 保存角色 |
| | | this.save(role); |
| | | } |
| | | |
| | | /** |
| | | * 编辑角色 |
| | | * |
| | | * @param dto 编辑角色请求 |
| | | */ |
| | | @Override |
| | | public void editRole(SysRoleEditDTO dto) { |
| | | // 校验角色是否存在 |
| | | SysRole existRole = this.getById(dto.getId()); |
| | | if (existRole == null) { |
| | | throw new ServiceException("角色不存在"); |
| | | } |
| | | |
| | | // 校验角色名称唯一性(排除自身) |
| | | if (!checkRoleNameUnique(dto.getRoleName(), dto.getId())) { |
| | | throw new ServiceException("角色名称已存在"); |
| | | } |
| | | |
| | | // 更新角色信息 |
| | | existRole.setGroupId(dto.getGroupId()); |
| | | existRole.setRoleName(dto.getRoleName()); |
| | | existRole.setRemarks(dto.getRemarks()); |
| | | |
| | | this.updateById(existRole); |
| | | } |
| | | |
| | | /** |
| | | * 获取角色详情(含菜单树) |
| | | * |
| | | * @param id 角色ID |
| | | * @return 角色详情 |
| | | */ |
| | | @Override |
| | | public SysRoleDetailVO getRoleDetail(Long id) { |
| | | // 查询角色基础信息 |
| | | SysRole role = this.getById(id); |
| | | if (role == null) { |
| | | throw new ServiceException("角色不存在"); |
| | | } |
| | | |
| | | SysRoleDetailVO vo = BeanUtil.toBean(role, SysRoleDetailVO.class); |
| | | |
| | | // 根据权限组ID获取菜单ID列表 |
| | | List<Long> menuIds = groupMenuService.selectMenuIdsByGroupId(role.getGroupId()); |
| | | if (CollectionUtils.isEmpty(menuIds)) { |
| | | vo.setMenus(new ArrayList<>()); |
| | | return vo; |
| | | } |
| | | |
| | | // 通过Feign调用获取菜单详情 |
| | | try { |
| | | R<List<SysMenu>> result = sysMenuClient.getMenusByMenuIds(menuIds); |
| | | if (result != null && result.getData() != null) { |
| | | List<SysMenu> menus = result.getData(); |
| | | // 构建菜单树 |
| | | vo.setMenus(buildMenuTree(menus)); |
| | | } else { |
| | | vo.setMenus(new ArrayList<>()); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("获取菜单列表失败: {}", e.getMessage()); |
| | | vo.setMenus(new ArrayList<>()); |
| | | } |
| | | |
| | | return vo; |
| | | } |
| | | |
| | | /** |
| | | * 角色分页列表 |
| | | * |
| | | * @param query 分页查询参数 |
| | | * @return 分页结果 |
| | | */ |
| | | @Override |
| | | public PageInfo<SysRolePageVO> pageList(SysRolePageQuery query) { |
| | | // 构建查询条件 |
| | | LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>(); |
| | | if (StringUtils.isNotBlank(query.getRoleName())) { |
| | | wrapper.like(SysRole::getRoleName, query.getRoleName()); |
| | | } |
| | | wrapper.orderByDesc(SysRole::getCreateTime); |
| | | |
| | | // 分页查询 |
| | | PageInfo<SysRole> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize()); |
| | | PageInfo<SysRole> rolePage = this.page(pageInfo, wrapper); |
| | | |
| | | // 转换为VO |
| | | PageInfo<SysRolePageVO> resultPage = new PageInfo<>(query.getPageNum(), query.getPageSize()); |
| | | resultPage.setTotal(rolePage.getTotal()); |
| | | |
| | | List<SysRolePageVO> voList = rolePage.getRecords().stream().map(role -> { |
| | | SysRolePageVO vo = new SysRolePageVO(); |
| | | vo.setId(role.getId()); |
| | | vo.setGroupId(role.getGroupId()); |
| | | vo.setRoleName(role.getRoleName()); |
| | | vo.setRemarks(role.getRemarks()); |
| | | vo.setCreateTime(role.getCreateTime()); |
| | | // 统计绑定用户数 |
| | | Long bindCount = baseMapper.countBindUsers(role.getId()); |
| | | vo.setBindCount(bindCount); |
| | | return vo; |
| | | }).collect(Collectors.toList()); |
| | | |
| | | resultPage.setRecords(voList); |
| | | return resultPage; |
| | | } |
| | | |
| | | /** |
| | | * 删除角色(逻辑删除) |
| | | * |
| | | * @param id 角色ID |
| | | */ |
| | | @Override |
| | | public void deleteRole(Long id) { |
| | | // 校验角色是否存在 |
| | | SysRole role = this.getById(id); |
| | | if (role == null) { |
| | | throw new ServiceException("角色不存在"); |
| | | } |
| | | |
| | | // 检查是否有用户绑定该角色 |
| | | Long bindCount = baseMapper.countBindUsers(id); |
| | | if (bindCount != null && bindCount > 0) { |
| | | throw new ServiceException("该角色已绑定用户,无法删除"); |
| | | } |
| | | |
| | | // 逻辑删除 |
| | | this.removeById(id); |
| | | } |
| | | |
| | | /** |
| | | * 校验角色名称唯一性 |
| | | * |
| | | * @param roleName 角色名称 |
| | | * @param excludeId 排除的角色ID(编辑时使用) |
| | | * @return true=唯一,false=不唯一 |
| | | */ |
| | | @Override |
| | | public boolean checkRoleNameUnique(String roleName, Long excludeId) { |
| | | LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>(); |
| | | wrapper.eq(SysRole::getRoleName, roleName); |
| | | if (excludeId != null) { |
| | | wrapper.ne(SysRole::getId, excludeId); |
| | | } |
| | | return this.count(wrapper) == 0; |
| | | } |
| | | |
| | | /** |
| | | * 构建菜单树 |
| | | * |
| | | * @param menus 菜单列表 |
| | | * @return 菜单树 |
| | | */ |
| | | private List<SysMenuVO> buildMenuTree(List<SysMenu> menus) { |
| | | if (CollectionUtils.isEmpty(menus)) { |
| | | return new ArrayList<>(); |
| | | } |
| | | |
| | | Map<Long, SysMenuVO> menuMap = new HashMap<>(); |
| | | List<SysMenuVO> rootMenus = new ArrayList<>(); |
| | | |
| | | // 转换为VO并建立映射 |
| | | for (SysMenu menu : menus) { |
| | | SysMenuVO vo = convertToMenuVO(menu); |
| | | vo.setChildren(new ArrayList<>()); |
| | | menuMap.put(vo.getId(), vo); |
| | | } |
| | | |
| | | // 构建树结构 |
| | | for (SysMenuVO vo : menuMap.values()) { |
| | | if (vo.getParentId() == null || vo.getParentId() == 0) { |
| | | rootMenus.add(vo); |
| | | } else { |
| | | SysMenuVO parent = menuMap.get(vo.getParentId()); |
| | | if (parent != null) { |
| | | parent.getChildren().add(vo); |
| | | } else { |
| | | // 父节点不在列表中,作为根节点处理 |
| | | rootMenus.add(vo); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 按orderNum排序 |
| | | sortMenuTree(rootMenus); |
| | | |
| | | return rootMenus; |
| | | } |
| | | |
| | | /** |
| | | * 转换为菜单VO |
| | | * |
| | | * @param menu 菜单实体 |
| | | * @return 菜单VO |
| | | */ |
| | | private SysMenuVO convertToMenuVO(SysMenu menu) { |
| | | SysMenuVO vo = new SysMenuVO(); |
| | | BeanUtils.copyProperties(menu, vo); |
| | | return vo; |
| | | } |
| | | |
| | | /** |
| | | * 递归排序菜单树 |
| | | * |
| | | * @param menus 菜单列表 |
| | | */ |
| | | private void sortMenuTree(List<SysMenuVO> menus) { |
| | | if (CollectionUtils.isEmpty(menus)) { |
| | | return; |
| | | } |
| | | menus.sort(Comparator.comparing(SysMenuVO::getOrderNum, Comparator.nullsLast(Comparator.naturalOrder()))); |
| | | for (SysMenuVO menu : menus) { |
| | | if (!CollectionUtils.isEmpty(menu.getChildren())) { |
| | | sortMenuTree(menu.getChildren()); |
| | | } |
| | | } |
| | | } |
| | | } |