尚筹网 —— 6、菜单维护

目录

1、树形结构基础知识

1.1、节点类型

1.2、在数据库表中表示属性结构

1.2.1、创建菜单的数据库表

1.2.2、插入数据

1.2.3、关联方式

1.3、在 Java 类中表示属性结构

1.3.1、基本方式

1.3.2、为了配合 zTree 所需添加的属性

2、菜单维护:页面显示树型结构

2.1、目标

2.2、思路

2.3、逆向工程生成资源

2.4、将数据在 Java 代码中组装成树形结构 

2.4.1、生成 service 层方法

2.4.2、完成 handle 方法

2.5、跳转页面

2.6、引入 zTree 环境

2.7、创建 menu-page.jsp 页面

2.8、修改侧边栏菜单维护的跳转地址

2.9、在页面上显示树形结构

遇到的问题:树形结构的图标不显示

2.10、实现点击不跳转

2.11、添加按钮组

2.11.1、思路

2.11.2、步骤

2.12、将生成树形结构的代码封装为函数

3、添加子节点

3.1、目标

3.2、思路

3.3、代码

3.3.1、导入前端页面

        出现的问题:

3.3.2、完成 service 方法

3.3.3、完成 handle 方法

3.3.4、给添加子节点按钮绑定单击事件

3.3.5、给添加子节点的模态框中的保存按钮绑定单击事件

4、更新节点

4.1、目标

4.2、思路

4.3、代码

4.3.1、给修改按钮绑定单击事件

4.3.2、给更新模态框中的更新按钮绑定单击事件

4.3.3、完成 service 方法

4.3.4、完成 handle 方法

5、删除节点

5.1、思路

5.3、代码

5.3.1、给删除节点按钮绑定单击事件

5.3.2、给确认模态框的确认按钮绑定单击事件

5.3.3、完成 service 方法

5.3.4、完成 handle 方法


1、树形结构基础知识

1.1、节点类型

约定:整个树形结构节点的层次最多只能有 3 级

1.2、在数据库表中表示属性结构

1.2.1、创建菜单的数据库表

pid 时是父节点的 id 

create table t_menu
(
	id int(11) not null auto_increment, 
	pid int(11), 
	name varchar(200), 
	url varchar(200),
	icon varchar(200), 
	primary key (id)
);

1.2.2、插入数据

INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('1',NULL,'系统权限菜单','glyphiconglyphicon-th-list',NULL);
INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('2','1',' 控 制 面 板 ','glyphiconglyphicon-dashboard','main.htm');
INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('3','1','权限管理','glyphicon glyphiconglyphicon-tasks',NULL);
INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('4','3',' 用 户 维 护 ','glyphiconglyphicon-user','user/index.htm');
INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('5','3',' 角 色 维 护 ','glyphiconglyphicon-king','role/index.htm');
INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('6','3',' 菜 单 维 护 ','glyphiconglyphicon-lock','permission/index.htm');
INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('7','1',' 业 务 审 核 ','glyphiconglyphicon-ok',NULL);
INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('8','7',' 实 名 认 证 审 核 ','glyphiconglyphicon-check','auth_cert/index.htm');
INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('9','7',' 广 告 审 核 ','glyphiconglyphicon-check','auth_adv/index.htm');
INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('10','7',' 项 目 审 核 ','glyphiconglyphicon-check','auth_project/index.htm');
INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('11','1',' 业 务 管 理 ','glyphiconglyphicon-th-large',NULL);
INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('12','11',' 资 质 维 护 ','glyphiconglyphicon-picture','cert/index.htm');
INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('13','11',' 分 类 管 理 ','glyphiconglyphicon-equalizer','certtype/index.htm');
INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('14','11',' 流 程 管 理 ','glyphiconglyphicon-random','process/index.htm');
INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('15','11',' 广 告 管 理 ','glyphiconglyphicon-hdd','advert/index.htm');
INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('16','11',' 消 息 模 板 ','glyphiconglyphicon-comment','message/index.htm');
INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('17','11',' 项 目 分 类 ','glyphiconglyphicon-list','projectType/index.htm');
INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('18','11',' 项 目 标 签 ','glyphiconglyphicon-tags','tag/index.htm');
INSERT INTO `t_menu` (`id`, `pid`, `name`, `icon`, `url`) VALUES('19','1',' 参 数 管 理 ','glyphiconglyphicon-list-alt','param/index.htm');

