目录
- 先看一下显示的效果图
- 案例对应的实体类Dept
- 完整代码如下
树形结构在实际开发中很长用到,比如部门管理,权限菜单等。因为用树形结构来展示会显的很清晰明了。
最近写了一个个人博客小项目中用到了LayUI的树形结构,之后写了一个小案例整理一下。
先看一下显示的效果图
点击节点右面会显示对应部门的详情信息,可以修改。可以自定义按钮添加部门,也可以直接用自带的方法对部门进行新增,修改和删除。可以获取选中的节点,根据项目需求(有的需要选中保存)。
先需要引入LayUI的样式文件JS和CSS。
案例对应的实体类Dept
public class Dept { | |
private Integer id; | |
private String name; //部门名称 | |
private String deptName; //部门负责人 | |
private String phone; //电话号 | |
private String number; //编号 | |
private double idx; //排序 | |
private Dept parent; | |
private List<Dept> children = new ArrayList<>(); | |
public Integer getId() { | |
return id; | |
} | |
public void setId(Integer id) { | |
this.id = id; | |
} | |
public String getName() { | |
return name; | |
} | |
public void setName(String name) { | |
this.name = name; | |
} | |
public String getDeptName() { | |
return deptName; | |
} | |
public void setDeptName(String deptName) { | |
this.deptName = deptName; | |
} | |
public String getPhone() { | |
return phone; | |
} | |
public void setPhone(String phone) { | |
this.phone = phone; | |
} | |
public String getNumber() { | |
return number; | |
} | |
public void setNumber(String number) { | |
this.number = number; | |
} | |
public double getIdx() { | |
return idx; | |
} | |
public void setIdx(double idx) { | |
this.idx = idx; | |
} | |
public Dept getParent() { | |
return parent; | |
} | |
public void setParent(Dept parent) { | |
this.parent = parent; | |
} | |
CascadeType.ALL,mappedBy="parent") | (cascade=|
"idx") | (value=|
public List<Dept> getChildren() { | |
return children; | |
} | |
public void setChildren(List<Dept> children) { | |
this.children = children; | |
} | |
public Dept(Integer id, String name, String deptName, String phone, String number, double idx, Dept parent, List<Dept> children) { | |
this.id = id; | |
this.name = name; | |
this.deptName = deptName; | |
this.phone = phone; | |
this.number = number; | |
this.idx = idx; | |
this.parent = parent; | |
this.children = children; | |
} | |
public Dept(Integer id) { | |
this.id = id; | |
} | |
public Dept() { | |
} | |
} |
显示LayUI树形菜单,只需要一个标签容器即可。
<div id="dept_tree"> | |
</div> |
在案例中还有一些其他样式,比如右边的详情信息,新增按钮等。
完整代码如下
<style type="text/css"> | |
#dept_main, #dept_particulars{ | |
width: 48.5%; | |
display: inline-block; | |
vertical-align: top; | |
padding: 20px; | |
background: white; | |
box-sizing: border-box; | |
} | |
#dept_tree{ | |
margin-top: 20px; | |
} | |
</style> | |
<div id="dept_main" style="margin-right: 2%;"> | |
<fieldset class="layui-elem-field layui-field-title"> | |
<legend>所有部门</legend> | |
</fieldset> | |
<button class="layui-btn layui-btn-sm layui-btn-radius layui-btn-normal" lay-demo="addDept"><i class="layui-icon"></i>添加部门</button> | |
<button class="layui-btn layui-btn-sm layui-btn-radius layui-btn-normal" lay-demo="gain">获取选中节点</button> | |
<div id="dept_tree"> | |
</div> | |
</div> | |
<div id="dept_particulars"> | |
<fieldset class="layui-elem-field layui-field-title"> | |
<legend>部门详情</legend> | |
</fieldset> | |
<div id="dept_home"> | |
<div class="layui-tree-emptyText">无数据</div> | |
</div> | |
</div> |
JS请求数据渲染页面代码,data为请求数据源,当时直接放入的请求链接,好像不行,所以之后才写了一个方法去请求数据源。
layui.use(['tree', 'util'], function() { | |
var tree = layui.tree; | |
var util = layui.util; | |
tree.render({ | |
elem: '#dept_tree', | |
data: getData(), | |
id: 'treeId', | |
showCheckbox: true, //是否显示复选框 | |
onlyIconControl: true | |
}); | |
}); | |
function getData(){ | |
var data = []; | |
$.ajax({ | |
url: "dept/treeload", //后台数据请求地址 | |
type: "post", | |
async:false, | |
success: function(resut){ | |
data = resut; | |
} | |
}); | |
return data; | |
} |
tree 组件提供的有以下基础参数,可根据需要进行相应的设置。
参数选项 | 说明 | 类型 | 示例值 |
elem | 指向容器选择器 | String/Object | - |
data | 数据源 | Array | |
id | 设定实例唯一索引,用于基础方法传参使用。 | String | - |
showCheckbox | 是否显示复选框 | Boolean | false |
edit | 是否开启节点的操作图标。默认 false。
| Boolean/Array | ['update', 'del'] |
accordion | 是否开启手风琴模式,默认 false | Boolean | false |
onlyIconControl | 是否仅允许节点左侧图标控制展开收缩。默认 false(即点击节点本身也可控制)。若为 true,则只能通过节点左侧图标来展开收缩 | Boolean | false |
isJump | 是否允许点击节点时弹出新窗口跳转。默认 false,若开启,需在节点数据中设定 link 参数(值为 url 格式) | Boolean | false |
showLine | 是否开启连接线。默认 true,若设为 false,则节点左侧出现三角图标。 | Boolean | true |
text | 自定义各类默认文本,目前支持以下设定: text: { defaultNodeName: '未命名' //节点默认名称 ,none: '无数据' //数据为空时的提示文本 } | Object | - |
因为tree指定了json数据的键名称,所以后台传递过来的数据对应的键名不一样时需要做一下处理,或者实体类中的属性名就和tree的JSON数据的键名称一样。
键名:
属性选项 | 说明 | 类型 | 示例值 |
title | 节点标题 | String | 未命名 |
id | 节点唯一索引,用于对指定节点进行各类操作 | String/Number | 任意唯一的字符或数字 |
children | 子节点。支持设定选项同父节点 | Array | [{title: '子节点1', id: '111'}] |
href | 点击节点弹出新窗口对应的 url。需开启 isJump 参数 | String | 任意 URL |
spread | 节点是否初始展开,默认 false | Boolean | true |
checked | 节点是否初始为选中状态(如果开启复选框的话),默认 false | Boolean | true |
disabled | 节点是否为禁用状态。默认 false | Boolean | false |
后台请求数据的方法。
public Object treeload(){ | |
Sort sort = Sort.by("idx"); | |
List<Dept> dpet = deptService.findByParentIsNull(sort); //查找所有菜单 | |
List<HashMap<String, Object>> result = new ArrayList<>(); //定义一个map处理json键名问题 | |
return fun(dpet, result); | |
} | |
private Object fun(List<Dept> dpet, List<HashMap<String, Object>> result) { | |
for(Dept d : dpet){ | |
HashMap<String, Object> map = new HashMap<>(); | |
map.put("id", d.getId()); | |
map.put("title", d.getName()); | |
map.put("spread", true); //设置是否展开 | |
List<HashMap<String, Object>> result1 = new ArrayList<>(); | |
List<Dept> children = d.getChildren(); //下级菜单 | |
//这里可以根据自己需求判断节点默认选中 | |
/*if(m.getParent() != null || m.getChildren().size() == 0){ | |
map.put("checked", true); //设置为选中状态 | |
}*/ | |
map.put("children", fun(children, result1)); | |
result.add(map); | |
} | |
return result; | |
} |
因为这里新建的实体类字段名和tree指定了json数据的键名称不一样,所以这里用了一个fun递归方法处理的。中间可以根据项目需求,根据条件判断是否需要选中该节点。
返回的JSON数据格式
[ | |
{ | |
"children": [ //子节点 | |
{ | |
"children": [ | |
{ | |
"children": [], | |
"id": 30, | |
"title": "测试", | |
"spread": true | |
}, { | |
"children": [], | |
"id": 31, | |
"title": "开发", | |
"spread": true | |
}, { | |
"children": [ | |
{ | |
"children": [], | |
"id": 36, | |
"title": "测试节点", | |
"spread": true | |
} | |
], | |
"id": 32, | |
"title": "测试", | |
"spread": true | |
} | |
], | |
"id": 2, | |
"title": "技术部", | |
"spread": true | |
}, { | |
"children": [], | |
"id": 19, | |
"title": "财务部", | |
"spread": true | |
} | |
], | |
"id": 1, //节点id | |
"title": "某某公司", //节点名称 | |
"spread": true | |
}, { | |
"children": [], | |
"id": 33, | |
"title": "测试", | |
"spread": true | |
} | |
] |
设置节点点击回调方法(在加载数据方法tree.render中添加以下代码)。
click: function (obj) { | |
var id = obj.data.id; | |
$("#dept_home").load("dept/show?id="+id); | |
} |
把请求过来的详情页面load到右边的div中显示。后台请求方法
public void show(DeptForm form, ModelMap map) throws InstantiationException, IllegalAccessException { | |
Dept model = new Dept(); | |
Integer id = form.getId(); | |
Integer parentId = 0; | |
if(id!=null) { | |
model = deptService.findById(id); | |
parentId = model.getParent()==null?0:model.getParent().getId(); | |
} | |
map.put("parentId", parentId); | |
map.put("model", model); | |
} |
DeptForm类为一个接收类,其中字段和实体类中一样。根据请求传递过来的id,查询这条数据的详细信息,之后把查询的当前部门详情数据及父级节点id(用于下拉树TreeSelect)传递给详情页面。
show.html详情页面代码。
<meta charset="UTF-8" /> | |
<style type="text/css"> | |
.myData .layui-form-item{ | |
margin: 20px 100px 10px 45px; | |
} | |
.myData .layui-form-label{ | |
width: 85px; | |
} | |
.layui-input-block { | |
margin-left: 120px; | |
} | |
</style> | |
<form class="layui-form myData" action="save" method="post" lay-filter="stuform"> | |
<input type="hidden" name="id" data-th-value="${model.id}" /> | |
<div class="layui-form-item"> | |
<label class="layui-form-label">上级部门:</label> | |
<div class="layui-input-block"> | |
<input type="text" name="parentId" id="tree" lay-filter="tree" class="layui-input" /> | |
</div> | |
</div> | |
<div class="layui-form-item"> | |
<label class="layui-form-label">部门名称:</label> | |
<div class="layui-input-block"> | |
<input type="text" name="name" lay-verify="required" th:value="${model.name}" class="layui-input" /> | |
</div> | |
</div> | |
<div class="layui-form-item" > | |
<label class="layui-form-label">部门负责人:</label> | |
<div class="layui-input-block"> | |
<input type="text" name="deptName" th:value="${model.deptName}" class="layui-input" /> | |
</div> | |
</div> | |
<div class="layui-form-item" > | |
<label class="layui-form-label">电话:</label> | |
<div class="layui-input-block"> | |
<input type="text" name="phone" th:value="${model.phone}" class="layui-input" /> | |
</div> | |
</div> | |
<div class="layui-form-item" > | |
<label class="layui-form-label">编号:</label> | |
<div class="layui-input-block"> | |
<input type="text" name="number" th:value="${model.number}" class="layui-input" /> | |
</div> | |
</div> | |
<div class="layui-form-item" > | |
<label class="layui-form-label">排序:</label> | |
<div class="layui-input-block"> | |
<input type="text" name="idx" value="0" th:value="${model.idx}" class="layui-input" /> | |
</div> | |
</div> | |
<div class="layui-form-item"> | |
<label class="layui-form-label"></label> | |
<div class="layui-input-block"> | |
<button lay-submit class="layui-btn layui-btn-radius layui-btn-normal" lay-filter="btnSub"> | |
<i class="layui-icon"></i>修改并保存 | |
</button> | |
</div> | |
</div> | |
</form> | |
<script th:inline="javascript"> | |
layui.use(["treeSelect", "form", "tree"], function () { | |
var form = layui.form; | |
var tree = layui.tree; | |
form.render('select'); | |
var treeSelect = layui.treeSelect; | |
treeSelect.render({ | |
// 选择器 | |
elem: '#tree', | |
// 数据 | |
data: 'dept/treeSelect?id='+[[${model.id==null ? 0 : model.id}]], | |
// 异步加载方式:get/post,默认get | |
type: 'post', | |
// 占位符 | |
placeholder: '上级菜单', | |
// 是否开启搜索功能:true/false,默认false | |
search: true, | |
// 一些可定制的样式 | |
style: { | |
folder: { | |
enable: true | |
}, | |
line: { | |
enable: true | |
} | |
}, | |
// 加载完成后的回调函数 | |
success: function (d) { | |
// 选中节点,根据id筛选 | |
treeSelect.checkNode('tree', [[${model.parent == null? parentId: model.parent.id}]]); | |
treeSelect.refresh('tree'); | |
} | |
}); | |
form.on('submit(btnSub)', function (data) { | |
$.post('dept/save', data.field, function (result) { | |
if (result.success) { | |
tree.reload('treeId', {data: getData()}); | |
} | |
layer.msg(result.msg, {offset: 'rb'}); | |
}); | |
return false; | |
}); | |
}); | |
</script> |
上级部门使用的是LayUI下拉树显示的,下拉树数据请求方法。关于下拉树的使用,可以访问LayUI下拉树TreeSelect的使用
"/treeSelect") | (value=|
public Object treeSelect(Integer id) { | |
Sort sort = Sort.by("idx"); | |
Specification<Dept> spec = buildSpec1(); | |
List<Dept> list = deptService.findAll(spec,sort); | |
return buildTree(list, id); | |
} | |
private Object buildTree(List<Dept> list, Integer id) { | |
List<HashMap<String, Object>> result=new ArrayList<>(); | |
for (Dept dept : list) { | |
if(dept.getId() != id) { | |
HashMap<String, Object> node=new HashMap<>(); | |
node.put("id", dept.getId()); | |
node.put("name",dept.getName()); | |
node.put("open", false); | |
node.put("checked", false); | |
if(dept.getChildren().size() != 0) { | |
node.put("children",buildTree(dept.getChildren(), id)); | |
} | |
result.add(node); | |
} | |
} | |
return result; | |
} | |
public Specification<Dept> buildSpec1() { | |
Specification<Dept> specification = new Specification<Dept>() { | |
private static final long serialVersionUID = 1L; | |
public Predicate toPredicate(Root<Dept> root, CriteriaQuery<?> query, CriteriaBuilder cb) { | |
HashSet<Predicate> rules=new HashSet<>(); | |
Predicate parent = cb.isNull(root.get("parent")); | |
rules.add(parent); | |
return cb.and(rules.toArray(new Predicate[rules.size()])); | |
} | |
}; | |
return specification; | |
} |
显示的效果。
上面修改并保存后台方法(因为修改和新增共用的一个方法,用id区分的)。
public Object save(DeptForm form) { | |
try { | |
Dept model = new Dept(); | |
Integer id = form.getId(); | |
if(id != null) { | |
model = deptService.findById(id); | |
} | |
//父级菜单id | |
Integer parentId = form.getParentId(); | |
if(parentId == null) { | |
model.setParent(null); | |
}else { | |
model.setParent(new Dept(parentId)); | |
} | |
BeanUtils.copyProperties(form, model,"id", "parent"); | |
deptService.save(model); | |
return new AjaxResult("数据保存成功!"); | |
} catch (Exception e) { | |
return new AjaxResult(false,"数据保存失败"); | |
} | |
} |
设置节点操作(在加载数据方法tree.render中添加以下代码)。
edit: ['add', 'update', 'del'], //操作节点的图标 | |
operate: function(obj){ | |
var type = obj.type; //得到操作类型:add、edit、del | |
var data = obj.data; //得到当前节点的数据 | |
var elem = obj.elem; //得到当前节点元素 | |
var id = data.id; | |
var name = data.title; | |
if(type === 'add'){ //增加节点 | |
$.post("dept/save", {parentId: id, name: "未命名"}, function (result) { | |
tree.reload('treeId', {data: getData()}); | |
}) | |
//返回 key 值 | |
return ; | |
} else if(type === 'update'){ //修改节点 | |
$.post("dept/update", {id: id, name: name}, function () { | |
tree.reload('treeId', {data: getData()}); | |
}) | |
} else if(type === 'del'){ //删除节点 | |
$.post("dept/delete", {id: id}, function () { | |
tree.reload('treeId', {data: getData()}); | |
}); | |
}; | |
} |
其中operate为操作节点回调方法。
obj.type为操作类型,add为新增,update为修改,edl为删除。obj.data为操作节点后的数据。
新增节点后,向后台发送请求添加节点,save方法和上面修改方法一样,id为新建节点的父级节点id。
修改节点,同样,向后台发送修改请求,并传递对象的id,和修改后的数据作为参数。后台响应方法。
"/update") | (value =|
public Object update(DeptForm form) { | |
try { | |
Dept model = deptService.findById(form.getId()); | |
model.setName(form.getName()); | |
deptService.save(model); | |
return new AjaxResult("数据保存成功!"); | |
} catch (Exception e) { | |
return new AjaxResult(false,"数据保存失败"); | |
} | |
} |
删除节点同理,传递删除节点的id。删除请求方法。
"/delete") | (value=|
public Object delete(Integer id) { | |
try { | |
deptService.deleteById(id); | |
return new AjaxResult("数据删除成功"); | |
} catch (Exception e) { | |
return new AjaxResult(false,"数据删除失败"); | |
} | |
} |
使用按钮操作树形菜单。
现在页面中定义两个按钮,给按钮添加lay-demo=""属性,并设置属性值,JS通过这个属性值,绑定点击事件。
<button class="layui-btn layui-btn-sm layui-btn-radius layui-btn-normal" lay-demo="addDept"><i class="layui-icon"></i>添加部门</button> | |
<button class="layui-btn layui-btn-sm layui-btn-radius layui-btn-normal" lay-demo="gain">获取选中节点</button> |
绑定添加部门和获取选中节点按钮的点击事件的JS代码。
util.event('lay-demo', { | |
addDept: function(othis){ | |
$.get('dept/edit', function(data) { | |
layer.open({ | |
type: 1, | |
title: '新增', | |
area: ['530px'], | |
content: data, | |
btn: ['提交', '退出'], | |
yes: function () { | |
}, | |
success: function (layero, index) { | |
layui.use('form', function () { | |
var form = layui.form; | |
layero.addClass('layui-form'); | |
var submitBtn = layero.find('.layui-layer-btn0'); | |
submitBtn.attr('lay-filter', 'formVerify').attr('lay-submit', ''); | |
layero.keydown(function (e) { | |
if (e.keyCode == 13) { | |
submitBtn.click(); | |
} | |
}); | |
form.on('submit(formVerify)', function (data) { | |
$.post('dept/save', data.field, function (result) { | |
if (result.success) { | |
layer.close(index); | |
tree.reload('treeId', {data: getData()}); | |
} | |
layer.msg(result.msg, {offset: 'rb'}); | |
}); | |
return false; | |
}); | |
}); | |
} | |
}) | |
}) | |
}, | |
gain: function () { | |
var checkData = tree.getChecked('treeId'); | |
var str = JSON.stringify(checkData); | |
$.post('dept/checkedGain', {data: str}, function () { | |
}); | |
layer.alert(JSON.stringify(checkData), {shade:0}); | |
} | |
}); |
添加部门按钮点击事件,先发送请求到后台,跳转到eidt新增页面,edit.html新增页面代码,和上面的show.html显示部门详情页面差不多。上级部门同样使用的LayUI下拉树显示的,下拉树数据请求方法,和上面的详情页面下拉树请求方法一致。LayUI下拉树TreeSelect的使用。新增后的保存方法也和上面的保存方法一致。
后台请求方法代码,跳转到edit页面。
"/edit") | (value =|
public void edit(){ | |
} |
edit.html页面完整代码如下。
<meta charset="UTF-8" /> | |
<style type="text/css"> | |
.myData .layui-form-item{ | |
margin: 20px 100px 10px 45px; | |
} | |
.myData .layui-form-label{ | |
width: 85px; | |
} | |
.layui-input-block { | |
margin-left: 120px; | |
} | |
</style> | |
<form class="layui-form myData" action="save" method="post" lay-filter="stuform"> | |
<div class="layui-form-item"> | |
<label class="layui-form-label">上级部门:</label> | |
<div class="layui-input-block"> | |
<input type="text" name="parentId" id="tree2" lay-filter="tree2" class="layui-input" /> | |
</div> | |
</div> | |
<div class="layui-form-item"> | |
<label class="layui-form-label">部门名称:</label> | |
<div class="layui-input-block"> | |
<input type="text" name="name" lay-verify="required" class="layui-input" /> | |
</div> | |
</div> | |
<div class="layui-form-item" > | |
<label class="layui-form-label">部门负责人:</label> | |
<div class="layui-input-block"> | |
<input type="text" name="deptName" class="layui-input" /> | |
</div> | |
</div> | |
<div class="layui-form-item" > | |
<label class="layui-form-label">电话:</label> | |
<div class="layui-input-block"> | |
<input type="text" name="phone" class="layui-input" /> | |
</div> | |
</div> | |
<div class="layui-form-item" > | |
<label class="layui-form-label">编号:</label> | |
<div class="layui-input-block"> | |
<input type="text" name="number" class="layui-input" /> | |
</div> | |
</div> | |
<div class="layui-form-item" > | |
<label class="layui-form-label">排序:</label> | |
<div class="layui-input-block"> | |
<input type="text" name="idx" value="0" class="layui-input" /> | |
</div> | |
</div> | |
</form> | |
<script th:inline="javascript"> | |
layui.use(["treeSelect", "form"], function () { | |
var form = layui.form; | |
form.render('select'); | |
var treeSelect = layui.treeSelect; | |
treeSelect.render({ | |
// 选择器 | |
elem: '#tree2', | |
// 数据 | |
data: 'dept/treeSelect', | |
// 异步加载方式:get/post,默认get | |
type: 'post', | |
// 占位符 | |
placeholder: '上级菜单', | |
// 是否开启搜索功能:true/false,默认false | |
search: true, | |
// 一些可定制的样式 | |
style: { | |
folder: { | |
enable: true | |
}, | |
line: { | |
enable: true | |
} | |
}, | |
// 加载完成后的回调函数 | |
success: function (d) { | |
} | |
}); | |
}); | |
</script> |
页面效果。
获取选中节点按钮点击事件。如果项目需要保存数据时,就需要获取到选中节点的数据了。这里可以获取到选中节点的数据,之后当参数传递到后台。传递到后台是一个JSON数据的字符串,需要转换一下,这里给推荐大家两个很好用的JSON转换工具net.sf.json.JSONObject和Alibaba Fastjson。这里用的是Alibaba Fastjson,需要引入以下依赖。
<dependency> | |
<groupId>com.alibaba</groupId> | |
<artifactId>fastjson</artifactId> | |
<version>1.2.47</version> | |
</dependency> |
这里用于输出,新建了一个和tree的json数据的键名称一样的工具类DeptTree,代码如下。
import java.util.ArrayList; | |
import java.util.List; | |
public class DeptTree { | |
private Integer id; | |
private String title; | |
private boolean checked; | |
private boolean spread; | |
private List<DeptTree> children = new ArrayList<>(); | |
public Integer getId() { | |
return id; | |
} | |
public void setId(Integer id) { | |
this.id = id; | |
} | |
public String getTitle() { | |
return title; | |
} | |
public void setTitle(String title) { | |
this.title = title; | |
} | |
public List<DeptTree> getChildren() { | |
return children; | |
} | |
public void setChildren(List<DeptTree> children) { | |
this.children = children; | |
} | |
public boolean isChecked() { | |
return checked; | |
} | |
public void setChecked(boolean checked) { | |
this.checked = checked; | |
} | |
public boolean isSpread() { | |
return spread; | |
} | |
public void setSpread(boolean spread) { | |
this.spread = spread; | |
} | |
} |
后台接收到传递过来的JSON数据字符串,转换后输出方法。
"/checkedGain") | (value =|
public void checkedGain(String data){ | |
List<DeptTree> array2 = JSONArray.parseArray(data, DeptTree.class); | |
treeData(array2); | |
} | |
//递归输出选中数据 | |
private void treeData(List<DeptTree> array2) { | |
for (DeptTree tree: array2){ | |
System.out.println(tree.getTitle()+"==="+tree.getId()); | |
if(tree.getChildren() != null){ | |
treeData(tree.getChildren()); | |
} | |
} | |
} |
选中节点,点击获取选中节点数据。
后台对应方法接收到数据,转换后输出结果。
数据拿到了,之后保存方法就简单了。
后台方法代码基本都在上面了,页面全部代码。
<style type="text/css"> | |
#dept_main, #dept_particulars{ | |
width: 48.5%; | |
display: inline-block; | |
vertical-align: top; | |
padding: 20px; | |
background: white; | |
box-sizing: border-box; | |
} | |
#dept_tree{ | |
margin-top: 20px; | |
} | |
</style> | |
<div id="dept_main" style="margin-right: 2%;"> | |
<fieldset class="layui-elem-field layui-field-title"> | |
<legend>所有部门</legend> | |
</fieldset> | |
<button class="layui-btn layui-btn-sm layui-btn-radius layui-btn-normal" lay-demo="addDept"><i class="layui-icon"></i>添加部门</button> | |
<button class="layui-btn layui-btn-sm layui-btn-radius layui-btn-normal" lay-demo="gain">获取选中节点</button> | |
<div id="dept_tree"> | |
</div> | |
</div> | |
<div id="dept_particulars"> | |
<fieldset class="layui-elem-field layui-field-title"> | |
<legend>部门详情</legend> | |
</fieldset> | |
<div id="dept_home"> | |
<div class="layui-tree-emptyText">无数据</div> | |
</div> | |
</div> | |
<script type="text/javascript"> | |
layui.use(['tree', 'util', 'layer'], function() { | |
var tree = layui.tree; | |
var util = layui.util; | |
var layer = layui.layer; | |
tree.render({ | |
elem: '#dept_tree', | |
data: getData(), | |
id: 'treeId', | |
showCheckbox: true, //时候显示复选框 | |
onlyIconControl: true, | |
edit: ['add', 'update', 'del'], //操作节点的图标 | |
click: function (obj) { | |
var id = obj.data.id; | |
$("#dept_home").load("dept/show?id="+id); | |
}, | |
operate: function(obj){ | |
var type = obj.type; //得到操作类型:add、edit、del | |
var data = obj.data; //得到当前节点的数据 | |
var elem = obj.elem; //得到当前节点元素 | |
var id = data.id; | |
var name = data.title; | |
if(type === 'add'){ //增加节点 | |
$.post("dept/save", {parentId: id, name: "未命名"}, function (result) { | |
tree.reload('treeId', {data: getData()}); | |
}) | |
//返回 key 值 | |
return ; | |
} else if(type === 'update'){ //修改节点 | |
$.post("dept/update", {id: id, name: name}, function () { | |
tree.reload('treeId', {data: getData()}); | |
}) | |
} else if(type === 'del'){ //删除节点 | |
$.post("dept/delete", {id: id}, function () { | |
tree.reload('treeId', {data: getData()}); | |
}); | |
}; | |
} | |
}); | |
util.event('lay-demo', { | |
addDept: function(othis){ | |
$.get('dept/edit', function(data) { | |
layer.open({ | |
type: 1, | |
title: '新增', | |
area: ['530px'], | |
content: data, | |
btn: ['提交', '退出'], | |
yes: function () { | |
}, | |
success: function (layero, index) { | |
layui.use('form', function () { | |
var form = layui.form; | |
layero.addClass('layui-form'); | |
var submitBtn = layero.find('.layui-layer-btn0'); | |
submitBtn.attr('lay-filter', 'formVerify').attr('lay-submit', ''); | |
layero.keydown(function (e) { | |
if (e.keyCode == 13) { | |
submitBtn.click(); | |
} | |
}); | |
form.on('submit(formVerify)', function (data) { | |
$.post('dept/save', data.field, function (result) { | |
if (result.success) { | |
layer.close(index); | |
tree.reload('treeId', {data: getData()}); | |
} | |
layer.msg(result.msg, {offset: 'rb'}); | |
}); | |
return false; | |
}); | |
}); | |
} | |
}) | |
}) | |
}, | |
gain: function () { | |
var checkData = tree.getChecked('treeId'); | |
var str = JSON.stringify(checkData); | |
$.post('dept/checkedGain', {data: str}, function () { | |
}); | |
layer.alert(JSON.stringify(checkData), {shade:0}); | |
} | |
}); | |
}); | |
function getData(){ | |
var data = []; | |
$.ajax({ | |
url: "dept/treeload", //后台数据请求地址 | |
type: "post", | |
async:false, | |
success: function(resut){ | |
data = resut; | |
} | |
}); | |
return data; | |
} | |
</script> |