java开发疑难杂点汇总

2023-02-17 16:37:21

java开发过程中遇到的新知识、重点、难点以及出错的解决方法的汇总


1.树形结构的基础知识

1.1节点类型

生成页面上的效果(下面的效果)需要用到zTree插件

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

1.2 在数据库表中表示树形结构

在数据库表的记录之间如果没办法建立起父子关系,在页面上显示树形结构就没有依据

1.2.1创建菜单的数据库表

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

1.2.3关联方式(如何建立父子关系):根节点的 pid 为 null

1.3 在java类中表示树形结构

1.3.1基本方式:在Menu类中使用List<Menu> children 属性存储当前节点的子节点

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

  • pid属性:找到父节点
  • name属性:作为节点的名称
  • icon属性:当前节点使用的图标
  • open属性:控制节点是否默认打开
  • url属性:点击节点时跳转的位置

1.4 按钮增删改查的规则

        level 0:根节点
                只能添加子节点
        level 1:分支节点
                修改
                添加子节点
                没有子节点:可以删除
                有子节点:不能删除
        level 2:叶子节点
                修改
                删除

2.1菜单维护:页面显示属性结构

2.1.1目标:将数据库中查询到的数据到页面上显示出来

2.1.2思路:数据库查询全部 → java对象组装 → 页面上使用zTree显示

2.1.3代码:逆向工程生成Menu、MenuExample、MenuMapper、MenuMapper.xml等

    对生成的Menu做一些调整:
    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;
    }

    //主键
    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;

2.1.4代码:将数据在 Java 代码中组装成树形结构

MenuServiceImpl中:
@Override
public List<Menu> getAll() {
    return menuMapper.selectByExample(new MenuExample());
}

MenuController中:改进前,要改进的原因是存在嵌套遍历,如果循环次数较多,对性能是一个极大的消耗
@ResponseBody
@RequestMapping("/menu/get/whole/tree")
public ResultEntity<Menu> getWholeTreeOld(){
    // 1.查询全部的Menu对象
    List<Menu> menuList = menuService.getAll();
    // 2.声明一个变量用来存储找到的根节点
    Menu root = null;
    // 3.遍历menuList
    for (Menu menu : menuList) {
        // 4.获取当前menu对象的pid
        Integer pid = menu.getPid();
        // 5.检查pid是否为空
        if(pid == null){
            // 6.把当前正在遍历的这个menu对象复制给root
            root = menu;
            // 7.停止本次循环,继续执行下一次循环
            continue ;
        }
        // 8.如果pid不为null,说明当前节点有父节点,找到父节点就可以进行组装,建立父子关系
        for(Menu maybeFather : menuList){
            // 9.获取maybeFather的id属性
            Integer id = maybeFather.getId();
            // 10.将子节点的pid和疑似父节点的id进行比较
            if(Objects.equals(pid,id)){
                // 11.将子节点存入父节点的children集合
                maybeFather.getChildren().add(menu);
                // 12.找到即可停止运行循环
                break;
            }
        }
    }
    // 13.经过上面的运算,根节点包含了整个树形结构,返回根节点就是返回整个树
    return ResultEntity.successWithData(root);
}
MenuController中:改进后
@ResponseBody
@RequestMapping("/menu/get/whole/tree")
public ResultEntity<Menu> getWholeTreeNew(){
    // 1.查询全部的Menu对象
    List<Menu> menuList = menuService.getAll();
    // 2.声明一个变量用来存储找到的根节点
    Menu root = null;
    // 3.创建Map对象用来存储id和Menu对象的对应关系,便于查找父节点
    Map<Integer,Menu> menuMap = new HashMap<>();
    // 4.遍历menuList填充menuMap
    for (Menu menu : menuList) {
        Integer id = menu.getId();
        menuMap.put(id,menu);
    }
    // 5.再次遍历menuList查找根节点,组装父子节点
    for (Menu menu : menuList) {
        // 6.获取当前menu对象的pid属性值
        Integer pid = menu.getPid();
        // 7.如果pid为null,判定为根节点
        if(pid == null){
            root = menu;
            // 8.如果当前节点是根节点,那么肯定没有父节点,不必继续执行
            continue;
        }
        // 9.如果pid不为null,说明当前节点有父节点,那么可以根据pid到menuMap中查找对应的Menu对象
        Menu father = menuMap.get(pid);
        // 10.将当前节点存入父节点的children集合
        father.getChildren().add(menu);
    }
    // 11.经过上面的运算,根节点包含了整个树形结构,返回根节点就是返回整个树
    return ResultEntity.successWithData(root);
}

