Layui—tree树形结构的使用

本文介绍了如何在个人博客项目中使用LayUI实现树形结构,展示了树形结构在部门管理中的应用,包括添加、编辑、删除节点功能,以及获取选中节点信息。详细讲解了前端页面的样式设置、JS代码实现、实体类与JSON数据对应、后台接口处理等步骤,提供了完整的代码示例。
摘要由CSDN通过智能技术生成

树形结构在实际开发中很长用到,比如部门管理,权限菜单等。因为用树形结构来展示会显的很清晰明了。最近写了一个个人博客小项目中用到了LayUI的树形结构,之后写了一个小案例整理一下。

官网地址:https://www.layui.com/v1/doc/modules/tree.html

先看一下显示的效果图。

点击节点右面会显示对应部门的详情信息,可以修改。可以自定义按钮添加部门,也可以直接用自带的方法对部门进行新增,修改和删除。可以获取选中的节点,根据项目需求(有的需要选中保存)。

先需要引入LayUI的样式文件JS和CSS。

案例对应的实体类Dept。


   
   
  1. @Entity
  2. public class Dept {
  3. private Integer id;
  4. private String name; //部门名称
  5. private String deptName; //部门负责人
  6. private String phone; //电话号
  7. private String number; //编号
  8. private double idx; //排序
  9. @JsonIgnore
  10. private Dept parent;
  11. @JsonIgnore
  12. private List<Dept> children = new ArrayList<>();
  13. @Id
  14. @GeneratedValue
  15. public Integer getId() {
  16. return id;
  17. }
  18. public void setId(Integer id) {
  19. this.id = id;
  20. }
  21. public String getName() {
  22. return name;
  23. }
  24. public void setName(String name) {
  25. this.name = name;
  26. }
  27. public String getDeptName() {
  28. return deptName;
  29. }
  30. public void setDeptName(String deptName) {
  31. this.deptName = deptName;
  32. }
  33. public String getPhone() {
  34. return phone;
  35. }
  36. public void setPhone(String phone) {
  37. this.phone = phone;
  38. }
  39. public String getNumber() {
  40. return number;
  41. }
  42. public void setNumber(String number) {
  43. this.number = number;
  44. }
  45. public double getIdx() {
  46. return idx;
  47. }
  48. public void setIdx(double idx) {
  49. this.idx = idx;
  50. }
  51. @ManyToOne
  52. @CreatedBy
  53. public Dept getParent() {
  54. return parent;
  55. }
  56. public void setParent(Dept parent) {
  57. this.parent = parent;
  58. }
  59. @OneToMany(cascade=CascadeType.ALL,mappedBy="parent")
  60. @OrderBy(value="idx")
  61. public List<Dept> getChildren() {
  62. return children;
  63. }
  64. public void setChildren(List<Dept> children) {
  65. this.children = children;
  66. }
  67. public Dept(Integer id, String name, String deptName, String phone, String number, double idx, Dept parent, List<Dept> children) {
  68. this.id = id;
  69. this.name = name;
  70. this.deptName = deptName;
  71. this.phone = phone;
  72. this.number = number;
  73. this.idx = idx;
  74. this.parent = parent;
  75. this.children = children;
  76. }
  77. public Dept(Integer id) {
  78. this.id = id;
  79. }
  80. public Dept() {
  81. }
  82. }

显示LayUI树形菜单,只需要一个标签容器即可。


   
   
  1. <div id="dept_tree">
  2. </div>

