package com.vci.ubcs.system.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.vci.ubcs.code.feign.ICodeClassifyClient; import com.vci.ubcs.starter.web.util.VciBaseUtil; import com.vci.ubcs.system.entity.ClassifyAuth; import com.vci.ubcs.system.entity.Menu; import com.vci.ubcs.system.mapper.ClassifyAuthMapper; import com.vci.ubcs.system.service.IClassifyAuthService; import com.vci.ubcs.system.service.IMenuService; import com.vci.ubcs.system.vo.ClassifyAuthVO; import com.vci.ubcs.system.vo.MenuVO; import com.vci.ubcs.system.wrapper.ClassifyAuthWrapper; import lombok.AllArgsConstructor; import org.springblade.core.log.exception.ServiceException; import org.springblade.core.secure.utils.AuthUtil; import org.springblade.core.tool.api.R; import org.springblade.core.tool.utils.Func; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; import java.util.stream.Collectors; /** * 分类授权,数据授权 * @author ludc * @date 2023/12/25 15:35 */ @Service @AllArgsConstructor public class ClassifyAuthServiceImpl extends ServiceImpl implements IClassifyAuthService { private final ClassifyAuthMapper classifyAuthMapper; private final IMenuService menuService; private final ICodeClassifyClient codeClassifyClient; /** * 分类授权保存接口 * @param classifyAuthList * @return */ @Override @Transactional(rollbackFor = Exception.class) public R submit(List classifyAuthList) { if(classifyAuthList.isEmpty()){ R.fail("授权列表不能为空!"); } // 判重,查看是否存在同一个classid下配置了相同的角色 Map roleidCounts = classifyAuthList.stream() .collect(Collectors.groupingBy(ClassifyAuth::getRoleId, Collectors.counting())); // 检查是否有roleid出现次数大于1的情况 boolean hasDuplicateRoleid = roleidCounts.values().stream() .anyMatch(count -> count > 1); if(hasDuplicateRoleid){ R.fail("角色和分类已经存在,请重新配置!"); } // 如果传过来的集合中该分类id下删除了部分角色的授权,就需要将该库中classifyId下不存在的数据删掉 List roleIds = classifyAuthList.stream().map(ClassifyAuth::getRoleId).collect(Collectors.toList()); // 删除 LambdaUpdateWrapper updateWrapper = Wrappers.update() .lambda().eq(ClassifyAuth::getClassifyId, classifyAuthList.get(0).getClassifyId()) .notIn(ClassifyAuth::getRoleId, roleIds); try { this.classifyAuthMapper.delete(updateWrapper); }catch (Exception e){ throw new ServiceException("分类授权过程中出现错误,错误原因:"+e.getMessage()); } return R.status(saveOrUpdateBatch(classifyAuthList)); } /** * 获取分类授权集合 * @param classifyAuthVO * @return */ @Override public List getClassifyAuthList(ClassifyAuthVO classifyAuthVO) { if(Func.isBlank(classifyAuthVO.getClassifyId())){ throw new ServiceException("缺少必传参数分类id"); } LambdaQueryWrapper wrapper = Wrappers.query() .lambda().eq(ClassifyAuth::getClassifyId,classifyAuthVO.getClassifyId()) .eq(ClassifyAuth::getAuthType,classifyAuthVO.getAuthType()); List classifyAuths = this.classifyAuthMapper.selectList(wrapper); if(classifyAuths.isEmpty()){ return new ArrayList(); } return ClassifyAuthWrapper.build().listVO(classifyAuths); } /** * 查询该分类下,当前登录的角色有哪些按钮权限 * @param classifyId * @param menuCode * @param authType * @return */ public Map getAuthButtonList(String classifyId,String menuCode,String authType){ List menuList = this.getButtonList(classifyId, menuCode, authType); if(menuList.isEmpty()){ return new HashMap<>(); } Map buttonMaps = menuList.stream() .collect(Collectors.toMap(Menu::getCode, menu -> true)); return buttonMaps; } /** * 查询该主数据下,当前登录的角色有哪些按钮菜单权限 * @param classifyId * @param menuCode * @param authType * @return */ public List getAuthMenuButtonList(String classifyId,String menuCode,String authType){ List buttonList = getButtonList(classifyId, menuCode, authType); return buttonList; } private List getButtonList(String classifyId,String menuCode,String authType){ if(Func.isBlank(classifyId)){ throw new ServiceException("必传参数分类oid不能为空!"); } //查询分类节点的所有父级节点 R> listR = codeClassifyClient.selectAllParentOid(classifyId); if (!listR.isSuccess() && !listR.getData().isEmpty()) { throw new ServiceException("获取分类信息失败!"); } // 返回的分类oid是当前节点为第一个,后面依次是他的上层节点 List classifyOidList = listR.getData(); final String roleIds = AuthUtil.getUser().getRoleId(); // 先查询按钮id列表 LambdaQueryWrapper wrapper = Wrappers.query() .lambda().eq(ClassifyAuth::getClassifyId, classifyId) .eq(ClassifyAuth::getAuthType,authType) .in(ClassifyAuth::getRoleId, roleIds); List classifyAuths = this.classifyAuthMapper.selectList(wrapper); //如果当前分类没有找到授权配置,就依次从当前节点往上层节点找授权配置,找到了就停止,没找到就一直找到最后 if(classifyAuths.isEmpty()){ // 下标从1开始因为当前节点0已经查询过 for (int i = 1; i < classifyOidList.size(); i++) { classifyAuths = this.classifyAuthMapper.selectList( Wrappers.query() .lambda().eq(ClassifyAuth::getClassifyId, classifyOidList.get(i)) .in(ClassifyAuth::getRoleId, roleIds) ); if(!classifyAuths.isEmpty()){ break; } } } //出现了错误数据,同一个角色和同一个分类id存在多条授权记录 if(classifyAuths.size()>1){ throw new ServiceException("角色和分类配置存在多条记录,请联系管理人员清理错误配置!"); } // 是否为超管 Boolean isAdmin = VciBaseUtil.checkAdminTenant(); // 未配置按钮权限 if(!isAdmin && (classifyAuths.isEmpty() || Func.isBlank(classifyAuths.get(0).getButtonIds()))){ return new ArrayList<>(); } List ids = new ArrayList<>(); // 如果不是超管用户 if(!isAdmin){ ids.addAll(Arrays.asList(classifyAuths.get(0).getButtonIds().split(","))); } return menuService.getMenuListByCode(ids,menuCode,roleIds); } /** * 根据角色id查看有哪些分类具备查看权限 * @param roleIds * @return */ @Override public List getViewClassByRoleIds(List roleIds,String authType,String menuCode) { if(roleIds.isEmpty()){ return new ArrayList<>(); } return this.classifyAuthMapper.getViewClassByRoleIds(roleIds, authType,menuCode); } }