1.2.3、关联方式

子节点通过 pid 字段关联到父节点的 id 字段,建立父子关系。根节点的 pid 为 null。

1.3、在 Java 类中表示属性结构

1.3.1、基本方式

在 Menu 类中使用 属性存储 List<Menu> children 当前节点的子节点。

1.3.2、为了配合 zTree 所需添加的属性

pid 属性:找到父节点

name 属性:作为节点名称

icon 属性:当前节点使用的图标

open 属性:控制节点是否默认打开

url 属性:点击节点时跳转的位置

2、菜单维护:页面显示树型结构

2.1、目标

将数据库中查询得到的数据到页面上显示出来。

2.2、思路

数据库查询全部→Java 对象组装→页面上使用 zTree 显示

2.3、逆向工程生成资源

① 在 atcrowdfunding06-common-reverse 模块的 resources 下的 generatorConfig.xml 修改配置相关信息

        <!-- 数据库表名字和我们的entity 类对应的映射指定-->
        <!--<table tableName="t_admin" domainObjectName="Admin" />-->
        <!--<table tableName="t_role" domainObjectName="Role" />-->
        <table tableName="t_menu" domainObjectName="Menu" />

② 执行逆向工程

③ 在生成的 Menu 类添加配合 zTree 使用的属性,并生成 get/set 方法、构造器、toString() 方法

    // 主键
    private Integer id;

    // 父节点的id
    private Integer pid;

    // 节点名称
    private String name;

    // 节点附带的URL地址,是将来点击菜单项时要跳转的地址
    private String url;

    // 节点图标的样式
    private String icon;

    // 存储子节点的集合,初始化是为了避免空指针异常
    private List<Menu> children = new ArrayList<>();

    // 控制节点是否默认为打开状态,true表示默认打开
    private Boolean open = true;

    public Menu() {
    }

    public Menu(Integer id, Integer pid, String name, String url, String icon, List<Menu> children, Boolean open) {
        this.id = id;
        this.pid = pid;
        this.name = name;
        this.url = url;
        this.icon = icon;
        this.children = children;
        this.open = open;
    }

    public List<Menu> getChildren() {
        return children;
    }

    public void setChildren(List<Menu> children) {
        this.children = children;
    }

    @Override
    public String toString() {
        return "Menu{" +
                "id=" + id +
                ", pid=" + pid +
                ", name='" + name + '\'' +
                ", url='" + url + '\'' +
                ", icon='" + icon + '\'' +
                ", children=" + children +
                ", open=" + open +
                '}';
    }

④ 将生成的资源归位

2.4、将数据在 Java 代码中组装成树形结构 

2.4.1、生成 service 层方法

MenuService

package com.atguigu.crowd.service.api;

import com.atguigu.crowd.entity.Menu;

import java.util.List;

/**
 * @Author zhang
 * @Date 2022/5/9 - 21:18
 * @Version 1.0
 */
public interface MenuService {
    /**
     * 获取全部菜单信息
     * @return
     */
    List<Menu> getAll();
}

MenuServiceImpl

package com.atguigu.crowd.service.impl;

import com.atguigu.crowd.entity.Menu;
import com.atguigu.crowd.entity.MenuExample;
import com.atguigu.crowd.mapper.MenuMapper;
import com.atguigu.crowd.service.api.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Author zhang
 * @Date 2022/5/9 - 21:18
 * @Version 1.0
 */
@Service
public class MenuServiceImpl implements MenuService {

    @Autowired
    private MenuMapper menuMapper;

    /**
     * 获取全部菜单信息
     * @return
     */
    @Override
    public List<Menu> getAll() {
        return menuMapper.selectByExample(new MenuExample());
    }
}

2.4.2、完成 handle 方法

MenuHandle

package com.atguigu.crowd.mvc.handle;

import com.atguigu.crowd.entity.Menu;
import com.atguigu.crowd.service.api.MenuService;
import com.atguigu.crowd.util.ResultEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author zhang
 * @Date 2022/5/9 - 21:19
 * @Version 1.0
 */
@Controller
public class MenuHandle {

    @Autowired
    private MenuService menuService;

