多级分类的实现方式

一:

字段里有一个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);
}
相关推荐
Byron Loong13 小时前
【调试】Dump 文件分析的完整流程
windows
Geoking.15 小时前
VSCode 安装 Claude Code 插件 + ccswitch 配置 DeepSeek API 完整教程(Windows 新手向)
ide·windows·vscode
潘达斯奈基~16 小时前
Windows 下 Claude Code使用 Agent Teams 配置教程
windows
happymaker062619 小时前
Spring框架学习日记——DAY02(依赖注入的方式)
windows
honder试试19 小时前
Elasticsearch(es)在Windows系统上的安装与部署(含Kibana)
windows·elasticsearch·jenkins
IT里的交易员20 小时前
【系统】Windows 安装 uv
windows·uv
我不是立达刘宁宇1 天前
windows密码操作
windows
Royzst1 天前
一、集合概述(前置基础)
开发语言·windows·python
时光追逐者1 天前
一款基于 C# 开发的 Windows 10/11 系统增强工具,精简、优化、定制一站完成!
开发语言·windows·c#·.net
liuhuizuikeai1 天前
菜品抽奖活动MFC+服务端
c++·windows·mfc