在案例中还有一些其他样式,比如右边的详情信息,新增按钮等。完整代码如下。


   
   
  1. <style type="text/css">
  2. #dept_main, #dept_particulars{
  3. width: 48.5%;
  4. display: inline-block;
  5. vertical-align: top;
  6. padding: 20px;
  7. background: white;
  8. box-sizing: border-box;
  9. }
  10. #dept_tree{
  11. margin-top: 20px;
  12. }
  13. </style>
  14. <div id="dept_main" style="margin-right: 2%;">
  15. <fieldset class="layui-elem-field layui-field-title">
  16. <legend>所有部门 </legend>
  17. </fieldset>
  18. <button class="layui-btn layui-btn-sm layui-btn-radius layui-btn-normal" lay-demo="addDept"> <i class="layui-icon"> &#xe654; </i>添加部门 </button>
  19. <button class="layui-btn layui-btn-sm layui-btn-radius layui-btn-normal" lay-demo="gain">获取选中节点 </button>
  20. <div id="dept_tree">
  21. </div>
  22. </div>
  23. <div id="dept_particulars">
  24. <fieldset class="layui-elem-field layui-field-title">
  25. <legend>部门详情 </legend>
  26. </fieldset>
  27. <div id="dept_home">
  28. <div class="layui-tree-emptyText">无数据 </div>
  29. </div>
  30. </div>

JS请求数据渲染页面代码,data为请求数据源,当时直接放入的请求链接,好像不行,所以之后才写了一个方法去请求数据源。


   
   
  1. layui. use([ 'tree', 'util'], function() {
  2. var tree = layui.tree;
  3. var util = layui.util;
  4. tree.render({
  5. elem: '#dept_tree',
  6. data: getData(),
  7. id: 'treeId',
  8. showCheckbox: true, //是否显示复选框
  9. onlyIconControl: true
  10. });
  11. });
  12. function getData(){
  13. var data = [];
  14. $.ajax({
  15. url: "dept/treeload", //后台数据请求地址
  16. type: "post",
  17. async: false,
  18. success: function(resut){
  19. data = resut;
  20. }
  21. });
  22. return data;
  23. }

 tree 组件提供的有以下基础参数,可根据需要进行相应的设置。

参数选项说明类型示例值
elem指向容器选择器String/Object-
data数据源Array-
id设定实例唯一索引,用于基础方法传参使用。String-
showCheckbox是否显示复选框Booleanfalse
edit是否开启节点的操作图标。默认 false。
  • 若为 true,则默认显示“改删”图标
  • 若为 数组,则可自由配置操作图标的显示状态和顺序,目前支持的操作图标有:addupdatedel,如: 
    edit: ['add', 'update', 'del']
Boolean/Array['update', 'del']
accordion是否开启手风琴模式,默认 falseBooleanfalse
onlyIconControl是否仅允许节点左侧图标控制展开收缩。默认 false(即点击节点本身也可控制)。若为 true,则只能通过节点左侧图标来展开收缩Booleanfalse
isJump是否允许点击节点时弹出新窗口跳转。默认 false,若开启,需在节点数据中设定 link 参数(值为 url 格式)Booleanfalse
showLine是否开启连接线。默认 true,若设为 false,则节点左侧出现三角图标。Booleantrue
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节点是否初始展开,默认 falseBooleantrue
checked节点是否初始为选中状态(如果开启复选框的话),默认 falseBooleantrue
disabled节点是否为禁用状态。默认 falseBooleanfalse

后台请求数据的方法。


   
   
  1. @RequestMapping(value = "/treeload")
  2. @ResponseBody
  3. public Object treeload(){
  4. Sort sort = Sort. by( "idx");
  5. List<Dept> dpet = deptService.findByParentIsNull(sort); //查找所有菜单
  6. List<HashMap<String, Object>> result = new ArrayList<>(); //定义一个map处理json键名问题
  7. return fun(dpet, result);
  8. }
  9. private Object fun(List<Dept> dpet, List<HashMap<String, Object>> result) {
  10. for(Dept d : dpet){
  11. HashMap<String, Object> map = new HashMap<>();
  12. map.put( "id", d.getId());
  13. map.put( "title", d.getName());
  14. map.put( "spread", true); //设置是否展开
  15. List<HashMap<String, Object>> result1 = new ArrayList<>();
  16. List<Dept> children = d.getChildren(); //下级菜单
  17. //这里可以根据自己需求判断节点默认选中
  18. /*if(m.getParent() != null || m.getChildren().size() == 0){
  19. map.put("checked", true); //设置为选中状态
  20. }*/
  21. map.put( "children", fun(children, result1));
  22. result.add(map);
  23. }
  24. return result;
  25. }

