菜单管理又称为资源管理,是系统资源对外的表现形式。本模块主要是实现对菜单进行添加、修改、查询、删除等操做。javascript
CREATE TABLE `sys_menus` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL COMMENT '资源名称', `url` varchar(200) DEFAULT NULL COMMENT '资源URL', `type` int(11) DEFAULT NULL COMMENT '类型 1:菜单 2:按钮', `sort` int(11) DEFAULT NULL COMMENT '排序', `note` varchar(100) DEFAULT NULL COMMENT '备注', `parentId` int(11) DEFAULT NULL COMMENT '父菜单ID,一级菜单为0', `permission` varchar(500) DEFAULT NULL COMMENT '受权(如:sys:user:create)', `createdTime` datetime DEFAULT NULL COMMENT '建立时间', `modifiedTime` datetime DEFAULT NULL COMMENT '修改时间', `createdUser` varchar(20) DEFAULT NULL COMMENT '建立用户', `modifiedUser` varchar(20) DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='资源管理';
菜单表与角色表是多对多的关系,在表设计时,多对多关系一般由中间表(关系表)进行维护css
基于角色菜单表的设计,其角色和菜单对应的关系数据要存储到关系表中,其具体存储形式
菜单与角色的关系表脚本设计以下:html
CREATE TABLE `sys_role_menus` ( `id` int(11) NOT NULL AUTO_INCREMENT, `role_id` int(11) DEFAULT NULL COMMENT '角色ID', `menu_id` int(11) DEFAULT NULL COMMENT 'ID', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='角色与菜单对应关系';
当在主页左侧菜单栏,点击菜单管理时,在主页内容呈现区,呈现菜单列表页面java
当在菜单列表页面点击添加按钮时,异步加载菜单编辑页面,并在列表内容呈现区,呈现菜单编辑页面,如图-4所示。node
在菜单编辑页面选择上级菜单时,异步加载菜单信息,并以树结构的形式呈现上级菜单jquery
菜单管理业务后台API分层架构及调用关系如图web
▪ 业务描述与设计实现ajax
首先准备菜单列表页面(/templates/pages/sys/menu_list.html),而后在starter.html页面中点击菜单管理时异步加载菜单列表页面。spring
▪ 关键代码设计与实现数据库
找到项目中的starter.html页面,页面加载完成之后,注册菜单管理项的点击事件,当点击菜单管理时,执行事件处理函数。关键代码以下:
$(function(){ … doLoadUI("load-menu-id","menu/menu_list") })
说明:对于doLoadUI函数,假如在starter.html中已经定义,则无需再次定义.
function doLoadUI(id,url){ $("#"+id).click(function(){ $("#mainContentId").load(url); }); }
其中,load函数为jquery中的ajax异步请求函数。
▪ 业务描述与设计实现
本页面呈现菜单信息时要以树结构形式进行呈现。此树结构会借助jquery中的treeGrid插件进行实现,因此在菜单列表页面须要引入treeGrid相关JS。可是,具体的treeGrid怎么用可自行在网上进行查询(已比较成熟)。
▪ 关键代码设计与实现:
关键JS引入(menu_list.html),代码以下:
<script type="text/javascript" src="bower_components/treegrid/jquery.treegrid.extension.js"></script> <script type="text/javascript" src="bowe r_components/treegrid/jquery.treegrid.min.js"></script> <script type="text/javascript" src="bower_components/treegrid/tree.table.js"></script>
页面数据展现
菜单列表页面加载完成,启动菜单数据异步加载操做,本次菜单列表页面要呈现菜单以及上级菜单信息,其数据查询时,数据的封装及传递过程
页面菜单数据删除展现
基于用户在列表页面上选择的的菜单记录ID,执行删除操做,本次删除业务实现中,首先要基于id判断当前菜单是否有子菜单,假若有子菜单则不容许删除,没有则先删除菜单角色关系数据,而后再删除菜单自身信息。
上级菜单页面展现
在菜单编辑页面上,点击上级菜单时,其数据加载时序分析
菜单数据添加实现
用户在菜单编辑页面输入数据,而后异步提交到服务端,其简易数据传递基本架构
用户在菜单添加页面中填写好菜单数据,而后点击保存按钮,将用户填写的数据添加到数据库。
菜单数据更新展现
当点击编辑页面更新按钮时
第一步:建立SysMenuDao层接口
package com.cy.pj.sys.dao; import com.cy.pj.common.pojo.Node; import com.cy.pj.sys.pojo.SysMenu; import com.cy.pj.sys.pojo.SysUserMenu; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import java.util.List; import java.util.Map; @Mapper public interface SysMenuDao { List<SysUserMenu> findMenusByIds(List<Integer> menuIds); //基于菜单ID获取受权表示 List<String> findPermissions(List<Integer> menuIds); int updateObject(SysMenu entity); @Insert(" insert into sys_menus " + "(name,url,type,sort,note,parentId,permission,createdTime,modifiedTime,createdUser,modifiedUser) " + "values " + "(#{name},#{url},#{type},#{sort},#{note},#{parentId},#{permission},now(),now(),#{createdUser},#{modifiedUser})") int insertObject(SysMenu entity); @Select("select id,name,parentId from sys_menus") List<Node> findZtreeMenuNodes(); @Select("select count(*) from sys_menus where parentId=#{id}") int getChildCount(Integer id); @Delete("delete from sys_menus where id=#{id}") int deleteObject(Integer id); //查询全部菜单信息 List<Map<String,Object>> findObjects(); }
第二步:建立SysMenuMapper.xml映射文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.cy.pj.sys.dao.SysMenuDao"> <resultMap type="com.cy.pj.sys.pojo.SysUserMenu" id="sysUserMenu"> <!-- 一级菜单映射 --> <id property="id" column="id"/> <result property="name" column="name"/> <result property="url" column="url"/> <!-- 二级菜单映射 --> <collection property="childs" ofType="com.cy.pj.sys.pojo.SysUserMenu"> <id property="id" column="cid"/> <result property="name" column="cname"/> <result property="url" column="curl"/> </collection> </resultMap> <select id="findMenusByIds" resultMap="sysUserMenu"> select p.id,p.name,p.url,c.id cid,c.name cname,c.url curl from sys_menus p join sys_menus c on c.parentId=p.id <where> <foreach collection="menuIds" open="(" close=")" separator="or" item="menuId"> c.id=#{menuId} </foreach> and p.parentId is null </where> </select> <select id="findPermissions" resultType="string"> select permission <!-- sys:user:update --> from sys_menus where id in <foreach collection="menuIds" open="(" close=")" separator="," item="item"> #{item} </foreach> </select> <!--查询全部菜单以及菜单对应的上级菜单,当没有上级菜单时,当前菜单的上级菜单显示为null--> <select id="findObjects" resultType="map"> /*方法1(左外关联查询)*/ /*select c.*,p.name parentName from sys_menus c left join sys_menus p on c.parentId=p.id*/ /*方法2(嵌套查询)*/ select c.*,(select p.name from sys_menus p where c.parentId=p.id) parentName from sys_menus c </select> <update id="updateObject" parameterType="com.cy.pj.sys.pojo.SysMenu"> update sys_menus set name=#{name}, type=#{type}, sort=#{sort}, url=#{url}, parentId=#{parentId}, permission=#{permission}, modifiedUser=#{modifiedUser}, modifiedTime=now() where id=#{id} </update> </mapper>
第三步:建立SysMenuService接口
在菜单查询中,业务层对象主要是借助数据层对象完成菜单数据的查询。后续还能够基于AOP对数据进行缓存,记录访问日志等。
package com.cy.pj.sys.servive; import com.cy.pj.common.pojo.Node; import com.cy.pj.sys.pojo.SysMenu; import com.cy.pj.sys.pojo.SysUserMenu; import java.util.List; import java.util.Map; public interface SysMenuService { List<SysUserMenu> findUserMenusByUserId(Integer id); int updateObject(SysMenu entity); int saveObject(SysMenu entity); List<Node> findZtreeMenuNodes(); int deleteObject(Integer id); List<Map<String,Object>> findObjects(); }
第四步:建立SysMenuServiceImpl实现类
package com.cy.pj.sys.servive.impl; import com.cy.pj.common.exception.ServiceException; import com.cy.pj.common.pojo.Node; import com.cy.pj.sys.dao.SysUserRoleDao; import com.cy.pj.sys.pojo.SysMenu; import com.cy.pj.sys.dao.SysMenuDao; import com.cy.pj.sys.dao.SysRoleMenuDao; import com.cy.pj.sys.pojo.SysUserMenu; import com.cy.pj.sys.servive.SysMenuService; import io.micrometer.core.instrument.util.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; @Service public class SysMenuServiceImpl implements SysMenuService { @Autowired private SysMenuDao sysMenuDao; @Autowired private SysRoleMenuDao sysRoleMenuDao; @Autowired private SysUserRoleDao sysUserRoleDao; @Override public List<SysUserMenu> findUserMenusByUserId(Integer id) { //1.对用户id进行判断 //2.基于用户id查找用户对应的角色id List<Integer> roleIds= sysUserRoleDao.findRoleIdsByUserId(id); //3.基于角色id获取角色对应的菜单信息,并进行封装. List<Integer> menuIds= sysRoleMenuDao.findMenuIdsByRoleIds(roleIds); //4.基于菜单id获取用户对应的菜单信息并返回 return sysMenuDao.findMenusByIds(menuIds); } @Override public int updateObject(SysMenu entity) { //1.合法验证 if(entity==null) throw new ServiceException("保存对象不能为空"); if(StringUtils.isEmpty(entity.getName())) throw new ServiceException("菜单名不能为空"); //2.更新数据 int rows=sysMenuDao.updateObject(entity); if(rows==0) throw new ServiceException("记录可能已经不存在"); //3.返回数据 return rows; } @Override public int saveObject(SysMenu entity) { //1.合法验证 if(entity==null) throw new IllegalArgumentException("保存对象不能为空"); if(StringUtils.isEmpty(entity.getName())) throw new IllegalArgumentException("菜单名不能为空"); //2.保存数据 int rows=sysMenuDao.insertObject(entity); //3.返回数据 return rows; } @Override public List<Node> findZtreeMenuNodes() { return sysMenuDao.findZtreeMenuNodes(); } @Override public int deleteObject(Integer id) { //1,参数校验 if(id==null||id<1) throw new IllegalArgumentException("id值无效"); //2,断定菜单是否有子菜单,有则不容许删除 int childCount=sysMenuDao.getChildCount(id); if(childCount>0) throw new ServiceException("请先删除子菜单"); //3,删除关系数据 sysRoleMenuDao.deleteObjectsByMenuId(id); int rows=sysMenuDao.deleteObject(id); //4,删除自身信息 if(rows==0) throw new ServiceException("记录可能已经不存在"); return rows; } @Override public List<Map<String, Object>> findObjects() { return sysMenuDao.findObjects(); } }
第五步:建立SysMenuController控制层
控制层对象主要负责请求和响应数据的处理,例如,本模块经过业务层对象执行业务逻辑,再经过VO对象封装响应结果(主要对业务层数据添加状态信息),最后将响应结果转换为JSON格式的字符串响应到客户端。
package com.cy.pj.sys.controller; import com.cy.pj.common.pojo.JsonResult; import com.cy.pj.sys.pojo.SysMenu; import com.cy.pj.sys.servive.SysMenuService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class SysMenuController { @Autowired private SysMenuService sysMenuService; @RequestMapping("/menu/doUpdateObject") public JsonResult doUpdateObject(SysMenu entity){ sysMenuService.updateObject(entity); return new JsonResult("update ok"); } @RequestMapping("/menu/doSaveObject") public JsonResult doSaveObject(SysMenu entity){ sysMenuService.saveObject(entity); return new JsonResult("save ok"); } @RequestMapping("/menu/doFindZtreeMenuNodes") public JsonResult doFindZtreeMenuNodes(){ return new JsonResult( sysMenuService.findZtreeMenuNodes()); } @RequestMapping("/menu/doDeleteObject") public JsonResult doDeleteObject(Integer id){ sysMenuService.deleteObject(id); return new JsonResult("delete ok"); } @GetMapping("menu/doFindObjects") public JsonResult doFindObjects(){ return new JsonResult(sysMenuService.findObjects()); } }
第六步:建立SysRoleMenuDao接口
package com.cy.pj.sys.dao; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; @Mapper public interface SysRoleMenuDao { List<Integer> findMenuIdsByRoleIds( @Param("roleIds")List<Integer> roleIds); int insertObjects( @Param("roleId")Integer roleId, @Param("menuIds")Integer[] menuIds); @Delete("delete from sys_role_menus where role_id=#{roleId}") int deleteObjectsByRoleId(Integer roleId); //基于菜单id执行关系 @Delete("delete from sys_role_menus where menu_id=#{menuId}") int deleteObjectsByMenuId(Integer menuId); }
第七步:建立SysRoleMenuMapper.xml文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.cy.pj.sys.dao.SysRoleMenuDao"> <select id="findMenuIdsByRoleIds" resultType="int"> select menu_id from sys_role_menus where role_id in <foreach collection="roleIds" open="(" close=")" separator="," item="item"> #{item} </foreach> </select> <select id="findMenuIdsByRoleId" resultType="int"> select menu_id from sys_role_menus where role_id=#{id} </select> <insert id="insertObjects"> insert into sys_role_menus (role_id,menu_id) values <foreach collection="menuIds" separator="," item="menuId"> (#{roleId},#{menuId}) </foreach> </insert> </mapper>
第八步:建立Node 类
定义值对象封装查询到的上级菜单id,name,parentId信息。
package com.cy.pj.common.pojo; import lombok.Data; import java.io.Serializable; @Data public class Node implements Serializable { private static final long serialVersionUID = -7022202313802285223L; private Integer id; private String name; private Integer parentId; }
第九步:建立SysMenu 类
定义持久化对象,封装客户端请求数据,并将数据传递到数据层进行持久化。
package com.cy.pj.sys.pojo; import lombok.Data; import java.io.Serializable; import java.util.Date; @Data public class SysMenu implements Serializable { private static final long serialVersionUID = -1086340530112865421L; private Integer id; /**菜单名称*/ private String name; /**菜单url: log/doFindPageObjects*/ private String url; /**菜单类型(两种:按钮,普通菜单)*/ private Integer type=1; /**排序(序号)*/ private Integer sort; /**备注*/ private String note; /**上级菜单id*/ private Integer parentId; /**菜单对应的权限标识(sys:log:delete)*/ private String permission; /**建立用户*/ private String createdUser; /**修改用户*/ private String modifiedUser; private Date createdTime; private Date modifiedTime; }
menu_list.html
<div class="row"> <div class="col-xs-12"> <div class="box"> <div class="box-header"> <h3 class="box-title"> 菜单管理</h3> <div class="box-tools"> <div class="input-group input-group-sm" style="width: 100px;"> <div class="input-group-btn"> <button type="button" class="btn btn-success btn-delete"> 删除</button> <button type="button" class="btn btn-default btn-add">添加</button> <button type="button" class="btn btn-default btn-update">修改</button> </div> </div> </div> </div> <!-- /.box-header --> <div class="box-body table-responsive no-padding"> <table id="menuTable" class="table table-hover"> <thead> <tr> <th data-field="selectItem" data-checkbox="true"></th> </tr> </thead> </table> </div> </div> <!-- /.box --> </div> </div> <script type="text/javascript" src="bower_components/treegrid/jquery.treegrid.extension.js"></script> <script type="text/javascript" src="bower_components/treegrid/jquery.treegrid.min.js"></script> <script type="text/javascript" src="bower_components/treegrid/tree.table.js"></script> <script type="text/javascript"> /** * 初始化表格的列 */ var columns = [ { field : 'selectItem', radio : true }, { title : '菜单ID', field : 'id', align : 'center', valign : 'middle', width : '80px' }, { title : '菜单名称', field : 'name', align : 'center', valign : 'middle', width : '130px' }, { title : '上级菜单', field : 'parentName', align : 'center', valign : 'middle', sortable : true, width : '100px' }, { title : '类型', field : 'type', align : 'center', valign : 'middle', width : '70px', formatter : function(item, index) { if (item.type == 1) { return '<span class="label label-success">菜单</span>'; } if (item.type == 2) { return '<span class="label label-warning">按钮</span>'; } } }, { title : '排序号', field : 'sort', align : 'center', valign : 'middle', sortable : true, width : '70px' }, { title : '菜单URL', field : 'url', align : 'center', valign : 'middle', width : '160px' }, { title : '受权标识',//要显示的标题名称 field : 'permission',//json串中的key align : 'center',//水平居中 valign : 'middle',//垂直居中 sortable : false //是否排序 } ];//格式来自官方demos -->treeGrid(jquery扩展的一个网格树插件) $(function(){ doGetObjects(); $(".input-group-btn") .on("click",".btn-delete",doDeleteObject) .on("click",".btn-add,.btn-update",doLoadEditUI); }) function doLoadEditUI(){ var title; //基于点击对象的class属性值,修改标题 if($(this).hasClass("btn-add")){ title="添加菜单"; }else{ title="修改菜单"; var item=doGetCheckedItem(); if(!item){ alert("请先选择"); return; } $("#mainContentId") .data("rowData",item); } //异步加载编辑页面 var url="menu/menu_edit"; $("#mainContentId").load(url,function(){ $(".box-title").html(title); }) } function doGetCheckedItem(){ return $("tbody input[type='radio']:checked") .parents("tr").data("rowData"); } function doGetCheckedId(){ //方法1: //var radio=$("tbody input[type='radio']:checked"); //if(radio)return radio.val(); //方法2: //1.获取选中的记录 var selections=$("#menuTable") //bootstrapTreeTable是treeGrid插件内部定义的jquery扩展函数 //getSelections为扩展函数内部要调用的一个方法 .bootstrapTreeTable("getSelections"); //2.对记录进行断定 if(selections.length==1) return selections[0].id; } function doDeleteObject(){ //1.获取选中记录的id值 var id=doGetCheckedId(); console.log("id="+id); if(!id){ alert("请先选中"); return; } //2.给出提示是否确认删除 if(!confirm("确认删除吗"))return; //3.发送异步请求执行删除操做 //3.1定义请求参数 var params={"id":id}; //3.2定义请求url var url="menu/doDeleteObject"; //3.3发送异步请求 $.post(url,params,function(result){ if(result.state==1){ alert(result.message); $("tbody input[type='radio']:checked") .parents("tr").remove(); }else{ alert(result.message); } }) } function doGetObjects(){ //移除mainContentId位置的数据 $("#mainContentId").removeData(); var treeTable=new TreeTable( "menuTable",//tableId "menu/doFindObjects",//url columns);//表中列的配置 //treeTable.setExpandColumn(2); //作表格初始化 treeTable.init(); //发起ajax请求(借助ajax函数) }
菜单列表页面(/templates/pages/sys/menu_edit.html)
<!-- Horizontal Form --> <div class="box box-info"> <div class="box-header with-border"> <h3 class="box-title">添加菜单</h3> </div> <!-- /.box-header --> <!-- form start --> <form class="form-horizontal"> <div class="box-body"> <div class="form-group"> <label for="nameId" class="col-sm-2 control-label">类型</label> <div class="col-sm-10 typeRadio"> <label class="radio-inline"> <input type="radio" name="typeId" value="1" checked> 菜单 </label> <label class="radio-inline"> <input type="radio" name="typeId" value="2"> 按钮 </label> </div> </div> <div class="form-group"> <label for="nameId" class="col-sm-2 control-label">菜单名称</label> <div class="col-sm-10"> <input type="text" class="form-control" id="nameId" placeholder="名称"> </div> </div> <div class="form-group"> <label for="parentId" class="col-sm-2 control-label">上级菜单</label> <div class="col-sm-10"> <input type="text" class="form-control load-sys-menu" readonly="readonly" id="parentId" placeholder="上级菜单"> </div> </div> <div class="form-group"> <label for="urlId" class="col-sm-2 control-label">菜单URL</label> <div class="col-sm-10"> <input type="text" class="form-control" id="urlId" placeholder="url"> </div> </div> <div class="form-group"> <label for="permissionId" class="col-sm-2 control-label">受权标识:</label> <div class="col-sm-10"> <input type="text" id="permissionId" placeholder="多个用逗号分隔,如:user:list,user:create" class="form-control"> </div> </div> <div class="form-group"> <label for="sortId" class="col-sm-2 control-label">排序号:</label> <div class="col-sm-10"> <input type="text" id="sortId" placeholder="排序号" class="form-control"> </div> </div> </div> <!-- /.box-body --> <div class="box-footer"> <button type="button" class="btn btn-default btn-cancel">Cancel</button> <button type="button" class="btn btn-info pull-right btn-save">Save</button> </div> <!-- /.box-footer --> </form> <!-- zTree 对应的div --> <div class="layui-layer layui-layer-page layui-layer-molv layer-anim" id="menuLayer" type="page" times="2" showtime="0" contype="object" style="z-index:59891016; width: 300px; height: 450px; top: 100px; left: 500px; display:none"> <div class="layui-layer-title" style="cursor: move;">选择菜单</div> <div class="layui-layer-content" style="height: 358px;"> <div style="padding: 10px;" class="layui-layer-wrap"> <ul id="menuTree" class="ztree"></ul> <!-- 动态加载树 --> </div> </div> <span class="layui-layer-setwin"> <a class="layui-layer-ico layui-layer-close layui-layer-close1 btn-cancel" ></a></span> <div class="layui-layer-btn layui-layer-btn-"> <a class="layui-layer-btn0 btn-confirm">肯定</a> <a class="layui-layer-btn1 btn-cancel">取消</a> </div> </div> </div> <script type="text/javascript" src="bower_components/ztree/jquery.ztree.all.min.js"></script> <script type="text/javascript" src="bower_components/layer/layer.js"> </script> <script type="text/javascript"> var zTree; //zTree是第三方扩展的一个Jquery插件 //初始化zTree时会用到 var setting = { data : { simpleData : { enable : true,//表示使用简单数据模式 idKey : "id", //节点数据中保存惟一标识的属性名称 pIdKey : "parentId", //节点数据中保存其父节点惟一标识的属性名称 rootPId : null //根节点id }//json 格式javascript对象 } }//json 格式的javascript对象 $(function(){ $(".form-horizontal")//事件不能注册到$("#mainContentId")对象上 .on("click",".load-sys-menu",doLoadZtreeNodes); $("#menuLayer") .on("click",".btn-confirm",doSetSelectNode) .on("click",".btn-cancel",doHideTree); $(".box-footer") .on("click",".btn-cancel",doCancel) .on("click",".btn-save",doSaveOrUpdate) var data=$("#mainContentId").data("rowData"); if(data)doInitEditFormData(data); }) function doInitEditFormData(data){ /* $("input[type='radio']").each(function(){ if($(this).val()==data.type){ $(this).prop("checked",true); } }) */ $(".typeRadio input[value='"+data.type+"']").prop("checked",true); $("#nameId").val(data.name); $("#sortId").val(data.sort); $("#urlId").val(data.url); $("#permissionId").val(data.permission); $("#parentId").val(data.parentName); $("#parentId").data("parentId",data.parentId); } //获取表单数据 function doGetEditFormData(){ var params={ type:$("form input[name='typeId']:checked").val(), name:$("#nameId").val(), url:$("#urlId").val(), sort:$("#sortId").val(), permission:$("#permissionId").val(), parentId:$("#parentId").data("parentId") } return params; } function doSaveOrUpdate(){ //1.获取表单数据 var params=doGetEditFormData(); var rowData= $("#mainContentId").data("rowData"); //2.异步提交表单数据(post) var insertUrl="menu/doSaveObject"; var updateUrl="menu/doUpdateObject"; var url=rowData?updateUrl:insertUrl; if(rowData)params.id=rowData.id; $.post(url,params,function(result){ if(result.state==1){ alert(result.message); doCancel(); }else{ alert(result.message); } }); } //编辑页面cancel事件处理 function doCancel(){ //1.定义url var url="menu/menu_list"; //2.异步加载列表页面 $("#mainContentId").load(url); } //zTree取消按钮事件处理函数 function doHideTree(){ $("#menuLayer").css("display","none"); } //zTree肯定按钮事件处理函数 function doSetSelectNode(){ //1.获取选中的节点对象 var nodes=zTree.getSelectedNodes(); if(nodes.length==1){ var selectedNode=nodes[0]; console.log("selectNode",selectedNode); var rowData=$("#mainContentId").data("rowData"); if(rowData){//修改时作以下处理 //断定当前选中的上级菜单节点是否为当前要修改节点的子节点. var flag=isChild(rowData.id,selectedNode); if(flag){ alert("不能选择当前节点以及对应子节点"); return; } } //2.将对象中内容,填充到表单 $("#parentId").data("parentId",selectedNode.id); $("#parentId").val(selectedNode.name); } //3.隐藏树对象 doHideTree(); } //断定当前选中节点是不是当前节点的子节点 function isChild(currentNodeId,selectNode){ if(selectNode.id==currentNodeId)return true; var node=selectNode.getParentNode(); if(!node)return false; return isChild(currentNodeId,node); } function doLoadZtreeNodes(){ var url="menu/doFindZtreeMenuNodes"; //异步加载数据,并初始化数据 $.getJSON(url,function(result){ if(result.state==1){ //使用init函数须要先引入ztree对应的js文件 zTree=$.fn.zTree.init( $("#menuTree"), setting, result.data);//id,name,parentId //doRemoveNodeFromZtree();//修改时,可考虑此方案 //显示zTree对应的div $("#menuLayer").css("display","block"); }else{ alert(result.message); } }) } function doRemoveNodeFromZtree(){ //断定是不是修改,假如是修改,从zTree中移除当前菜单以及对应子菜单 var rowData=$("#mainContentId").data("rowData"); if(rowData){//rowData有值,表示是修改. console.log("zTree",zTree); //1.获取当前的菜单对象 var node=zTree.getNodeByParam("id",rowData.id,null); console.log("node",node); //2.移除当前菜单. zTree.removeNode(node); } } </script>