puzhibing
2026-02-04 85bafa86f44fbe6646019fd8ecbab79f552ccd0a
xp-service/xp-account/src/main/java/com/xiaopeng/account/service/impl/SysRoleServiceImpl.java
@@ -1,18 +1,35 @@
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>
@@ -22,11 +39,16 @@
 * @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
@@ -70,4 +92,244 @@
        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());
            }
        }
    }
}