2.1.5代码:跳转页面

<a th:href="@{/menu/to/page}"><i class="glyphicon glyphicon-lock"></i> 菜单维护</a>

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

2.1.6引入zTree环境

<link  th:href="@{/ztree/zTreeStyle.css}"/>
<script type="text/javascript" th:src="@{/ztree/jquery.ztree.all-3.5.min.js}"></script>

 2.1.7 代码:页面上使用 zTree 初步显示树形结构(假数据)

页面效果:

<script type="text/javascript">
    $(function () {
        // 1.创建 JSON 对象用于存储对 zTree 所做的设置
        var setting = {};
        // 2.准备生成树形结构的JSON数据
        var zNodes =[
            { name:"父节点1 - 展开", open:true,
                children: [
                    { name:"父节点11 - 折叠",
                        children: [
                            { name:"叶子节点111"},
                            { name:"叶子节点112"},
                            { name:"叶子节点113"},
                            { name:"叶子节点114"}
                        ]},
                    { name:"父节点12 - 折叠",
                        children: [
                            { name:"叶子节点121"},
                            { name:"叶子节点122"},
                            { name:"叶子节点123"},
                            { name:"叶子节点124"}
                        ]},
                    { name:"父节点13 - 没有子节点", isParent:true}
                ]},
            { name:"父节点2 - 折叠",
                children: [
                    { name:"父节点21 - 展开", open:true,
                        children: [
                            { name:"叶子节点211"},
                            { name:"叶子节点212"},
                            { name:"叶子节点213"},
                            { name:"叶子节点214"}
                        ]},
                    { name:"父节点22 - 折叠",
                        children: [
                            { name:"叶子节点221"},
                            { name:"叶子节点222"},
                            { name:"叶子节点223"},
                            { name:"叶子节点224"}
                        ]},
                    { name:"父节点23 - 折叠",
                        children: [
                            { name:"叶子节点231"},
                            { name:"叶子节点232"},
                            { name:"叶子节点233"},
                            { name:"叶子节点234"}
                        ]}
                ]},
            { name:"父节点3 - 没有子节点", isParent:true}
        ];
        // 3.初始化树形结构
        $.fn.zTree.init($("#treeDemo"), setting, zNodes);
    });
</script>

2.1.8 代码:在页面上使用真实数据显示树形结构

<script type="text/javascript">
    $(function () {
        // 1.准备生成树形结构的 JSON 数据,数据的来源是发送 Ajax 请求得到
        $.ajax({
            "url":"/menu/get/whole/tree",
            "type":"post",
            "dataType":"json",
            "success":function (response) {
                var result = response.operationResult;
                if(result == "SUCCESS") {
                    // 2.创建 JSON 对象用于存储对 zTree 所做的设置
                    var setting = {};

                    console.log(response);
                    // 3.从响应体中获取用来生成树形结构的JSON数据
                    var zNodes = response.queryData;
                    // 4.初始化树形结构
                    $.fn.zTree.init($("#treeDemo"), setting, zNodes);
                }
                if(result == "FAILED") {
                    layer.msg("操作失败!"+response.message);
                }
            },
            "error":function(response){
                layer.msg(response.status+" "+response.statusText);
            }
        });
    });
</script>

2.1.9 代码:修改默认图标为真实图标代码:修改默认图标为真实图标

menu-page.html中:

<script type="text/javascript" th:src="@{/crowd/my-menu.js}"></script>

// 2.创建 JSON 对象用于存储对 zTree 所做的设置
var setting = {
    "view":{
        // 每生成一个节点都会调用一下这个函数
        "addDiyDom": myAddDiyDom
    }
};