因为这里新建的实体类字段名和tree指定了json数据的键名称不一样,所以这里用了一个fun递归方法处理的。中间可以根据项目需求,根据条件判断是否需要选中该节点。

返回的JSON数据格式


   
   
  1. [
  2. {
  3. "children": [ //子节点
  4. {
  5. "children": [
  6. {
  7. "children": [],
  8. "id": 30,
  9. "title": "测试",
  10. "spread": true
  11. }, {
  12. "children": [],
  13. "id": 31,
  14. "title": "开发",
  15. "spread": true
  16. }, {
  17. "children": [
  18. {
  19. "children": [],
  20. "id": 36,
  21. "title": "测试节点",
  22. "spread": true
  23. }
  24. ],
  25. "id": 32,
  26. "title": "测试",
  27. "spread": true
  28. }
  29. ],
  30. "id": 2,
  31. "title": "技术部",
  32. "spread": true
  33. }, {
  34. "children": [],
  35. "id": 19,
  36. "title": "财务部",
  37. "spread": true
  38. }
  39. ],
  40. "id": 1, //节点id
  41. "title": "某某公司", //节点名称
  42. "spread": true
  43. }, {
  44. "children": [],
  45. "id": 33,
  46. "title": "测试",
  47. "spread": true
  48. }
  49. ]

设置节点点击回调方法(在加载数据方法tree.render中添加以下代码)。


   
   
  1. click: function (obj) {
  2. var id = obj.data.id;
  3. $( "#dept_home").load( "dept/show?id="+id);
  4. }

把请求过来的详情页面load到右边的div中显示。后台请求方法


   
   
  1. @RequestMapping(value = "/show")
  2. public void show(DeptForm form, ModelMap map) throws InstantiationException, IllegalAccessException {
  3. Dept model = new Dept();
  4. Integer id = form.getId();
  5. Integer parentId = 0;
  6. if(id!= null) {
  7. model = deptService.findById(id);
  8. parentId = model.getParent()== null? 0:model.getParent().getId();
  9. }
  10. map.put( "parentId", parentId);
  11. map.put( "model", model);
  12. }

DeptForm类为一个接收类,其中字段和实体类中一样。根据请求传递过来的id,查询这条数据的详细信息,之后把查询的当前部门详情数据及父级节点id(用于下拉树TreeSelect)传递给详情页面。

