背景
项目中有一个需求是创建一些树状多层级的目录,这些目录为了方便还要支持随时可编辑顺序。技术选型上,使用了ElementUI的可拖拽节点树即可实现拖拽节点编辑,技术难度是在后端对拖拽后的顺序重排序持久化上。
设计思路
- 添加节点,默认排序位置为最后
- 删除节点,删除父节点时连带子节点一并删除,并且要对已有树排序进行重排序
- 获取数据时,需要将数据拼装成树
- 更新节点,除了更新名字好像没啥要更新了
- 拖拽时对变动的位置进行上移或下移,原理是变动排序数字,可放到更新节点里一起做,但我建议这个单独写一个方法,单一职责
详细设计
约定
- 根节点的parentId为0;
- 排序号由小到大;
- 新建时排序号为父节点下最大的排序;
- 前端会传输Node节点信息到后端
实体类Node
这是最基本的节点要素,数据库中也要创建与之对应的字段。
@Data
public class Node {
private Integer id; // 主键
private Integer parentId; // 父节点
private Integer sort; // 排序
}
添加节点
添加节点需要获得新建节点在所在父节点下的最大排序值,根节点是parentId为0的节点
public void addNode(Node node) {
node.setSort(getMaxSortFromParentId(node.getParentId()) + 1);
nodeService.addNode(node);
}
public int getMaxSortFromParentId(Integer parentId) {
// select count(1) from node where parent_id = #{parentId}
....
}
删除节点
删除节点需要考虑的是,删除之后,原先节点下面的节点排序号要 - 1。若删除父节点,其子节点是删除或者放置外层。这里只做排序号更新操作。不考虑子节点的问题,但这是不合规的,实际开发中一定要处理这个问题。
public void deleteNode(Node node) {
// 1. 直接删除节点
nodeService.removeById(node.getId());