my-menu.js中:
// 修改默认的图标
function myAddDiyDom(treeId, treeNode) {
    // treeId是整个树形结构附着的ul标签的id:treeDemo
    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.1.10代码:实现 "点了不跑"

// 2.创建 JSON 对象用于存储对 zTree 所做的设置
var setting = {
    //当后台数据只能生成url属性,又不想实现点击节点跳转的功能时,可以直接修改此属性为其他不存在的属性名称
    "data":{
        // 实现"点了不跑的功能"
        "key":{
            "url":"notExists"
        }
    },
    "view":{
        // 每生成一个节点都会调用一下这个函数
        "addDiyDom": myAddDiyDom
    }
};

 2.1.11代码:显示按钮组

思路:

  • 第一步:控制<span>A</span>是否显示
  • 第二步:明确具体按钮的添加规则(根据节点的级别)
  • 第三步:准备好按钮的 HTML 标签
  • 第四步:根据按钮规则把按钮填充到 span 中
menu-page.html中:
"view":{
    // 每生成一个节点都会调用一下这个函数
    "addDiyDom": myAddDiyDom,
    "addHoverDom": myAddHoverDom,
    "removeHoverDom": myRemoveHoverDom
}

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

    // 根据 id 的生成规则拼接出来 a超链接 的 id
    var anchorId = treeNode.tId + "_a";

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

    // 节点的范围是有一定的区域的,在鼠标移动的过程中可能多次触发添加按钮组事件
    // 所以需要判断,每次移入只加一次按钮组
    if($("#"+btnGroupId).length > 0){
        return;
    }

    // 准备各个按钮的Html标签
    var addBtn = "<a id='"+treeNode.id+"' class='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='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='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;
    }
    // 找到附着按钮组的超链接$("#"+anchorId),找到之后执行在超链接后面附加span元素的操作after

    $("#"+anchorId).after("<span id='"+btnGroupId+"'>"+btnHTML+"</span>")
}
// 在鼠标离开节点范围时删除按钮组
function myRemoveHoverDom(treeId, treeNode) {
    // 拼接按钮组的id
    var btnGroupId = treeNode.tId + "_btnGrp";

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

2.2菜单维护:添加子节点

2.2.1目标:给当前节点添加子节点,保存到数据库并刷新

2.2.2思路:

 2.2.3前端代码:

①.引入模态框

模态框的代码以及引入:
<div th:include="modal-menu-add"></div>

<div id="menuAddModal" class="modal fade" tabindex="-1" role="dialog">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"
                        aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
                <h4 class="modal-title"> 尚筹网系统弹窗</h4>
            </div>
            <div class="modal-body">
                <form class="form-signin" role="form">
                    <div class="form-group has-success has-feedback">
                        节点的pid:<input type="text" name="pid" /><br />
                        请输入节点名称:<input type="text" name="name" /><br />
                        请输入URL地址:<input type="text" name="url" /><br />
                        <i class="glyphicon glyphicon-th-list"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-th-list" />&nbsp;

                        <i class="glyphicon glyphicon-dashboard"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-dashboard" /> &nbsp;

                        <i class="glyphicon glyphicon glyphicon-tasks"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon glyphicon-tasks" /> &nbsp;

                        <i class="glyphicon glyphicon-user"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-user" /> &nbsp;

                        <i class="glyphicon glyphicon-king"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-king" /> &nbsp;

                        <i class="glyphicon glyphicon-lock"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-lock" /> &nbsp;

                        <i class="glyphicon glyphicon-ok"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-ok" /> &nbsp;

                        <i class="glyphicon glyphicon-check"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-check" /> &nbsp;

                        <i class="glyphicon glyphicon-th-large"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-th-large" /> <br />

                        <i class="glyphicon glyphicon-picture"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-picture" /> &nbsp;

                        <i class="glyphicon glyphicon-equalizer"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-equalizer" /> &nbsp;

                        <i class="glyphicon glyphicon-random"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-random" /> &nbsp;

                        <i class="glyphicon glyphicon-hdd"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-hdd" /> &nbsp;

                        <i class="glyphicon glyphicon-comment"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-comment" /> &nbsp;

                        <i class="glyphicon glyphicon-list"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-list" /> &nbsp;

                        <i class="glyphicon glyphicon-tags"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-tags" /> &nbsp;

                        <i class="glyphicon glyphicon-list-alt"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-list-alt" /> &nbsp;
                        <br />
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button id="menuSaveBtn" type="button" class="btn btn-default"><i class="glyphicon glyphicon-plus"></i> 保存</button>
                <button id="menuResetBtn" type="reset" class="btn btn-primary"><i class="glyphicon glyphicon-refresh"></i> 重置</button>
            </div>
        </div>
    </div>
</div>

②.给"+"按钮添加class值,用于绑定单击响应函数

//my-menu.js中给"+"按钮添加class:addBtn
var addBtn = "<a id='"+treeNode.id+"' class='btn btn-info dropdown-toggle btn-xs addBtn' style='margin-left:10px;padding-top:0px;' href='#' title='添加子节点'>&nbsp;&nbsp;<i class='fa fa-fw fa-plus rbg '></i></a>";

menu-page.html中:
// 给添加子节点按钮绑定单击响应函数
$("#treeDemo").on("click",".addBtn",function () {
    // 打开模态框
    $("#menuAddModal").modal("show");

    // 将当前节点的id,作为新节点的pid保存到全局变量
    window.menuPid = this.id;
    // 回显到模态框
    $("#menuAddModal [name=pid]").val(menuPid);

    // 取消超链接的默认跳转行为
    return false;
});

③.给模态框中的" 保存 "按钮绑定单击响应函数

$("#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({
        "url":"/menu/save",
        "type":"post",
        "data":{
            "pid":window.menuPid,
            "name":name,
            "url":url,
            "icon":icon
        },
        "dataType":"json",
        "success":function (response) {
            var result = response.operationResult;
            if(result == "SUCCESS") {
                layer.msg("操作成功!");
                // 重新加载树形结构,注意:要在确认服务器端完成保存操作后再刷新,否则有可能刷新不到最新的数据,因为这里是异步的
                generateTree();
            }
            if(result == "FAILED") {
                layer.msg("操作失败!"+response.message);
            }
        },
        "error":function (response) {
            layer.msg(response.status+" "+response.statusText);
        }
    });
    // 关闭模态框
    $("#menuAddModal").modal("hide");
    // 清空表单
    // jQuery对象调用click()函数,里面不传任何参数,相当于用户点击了一下
    $("menuResetBtn").click();
    // 清空模态框的内容
    $("#menuAddModal [name=pid]").val("");
    $("#menuAddModal [name=name]").val("");
    $("#menuAddModal [name=url]").val("");
    $("#menuAddModal [name=icon]").prop("checked",false);
});

