package cn.iocoder.yudao.module.crm.util; import cn.hutool.core.collection.CollUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.biz.system.permission.PermissionCommonApi; import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.github.yulichang.autoconfigure.MybatisPlusJoinProperties; import com.github.yulichang.wrapper.MPJLambdaWrapper; import java.util.List; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; /** * 数据权限工具类 * * @author HUIHUI */ public class CrmPermissionUtils { /** * 校验用户是否是 CRM 管理员 * * @return 是/否 */ public static boolean isCrmAdmin() { PermissionCommonApi permissionApi = SpringUtil.getBean(PermissionCommonApi.class); return permissionApi.hasAnyRoles(getLoginUserId(), RoleCodeEnum.CRM_ADMIN.getCode()); } /** * 构造 CRM 数据类型数据【分页】查询条件 * * @param query 连表查询对象 * @param bizType 数据类型 {@link CrmBizTypeEnum} * @param bizId 数据编号 * @param userId 用户编号 * @param sceneType 场景类型 */ public static , S> void appendPermissionCondition(T query, Integer bizType, SFunction bizId, Long userId, Integer sceneType) { MybatisPlusJoinProperties mybatisPlusJoinProperties = SpringUtil.getBean(MybatisPlusJoinProperties.class); final String ownerUserIdField = mybatisPlusJoinProperties.getTableAlias() + ".owner_user_id"; // 场景一:我负责的数据 if (CrmSceneTypeEnum.isOwner(sceneType)) { query.eq(ownerUserIdField, userId); } // 场景二:我参与的数据(我有读或写权限,并且不是负责人) if (CrmSceneTypeEnum.isInvolved(sceneType)) { if (CrmPermissionUtils.isCrmAdmin()) { // 特殊逻辑:如果是超管,直接查询所有,不过滤数据权限 return; } // 商机特殊处理:同时关联商机团队和客户团队的权限 if (CrmBizTypeEnum.CRM_BUSINESS.getType().equals(bizType)) { appendBusinessPermissionCondition(query, bizId, userId, ownerUserIdField); } else { query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType) .eq(CrmPermissionDO::getBizId, bizId) .in(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.READ.getLevel(), CrmPermissionLevelEnum.WRITE.getLevel()) .eq(CrmPermissionDO::getUserId, userId)); query.ne(ownerUserIdField, userId); } } // 场景三:下属负责的数据(下属是负责人) if (CrmSceneTypeEnum.isSubordinate(sceneType)) { AdminUserApi adminUserApi = SpringUtil.getBean(AdminUserApi.class); List subordinateUsers = adminUserApi.getUserListBySubordinate(userId); if (CollUtil.isEmpty(subordinateUsers)) { query.eq(ownerUserIdField, -1); // 不返回任何结果 } else { query.in(ownerUserIdField, convertSet(subordinateUsers, AdminUserRespDTO::getId)); } } } /** * 商机特殊权限条件:同时关联商机团队和客户团队的权限 * 商机继承客户团队的权限,即客户团队成员也能看到该客户下的商机 */ private static , S> void appendBusinessPermissionCondition(T query, SFunction bizId, Long userId, String ownerUserIdField) { // 使用子查询方式:商机团队成员 OR 客户团队成员 // 子查询1:商机团队成员权限 String subQuery1 = "(SELECT p1.biz_id FROM crm_permission p1 " + "WHERE p1.biz_type = " + CrmBizTypeEnum.CRM_BUSINESS.getType() + " " + "AND p1.level IN (" + CrmPermissionLevelEnum.READ.getLevel() + "," + CrmPermissionLevelEnum.WRITE.getLevel() + ") " + "AND p1.user_id = " + userId + ")"; // 子查询2:客户团队成员权限(通过商机的 customer_id 关联) String subQuery2 = "(SELECT b.id FROM crm_business b " + "INNER JOIN crm_permission p2 ON p2.biz_type = " + CrmBizTypeEnum.CRM_CUSTOMER.getType() + " " + "AND p2.biz_id = b.customer_id " + "AND p2.level IN (" + CrmPermissionLevelEnum.READ.getLevel() + "," + CrmPermissionLevelEnum.WRITE.getLevel() + ") " + "AND p2.user_id = " + userId + ")"; // 使用 OR 连接两个子查询,并排除自己是负责人的情况 query.apply("t.id IN (" + subQuery1 + " UNION " + subQuery2 + ")") .ne(ownerUserIdField, userId); } }