    @ResponseBody
    @RequestMapping("/menu/get/whole/tree.json")
    public ResultEntity<Menu> getAll() {
        // 查询全部的menu对象
        List<Menu> menuList = menuService.getAll();

        // 声明一个变量用来存储找到的根节点
        Menu root = null;

        // 创建Map对象用来存储id和Menu对象的对应关系便于查找父节点
        Map<Integer,Menu> menuMap = new HashMap<>();

        // 遍历menuList找出所有id所对应的menu
        for (Menu menu : menuList) {
            // 获取当前菜单的id
            Integer id = menu.getId();

            // 填充menuMap:id所对应的menu对象
            menuMap.put(id,menu);
        }


        for (Menu menu : menuList) {
            // 获取父节点id
            Integer pid = menu.getPid();

            // 若父节点为空,则该节点为根节点
            if (pid == null) {
                // 赋值根节点
                root = menu;
                continue;
            }

            // 若父节点不为空,则找出对应关系
            Menu father = menuMap.get(pid);

            // 将当前节点放入父节点的子节点列表中
            father.getChildren().add(menu);
        }

        // 根节点包含了整个树形结构,返回根节点就是返回整个树
        return ResultEntity.successWithData(root);
    }


}

2.5、跳转页面

spring-web-mvc.xml

<mvc:view-controller path="/menu/to/page.html" view-name="menu-page"/>

2.6、引入 zTree 环境

2.7、创建 menu-page.jsp 页面

注意引入 zTree 环境 

在 WEB-INF 下创建

<%--
  Created by IntelliJ IDEA.
  User: zhang
  Date: 2022/5/9
  Time: 23:08
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html lang="zh-CN">

<%@include file="/WEB-INF/include-head.jsp" %>

<%-- 引入zTree环境 --%>
<link rel="stylesheet" href="ztree/zTreeStyle.css">
<script type="text/javascript" src="ztree/jquery.ztree.all-3.5.min.js"></script>

<body>

<%@include file="/WEB-INF/include-nav.jsp" %>

<div class="container-fluid">
    <div class="row">
        <%@include file="/WEB-INF/include-sidebar.jsp" %>
        <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">

            <div class="panel panel-default">
                <div class="panel-heading"><i class="glyphicon glyphicon-th-list"></i> 权限菜单列表
                    <div style="float:right;cursor:pointer;" data-toggle="modal" data-target="#myModal"><i
                            class="glyphicon glyphicon-question-sign"></i></div>
                </div>
                <div class="panel-body">
                    <ul id="treeDemo" class="ztree"></ul>
                </div>
            </div>
        </div>
    </div>
</div>

</body>
</html>

2.8、修改侧边栏菜单维护的跳转地址

          <li style="height:30px;">
            <a href="menu/to/page.html"><i class="glyphicon glyphicon-lock"></i> 菜单维护</a>
          </li>

2.9、在页面上显示树形结构

遇到的问题:树形结构的图标不显示

解决方法:数据库 icon 字段数据错误,在第一个 glyphicon 后要加一个空格,如下图

menu-page.jsp

        // 1.准备生成树形结构的JSON数据,数据的来源是发送Ajax请求得到
        $.ajax({
            "url": "menu/get/whole/tree.json",
            "type":"post",
            "dataType":"json",
            "success":function(response){
                var result = response.result;
                if(result == "SUCCESS") {

                    // 2.创建JSON对象用于存储对zTree所做的设置
                    var setting = {
                        "view": {
                            "addDiyDom": myAddDiyDom
                        }
                    };

                    // 3.从响应体中获取用来生成树形结构的JSON数据
                    var zNodes = response.data;

                    // 4.初始化树形结构
                    $.fn.zTree.init($("#treeDemo"), setting, zNodes);
                }

                if(result == "FAILED") {
                    layer.msg(response.message);
                }
            }
        });

 

// 生成树形结构的函数
function generateTree() {
    // 1.准备生成树形结构的JSON数据,数据的来源是发送Ajax请求得到
    $.ajax({
        "url": "menu/get/whole/tree.json",
        "type":"post",
        "dataType":"json",
        "success":function(response){
            var result = response.result;
            if(result == "SUCCESS") {

                // 2.创建JSON对象用于存储对zTree所做的设置
                var setting = {
                    "view": {
                        "addDiyDom": myAddDiyDom
                    }
                };

                // 3.从响应体中获取用来生成树形结构的JSON数据
                var zNodes = response.data;

                // 4.初始化树形结构
                $.fn.zTree.init($("#treeDemo"), setting, zNodes);
            }

            if(result == "FAILED") {
                layer.msg(response.message);
            }
        }
    });
}