2.2.4后端代码

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

@Override
public void saveMenu(Menu menu) {
    menuMapper.insert(menu);
}

2.3菜单维护:更新节点

2.3.1回显的技巧:zTree提供的功能:只要知道当前节点的一个属性,zTree就可以根据这个属性把节点给搜索出来。在这里我们可以知道节点的id

2.3.2更新的目标:修改当前节点的基本属性,不更换父节点

2.3.3更新的思路:

2.3.4前端代码

①.引入模态框

<div th:include="modal-menu-edit"></div>

<div id="menuEditModal" class="modal fade" tabindex="-1" role="dialog">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"
                        aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
                <h4 class="modal-title"> 尚筹网系统弹窗</h4>
            </div>
            <div class="modal-body">
                <form class="form-signin" role="form">
                    <div class="form-group has-success has-feedback">
                        节点的id:<input type="text" name="id" /><br />
                        请输入节点名称:<input type="text" name="name" /><br />
                        请输入URL地址:<input type="text" name="url" /><br />
                        <i class="glyphicon glyphicon-th-list"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-th-list" />&nbsp;

                        <i class="glyphicon glyphicon-dashboard"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-dashboard" /> &nbsp;

                        <i class="glyphicon glyphicon glyphicon-tasks"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon glyphicon-tasks" /> &nbsp;

                        <i class="glyphicon glyphicon-user"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-user" /> &nbsp;

                        <i class="glyphicon glyphicon-king"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-king" /> &nbsp;

                        <i class="glyphicon glyphicon-lock"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-lock" /> &nbsp;

                        <i class="glyphicon glyphicon-ok"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-ok" /> &nbsp;

                        <i class="glyphicon glyphicon-check"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-check" /> &nbsp;

                        <i class="glyphicon glyphicon-th-large"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-th-large" /> <br />

                        <i class="glyphicon glyphicon-picture"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-picture" /> &nbsp;

                        <i class="glyphicon glyphicon-equalizer"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-equalizer" /> &nbsp;

                        <i class="glyphicon glyphicon-random"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-random" /> &nbsp;

                        <i class="glyphicon glyphicon-hdd"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-hdd" /> &nbsp;

                        <i class="glyphicon glyphicon-comment"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-comment" /> &nbsp;

                        <i class="glyphicon glyphicon-list"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-list" /> &nbsp;

                        <i class="glyphicon glyphicon-tags"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-tags" /> &nbsp;

                        <i class="glyphicon glyphicon-list-alt"></i>
                        <input type="radio" name="icon" value="glyphicon glyphicon-list-alt" /> &nbsp;
                        <br />
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button id="menuEditBtn" type="button" class="btn btn-default"><i class="glyphicon glyphicon-edit"></i> 更新</button>
            </div>
        </div>
    </div>
</div>

②.给更新按钮添加class值,用于绑定单击响应函数

