介绍: 前端基于elementUI(el-tree组件),后端基于SpringDataJpa(递归) 的树形图
<template>
<span style="flex: 1; display: flex; align-items: center; justify-content: space-between; font-size: 14px; padding-right: 8px;display:inline-block;width:100%">
<span style="width:30%">
<span v-if="!showEdit"></span>
</span>
<span style="width:40%">
<el-input v-if="showEdit" style="width:300px" placeholder="请输入内容" size="mini" v-model='toAddLable' >
</el-input>
<i v-if="showEdit" class="el-icon-check" @click='add'></i>
</span>
<span style="width:30%">
<el-button style="font-size: 12px;" type="text" @click='append'>新增</el-button>
<el-button style="font-size: 12px;" type="text" @click='edit'>修改</el-button>
<el-button style="font-size: 12px;" type="text" @click='remove'>删除</el-button>
</span>
</span>
</template>
<script>
import concrete from '../../../api/jquery-concrete';
let SystemImpl = concrete.module("com.design.SystemUserMgmt");
export default {
name: 'mySpan',
props: {
node: Object
},
data() {
return {
showEdit: false,
toAddLable: ""
}
},
mounted: function() {
// Object.assign(o1, o2, o3);
this.showEdit = !this.node.label;
},
methods: {
append: function(e) {
this.$emit("addNode", this.node);
},
add: function(e) {
let _self=this,deptName=this.node.data.deptName;
this.node.data.deptName=this.toAddLable;
let onSuccess=(data) =>{
_self.$emit("reloadTree", this.node);
this.toAddLable = "";
this.showEdit = false;
};
if((this.node.data.deptId+"").endsWith("add")){
SystemImpl.addDept(this.node.data).success(onSuccess)
}else{
SystemImpl.modifyDept(this.node.data).success(onSuccess)
}
this.node.data.deptName=this.deptName;
},
edit: function() {
this.toAddLable = this.node.label;
this.showEdit = true;
},
remove: function(e) {
this.$emit("removeNode",this.node);
},
},
watch: {
'node' (to, from) { }
}
}
</script>
<template>
<div id="app1">
<el-tree :data="treeData" :props="defaultProps" show-checkbox node-key="id" default-expand-all :expand-on-click-node="false" :render-content="renderContent">
</el-tree>
</div>
</template>
<script>
let id = 1000;
import Vue from 'vue'
import mySpan from './MySpan.vue'
Vue.component('my-span', mySpan)//注册为全局组件
import concrete from '../../../api/jquery-concrete';
let SystemImpl = concrete.module("com.design.SystemUserMgmt");
export default {
name: 'MyTree',
data() {
return {
treeData:[],// 树的数据
defaultProps: {// 属性对应
children: 'children',
label: 'deptName',
id:'deptId'
}
}
},
methods: {
reloadTree() {// 重新加载树
let _self=this;
SystemImpl.getDeptTree().success(function(data){
_self.treeData=[];
_self.treeData.push(data);
})
},
addNode(node) {// 添加节点
const newChild = { deptId: (id++)+"add", deptName: '',department:node.data.deptId,departmentName:node.data.deptName , children: [] };
if (!node.data.children) {
node.data.children = [];
}
node.data.children.push(newChild);
},
editNode(data){
data.node.data.label=data.label;
},
removeNode(node) {//移除节点
const parent = node.parent;
const children = parent.data.children || parent.data;
const index = children.findIndex(d => d.id === node.data.id);
children.splice(index, 1);
},
renderContent(h, { node, data, store }) {
return h("my-span", {
attrs: { node: node },//添加属性
on: { //添加监控事件
addNode: this.addNode,
reloadTree:this.reloadTree
removeNode:this.removeNode,
},
});
}
},
mounted(){
this.reloadTree();
}
};
</script>
<style></style>
@Entity
@Table(name="dept_user")
public class DeptUserEntity implements Serializable {
@Id
private String deptId = Common.getUUIDStr();
private String department;
private String deptName;
// get/set ...
}
public class TreeNodeInfo extends DeptUserInfo {
private String deptId;
private String deptName;
private String department;
private String departmentName;
private List<TreeNodeInfo> children;
//get/set
}
public class DeptUserRepo extends JpaRepository<DeptUserEntity,String>, JpaSpecificationExecutor<DeptUserEntity> {
// 设定根部门标识为:deptId =department
@Query(value = "select * from dept_user where deptId =department;",nativeQuery =true )
List<DeptUserEntity> findRootDept();
}
// 获取部门信息
public TreeNodeInfo getNodeById(String nodeId, List<TreeNodeInfo> treeNodeList) {
TreeNodeInfo treeNode = new TreeNodeInfo();
for (TreeNodeInfo item : treeNodeList) {
if (item.getDeptId().equals(nodeId)) {
treeNode = item;
break;
}
}
return treeNode;
}
// 获取子部门
public List<TreeNodeInfo> getChildrenNodeById(String nodeId, List<TreeNodeInfo> treeNodeList) {
List<TreeNodeInfo> childrenTreeNode = new ArrayList<TreeNodeInfo>();
for (TreeNodeInfo item : treeNodeList) {
if (item.getDepartment().equals(nodeId)) {
childrenTreeNode.add(item);
}
}
return childrenTreeNode;
}
// 组装树
public TreeNodeInfo getDeptTreeFun(String pid, List<TreeNodeInfo> treeNodeList) {
TreeNodeInfo rootDept = this.getNodeById(pid, treeNodeList);
List<TreeNodeInfo> childrenTreeNode = this.getChildrenNodeById(pid, treeNodeList);
if (childrenTreeNode != null && childrenTreeNode.size() > 0) {
for (TreeNodeInfo item : childrenTreeNode) {
if (pid.equals(item.getDeptId())) {
continue;
}
TreeNodeInfo node = this.getDeptTreeFun(item.getDeptId(), treeNodeList);
if (rootDept.getChildren() == null) {
rootDept.setChildren(new ArrayList<TreeNodeInfo>());
}
rootDept.getChildren().add(node);
}
}
return rootDept;
}
//获取树(对外使用)
public Object getDeptTree() {
// 数据库取出所有部门实体
List<DeptUserEntity> allList = deptUserRepo.findAll();
List<TreeNodeInfo> treeNodeList = new ArrayList<TreeNodeInfo>();
// 实体转为pojo
for (DeptUserEntity entity : allList) {
TreeNodeInfo info = new TreeNodeInfo();
BeanUtils.copyProperties(entity, info);
treeNodeList.add(info);
}
// 获取根部门(应该是一个根部门)
List<DeptUserEntity> rootEntity = deptUserRepo.findRootDept();
String pid = rootEntity.get(0).getDeptId();
return (Object) getDeptTreeFun(pid, treeNodeList);
}