// 在鼠标离开节点范围时删除按钮组
function myRemoveHoverDom(treeId, treeNode) {

    // 拼接按钮组的id
    var btnGroupId = treeNode.tId + "_btnGrp";

    // 移除对应的元素
    $("#"+btnGroupId).remove();

}

// 在鼠标移入节点范围时添加按钮组
function myAddHoverDom(treeId, treeNode) {

    // 按钮组的标签结构:<span><a><i></i></a><a><i></i></a></span>
    // 按钮组出现的位置:节点中treeDemo_n_a超链接的后面

    // 为了在需要移除按钮组的时候能够精确定位到按钮组所在span,需要给span设置有规律的id
    var btnGroupId = treeNode.tId + "_btnGrp";

    // 判断一下以前是否已经添加了按钮组
    if($("#"+btnGroupId).length > 0) {
        return ;
    }

    // 准备各个按钮的HTML标签
    var addBtn = "<a id='"+treeNode.id+"' class='addBtn btn btn-info dropdown-toggle btn-xs' style='margin-left:10px;padding-top:0px;' href='#' title='添加子节点'>&nbsp;&nbsp;<i class='fa fa-fw fa-plus rbg '></i></a>";
    var removeBtn = "<a id='"+treeNode.id+"' class='removeBtn btn btn-info dropdown-toggle btn-xs' style='margin-left:10px;padding-top:0px;' href='#' title='删除节点'>&nbsp;&nbsp;<i class='fa fa-fw fa-times rbg '></i></a>";
    var editBtn = "<a id='"+treeNode.id+"' class='editBtn btn btn-info dropdown-toggle btn-xs' style='margin-left:10px;padding-top:0px;' href='#' title='修改节点'>&nbsp;&nbsp;<i class='fa fa-fw fa-edit rbg '></i></a>";

    // 获取当前节点的级别数据
    var level = treeNode.level;

    // 声明变量存储拼装好的按钮代码
    var btnHTML = "";

    // 判断当前节点的级别
    if(level == 0) {
        // 级别为0时是根节点,只能添加子节点
        btnHTML = addBtn;
    }

    if(level == 1) {
        // 级别为1时是分支节点,可以添加子节点、修改
        btnHTML = addBtn + " " + editBtn;

        // 获取当前节点的子节点数量
        var length = treeNode.children.length;

        // 如果没有子节点,可以删除
        if(length == 0) {
            btnHTML = btnHTML + " " + removeBtn;
        }

    }

    if(level == 2) {
        // 级别为2时是叶子节点,可以修改、删除
        btnHTML = editBtn + " " + removeBtn;
    }

    // 找到附着按钮组的超链接
    var anchorId = treeNode.tId + "_a";

    // 执行在超链接后面附加span元素的操作
    $("#"+anchorId).after("<span id='"+btnGroupId+"'>"+btnHTML+"</span>");

}

// 修改默认的图标
function myAddDiyDom(treeId, treeNode) {

    // treeId是整个树形结构附着的ul标签的id
    console.log("treeId="+treeId);

    // 当前树形节点的全部的数据,包括从后端查询得到的Menu对象的全部属性
    console.log(treeNode);

    // zTree生成id的规则
    // 例子:treeDemo_7_ico
    // 解析:ul标签的id_当前节点的序号_功能
    // 提示:“ul标签的id_当前节点的序号”部分可以通过访问treeNode的tId属性得到
    // 根据id的生成规则拼接出来span标签的id
    var spanId = treeNode.tId + "_ico";

    // 根据控制图标的span标签的id找到这个span标签
    // 删除旧的class
    // 添加新的class
    $("#"+spanId)
        .removeClass()
        .addClass(treeNode.icon);

}

2.10、实现点击不跳转

menu-page.jsp 

在设置数组 setting 添加 data.key.url 属性

                    var setting = {
                        "view": {
                            "addDiyDom": myAddDiyDom
                        },
                        "data" : {
                            "key" : {
                                "url" : "maomi"
                            }
                        }
                    };

2.11、添加按钮组

2.11.1、思路

在鼠标移入时添加按钮组,鼠标移出后删除按钮组。 

根据 treeNode 中的 level 属性,可得按钮增删改查的规则:
        level0:根节点。添加子节点
        level1:分支节点。修改、添加、没有子节点可以删除、有子节点不能删除
        level2:叶子节点。修改、删除