show.html详情页面代码。


   
   
  1. <meta charset="UTF-8" />
  2. <style type="text/css">
  3. .myData .layui-form-item{
  4. margin: 20px 100px 10px 45px;
  5. }
  6. .myData .layui-form-label{
  7. width: 85px;
  8. }
  9. .layui-input-block {
  10. margin-left: 120px;
  11. }
  12. </style>
  13. <form class="layui-form myData" action="save" method="post" lay-filter="stuform">
  14. <input type="hidden" name="id" data-th-value="${model.id}" />
  15. <div class="layui-form-item">
  16. <label class="layui-form-label">上级部门: </label>
  17. <div class="layui-input-block">
  18. <input type="text" name="parentId" id="tree" lay-filter="tree" class="layui-input" />
  19. </div>
  20. </div>
  21. <div class="layui-form-item">
  22. <label class="layui-form-label">部门名称: </label>
  23. <div class="layui-input-block">
  24. <input type="text" name="name" lay-verify="required" th:value="${model.name}" class="layui-input" />
  25. </div>
  26. </div>
  27. <div class="layui-form-item" >
  28. <label class="layui-form-label">部门负责人: </label>
  29. <div class="layui-input-block">
  30. <input type="text" name="deptName" th:value="${model.deptName}" class="layui-input" />
  31. </div>
  32. </div>
  33. <div class="layui-form-item" >
  34. <label class="layui-form-label">电话: </label>
  35. <div class="layui-input-block">
  36. <input type="text" name="phone" th:value="${model.phone}" class="layui-input" />
  37. </div>
  38. </div>
  39. <div class="layui-form-item" >
  40. <label class="layui-form-label">编号: </label>
  41. <div class="layui-input-block">
  42. <input type="text" name="number" th:value="${model.number}" class="layui-input" />
  43. </div>
  44. </div>
  45. <div class="layui-form-item" >
  46. <label class="layui-form-label">排序: </label>
  47. <div class="layui-input-block">
  48. <input type="text" name="idx" value="0" th:value="${model.idx}" class="layui-input" />
  49. </div>
  50. </div>
  51. <div class="layui-form-item">
  52. <label class="layui-form-label"> </label>
  53. <div class="layui-input-block">
  54. <button lay-submit class="layui-btn layui-btn-radius layui-btn-normal" lay-filter="btnSub">
  55. <i class="layui-icon"> &#xe642; </i>修改并保存
  56. </button>
  57. </div>
  58. </div>
  59. </form>
  60. <script th:inline="javascript">
  61. layui.use([ "treeSelect", "form", "tree"], function () {
  62. var form = layui.form;
  63. var tree = layui.tree;
  64. form.render( 'select');
  65. var treeSelect = layui.treeSelect;
  66. treeSelect.render({
  67. // 选择器
  68. elem: '#tree',
  69. // 数据
  70. data: 'dept/treeSelect?id='+[[${model.id== null ? 0 : model.id}]],
  71. // 异步加载方式:get/post,默认get
  72. type: 'post',
  73. // 占位符
  74. placeholder: '上级菜单',
  75. // 是否开启搜索功能:true/false,默认false
  76. search: true,
  77. // 一些可定制的样式
  78. style: {
  79. folder: {
  80. enable: true
  81. },
  82. line: {
  83. enable: true
  84. }
  85. },
  86. // 加载完成后的回调函数
  87. success: function (d) {
  88. // 选中节点,根据id筛选
  89. treeSelect.checkNode( 'tree', [[${model.parent == null? parentId: model.parent.id}]]);
  90. treeSelect.refresh( 'tree');
  91. }
  92. });
  93. form.on( 'submit(btnSub)', function (data) {
  94. $.post( 'dept/save', data.field, function (result) {
  95. if (result.success) {
  96. tree.reload( 'treeId', { data: getData()});
  97. }
  98. layer.msg(result.msg, { offset: 'rb'});
  99. });
  100. return false;
  101. });
  102. });
  103. </script>

上级部门使用的是LayUI下拉树显示的,下拉树数据请求方法。关于下拉树的使用,可以访问LayUI下拉树TreeSelect的使用


   
   
  1. @RequestMapping(value= "/treeSelect")
  2. @ResponseBody
  3. public Object treeSelect( Integer id) {
  4. Sort sort = Sort.by( "idx");
  5. Specification<Dept> spec = buildSpec1();
  6. List<Dept> list = deptService.findAll(spec,sort);
  7. return buildTree( list, id);
  8. }
  9. private Object buildTree( List<Dept> list, Integer id) {
  10. List<HashMap< String, Object>> result= new ArrayList<>();
  11. for (Dept dept : list) {
  12. if(dept.getId() != id) {
  13. HashMap< String, Object> node= new HashMap<>();
  14. node.put( "id", dept.getId());
  15. node.put( "name",dept.getName());
  16. node.put( "open", false);
  17. node.put( "checked", false);
  18. if(dept.getChildren().size() != 0) {
  19. node.put( "children",buildTree(dept.getChildren(), id));
  20. }
  21. result.add(node);
  22. }
  23. }
  24. return result;
  25. }
  26. public Specification<Dept> buildSpec1() {
  27. Specification<Dept> specification = new Specification<Dept>() {
  28. private static final long serialVersionUID = 1L;
  29. @Override
  30. public Predicate toPredicate(Root<Dept> root, CriteriaQuery <?> query, CriteriaBuilder cb) {
  31. HashSet<Predicate> rules= new HashSet<>();
  32. Predicate parent = cb.isNull(root.get( "parent"));
  33. rules.add( parent);
  34. return cb. and(rules.toArray( new Predicate[rules.size()]));
  35. }
  36. };
  37. return specification;
  38. }