// 给更新节点按钮绑定单击响应函数
$("#treeDemo").on("click",".editBtn",function () {
    // 打开模态框
    $("#menuEditModal").modal("show");

    // 得到当前节点的id
    window.menuId = this.id;

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

    // 根据id属性查询节点对象
    var currentNode = treeObj.getNodeByParam("id",window.menuId);

    // 回显数据到模态框
    $("#menuEditModal [name=id]").val(menuId);
    $("#menuEditModal [name=name]").val(currentNode.name);
    $("#menuEditModal [name=url]").val(currentNode.url);
    // radio回显的本质是把value属性和currentNode.icon一致的radio选中
    $("#menuEditModal [name=icon]").val([currentNode.icon]);
    // 取消超链接的默认跳转行为
    return false;
});

③.给模态框中的" 更新 "按钮绑定单击响应函数

// 给更新模态框中的更新按钮绑定单击响应函数
$("#menuEditBtn").click(function () {
    // 收集表单项中用户输入的数据
    var name = $.trim($("#menuEditModal [name=name]").val());
    var url = $.trim($("#menuEditModal [name=url]").val());
    // 单选按钮要定位到被选中的那一个
    var icon = $("#menuEditModal [name=icon]:checked").val();
    $.ajax({
        "url":"/menu/update",
        "type":"post",
        "data":{
            "id":window.menuId,
            "name":name,
            "url":url,
            "icon":icon
        },
        "dataType":"json",
        "success":function (response) {
            var result = response.operationResult;
            if(result == "SUCCESS") {
                layer.msg("操作成功!");
                // 重新加载树形结构,注意:要在确认服务器端完成保存操作后再刷新,否则有可能刷新不到最新的数据,因为这里是异步的
                generateTree();
            }
            if(result == "FAILED") {
                layer.msg("操作失败!"+response.message);
            }
        },
        "error":function (response) {
            layer.msg(response.status+" "+response.statusText);
        }
    });
    // 关闭模态框
    $("#menuEditModal").modal("hide");
});

2.3.5后端代码

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

@Override
public void updateMenu(Menu menu) {
    // 由于pid没有传入,一定要使用有选择的更新,为了保证pid字段不会被置空
    menuMapper.updateByPrimaryKeySelective(menu);
}

2.4菜单维护:删除节点

2.4.1删除的目标:删除当前节点

2.4.2删除的思路:

2.4.3前端代码

①.引入模态框

<div th:include="modal-menu-confirm"></div>

<div id="menuConfirmModal" class="modal fade" tabindex="-1" role="dialog">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"
                        aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
                <h4 class="modal-title">尚筹网系统弹窗</h4>
            </div>
            <form>
                <div class="modal-body">
                    您真的要删除<span id="removeNodeSpan"></span>这个节点吗?
                </div>
                <div class="modal-footer">
                    <button id="confirmBtn" type="button" class="btn btn-danger"><i class="glyphicon glyphicon-ok"></i> OK</button>
                </div>
            </form>
        </div>
    </div>
</div>

②.给删除按钮添加class值,用于绑定单击响应函数

// 给删除的按钮绑定单击响应函数
$("#treeDemo").on("click",".removeBtn",function () {
    // 打开模态框
    $("#menuConfirmModal").modal("show");

    // 得到当前节点的id
    window.menuId = this.id;

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

    // 根据id属性查询节点对象
    var currentNode = treeObj.getNodeByParam("id",window.menuId);

    // text只能设置文本
    // $("#removeNodeSpan").text(currentNode.name);
    // 以下更美观
    $("#removeNodeSpan").html("【<i class='"+currentNode.icon+"'></i>"+currentNode.name + "】");
});

③.给模态框中的" 删除 "按钮绑定单击响应函数

// 给确认删除模态框中的删除按钮绑定单击响应函数
$("#confirmBtn").click(function () {
    $.ajax({
        "url":"/menu/delete",
        "type":"post",
        "data": {
            "id":window.menuId
        },
        "dataType":"json",
        "success":function (response) {
            var result = response.operationResult;
            if(result == "SUCCESS") {
                layer.msg("操作成功!");
                // 重新加载树形结构,注意:要在确认服务器端完成保存操作后再刷新,否则有可能刷新不到最新的数据,因为这里是异步的
                generateTree();
            }
            if(result == "FAILED") {
                layer.msg("操作失败!"+response.message);
            }
        },
        "error":function (response) {
            layer.msg(response.status+" "+response.statusText);
        }
    });
    // 关闭模态框
    $("#menuConfirmtModal").modal("hide");
});

2.4.4后端代码

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

@Override
public void deleteMenu(Integer id) {
    menuMapper.deleteByPrimaryKey(id);
}
  • 作者:w_rj0824
  • 原文链接:https://blog.csdn.net/w_rj0824/article/details/125677562
    更新时间:2023-02-17 16:37:21