2.11.2、步骤

① menu-page.jsp:在设置数组 setting 添加 maddHoverDom、removeHoverDom 属性

                    var setting = {
                        "view": {
                            "addDiyDom": myAddDiyDom,
                            "addHoverDom" : myAddHoverDom,
                            "removeHoverDom" : myRemoveHoverDom
                        },
                        "data" : {
                            "key" : {
                                "url" : "maomi"
                            }
                        }
                    };

② my-menu.js:添加鼠标移出节点时删除按钮组的函数

// 在鼠标离开节点范围时删除按钮组
function myRemoveHoverDom(treeId, treeNode) {
    // 拼接按钮组的id
    var btnGroupId = treeNode.tId + "_btnGrp";

    // 移除对应的元素
    $("#"+btnGroupId).remove();
}

③ my-menu.js:添加鼠标移入节点时显示按钮组,且按钮组根据节点增删改规律添加按钮

// 在鼠标移入节点范围时添加按钮组
function myAddHoverDom(treeId, treeNode) {
    // 按钮组的标签结构:<span><a><i></i></a><a><i></i></a></span>
    // 按钮组出现的位置:节点中treeDemo_n_a超链接的后面

    // 为了在需要移除按钮组的时候能够精确定位到按钮组所在span,需要给span设置有规律的id
    var btnGroupId = treeNode.tId + "_btnGrp";

    // 判断以前是否已经添加了按钮组
    if($("#"+btnGroupId).length > 0) {
        return ;
    }

    // 准备各个按钮的HTML标签,id属性为当前节点的id
    var addBtn = "<a id='"+treeNode.id+"' class='addBtn btn btn-info dropdown-toggle btn-xs' style='margin-left:10px;padding-top:0px;' href='#' title='添加子节点'>&nbsp;&nbsp;<i class='fa fa-fw fa-plus rbg '></i></a>";
    var removeBtn = "<a id='"+treeNode.id+"' class='removeBtn btn btn-info dropdown-toggle btn-xs' style='margin-left:10px;padding-top:0px;' href='#' title='删除节点'>&nbsp;&nbsp;<i class='fa fa-fw fa-times rbg '></i></a>";
    var editBtn = "<a id='"+treeNode.id+"' class='editBtn btn btn-info dropdown-toggle btn-xs' style='margin-left:10px;padding-top:0px;' href='#' title='修改节点'>&nbsp;&nbsp;<i class='fa fa-fw fa-edit rbg '></i></a>";

    // 获取当前节点的级别数据
    var level = treeNode.level;

    // 声明变量存储拼装好的按钮代码
    var btnHTML = "";

    // 判断当前节点的级别
    if(level == 0) {
        // 级别为0时是根节点,只能添加子节点
        btnHTML = addBtn;
    }
    if(level == 1) {
        // 级别为1时是分支节点,可以添加子节点、修改
        btnHTML = addBtn + " " + editBtn;

        // 获取当前节点的子节点数量
        var length = treeNode.children.length;

        // 如果没有子节点,可以删除
        if(length == 0) {
            btnHTML = btnHTML + " " + removeBtn;
        }
    }
    if(level == 2) {
        // 级别为2时是叶子节点,可以修改、删除
        btnHTML = editBtn + " " + removeBtn;
    }

    // 找到附着按钮组的超链接
    var anchorId = treeNode.tId + "_a";

    // 执行在超链接后面附加span元素的操作
    $("#"+anchorId).after("<span id='"+btnGroupId+"'>"+btnHTML+"</span>");
}

2.12、将生成树形结构的代码封装为函数

my-menu.js

// 生成树形结构的函数
function generateTree() {
    // 准备生成树形结构的JSON数据,数据的来源是发送Ajax请求得到
    $.ajax({
        "url": "menu/get/whole/tree.json",
        "type":"post",
        "dataType":"json",
        "success":function(response){
            var result = response.result;
            if(result == "SUCCESS") {

                // 创建JSON对象用于存储对zTree所做的设置
                var setting = {
                    "view": {
                        "addDiyDom": myAddDiyDom,
                        "addHoverDom" : myAddHoverDom,
                        "removeHoverDom" : myRemoveHoverDom
                    },
                    "data" : {
                        "key" : {
                            "url" : "maomi"
                        }
                    }
                };

                // 从响应体中获取用来生成树形结构的JSON数据
                var zNodes = response.data;

                // 4.初始化树形结构
                $.fn.zTree.init($("#treeDemo"), setting, zNodes);
            }

            if(result == "FAILED") {
                layer.msg(response.message);
            }
        }
    });
}