显示的效果。

上面修改并保存后台方法(因为修改和新增共用的一个方法,用id区分的)。


   
   
  1. @Override
  2. public Object save(DeptForm form) {
  3. try {
  4. Dept model = new Dept();
  5. Integer id = form.getId();
  6. if(id != null) {
  7. model = deptService.findById(id);
  8. }
  9. //父级菜单id
  10. Integer parentId = form.getParentId();
  11. if(parentId == null) {
  12. model.setParent( null);
  13. } else {
  14. model.setParent( new Dept(parentId));
  15. }
  16. BeanUtils.copyProperties(form, model, "id", "parent");
  17. deptService.save(model);
  18. return new AjaxResult( "数据保存成功!");
  19. } catch ( Exception e) {
  20. return new AjaxResult( false, "数据保存失败");
  21. }
  22. }

设置节点操作(在加载数据方法tree.render中添加以下代码)。


   
   
  1. edit: [ 'add', 'update', 'del'], //操作节点的图标
  2. operate: function(obj){
  3. var type = obj.type; //得到操作类型:add、edit、del
  4. var data = obj.data; //得到当前节点的数据
  5. var elem = obj.elem; //得到当前节点元素
  6. var id = data.id;
  7. var name = data.title;
  8. if(type === 'add'){ //增加节点
  9. $.post( "dept/save", { parentId: id, name: "未命名"}, function (result) {
  10. tree.reload( 'treeId', { data: getData()});
  11. })
  12. //返回 key 值
  13. return ;
  14. } else if(type === 'update'){ //修改节点
  15. $.post( "dept/update", { id: id, name: name}, function () {
  16. tree.reload( 'treeId', { data: getData()});
  17. })
  18. } else if(type === 'del'){ //删除节点
  19. $.post( "dept/delete", { id: id}, function () {
  20. tree.reload( 'treeId', { data: getData()});
  21. });
  22. };
  23. }

其中operate为操作节点回调方法。

obj.type为操作类型,add为新增,update为修改,edl为删除。obj.data为操作节点后的数据。

新增节点后,向后台发送请求添加节点,save方法和上面修改方法一样,id为新建节点的父级节点id。

修改节点,同样,向后台发送修改请求,并传递对象的id,和修改后的数据作为参数。后台响应方法。


   
   
  1. @RequestMapping(value = "/update")
  2. @ResponseBody
  3. public Object update(DeptForm form) {
  4. try {
  5. Dept model = deptService.findById(form.getId());
  6. model.setName(form.getName());
  7. deptService.save(model);
  8. return new AjaxResult( "数据保存成功!");
  9. } catch (Exception e) {
  10. return new AjaxResult( false, "数据保存失败");
  11. }
  12. }

删除节点同理,传递删除节点的id。删除请求方法。


   
   
  1. @RequestMapping(value= "/delete")
  2. @ResponseBody
  3. public Object delete(Integer id) {
  4. try {
  5. deptService .deleteById(id);
  6. return new AjaxResult( "数据删除成功");
  7. } catch (Exception e) {
  8. return new AjaxResult(false, "数据删除失败");
  9. }
  10. }

使用按钮操作树形菜单。

现在页面中定义两个按钮,给按钮添加lay-demo=""属性,并设置属性值,JS通过这个属性值,绑定点击事件。


   
   
  1. <button class="layui-btn layui-btn-sm layui-btn-radius layui-btn-normal" lay-demo="addDept"> <i class="layui-icon"> &#xe654; </i>添加部门 </button>
  2. <button class="layui-btn layui-btn-sm layui-btn-radius layui-btn-normal" lay-demo="gain">获取选中节点 </button>

