package com.xiaopeng.account.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.DesensitizedUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 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.account.service.ISysRoleService; import com.xiaopeng.api.feignClient.operation.SysMenuClient; import com.xiaopeng.api.model.account.SysGroup; import com.xiaopeng.api.model.account.SysRole; import com.xiaopeng.api.model.account.SysUser; 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.SensitiveDataCryptoUtil; import com.xiaopeng.common.core.utils.StringUtils; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.common.security.service.TokenService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.shardingsphere.transaction.annotation.ShardingSphereTransactionType; import org.apache.shardingsphere.transaction.core.TransactionType; 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 javax.annotation.Resource; 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; @Resource private final SysMenuClient sysMenuClient; private final ISysRoleService sysRoleService; @Resource private TokenService tokenService; /** * 新增权限组 * * @param dto 新增权限组请求 */ @Override @Transactional public void addGroup(SysGroupAddDTO dto) { // 校验组名唯一性 if (!checkGroupNameUnique(dto.getGroupName(), null)) { throw new ServiceException("权限组名称已存在", I18nKeyConstant.GROUP_NAME_EXISTS); } // 创建权限组实体 SysGroup group = BeanUtil.copyProperties(dto, SysGroup.class); // 保存权限组 this.save(group); // 保存菜单关联 groupMenuService.saveGroupMenus(group.getId(), dto.getMenuIds()); } /** * 编辑权限组 * * @param dto 编辑权限组请求 */ @Override @Transactional 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()); 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()); query.setPhoneNumberQueryValues(SensitiveDataCryptoUtil.queryValues(query.getPhoneNumber())); Page records = baseMapper.queryUserPageList(pageInfo, query); records.getRecords().forEach(record -> { record.setPhoneNumber(SensitiveDataCryptoUtil.decryptIfPossible(record.getPhoneNumber())); record.setUserAccount(SensitiveDataCryptoUtil.decryptIfPossible(record.getUserAccount())); }); pageInfo.setRecords(records.getRecords()); // 手动设置分页信息(因为使用了自定义SQL) 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()); } } } /** * 删除权限组 * @param id */ @Override public void deleteById(Long id) { Long count = sysRoleService.lambdaQuery().eq(SysRole::getGroupId, id).count(); if (count > 0) { throw new ServiceException("删除失败,该权限组已关联角色", I18nKeyConstant.SYS_GROUP_DELETE_FAIL); } removeById(id); } /** * 获取手机号脱敏 * @param phoneNumber * @return */ @Override public String getPhoneDesensitization(String phoneNumber){ boolean b = getPhoneDesensitization(); if(b){ return DesensitizedUtil.mobilePhone(phoneNumber); } return phoneNumber; } /** * 获取登录用户的权限组,获取权限组的手机号是否脱敏的字段 * true 需要脱敏,false 否 * @return */ @Override public boolean getPhoneDesensitization(){ try { SysUser sysUser = tokenService.getLoginUser().getSysUser(); //用户查询角色 角色查询 权限组 int count = baseMapper.getPhoneDesensitization(sysUser.getId()); return count > 0; } catch (Exception e) { return false; } } }