3、添加子节点

3.1、目标

给当前节点添加子节点,保存到数据库并刷新树形结构的显示。

3.2、思路

3.3、代码

3.3.1、导入前端页面

在 modal-menu-edit.jsp 页面引入这三个页面

<%@include file="/WEB-INF/modal-menu-add.jsp"%>
<%@include file="/WEB-INF/modal-menu-confirm.jsp"%>
<%@include file="/WEB-INF/modal-menu-edit.jsp"%>

出现的问题:

报错:Page指令:非法出现多次出现的'contentType'具有不同的值(old:[text/html;charset=UTF-8],new:[text/html; charset=UTF-8])

原因:引入的 jsp 页面与现 jsp 页面的 contentType 不一致,将引入的前端页面的头改为与现在的一样即可

3.3.2、完成 service 方法

MenuService

    /**
     * 保存菜单节点
     * @param menu 要保存的菜单节点
     */
    void saveMenu(Menu menu);

MenuServiceImpl

    /**
     * 保存菜单节点
     * @param menu 要保存的菜单节点
     */
    @Override
    public void saveMenu(Menu menu) {
        menuMapper.insert(menu);
    }

3.3.3、完成 handle 方法

MenuHandle

    @ResponseBody
    @RequestMapping("/menu/save.json")
    public ResultEntity<String> saveMenu(Menu menu){
        menuService.saveMenu(menu);
        return ResultEntity.successWithoutData();
    }

3.3.4、给添加子节点按钮绑定单击事件

        // 给添加子节点按钮绑定单击事件
        $("#treeDemo").on("click", ".addBtn", function (){
            // 将当前节点的id作为新节点的pid保存到全局变量
            window.pid = this.id;

            // 打开添加节点的模态框
            $("#menuAddModal").modal("show");
            return false;
        });

3.3.5、给添加子节点的模态框中的保存按钮绑定单击事件

        // 给添加子节点的模态框中的保存按钮绑定单击事件
        $("#menuSaveBtn").click(function (){
            // 获取表单项中用户输入的数据
            var name = $.trim($("#menuAddModal [name=name]").val());
            var url = $.trim($("#menuAddModal [name=url]").val())
            var icon = $("#menuAddModal [name=icon]:checked").val()

            // 发送Ajax请求
            $.ajax({
                "url" : "menu/save.json",
                "type" : "post",
                "data" : {
                    "pid" : window.pid,
                    "name" : name,
                    "url" : url,
                    "icon" : icon
                },
                "dataType" : "json",
                "success" : function (response){
                    var result = response.result;
                    if(result == "SUCCESS"){
                        layer.msg("操作成功!");
                    }
                    if(result == "FAILED"){
                        layer.msg("操作失败!" + response.message);
                    }
                    // 在保存成功后刷新树形结构(重新生成)
                    generateTree();
                },
                "error" : function (response){
                    layer.msg(response.status + " " + response.statusText);
                }
            });

            // 关闭模态框
            $("#menuAddModal").modal("hide");

            // 清空表单:通过代码点击添加子节点的模态框中的重置按钮实现
            $("#menuResetBtn").click();
        });

4、更新节点

4.1、目标

contentType修改当前节点的基本属性。不更换父节点。

4.2、思路

4.3、代码

4.3.1、给修改按钮绑定单击事件

        // 给修改节点按钮绑定单击事件
        $("#treeDemo").on("click", ".editBtn", function (){
            // 将当前节点的id保存到全局变量
            window.id = this.id;

            // 打开编辑节点的模态框
            $("#menuEditModal").modal("show");

            // 获取zTreeObj对象
            var zTreeObj = $.fn.zTree.getZTreeObj("treeDemo");

            // 根据id属性查询节点对象
            var key = "id"; // 用来搜索节点的属性名
            var value = window.id; // 用来搜索节点的属性值
            var currentNode = zTreeObj.getNodeByParam(key, value);

            // 回显表单数据
            $("#menuEditModal [name=name]").val(currentNode.name);
            $("#menuEditModal [name=url]").val(currentNode.url);
            // 回显 radio 可以这样理解:被选中的radio的value属性可以组成一个数组,然后再用这个数组设置回radio就能够把对应的值选中
            // 注意值放在数组里
            $("#menuEditModal [name=icon]").val([currentNode.icon]);

            return false;
        });

