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、运行效果

  • 相关阅读:
    8.10
    今日头条笔试题 1~n的每个数,按字典序排完序后,第m个数是什么?
    Gym 100500B Conference Room(最小表示法,哈希)
    CodeForces 438D The Child and Sequence(线段树)
    UVALIVE 6905 Two Yachts(最小费用最大流)
    Gym Conference Room (最小表示法,哈希)
    hdu 2389 Rain on your Parade(二分图HK算法)
    Codeforces Fox And Dinner(最大流)
    zoj 3367 Counterfeit Money(dp)
    ZOJ3370. Radio Waves(2-sat)
  • 原文地址:https://www.cnblogs.com/iflytek/p/9370090.html
Copyright © 2011-2022 走看看