当前位置: 首页 > news >正文

多级分类的实现方式

一:

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

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

树形递归查询

 

 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

    /****  生产层级编号* @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"

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

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

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

/*** 组织部门树形* @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);
}

http://www.xdnf.cn/news/470125.html

相关文章:

  • Xinference推理框架
  • 遗传算法求解旅行商问题分析
  • Python内存管理:赋值、浅拷贝与深拷贝解析
  • Mendix 连接 MySQL 数据库
  • Linux动态库热加载驱动插件机制-示例
  • 国标GB28181视频平台EasyGBS助力智慧医院打造全方位视频监控联网服务体系
  • QML元素 - MaskedBlur
  • 力扣-236.二叉树的最近公共祖先
  • Elasticsearch 常用语法手册
  • 格恩朗椭圆齿轮流量计 工业流量测量的可靠之钥
  • MySQL库的操作
  • 【笔记】CosyVoice 模型下载小记:简单易懂的两种方法对比
  • vacuum、vacuum full的使用方法及注意事项
  • “禁塑行动·我先行”环保公益项目落地宁夏,共筑绿色生活新篇章
  • 4、前后端联调文生文、文生图事件
  • 趋势跟踪策略的回测
  • AI Agent开发第67课-彻底消除RAG知识库幻觉-文档分块全技巧(1)
  • pgsql14自动创建表分区
  • SpringBoot 自动装配流程
  • [Java实战]Spring Boot 3实现 RBAC 权限控制(二十五)
  • SpringBoot项目使用POI-TL动态生成Word文档
  • 去年开发一款鸿蒙Next Os的window工具箱
  • 软考软件评测师——软件工程之系统维护
  • ADS1220高精度ADC(TI)——应用 源码
  • 采用sherpa-onnx 实现 ios语音唤起的调研
  • 每周靶点:NY-ESO-1、GPC3、IL27分享
  • Linux操作
  • Oracle APEX IR报表列宽调整
  • [ctfshow web入门] web75
  • 运维实施30-FTP服务