20251204,职级权限,开发实践分享

1、所遇问题&需求

一个职位的树结构,根节点为公司,下边分为部门,取某个子节点下,勾选的职位集合(勾选上级,意味着下级也有权限,需要返回)

比如:

知年公司

销售

运营

华北

华南

华东

江苏

南京

上海

检测

技术

车商基本信息

城市:职位树(包括下级)对应的城市列表

市场:职位树(包括下级)对应的城市,过滤出市场(有城市属性,t_car_market)列表

车商归属信息(培训师/运维职位城市)

大区:职位树(包括下级)的大区

小区:职位树(包括下级)的小区

城市:职位树(包括下级)对应的城市列表

培训师、运维:职位树(包括下级)关联的人员列表,按照角色过滤

2、如何实现

  • 获取该产品运营负责人下的全部节点ID,为集合A
  • 根据用户,获取用户关联的职位(可以一个或多个,也可以是其他其他部门的节点)。集合B
  • 找到B集合里边,全部子节点。记录为集合C
  • 集合A和集合C,相交。即在部门小有权限的职位树。集合D
  • 集合D中,指定层级为大区、小区
  • 集合D中,会关联城市,获取城市列表
  • 集合D中,会关联人员,按照角色进行过滤。获取到人员列表
  • 在城市列表的基础上,根据城市查询市场
java 复制代码
/**
 * @author QUAN XIN
 * 新的职级相关接口
 * @date 2025/12/3 13:36
 */
public interface OwnPositionV2Service {

    /**
     * 获取全部职级ID。(仅培训系统)
     * 即产品运营负责人节点下
     * @return
     */
    List<Long> getTrainer();

    /**
     * 获取全部职级列表。(仅培训系统)
     * 即产品运营负责人节点下,全部职位信息
     * @return
     */
    List<OwnPositionVO> getTrainerAllPositionIds();

    /**
     * 获取用户有权限的职级。(含全部子节点、仅培训系统)
     * @param ownUserId
     * @return
     */
    List<Long> getSubTreeByUser(Long ownUserId);

    /**
     * 获取城市id列表(仅培训系统)
     * @param ownUserId
     * @return
     */
    List<Long> getCityIds(Long ownUserId);

    /**
     * 获取城市列表。(仅培训系统)
     * @param ownUserId
     * @return
     */
    List<CommonSelectVO> getCityList(Long ownUserId);

    /**
     * 获取大区列表。(仅培训系统)
     * @param ownUserId
     * @return
     */
    List<OwnPositionVO> getAreaList(Long ownUserId);

    /**
     * 获取小区列表(仅培训系统)
     * @param ownUserId
     * @return
     */
    List<OwnPositionVO> getSmallAreaList(Long ownUserId);

    /**
     * 获取市场列表(仅培训系统)
     * @param ownUserId
     * @return
     */
    List<CommonSelectVO> getMarketList(Long ownUserId);

    /**
     * 获取用户列表(仅培训系统)
     * 职位树(包括下级)关联的人员列表,按照角色过滤
     * @param ownUserId
     * @param roleId
     * @return
     */
    List<CommonSelectVO> getOwnUserList(Long ownUserId, Integer roleId);

}

递归查询getRecursionIds,一次自循环,一个根据父节点获取全部子节点getSubTreeByParent。

而根据父节点获取子节点,一次是获取集合A;一次是获取集合C;这两处,都走了缓存来减少跟数据库的交互。如下

java 复制代码
@Override
    public List<Long> getTrainer() {
        String key = TRAINER_SYS_REDIS_KEY + TRAINER_CLASS_REDIS_KEY + "getTrainer";
        List<Long> subTree = RedisClient.get(key, () -> getTrainerAct(),
                RedisClient.hour(2));
        return subTree;
    }
java 复制代码
  @Override
    public List<Long> getSubTreeByUser(Long ownUserId) {
        String key = TRAINER_SYS_REDIS_KEY + TRAINER_CLASS_REDIS_KEY + "getSubTreeByUser." + ownUserId;
        List<Long> filterTrainer = RedisClient.get(key, () -> getSubTreeByUserAct(ownUserId),
                RedisClient.hour(2));
        return filterTrainer;
    }

3、效果如何

4、优化、建议、思考

形成文档,利人利己

递归取子节点,总不太好

是否可以通过设计上来优化,比如冗余一个字段,是path的路径。直接关联取

相关推荐
Re_zero1 天前
线上日志被清空?这段仅10行的 IO 代码里竟然藏着3个毒瘤
java·后端
洋洋技术笔记1 天前
Spring Boot条件注解详解
java·spring boot
程序员清风2 天前
程序员兼职必看:靠谱软件外包平台挑选指南与避坑清单!
java·后端·面试
皮皮林5512 天前
利用闲置 Mac 从零部署 OpenClaw 教程 !
java
华仔啊2 天前
挖到了 1 个 Java 小特性:var,用完就回不去了
java·后端
SimonKing2 天前
SpringBoot整合秘笈:让Mybatis用上Calcite,实现统一SQL查询
java·后端·程序员
日月云棠3 天前
各版本JDK对比:JDK 25 特性详解
java
用户8307196840823 天前
Spring Boot 项目中日期处理的最佳实践
java·spring boot
JavaGuide3 天前
Claude Opus 4.6 真的用不起了!我换成了国产 M2.5,实测真香!!
java·spring·ai·claude code
IT探险家3 天前
Java 基本数据类型:8 种原始类型 + 数组 + 6 个新手必踩的坑
java