绑定添加部门和获取选中节点按钮的点击事件的JS代码。


   
   
  1. util.event( 'lay-demo', {
  2. addDept: function(othis){
  3. $.get( 'dept/edit', function(data) {
  4. layer.open({
  5. type: 1,
  6. title: '新增',
  7. area: [ '530px'],
  8. content: data,
  9. btn: [ '提交', '退出'],
  10. yes: function () {
  11. },
  12. success: function (layero, index) {
  13. layui.use( 'form', function () {
  14. var form = layui.form;
  15. layero.addClass( 'layui-form');
  16. var submitBtn = layero.find( '.layui-layer-btn0');
  17. submitBtn.attr( 'lay-filter', 'formVerify').attr( 'lay-submit', '');
  18. layero.keydown( function (e) {
  19. if (e.keyCode == 13) {
  20. submitBtn.click();
  21. }
  22. });
  23. form.on( 'submit(formVerify)', function (data) {
  24. $.post( 'dept/save', data.field, function (result) {
  25. if (result.success) {
  26. layer.close(index);
  27. tree.reload( 'treeId', { data: getData()});
  28. }
  29. layer.msg(result.msg, { offset: 'rb'});
  30. });
  31. return false;
  32. });
  33. });
  34. }
  35. })
  36. })
  37. },
  38. gain: function () {
  39. var checkData = tree.getChecked( 'treeId');
  40. var str = JSON.stringify(checkData);
  41. $.post( 'dept/checkedGain', { data: str}, function () {
  42. });
  43. layer.alert( JSON.stringify(checkData), { shade: 0});
  44. }
  45. });

添加部门按钮点击事件,先发送请求到后台,跳转到eidt新增页面,edit.html新增页面代码,和上面的show.html显示部门详情页面差不多。上级部门同样使用的LayUI下拉树显示的,下拉树数据请求方法,和上面的详情页面下拉树请求方法一致。LayUI下拉树TreeSelect的使用。新增后的保存方法也和上面的保存方法一致。

后台请求方法代码,跳转到edit页面。


   
   
  1. @RequestMapping( value = "/edit")
  2. public void edit(){
  3. }

edit.html页面完整代码如下。


   
   
  1. <meta charset="UTF-8" />
  2. <style type="text/css">
  3. .myData .layui-form-item{
  4. margin: 20px 100px 10px 45px;
  5. }
  6. .myData .layui-form-label{
  7. width: 85px;
  8. }
  9. .layui-input-block {
  10. margin-left: 120px;
  11. }
  12. </style>
  13. <form class="layui-form myData" action="save" method="post" lay-filter="stuform">
  14. <div class="layui-form-item">
  15. <label class="layui-form-label">上级部门: </label>
  16. <div class="layui-input-block">
  17. <input type="text" name="parentId" id="tree2" lay-filter="tree2" class="layui-input" />
  18. </div>
  19. </div>
  20. <div class="layui-form-item">
  21. <label class="layui-form-label">部门名称: </label>
  22. <div class="layui-input-block">
  23. <input type="text" name="name" lay-verify="required" class="layui-input" />
  24. </div>
  25. </div>
  26. <div class="layui-form-item" >
  27. <label class="layui-form-label">部门负责人: </label>
  28. <div class="layui-input-block">
  29. <input type="text" name="deptName" class="layui-input" />
  30. </div>
  31. </div>
  32. <div class="layui-form-item" >
  33. <label class="layui-form-label">电话: </label>
  34. <div class="layui-input-block">
  35. <input type="text" name="phone" class="layui-input" />
  36. </div>
  37. </div>
  38. <div class="layui-form-item" >
  39. <label class="layui-form-label">编号: </label>
  40. <div class="layui-input-block">
  41. <input type="text" name="number" class="layui-input" />
  42. </div>
  43. </div>
  44. <div class="layui-form-item" >
  45. <label class="layui-form-label">排序: </label>
  46. <div class="layui-input-block">
  47. <input type="text" name="idx" value="0" class="layui-input" />
  48. </div>
  49. </div>
  50. </form>
  51. <script th:inline="javascript">
  52. layui.use([ "treeSelect", "form"], function () {
  53. var form = layui.form;
  54. form.render( 'select');
  55. var treeSelect = layui.treeSelect;
  56. treeSelect.render({
  57. // 选择器
  58. elem: '#tree2',
  59. // 数据
  60. data: 'dept/treeSelect',
  61. // 异步加载方式:get/post,默认get
  62. type: 'post',
  63. // 占位符
  64. placeholder: '上级菜单',
  65. // 是否开启搜索功能:true/false,默认false
  66. search: true,
  67. // 一些可定制的样式
  68. style: {
  69. folder: {
  70. enable: true
  71. },
  72. line: {
  73. enable: true
  74. }
  75. },
  76. // 加载完成后的回调函数
  77. success: function (d) {
  78. }
  79. });
  80. });
  81. </script>

