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.constant.I18nKeyConstant; import com.xiaopeng.account.mapper.SysGroupMapper; import com.xiaopeng.account.model.dto.SysGroupAddDTO; import com.xiaopeng.account.model.dto.SysGroupEditDTO; import com.xiaopeng.account.model.query.GroupUserPageQuery; import com.xiaopeng.account.model.query.SysGroupPageQuery; import com.xiaopeng.account.model.vo.GroupUserVO; import com.xiaopeng.account.model.vo.SysGroupDetailVO; import com.xiaopeng.account.model.vo.SysGroupPageVO; import com.xiaopeng.account.model.vo.SysMenuVO; import com.xiaopeng.account.service.ISysGroupMenuService; import com.xiaopeng.account.service.ISysGroupService; import com.xiaopeng.api.feignClient.operation.SysMenuClient; import com.xiaopeng.api.model.account.SysGroup; 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 com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.common.security.utils.SecurityUtils; 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.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.util.*; import java.util.stream.Collectors; /** *

* 权限组设置 服务实现类 *

* * @author mitao * @since 2026-02-03 */ @Slf4j @Service @RequiredArgsConstructor(onConstructor_ = @Lazy) public class SysGroupServiceImpl extends ServiceImpl implements ISysGroupService { private final ISysGroupMenuService groupMenuService; private final SysMenuClient sysMenuClient; /** * 新增权限组 * * @param dto 新增权限组请求 */ @Override @Transactional(rollbackFor = Exception.class) public void addGroup(SysGroupAddDTO dto) { // 校验组名唯一性 if (!checkGroupNameUnique(dto.getGroupName(), null)) { throw new ServiceException("权限组名称已存在", I18nKeyConstant.GROUP_NAME_EXISTS); } // 创建权限组实体 SysGroup group = BeanUtil.copyProperties(dto, SysGroup.class); group.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName()); // 保存权限组 this.save(group); // 保存菜单关联 groupMenuService.saveGroupMenus(group.getId(), dto.getMenuIds()); } /** * 编辑权限组 * * @param dto 编辑权限组请求 */ @Override @Transactional(rollbackFor = Exception.class) public void editGroup(SysGroupEditDTO dto) { // 校验权限组是否存在 SysGroup existGroup = this.getById(dto.getId()); if (existGroup == null) { throw new ServiceException("权限组不存在", I18nKeyConstant.GROUP_NOT_EXISTS); } // 校验组名唯一性(排除自身) if (!checkGroupNameUnique(dto.getGroupName(), dto.getId())) { throw new ServiceException("权限组名称已存在", I18nKeyConstant.GROUP_NAME_EXISTS); } // 更新权限组信息 existGroup.setGroupName(dto.getGroupName()); existGroup.setRemarks(dto.getRemarks()); existGroup.setGroupType(dto.getGroupType()); existGroup.setUpdateBy(SecurityUtils.getLoginUser().getSysUser().getNickName()); this.updateById(existGroup); // 删除旧的菜单关联 groupMenuService.deleteByGroupId(dto.getId()); // 保存新的菜单关联 groupMenuService.saveGroupMenus(dto.getId(), dto.getMenuIds()); } /** * 获取权限组详情(含菜单树) * * @param id 权限组ID * @return 权限组详情 */ @Override public SysGroupDetailVO getGroupDetail(Long id) { // 查询权限组基础信息 SysGroup group = this.getById(id); if (group == null) { throw new ServiceException("权限组不存在", I18nKeyConstant.GROUP_NOT_EXISTS); } SysGroupDetailVO vo = BeanUtil.toBean(group, SysGroupDetailVO.class); // 根据权限组ID获取菜单ID列表 List menuIds = groupMenuService.selectMenuIdsByGroupId(id); if (CollectionUtils.isEmpty(menuIds)) { vo.setMenus(new ArrayList<>()); return vo; } // 通过Feign调用获取菜单详情 try { R> result = sysMenuClient.getMenusByMenuIds(menuIds); if (result != null && result.getData() != null) { List menus = result.getData(); // 构建菜单树 vo.setMenus(buildMenuTree(menus)); vo.setMenuIds(menus.stream().map(SysMenu::getId).collect(Collectors.toList())); } else { vo.setMenus(new ArrayList<>()); vo.setMenuIds(new ArrayList<>()); } } catch (Exception e) { log.error("获取菜单列表失败: {}", e.getMessage()); vo.setMenus(new ArrayList<>()); } return vo; } /** * 权限组分页列表 * * @param query 分页查询参数 * @return 分页结果 */ @Override public PageInfo pageList(SysGroupPageQuery query) { // 构建查询条件 LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); if (StringUtils.isNotBlank(query.getGroupName())) { wrapper.like(SysGroup::getGroupName, query.getGroupName()); } wrapper.orderByDesc(SysGroup::getCreateTime); // 分页查询 PageInfo pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize()); PageInfo groupPage = this.page(pageInfo, wrapper); // 转换为VO PageInfo resultPage = new PageInfo<>(query.getPageNum(), query.getPageSize()); resultPage.setTotal(groupPage.getTotal()); List voList = groupPage.getRecords().stream().map(group -> { SysGroupPageVO vo = BeanUtil.copyProperties(group, SysGroupPageVO.class); // 统计绑定用户数 Long bindCount = baseMapper.countBindUsers(group.getId()); vo.setBindCount(bindCount != null ? bindCount : 0L); return vo; }).collect(Collectors.toList()); resultPage.setRecords(voList); return resultPage; } /** * 查询权限组绑定用户分页列表 * * @param query 分页查询参数 * @return 分页结果 */ @Override public PageInfo queryUserPageList(GroupUserPageQuery query) { // 校验权限组是否存在 SysGroup group = this.getById(query.getGroupId()); if (group == null) { throw new ServiceException("权限组不存在"); } // 分页查询 PageInfo pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize()); query.setGroupType(group.getGroupType()); List records = baseMapper.queryUserPageList(query); // 手动设置分页信息(因为使用了自定义SQL) pageInfo.setRecords(records); pageInfo.setTotal((long) records.size()); return pageInfo; } /** * 校验权限组名称唯一性 * * @param groupName 权限组名称 * @param excludeId 排除的权限组ID(编辑时使用) * @return true=唯一,false=不唯一 */ @Override public boolean checkGroupNameUnique(String groupName, Long excludeId) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(SysGroup::getGroupName, groupName); if (excludeId != null) { wrapper.ne(SysGroup::getId, excludeId); } return this.count(wrapper) == 0; } /** * 构建菜单树 * * @param menus 菜单列表 * @return 菜单树 */ private List buildMenuTree(List menus) { if (CollectionUtils.isEmpty(menus)) { return new ArrayList<>(); } Map menuMap = new HashMap<>(); List 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 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()); } } } }