多级分类的实现方式

一:

字段里有一个parentId,0代表顶级,1是二级,2是三级

查一级分类,在实体类(对标数据库的表)添加一个对象,添加注解,因为这个对象在数据库不存在这个字段。

树形递归查询

java 复制代码
 public List<CategoryEntity> listWithTree() {
        //查出所有分类
        List<CategoryEntity>entities=baseMapper.selectList(null);
        //组装成父子树形结构
        //2.1)、找到所有一级分类
        List<CategoryEntity> levelMenus = entities.stream()
                .filter(e -> e.getParentCid() == 0)
                .map((menu) -> {
                    menu.setChildren(getChildrens(menu, entities));
                    return menu;
                })
                .sorted((menu, menu2) -> {
                    return (menu.getSort() == null ? 0 : menu.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
                })
                .collect(Collectors.toList());

        return levelMenus;
    }
    //递归查找所有菜单的子菜单
    private List<CategoryEntity> getChildrens(CategoryEntity root, List<CategoryEntity> all) {

        List<CategoryEntity> children = all.stream().filter(categoryEntity -> {
            return categoryEntity.getParentCid().equals(root.getCatId());
        }).map(categoryEntity -> {
            //1、找到子菜单(递归)
            categoryEntity.setChildren(getChildrens(categoryEntity, all));
            return categoryEntity;
        }).sorted((menu, menu2) -> {
            //2、菜单的排序
            return (menu.getSort() == null ? 0 : menu.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
        }).collect(Collectors.toList());

        return children;

    }

setchildren是往新增属性list里添加,所以才会有一级嵌套二级嵌套三级

二:

部门有多级部门,比如父部门,子部门

表中parent_dept_no和dept_no是用于构建树形结构的基础,通过这2个字段定义资源的上下级关系,通常添加部门,我们通过程序自动生成编号,生成的编号满足以下规则:

  • 1级:100000000000000

  • 2级:100001000000000

  • 3级:100001001000000

  • 4级:100001001001000

  • 5级:100001001001001

当我们在需要查询当前1级节点以下所有节点时,就不用再递归查询,使用like "dept_no%"即可。

举个例子:

想要查询100001001000000下所有的部门,我们的查询方式为:

复制代码
select * from sys_dept where dept_no like '100001001%'

这样就可以查询到100001001000000部门下所有的部门了

我的疑问:同级的不同部门怎么区分?

//构建部门编号,有两种情况,当前父部门编号,有子部门:在已有的子部门的基础上累加 | 没有子部门:新增子部门编号

DeptDto deptDto = DeptDto.builder().parentDeptNo(parentDeptNo).build();

List<DeptVo> deptVoList = deptMapper.selectList(deptDto);

//无下属节点则创建下属节点

if(EmptyUtil.isNullOrEmpty(deptVoList)){

return NoProcessing.createNo(parentDeptNo,false);

}else {

//有下属节点则累加下属节点

Long deptNo = deptVoList.stream().map(dept -> {

return Long.valueOf(dept.getDeptNo());

}).max(Comparator.comparing(i -> i)).get();

return NoProcessing.createNo(String.valueOf(deptNo),true);

}

即当前要创建节点的父节点经过我们查询有别的子节点,我们就累加,即找到子节点的最大一个序号,然后在下面创建序列号的逻辑里累加

比如:100001002000000,累加以后变成100001003000000

java 复制代码
    /***
     *  生产层级编号
     * @param input 输入编号
     * @param peerNode 是否下属节点
     * @return
     * @return: java.lang.String
     */
    public static String createNo(String input,boolean peerNode) {
        int step = input.length() / 3;
        int supplement = 0;
        for (int i =0;i<step;i++ ){
            String targetString = input.substring(input.length()-3,input.length());
            if ("000".equals(targetString)){
                input = input.substring(0,input.length()-3);
                supplement++;
            }else {
                break;
            }
        }
        if (peerNode){
            input = String.valueOf(Long.valueOf(input) + 1L);
            for (int i =0;i<supplement;i++ ){
                input = input+"000";
            }
        }else {
            input = String.valueOf(Long.valueOf(input+"001"));
            for (int i =0;i<supplement-1;i++ ){
                input = input+"000";
            }
        }
        return input;
    }
第一部分:处理尾部连续的"000"
  1. 计算步长step = input.length() / 3 计算出可以检查多少个三字符子串。
  2. 循环检查尾部 :从输入字符串的末尾开始,每次取最后三个字符进行检查。
    • 如果这三个字符是 "000",则将它们移除,并增加 supplement 计数器。
    • 如果不是 "000",则停止检查。
第二部分:根据 peerNode 标志调整编号
  • 如果 peerNodetrue

    • 将剩余的 input 转换为长整型并加 1。
    • 然后根据之前记录的 supplement 数量,向结果中追加相应数量的 "000"
  • 如果 peerNodefalse

    • 首先在 input 后面追加 "001",然后转换为长整型。
    • 接着根据 supplement - 1 的值,向结果中追加相应数量的 "000"

这样可以跟方便的查某一部门的子部门列表

还有一种需求就是查整个部门的树形结构

也是先查所有的,再通过所有的·慢慢拼出树形

java 复制代码
/**
     * 组织部门树形
     * @return
     */
@Override
public TreeVo deptTreeVo() {
    //获取根节点树形
    String parentDeptNo = SuperConstant.ROOT_DEPT_PARENT_ID;

    //构建查询条件
    DeptDto param = DeptDto.builder()
        .dataState(SuperConstant.DATA_STATE_0)
        .parentDeptNo(NoProcessing.processString(parentDeptNo))
        .build();
    //查询部门列表数据
    List<DeptVo> deptList =  deptMapper.selectList(param);

    if(EmptyUtil.isNullOrEmpty(deptList)){
        throw new BaseException("部门数据没有定义");
    }

    //找根节点
    DeptVo rootDept = deptList.stream().filter(d -> SuperConstant.ROOT_DEPT_PARENT_ID.equals(d.getParentDeptNo())).collect(Collectors.toList()).get(0);

    //返回的部门数据
    List<TreeItemVo> treeItemVoList = new ArrayList<>();

    //递归调用
    recursionTreeItem(treeItemVoList,rootDept,deptList);

    return TreeVo.builder().items(treeItemVoList).build();
}

/**
     * 递归调用拼装数据
     * @param treeItemVoList  封装返回的数据
     * @param rootDept  当前部门
     * @param deptList  部门列表(全部数据)
     */
private void recursionTreeItem(List<TreeItemVo> treeItemVoList, DeptVo rootDept, List<DeptVo> deptList) {
    //构建item对象
    TreeItemVo treeItemVo = TreeItemVo.builder().id(rootDept.getDeptNo()).label(rootDept.getDeptName()).build();
    //获得当前部门下的子部门
    List<DeptVo> childrenDept = deptList.stream()
        .filter(n -> n.getParentDeptNo().equals(rootDept.getDeptNo()))
        .collect(Collectors.toList());
    //如果子部门不为空,则继续递归调用
    if(!EmptyUtil.isNullOrEmpty(childrenDept)){

        ArrayList<TreeItemVo> listChildren = Lists.newArrayList();
        //子部门列表
        childrenDept.forEach(dept -> {
            this.recursionTreeItem(listChildren,dept,deptList);
        });
        treeItemVo.setChildren(listChildren);
    }

    treeItemVoList.add(treeItemVo);
}
相关推荐
开开心心就好11 小时前
仅168KB的桌面图标自动隐藏工具
windows·计算机视觉·计算机外设·excel·启发式算法·宽度优先·csdn开发云
怪兽软家14 小时前
DaVinci Resolve/达芬奇 20安装教程及下载
windows·经验分享·生活
chao18984414 小时前
完整MES系统实现 (C# 客户端服务器)
服务器·windows·c#
Hello_Embed15 小时前
Windows 安装 Claude Code 并接入 模型
windows·笔记·ai编程
Muyuan199816 小时前
28.Paper RAG Agent 开发记录:修复 LLM Rerank 的解析、Fallback 与可验证性
linux·人工智能·windows·python·django·fastapi
AxureMost17 小时前
4DDiG DLL Fixe 1.0.8.2 系统DLL修复工具
windows
怣疯knight19 小时前
Windows不安装 Android Studio如何打包安卓软件
android·windows·android studio
空中海20 小时前
02. 静态逆向、Manifest 分析与 Smali 重打包
服务器·网络·windows
一拳一个娘娘腔20 小时前
告别图形化界面:基于CLI的Windows系统入侵排查与防御实战手册
windows·安全
疋瓞21 小时前
批处理_基础补充、文件和文件夹处理_02
windows