页面效果。

获取选中节点按钮点击事件。如果项目需要保存数据时,就需要获取到选中节点的数据了。这里可以获取到选中节点的数据,之后当参数传递到后台。传递到后台是一个JSON数据的字符串,需要转换一下,这里给推荐大家两个很好用的JSON转换工具net.sf.json.JSONObjectAlibaba Fastjson。这里用的是Alibaba Fastjson,需要引入以下依赖。


   
   
  1. <dependency>
  2. <groupId>com.alibaba </groupId>
  3. <artifactId>fastjson </artifactId>
  4. <version>1.2.47 </version>
  5. </dependency>

这里用于输出,新建了一个和tree的json数据的键名称一样的工具类DeptTree,代码如下。


   
   
  1. import java.util.ArrayList;
  2. import java.util.List;
  3. public class DeptTree {
  4. private Integer id;
  5. private String title;
  6. private boolean checked;
  7. private boolean spread;
  8. private List<DeptTree> children = new ArrayList<>();
  9. public Integer getId() {
  10. return id;
  11. }
  12. public void setId(Integer id) {
  13. this.id = id;
  14. }
  15. public String getTitle() {
  16. return title;
  17. }
  18. public void setTitle(String title) {
  19. this.title = title;
  20. }
  21. public List<DeptTree> getChildren() {
  22. return children;
  23. }
  24. public void setChildren(List<DeptTree> children) {
  25. this.children = children;
  26. }
  27. public boolean isChecked() {
  28. return checked;
  29. }
  30. public void setChecked(boolean checked) {
  31. this.checked = checked;
  32. }
  33. public boolean isSpread() {
  34. return spread;
  35. }
  36. public void setSpread(boolean spread) {
  37. this.spread = spread;
  38. }
  39. }

后台接收到传递过来的JSON数据字符串,转换后输出方法。


   
   
  1. @RequestMapping(value = "/checkedGain")
  2. @ResponseBody
  3. public void checkedGain(String data){
  4. List<DeptTree> array2 = JSONArray.parseArray( data, DeptTree. class);
  5. treeData(array2);
  6. }
  7. //递归输出选中数据
  8. private void treeData(List<DeptTree> array2) {
  9. for (DeptTree tree: array2){
  10. System. out.println(tree.getTitle()+ "==="+tree.getId());
  11. if(tree.getChildren() != null){
  12. treeData(tree.getChildren());
  13. }
  14. }
  15. }

选中节点,点击获取选中节点数据。

后台对应方法接收到数据,转换后输出结果。

数据拿到了,之后保存方法就简单了。

