部门树状图的实现

部门架构图生成器 部门框架图_开发语言


点击用户管理,观察网络活动大概可以猜出treeselect应该是该方法,根据请求url:http://localhost/dev-api/system/dept/treeselect

可以找到对应的controller

/**
     * 获取部门下拉树列表
     */
    @GetMapping("/treeselect")
    public AjaxResult treeselect(SysDept dept)
    {
        List<SysDept> depts = deptService.selectDeptList(dept);
        return AjaxResult.success(deptService.buildDeptTreeSelect(depts));
    }

这里的参数其实是做摆设的,因为在测试的时候,这个参数为null,depts也是直接查出所有的部门信息。

部门架构图生成器 部门框架图_java_02


然后就把封装好的部门信息集合封装成树的结构,

deptService.buildDeptTreeSelect(depts)

点击进去看它的实现方法

/**
     * 构建前端所需要下拉树结构
     * 
     * @param depts 部门列表
     * @return 下拉树结构列表
     */
    @Override
    public List<TreeSelect> buildDeptTreeSelect(List<SysDept> depts)
    {
        List<SysDept> deptTrees = buildDeptTree(depts);
        return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

点击buildDeptTree()方法看实现

/**
     * 构建前端所需要树结构
     * 
     * @param depts 部门列表
     * @return 树结构列表
     */
    @Override
    public List<SysDept> buildDeptTree(List<SysDept> depts)
    {
        List<SysDept> returnList = new ArrayList<SysDept>();
        List<Long> tempList = new ArrayList<Long>();
        for (SysDept dept : depts)
        {
            tempList.add(dept.getDeptId());
        }
        for (Iterator<SysDept> iterator = depts.iterator(); iterator.hasNext();)
        {
            SysDept dept = (SysDept) iterator.next();
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(dept.getParentId()))
            {
                recursionFn(depts, dept);
                returnList.add(dept);
            }
        }
        if (returnList.isEmpty())
        {
            returnList = depts;
        }
        return returnList;
    }

该方法主要是把部门信息集合封装成类似树的几层结构。
首先将部门信息集合retrunList的部门id提取出来放入tempList中,通过遍历所有部门信息,在该集合用List的contains()方法来判断是否是顶级节点,List的contains()作用是如果List中至少有一个目标元素则返回true,很明显顶级结点的父id是不在部门id集合tempList中,所以就进入了recursionFn()递归方法。

我们来看下递归方法的实现

/**
     * 递归列表
     */
    private void recursionFn(List<SysDept> list, SysDept t)
    {
        // 得到子节点列表
        List<SysDept> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysDept tChild : childList)
        {
            if (hasChild(list, tChild))
            {
                recursionFn(list, tChild);
            }
        }
    }

这里方法和上一节的菜单集合处理逻辑很相似,也是先帮当前部门找子部门集合,在getChildList()方法中,会遍历所有部门信息与当前部门是否有父子关系,如果有,则加入子列表,直到找到所有对应的子部门并封装成childList ,然后在这个childList 中,又找下是否还有子部门,如果有则继续递归。
就这样从下往上封装成树。

总结思路:和上节一样,先收集完所有部门信息,再通过逻辑处理成树结构。
先找到顶级部门,让顶级部门进入递归找属于它的子部门,子部门集合在递归方法中再次递归,找属于子部门的子部门,最后从下往上返回结果,就封装成树。

回到buildDeptTreeSelect()方法中,

deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList());

将deptTrees转换成流,然后map(),参数为要转换的实体类,其中new为对应类构造方法将里面的元素转换成TreeSelect树结构实体类,最后返回给Controller层的AjaxResult的data域中,然后返回AjaxResult给前端。