若依部门树状图的实现
1、数据库表
2、具体的实现代码
先找到这个接口
/**
* 查询部门树结构信息
*
* @param dept 部门信息
* @return 部门树信息集合
*/
public List<TreeSelect> selectDeptTreeList(SysDept dept);
然后我们进入他具体的实现类,如下代码
/**
* 查询部门树结构信息
*
* @param dept 部门信息
* @return 部门树信息集合
*/
@Override
public List<TreeSelect> selectDeptTreeList(SysDept dept)
{
List<SysDept> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);
return buildDeptTreeSelect(depts);
}
框选的代码它是去查询了所有的部门信息然后存进去一个list里面
进入maaper层查询,就可以查询到所有的部门信息
<select id="selectDeptList" parameterType="SysDept" resultMap="SysDeptResult">
<include refid="selectDeptVo"/>
where d.del_flag = '0'
<if test="deptId != null and deptId != 0">
AND dept_id = #{deptId}
</if>
<if test="parentId != null and parentId != 0">
AND parent_id = #{parentId}
</if>
<if test="deptName != null and deptName != ''">
AND dept_name like concat('%', #{deptName}, '%')
</if>
<if test="status != null and status != ''">
AND status = #{status}
</if>
<!-- 数据范围过滤 -->
${params.dataScope}
order by d.parent_id, d.order_num
</select>
就可以获取到所有的部门信息,然后去构建树结构
进入上图框选的buildDeptTreeSelect方法里面,在进入buildDeptTree方法里查看树的构建,它参数传的是我们刚才查询的所有部门的信息
/**
* 构建前端所需要下拉树结构
*
* @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());
}
进入我们可以看到构建前端树结构的方法,首先它把所有部门里面的部门编号遍历出来存入一个tempList的集合里面,然后去遍历我们刚才传进来部门信息,它去获取了tempList集合里面的部门编号是否包含了部门集合(depts 传进来的参数集合)的父节点编号,如果不包含的话,那他肯定是顶级节点,那就遍历该父节点的所有子节点
/**
* 构建前端所需要树结构
*
* @param depts 部门列表
* @return 树结构列表
*/
@Override
public List<SysDept> buildDeptTree(List<SysDept> depts)
{
List<SysDept> returnList = new ArrayList<SysDept>();
List<Long> tempList = depts.stream().map(SysDept::getDeptId).collect(Collectors.toList());
for (SysDept dept : depts)
{
// 如果是顶级节点, 遍历该父节点的所有子节点
if (!tempList.contains(dept.getParentId()))
{
recursionFn(depts, dept);
returnList.add(dept);
}
}
if (returnList.isEmpty())
{
returnList = depts;
}
return returnList;
}
我们进入recursionFn方法里面,参数传的是部门的集合和部门
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方法里去查看,如下,主要代码为下面红色框框选的代码,它是用迭代器去遍历这个集合,一直去获取下个节点,条件是当它的父节点和子节点相等的情况下,把这个部门加进去部门对象的子部门里面,也就是集合tlist,一直找直到没有然后退出循环
/**
* 得到子节点列表
*/
private List<SysDept> getChildList(List<SysDept> list, SysDept t)
{
List<SysDept> tlist = new ArrayList<SysDept>();
Iterator<SysDept> it = list.iterator();
while (it.hasNext())
{
SysDept n = (SysDept) it.next();
if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getDeptId().longValue())
{
tlist.add(n);
}
}
return tlist;
}
返回回去一个子节点列表的集合,到下图方法这里,然后把它刚才子节点列表的集合set进去部门里面,再去遍历它的子节点
用hasChild方法再去做判断,跟进去方法看一下,如下,它又去调用了我们刚才的那个getChildList的方法去找有没有子节点的列表,如果有那他的集合就是大于0,也就是返回true,到我们的recursionFn的方法中,然后是true的话它又会去再次调用recursionFn这个方法,把子节点的集合传进去,实现了递归,这样就能把所有的部门信息查出来,然后实现树状结构
/**
* 判断是否有子节点
*/
private boolean hasChild(List<SysDept> list, SysDept t)
{
return getChildList(list, t).size() > 0;
}
最后,在遍历放进去 TreeSelect里面,返回给前端就实现了这个功能
可以看到他用stream流,存进去这个树结构的实体类里面,在这里面看到下面这个构造函数,id是的等于部门的id,label节点名称等于部门的部门名字,孩子节点就再去用stream流存进去这个属结构里面
/**
* Treeselect树结构实体类
*
* @author ruoyi
*/
public class TreeSelect implements Serializable
{
private static final long serialVersionUID = 1L;
/** 节点ID */
private Long id;
/** 节点名称 */
private String label;
/** 子节点 */
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<TreeSelect> children;
public TreeSelect(SysDept dept)
{
this.id = dept.getDeptId();
this.label = dept.getDeptName();
this.children=dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
}
总结
1、先查询除所有的部门放在一个集合List里面,再去new一个returnList存放顶级部门数据
2、再拿一个tempList取出集合里面所有部门的ID
3、遍历这个所有部门的集合,遍历的过程中判断每个部门的父节点有没有包含tempList的部门ID
3.1.如果没有包含的话,那这个部门就肯定是顶级节点,就应该去遍历该顶级节点下的所有节点
3.1.1.先获取该节点下的子节点列表,先new除一个tlist去存放子节点的数据,然后用迭代器Iterator去遍历传进来的list集合,如果这个部门对象的父节点不为空并且它父节点的id等于这个部门的id,那这个部门就是这个传进来部门的子部门,把他存进去list里面,在返回存放子节点的list
3.1.2.在把返回的子节点的list存进去这个部门对象的children孩子属性里面
3.1.3.再去遍历这个返回的子节点列表,判断他有没有孩子,判断的步骤里面其实还是再去执行了一次getChildList这个方法,去判断返回来的孩子节点的size有没有大于0,大于0肯定就是有孩子,就再去递归recursionFn这个方法,以此类推
3.2.如果有包含的话,那就不用做处理
4.再去判断这个returnList是不是为空
4.1.如果为空的话,那就直接就是传进来的部门数据
4.2.如果不为空的话直接把returnList返回出去就好了
5、最后用stream流把对象变成树结构返回出去就可以了