后台方法代码基本都在上面了,页面全部代码。


   
   
  1. <style type="text/css">
  2. #dept_main, #dept_particulars{
  3. width: 48.5%;
  4. display: inline-block;
  5. vertical-align: top;
  6. padding: 20px;
  7. background: white;
  8. box-sizing: border-box;
  9. }
  10. #dept_tree{
  11. margin-top: 20px;
  12. }
  13. </style>
  14. <div id="dept_main" style="margin-right: 2%;">
  15. <fieldset class="layui-elem-field layui-field-title">
  16. <legend>所有部门 </legend>
  17. </fieldset>
  18. <button class="layui-btn layui-btn-sm layui-btn-radius layui-btn-normal" lay-demo="addDept"> <i class="layui-icon"> &#xe654; </i>添加部门 </button>
  19. <button class="layui-btn layui-btn-sm layui-btn-radius layui-btn-normal" lay-demo="gain">获取选中节点 </button>
  20. <div id="dept_tree">
  21. </div>
  22. </div>
  23. <div id="dept_particulars">
  24. <fieldset class="layui-elem-field layui-field-title">
  25. <legend>部门详情 </legend>
  26. </fieldset>
  27. <div id="dept_home">
  28. <div class="layui-tree-emptyText">无数据 </div>
  29. </div>
  30. </div>
  31. <script type="text/javascript">
  32. layui.use([ 'tree', 'util', 'layer'], function() {
  33. var tree = layui.tree;
  34. var util = layui.util;
  35. var layer = layui.layer;
  36. tree.render({
  37. elem: '#dept_tree',
  38. data: getData(),
  39. id: 'treeId',
  40. showCheckbox: true, //时候显示复选框
  41. onlyIconControl: true,
  42. edit: [ 'add', 'update', 'del'], //操作节点的图标
  43. click: function (obj) {
  44. var id = obj.data.id;
  45. $( "#dept_home").load( "dept/show?id="+id);
  46. },
  47. operate: function(obj){
  48. var type = obj.type; //得到操作类型:add、edit、del
  49. var data = obj.data; //得到当前节点的数据
  50. var elem = obj.elem; //得到当前节点元素
  51. var id = data.id;
  52. var name = data.title;
  53. if(type === 'add'){ //增加节点
  54. $.post( "dept/save", { parentId: id, name: "未命名"}, function (result) {
  55. tree.reload( 'treeId', { data: getData()});
  56. })
  57. //返回 key 值
  58. return ;
  59. } else if(type === 'update'){ //修改节点
  60. $.post( "dept/update", { id: id, name: name}, function () {
  61. tree.reload( 'treeId', { data: getData()});
  62. })
  63. } else if(type === 'del'){ //删除节点
  64. $.post( "dept/delete", { id: id}, function () {
  65. tree.reload( 'treeId', { data: getData()});
  66. });
  67. };
  68. }
  69. });
  70. util.event( 'lay-demo', {
  71. addDept: function(othis){
  72. $.get( 'dept/edit', function(data) {
  73. layer.open({
  74. type: 1,
  75. title: '新增',
  76. area: [ '530px'],
  77. content: data,
  78. btn: [ '提交', '退出'],
  79. yes: function () {
  80. },
  81. success: function (layero, index) {
  82. layui.use( 'form', function () {
  83. var form = layui.form;
  84. layero.addClass( 'layui-form');
  85. var submitBtn = layero.find( '.layui-layer-btn0');
  86. submitBtn.attr( 'lay-filter', 'formVerify').attr( 'lay-submit', '');
  87. layero.keydown( function (e) {
  88. if (e.keyCode == 13) {
  89. submitBtn.click();
  90. }
  91. });
  92. form.on( 'submit(formVerify)', function (data) {
  93. $.post( 'dept/save', data.field, function (result) {
  94. if (result.success) {
  95. layer.close(index);
  96. tree.reload( 'treeId', { data: getData()});
  97. }
  98. layer.msg(result.msg, { offset: 'rb'});
  99. });
  100. return false;
  101. });
  102. });
  103. }
  104. })
  105. })
  106. },
  107. gain: function () {
  108. var checkData = tree.getChecked( 'treeId');
  109. var str = JSON.stringify(checkData);
  110. $.post( 'dept/checkedGain', { data: str}, function () {
  111. });
  112. layer.alert( JSON.stringify(checkData), { shade: 0});
  113. }
  114. });
  115. });
  116. function getData(){
  117. var data = [];
  118. $.ajax({
  119. url: "dept/treeload", //后台数据请求地址
  120. type: "post",
  121. async: false,
  122. success: function(resut){
  123. data = resut;
  124. }
  125. });
  126. return data;
  127. }
  128. </script>

如果对你有帮助,点赞关注一下呗^_^,留下你的足迹。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值