4.3.2、给更新模态框中的更新按钮绑定单击事件

menu-page.jsp

        // 给更新模态框中的更新按钮绑定单击事件
        $("#menuEditBtn").click(function (){
            // 收集表单数据
            var name = $("#menuEditModal [name=name]").val();
            var url = $("#menuEditModal [name=url]").val();
            var icon = $("#menuEditModal [name=icon]:checked").val();

            // 发送Ajax请求
            $.ajax({
                "url" : "menu/update.json",
                "type" : "post",
                "data" : {
                    "id" : window.id,
                    "name" : name,
                    "url" : url,
                    "icon" : icon
                },
                "dataType" : "json",
                "success" : function (response){
                    var result = response.result;
                    if(result == "SUCCESS"){
                        layer.msg("操作成功!");
                    }
                    if(result == "FAILED"){
                        layer.msg("操作失败!" + response.message);
                    }
                    // 在保存成功后刷新树形结构(重新生成)
                    generateTree();
                },
                "error" : function (response){
                    layer.msg(response.status + " " + response.statusText);
                }
            });

            // 关闭模态框
            $("#menuEditModal").modal("hide");
        });

4.3.3、完成 service 方法

MenuService

    /**
     * 更新菜单节点
     * @param menu 要更新的菜单节点
     */
    void updateMenu(Menu menu);

MenuServiceImpl

    /**
     * 更新菜单节点
     * @param menu 要更新的菜单节点
     */
    @Override
    public void updateMenu(Menu menu) {
        menuMapper.updateByPrimaryKeySelective(menu);
    }

4.3.4、完成 handle 方法

MenuHandle

    @ResponseBody
    @RequestMapping("/menu/update.json")
    public ResultEntity<String> updateMenu(Menu menu){
        menuService.updateMenu(menu);
        return ResultEntity.successWithoutData();
    }

5、删除节点

5.1、思路

5.3、代码

5.3.1、给删除节点按钮绑定单击事件

menu-page.jsp 

        // 给删除节点按钮绑定单击事件
        $("#treeDemo").on("click", ".removeBtn", function (){
            // 将当前节点的id保存到全局变量
            window.id = this.id;

            // 打开确认删除的模态框
            $("#menuConfirmModal").modal("show");

            // 获取zTreeObj对象
            var zTreeObj = $.fn.zTree.getZTreeObj("treeDemo");

            // 根据id属性查询节点对象
            var key = "id"; // 用来搜索节点的属性名
            var value = window.id; // 用来搜索节点的属性值
            var currentNode = zTreeObj.getNodeByParam(key, value);

            $("#removeNodeSpan").html("&nbsp;&nbsp;<i class='"+currentNode.icon+"'></i>" + currentNode.name + "&nbsp;&nbsp;");
            return false;
        });

5.3.2、给确认模态框的确认按钮绑定单击事件

        // 给确认模态框的确认按钮绑定单击事件
        $("#confirmBtn").click(function (){
            $.ajax({
                "url" : "menu/remove.json",
                "type" : "post",
                "data" : {
                    "id" : window.id
                },
                "dataType" : "json",
                "success" : function (response){
                    var result = response.result;
                    if(result == "SUCCESS"){
                        layer.msg("操作成功!");
                    }
                    if(result == "FAILED"){
                        layer.msg("操作失败!" + response.message);
                    }

                    // 刷新菜单页面
                    generateTree();
                }
            });

            $("#menuConfirmModal").modal("hide");
        });
    });

5.3.3、完成 service 方法

MenuService

    /**
     * 根据id删除菜单节点
     * @param id 要删除的菜单节点的id
     */
    void removeMenu(Integer id);

MenuServiceImpl

    /**
     * 根据id删除菜单节点
     * @param id 要删除的菜单节点的id
     */
    @Override
    public void removeMenu(Integer id) {
        menuMapper.deleteByPrimaryKey(id);
    }

5.3.4、完成 handle 方法

    @ResponseBody
    @RequestMapping("/menu/remove.json")
    public ResultEntity<String> removeMenu(@RequestParam("id") Integer id){
        menuService.removeMenu(id);
        return ResultEntity.successWithoutData();
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值