zoukankan      html  css  js  c++  java
  • 【原】无脑操作:EasyUI Tree实现左键只选择叶子节点、右键浮动菜单实现增删改

    Easyui中的Tree组件使用频率颇高,经常遇到的需求如下:

    1、在树形结构上,只有叶子节点才能被选中,其他节点不能被选中;

    2、在叶子节点上右键出现浮动菜单实现新增、删除、修改操作;

    3、在非叶子节点上右键出现浮动菜单实现新增、修改操作。

    ------------------------------------------------------------------------------------------------------------------

    实现方法如下:

    1、搭建测试环境(可以参考前文:【原】无脑操作:IDEA + maven + SpringBoot + JPA + EasyUI实现CRUD及分页

    2、建库建表

     1 DROP TABLE biz_department;
     2 CREATE TABLE biz_department
     3 (
     4     departmentid INT AUTO_INCREMENT PRIMARY KEY COMMENT '部门编号',
     5     departmentpid INT NOT NULL COMMENT '部门父编号',
     6     departmentname VARCHAR(10) NOT NULL COMMENT '部门名称'
     7 ) ENGINE=INNODB COMMENT='部门信息';
     8 INSERT INTO biz_department VALUES
     9 (NULL, 0, '总部'),
    10 (NULL, 1, '上海分公司'), (NULL, 1, '安徽分公司'),
    11 (NULL, 3, '合肥办事处'), (NULL, 3, '铜陵办事处');

    3、创建实体类 Department.java

     1 @Entity
     2 @Table(name = "biz_department")
     3 public class Department {
     4     @Id
     5     @GeneratedValue(strategy = GenerationType.IDENTITY)
     6     @Column(name = "departmentid")
     7     private Integer departmentid;
     8     @Column(name = "departmentpid")
     9     private Integer departmentpid;
    10     @Column(name = "departmentname")
    11     private String departmentname;
    12 
    13     public Department() {
    14     }
    15 
    16     public Department(Integer departmentpid, String departmentname) {
    17         this.departmentpid = departmentpid;
    18         this.departmentname = departmentname;
    19     }
    20 
    21     public Integer getDepartmentid() {
    22         return departmentid;
    23     }
    24 
    25     public void setDepartmentid(Integer departmentid) {
    26         this.departmentid = departmentid;
    27     }
    28 
    29     public Integer getDepartmentpid() {
    30         return departmentpid;
    31     }
    32 
    33     public void setDepartmentpid(Integer departmentpid) {
    34         this.departmentpid = departmentpid;
    35     }
    36 
    37     public String getDepartmentname() {
    38         return departmentname;
    39     }
    40 
    41     public void setDepartmentname(String departmentname) {
    42         this.departmentname = departmentname;
    43     }
    44 }

    4、编写DAO接口 DepartmentDao.java

    1 /**
    2  * 因为需要使用分页和条件查询,所以从JpaRepository接口 和 JpaSpecificationExecutor接口继承
    3  */
    4 public interface DepartmentDao extends JpaRepository<Department, Integer>, JpaSpecificationExecutor<Department> {
    5 
    6 }

    5、编写工具类 TreeNode.java 和  TreeUtil.java

      1 /**
      2  * EasyUI Tree的封装类
      3  */
      4 public class TreeNode {
      5     private Integer id;                      // 节点的 id
      6     private Integer parentId;                // 父节点id,java生成树时使用
      7     private String text;                    // 显示的节点文字。
      8     private String iconCls;                 // 节点图标样式    "iconCls":"icon-save",  "iconCls":"icon-ok", 等
      9     private String state;                   // 节点状态, 'open' 或 'closed',默认是 'open'。当设为 'closed' 时,此节点有子节点,并且将从远程站点加载它们。
     10     private String flag;                    // 节点类型
     11     private Integer trueId;                 // 应用系统真实 id
     12     private boolean checked;                // 指示节点是否被选中。
     13     private LinkedHashMap<?, ?> attributes; // 给一个节点追加的自定义属性。
     14     private List<TreeNode> children;        // 定义了一些子节点的节点数组。
     15     private String url;                     // 扩展属性url
     16 
     17     public Integer getTrueId() {
     18         return trueId;
     19     }
     20 
     21     public void setTrueId(Integer trueId) {
     22         this.trueId = trueId;
     23     }
     24 
     25     public String getFlag() {
     26         return flag;
     27     }
     28 
     29     public void setFlag(String flag) {
     30         this.flag = flag;
     31     }
     32 
     33     public Integer getId() {
     34         return id;
     35     }
     36 
     37     public void setId(Integer id) {
     38         this.id = id;
     39     }
     40 
     41     public Integer getParentId() {
     42         return parentId;
     43     }
     44 
     45     public void setParentId(Integer parentId) {
     46         this.parentId = parentId;
     47     }
     48 
     49     public String getText() {
     50         return text;
     51     }
     52 
     53     public void setText(String text) {
     54         this.text = text;
     55     }
     56 
     57     public String getIconCls() {
     58         return iconCls;
     59     }
     60 
     61     public void setIconCls(String iconCls) {
     62         this.iconCls = iconCls;
     63     }
     64 
     65     public String getState() {
     66         return state;
     67     }
     68 
     69     public void setState(String state) {
     70         this.state = state;
     71     }
     72 
     73     public boolean isChecked() {
     74         return checked;
     75     }
     76 
     77     public void setChecked(boolean checked) {
     78         this.checked = checked;
     79     }
     80 
     81     public LinkedHashMap<?, ?> getAttributes() {
     82         return attributes;
     83     }
     84 
     85     public void setAttributes(LinkedHashMap<?, ?> attributes) {
     86         this.attributes = attributes;
     87     }
     88 
     89     public List<TreeNode> getChildren() {
     90         return children;
     91     }
     92 
     93     public void setChildren(List<TreeNode> children) {
     94         this.children = children;
     95     }
     96 
     97     public String getUrl() {
     98         return url;
     99     }
    100 
    101     public void setUrl(String url) {
    102         this.url = url;
    103     }
    104 }
     1 /**
     2  * 树工具类
     3  */
     4 public class TreeUtil {
     5     /**
     6      * Tree装配方法
     7      *
     8      * @param tempTreeNodes
     9      * @param treeNodes
    10      * @return
    11      */
    12     public static List<TreeNode> Assemble(List<TreeNode> tempTreeNodes, List<TreeNode> treeNodes) {
    13         if (tempTreeNodes != null) {
    14             Map<Integer, TreeNode> map = new LinkedHashMap<>();
    15             for (TreeNode tn : tempTreeNodes) {
    16                 map.put(tn.getId(), tn);
    17             }
    18 
    19             TreeNode treeNode;
    20             TreeNode pTreeNode;
    21             for (Integer id : map.keySet()) {
    22                 treeNode = map.get(id);
    23                 if (treeNode.getParentId() == 0) {
    24                     treeNodes.add(treeNode);
    25                 } else {
    26                     pTreeNode = map.get(treeNode.getParentId());
    27                     List<TreeNode> children = pTreeNode.getChildren();
    28                     if (children != null) {
    29                         children.add(treeNode);
    30                     } else {
    31                         children = new ArrayList();
    32                         children.add(treeNode);
    33                         pTreeNode.setChildren(children);
    34                     }
    35                 }
    36             }
    37         }
    38 
    39         return treeNodes;
    40     }
    41 }

    6、规划控制器 DepartmentController.java

     1 @Controller
     2 @RequestMapping("/department")
     3 public class DepartmentController {
     4     @Autowired
     5     private DepartmentDao departmentDao;
     6 
     7     @RequestMapping("/view")
     8     public String view() {
     9         // 跳转至【资源管理】页面
    10         return "department";
    11     }
    12 
    13     @RequestMapping("/tree")
    14     @ResponseBody
    15     public String tree() {
    16         List<Department> list = departmentDao.findAll();
    17         List<TreeNode> tempTreeNodes = new ArrayList();
    18         List<TreeNode> treeNodes = new ArrayList();
    19 
    20         // 组装Easyui的Tree必须要有id、parentId、text属性,转换之
    21         for (Department department : list) {
    22             TreeNode tempTreeNode = new TreeNode();
    23             tempTreeNode.setId(department.getDepartmentid());
    24             tempTreeNode.setParentId(department.getDepartmentpid());
    25             tempTreeNode.setText(department.getDepartmentname());
    26             tempTreeNodes.add(tempTreeNode);
    27         }
    28 
    29         return JSONObject.toJSON(TreeUtil.Assemble(tempTreeNodes, treeNodes)).toString();
    30     }
    31 
    32     @RequestMapping("/saveNode")
    33     @ResponseBody
    34     public Map<String, Object> saveNode(Integer departmentpid, String departmentname) {
    35         Department model = new Department();
    36         model.setDepartmentpid(departmentpid);
    37         model.setDepartmentname(departmentname);
    38 
    39         Map<String, Object> resultMap = new HashMap<>();
    40         departmentDao.save(model);
    41         resultMap.put("success", true);
    42         return resultMap;
    43     }
    44 
    45     @RequestMapping("/updateNode")
    46     @ResponseBody
    47     public Map<String, Object> updateNode(Department model) {
    48         Map<String, Object> resultMap = new HashMap<>();
    49         departmentDao.save(model);
    50         resultMap.put("success", true);
    51         return resultMap;
    52     }
    53 
    54     @RequestMapping("/deleteNode")
    55     @ResponseBody
    56     public Map<String, Object> deleteNode(Integer departmentid) {
    57         Map<String, Object> resultMap = new HashMap<>();
    58         departmentDao.deleteById(departmentid);
    59         resultMap.put("success", true);
    60         return resultMap;
    61     }
    62 }

    7、编写前端代码

    HTML页面:department.html

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>测试Tree功能</title>
     6     <link rel="stylesheet" type="text/css" href="../easyui/themes/default/easyui.css">
     7     <link rel="stylesheet" type="text/css" href="../easyui/themes/icon.css">
     8     <script type="text/javascript" src="../easyui/jquery.min.js"></script>
     9     <script type="text/javascript" src="../easyui/jquery.easyui.min.js"></script>
    10     <script type="text/javascript" src="../easyui/locale/easyui-lang-zh_CN.js"></script>
    11     <script type="text/javascript" src="../biz/department.js"></script>
    12 </head>
    13 <body>
    14 <!-- 部门树 -->
    15 <ul id="deptTree" class="easyui-tree"></ul>
    16 <!-- 叶子节点右键菜单 -->
    17 <div id="leaf" class="easyui-menu" style=" 120px;">
    18     <div onclick="addNode()" iconcls="icon-add">新增节点</div>
    19     <div onclick="removeNode()" iconcls="icon-remove">删除节点</div>
    20     <div onclick="updateNode()" iconcls="icon-edit">编辑节点</div>
    21 </div>
    22 <!-- 非叶子节点右键菜单 -->
    23 <div id="parentNode" class="easyui-menu" style=" 120px;">
    24     <div onclick="addNode()" iconcls="icon-add">新增节点</div>
    25     <div onclick="updateNode()" iconcls="icon-edit">编辑节点</div>
    26 </div>
    27 <!-- 节点内容对话框 -->
    28 <div id="info" class="easyui-dialog" style="300px; height: 120px;" closed=true>
    29     <form id="treefrm" method="post">
    30         <input type="hidden" name="departmentid">
    31         <table style="margin: auto;" cellspacing="10">
    32             <tr>
    33                 <td>部门名称</td>
    34                 <td><input class="easyui-textbox" name="departmentname" value="" data-options="required:true"></td>
    35             </tr>
    36         </table>
    37         <div style="text-align: center; bottom: 15px; margin-top: 10px;">
    38             <a id="btnSave" class="easyui-linkbutton"
    39                data-options="iconCls:'icon-save'">保存</a>
    40             <a id="btnCancel" class="easyui-linkbutton"
    41                data-options="iconCls:'icon-cancel'">取消</a>
    42         </div>
    43     </form>
    44 </div>
    45 </body>
    46 </html>

    对应JS文件:department.js

      1 // 记录添加还是修改
      2 var flag;
      3 // 临时存储选中节点数据
      4 var tempNode;
      5 
      6 // 页面加载
      7 $(function () {
      8     // 菜单树绑定数据
      9     $('#deptTree').tree({
     10         url: '/department/tree',
     11         animate: true,
     12         lines: true,
     13         onBeforeSelect: function (node) {
     14             // onBeforeSelect事件:节点被选中前触发,返回false则取消选择动作
     15             if (!$(this).tree('isLeaf', node.target)) {
     16                 // 不是叶子节点,则不能选中
     17                 return false;
     18             }
     19         },
     20         onClick: function (node) {
     21             // alert(node.target.innerText);
     22         },
     23         onContextMenu: function (e, node) {
     24             // 记录选中的节点,为后续增删改操作提供节点数据
     25             tempNode = node;
     26 
     27             // 阻止右键默认事件
     28             e.preventDefault();
     29 
     30             // 判断该结点有没有父结点
     31             var root = $(this).tree('getParent', node.target);
     32             // 没有父节点则为根结点,可以新增、编辑,不可以删除
     33             if (root == null) {
     34                 // 如果是根节点,则可以新增、编辑,不可以删除
     35                 $('#parentNode').menu('show', {
     36                     left: e.pageX,
     37                     top: e.pageY
     38                 });
     39             }
     40 
     41             if ($(this).tree('isLeaf', node.target)) {
     42                 // 如果是叶子节点,则可以新增、编辑和删除
     43                 $('#leaf').menu('show', {
     44                     left: e.pageX,
     45                     top: e.pageY
     46                 });
     47             } else {
     48                 // 如果不是叶子节点,则可以新增、编辑,不可以删除
     49                 $('#parentNode').menu('show', {
     50                     left: e.pageX,
     51                     top: e.pageY
     52                 });
     53             }
     54         }
     55     });
     56 
     57     // 保存按钮押下处理
     58     $('#btnSave').click(function () {
     59         var tempdata, tempurl, tempmsg;
     60 
     61         if (flag == 'add') {
     62             tempurl = 'saveNode';
     63             tempmsg = '添加成功!';
     64             tempdata = {
     65                 departmentpid: tempNode.id,
     66                 departmentname: $('#treefrm').find('input[name=departmentname]').val()
     67             };
     68         } else if (flag == 'edit') {
     69             tempurl = 'updateNode';
     70             tempmsg = '编辑成功!';
     71             tempdata = {
     72                 departmentid: $('#treefrm').find('input[name=departmentid]').val(),
     73                 departmentpid: $('#deptTree').tree('getParent', tempNode.target).id,
     74                 departmentname: $('#treefrm').find('input[name=departmentname]').val()
     75             };
     76         }
     77 
     78         $.ajax({
     79             type: 'post',
     80             async: true,
     81             url: tempurl,
     82             data: tempdata,
     83             dataType: 'json',
     84             success: function (result) {
     85                 // 树重新加载
     86                 $('#deptTree').tree('reload');
     87 
     88                 $.messager.show({
     89                     title: '提示信息',
     90                     msg: tempmsg
     91                 });
     92             },
     93             error: function (result) {
     94                 // 请求失败时执行该函数
     95                 $.messager.show({
     96                     title: '错误信息',
     97                     msg: result.msg
     98                 });
     99             }
    100         });
    101 
    102         $('#treefrm').form('clear');
    103         $('#info').dialog('close');
    104     });
    105 
    106     // 取消按钮押下处理
    107     $('#btnCancel').click(function () {
    108         $('#treefrm').form('clear');
    109         $('#info').dialog('close');
    110     });
    111 });
    112 
    113 // 新增节点
    114 var addNode = function () {
    115     flag = 'add';
    116     // 清空表单数据
    117     $('#treefrm').form('clear');
    118     // 打开dialog
    119     $('#info').dialog('open').dialog('setTitle', '新增');
    120 };
    121 
    122 // 编辑节点
    123 var updateNode = function () {
    124     flag = 'edit';
    125     // 清空表单数据
    126     $('#treefrm').form('clear');
    127     $('#treefrm').form('load', {
    128         departmentid: tempNode.id,
    129         departmentname: tempNode.text
    130     });
    131     // 打开dialog
    132     $('#info').dialog('open').dialog('setTitle', '编辑');
    133 };
    134 
    135 // 删除节点
    136 var removeNode = function () {
    137     // 前台删除
    138     $('#deptTree').tree('remove', tempNode.target);
    139 
    140     // 后台删除
    141     $.ajax({
    142         type: "post",
    143         async: true,           // 异步请求(同步请求将会锁住浏览器,用户其他操作必须等待请求完成才可以执行)
    144         url: "deleteNode",
    145         data: {departmentid: tempNode.id},
    146         dataType: "json",      // 返回数据形式为json
    147         success: function (result) {
    148             // 请求成功时执行该函数内容,result即为服务器返回的json对象
    149             $.messager.show({
    150                 title: '提示信息',
    151                 msg: '删除成功!'
    152             });
    153         },
    154         error: function (result) {
    155             // 请求失败时执行该函数
    156             $.messager.show({
    157                 title: '错误信息',
    158                 msg: result.msg
    159             });
    160         }
    161     });
    162 };

    8、运行效果

  • 相关阅读:
    【C++】基础及引用
    gradle打包分编译环境
    gradle
    MediaPlayer滑动不准的问题
    python初步入门
    音频播放服务
    《深入理解Android2》读书笔记(二)
    缓存(LruCache)机制
    handler机制
    监听网络状态
  • 原文地址:https://www.cnblogs.com/iflytek/p/9370090.html
Copyright © 2011-2022 走看看