配色: 字号:
后台管理之菜单管理(2)
2018-01-13 | 阅:  转:  |  分享 
  












京淘

权限管理系统

菜单管理

Day21





1. 菜单列表模块 1-2

1.1. 业务描述 1-2

1.2. 服务端设计及实现 1-3

1.2.1. 创建表sys_menus 1-3

1.2.2. DAO接口及方法定义 1-4

1.2.3. Mapper元素定义 1-4

1.2.4. Service中方法的定义 1-5

1.2.5. Controller中方法定义 1-5

1.3. 客户端设计及实现 1-5

1.3.1. 定义menu_list.html页面 1-5

1.3.2. 设置start.html页面 1-8

2. 菜单删除模块 2-9

2.1. 服务端设计及实现 2-9

2.1.1. Dao接口方法定义 2-9

2.1.2. Mapper中元素定义 2-9

2.1.3. Service接口中方法定义 2-10

2.1.4. Controller中方法定义 2-10

2.2. 客户端设计及实现 2-10

2.2.1. 删除按钮事件注册 2-10

2.2.2. 删除按钮事件处理 2-11

3. 菜单添加页面设计 3-12

3.1. 业务描述 3-12

3.2. 页面呈现 3-12

3.2.1. Controller方法定义 3-13

3.2.2. 定义添加页面 3-13

3.2.3. Js定义 3-14

4. 上级菜单操作 4-15

4.1. 服务端设计及实现 4-15

4.1.1. 定义Node对象封装树节点 4-15

4.1.2. DAO操作 4-15

4.1.3. Mapper操作 4-15

4.1.4. Service操作 4-16

4.1.5. Controller操作 4-16

4.2. 客户端设计与实现 4-16

4.2.1. 编辑页面添加DIV元素 4-17

4.2.2. 上级菜单选项注册事件 4-17

4.2.3. 上级菜单事件处理 4-18

5. 菜单数据保存 5-19

5.1. 服务端设计与实现 5-19

5.1.1. Entity类定义 5-19

5.1.2. Dao方法定义及实现 5-19

5.1.3. Service方法定义及实现 5-19

5.1.4. Controller方法定义及实现 5-20

5.2. 客户端设计与实现 5-20

5.2.1. 保存按钮事件注册 5-20

5.2.2. 保存按钮事件处理 5-20

6. 修改页面加载 6-21

6.1. 服务端实现 6-21

6.1.1. Dao方法定义 6-21

6.1.2. Mapper元素定义 6-22

6.1.3. Service方法定义 6-22

6.1.4. Controller方法定义 6-22

6.2. 客户端实现 6-23

6.2.1. 列表页面操作 6-23

6.2.2. 编辑页面操作 6-23

7. 修改页面数据保存 7-25

7.1. 服务端设计与实现 7-25

7.1.1. Dao方法定义 7-25

7.1.2. Mapper元素定义 7-25

7.1.3. Service方法定义 7-25

7.1.4. Controller方法定义 7-26

7.2. 客户端设计及实现 7-26

7.2.1. 获取表单数据异步更新 7-26

8. 总结 8-27

8.1. 重点和难点分析 8-27

8.2. 常见FAQ 8-27

菜单



点击菜单名称可展开,例如点击系统管理







服务端设计及实现



创建表sys_menus



CREATETABLE`sys_menus`(

`id`int(11)NOTNULLAUTO_INCREMENT,

`name`varchar(50)DEFAULTNULLCOMMENT''资源名称'',

`url`varchar(200)DEFAULTNULLCOMMENT''资源URL'',

`type`int(11)DEFAULTNULLCOMMENT''类型1:菜单2:按钮'',

`sort`int(11)DEFAULTNULLCOMMENT''排序'',

`note`varchar(100)DEFAULTNULLCOMMENT''备注'',

`parentId`int(11)DEFAULTNULLCOMMENT''父菜单ID,一级菜单为0'',

`permission`varchar(500)DEFAULTNULLCOMMENT''授权(如:user:create)'',

`createdTime`datetimeDEFAULTNULLCOMMENT''创建时间'',

`modifiedTime`datetimeDEFAULTNULLCOMMENT''修改时间'',

`createdUser`varchar(20)DEFAULTNULLCOMMENT''创建用户'',

`modifiedUser`varchar(20)DEFAULTNULLCOMMENT''修改用户'',

PRIMARYKEY(`id`)

)ENGINE=InnoDBAUTO_INCREMENT=141DEFAULTCHARSET=utf8;



DAO接口及方法定义

在此模块没有分页,没有查询,重点是要查询本菜单和一级.



publicinterfaceSysMenuDao{

List>findObjects();

}





Mapper元素定义

创建SysMenuMapper,并添加select元素,实现菜单信息的获取







Selectm.,

(selectp.namefromsys_menuspwherep.id=m.parentId)as

parentName

fromsys_menusm







对于这个查询也可以这样写:







selectm.,p.nameparentName fromsys_menusmleftjoinsys_menusp

onm.parentId=p.id









Service中方法的定义

定义SysMenuService接口以及实现类,并添加findObjects方法

@Service

publicclassSysMenuServiceImplimplementsSysMenuService{

@Autowired

privateSysMenuDaomenuDao;

@Override

publicList>findObjects(){

returnmenuDao.findObjects();

}

}



Controller中方法定义



@Controller

@RequestMapping("/menu/")

publicclassSysMenuController{

@Resource

privateSysMenuServicemenuService;

@RequestMapping("listUI")

publicStringlistUI(){

return"sys/menu_list";

}

@RequestMapping("doFindObjects")

@ResponseBody

publicJsonResultdoFindObjects(){

List>list=menuService.findObjects();

returnnewJsonResult(1,"ok",list);

}

}





客户端设计及实现

定义menu_list.html页面



重点关注table元素定义,假如使用的库以树结构形式

表格数据,就需要按照treeGrid的定义规范table.













页面中添加js(第一步需要将treegrid放到项目对应目录)







/

初始化表格的列(这些列如何定义,按照treeGrid规范即可

我自己在实现时是先treeGridDemo案例,然后从拷贝

实现./

varcolunms=[

{

field:''selectItem'',

radio:true

},

{

title:''菜单ID'',

field:''id'',

visible:false,

align:''center'',

valign:''middle'',

width:''80px''

},

{

title:''菜单名称'',

field:''name'',

align:''center'',

valign:''middle'',

sortable:true,

width:''180px''

},

{

title:''上级菜单'',

field:''parentName'',

align:''center'',

valign:''middle'',

sortable:true,

width:''180px''

},

{

title:''类型'',

field:''type'',

align:''center'',

valign:''middle'',

sortable:true,

width:''100px'',

formatter:function(item,index){

if(item.type==1){

return''菜单
'';

}

if(item.type==2){

return''按钮'';

}

}

},

{

title:''排序号'',

field:''sort'',

align:''center'',

valign:''middle'',

sortable:true,

width:''100px''

},

{

title:''菜单URL'',

field:''url'',

align:''center'',

valign:''middle'',

sortable:true,

width:''160px''

},

{

title:''授权标识'',

field:''permission'',

align:''center'',

valign:''middle'',

sortable:true

}];



$(function(){

doGetObjects();

});

functiondoGetObjects(){

vartableId="menuTable";

vartable=newTreeTable(tableId,"menu/doFindObjects.do",colunms);

table.setExpandColumn(2);

table.init();//底层会发起异步请求加载数据,然后初始化表格}





说明:本案例中会用到treeGrid库,需要将相应的js引入到当前页面



课后了解内容(js内容进行强化,代码是treetable.js的实现原理分析)

(function(){

vartree=function(id,name){

this.id=id;

this.name=name;

};

tree.prototype={

setId:function(id){

this.id=id;

}

setName:function(name){

this.name=name;

}

};

window.tree=tree;

}())$("#load-menu-id").click(function(){

//console.log("helloworld");

$(".container-fluid").load("menu/listUI.do",function(){

$(".container-fluid").removeData("id");

});

})



菜单删除模块

服务端设计及实现

Dao接口方法定义

SysMenuDao接口中添加如下两个方法



publicinterfaceSysMenuDao{



inthasChild(IntegermenuId);

intdeleteObject(Integerid);

}



从业务菜单进行删除操作时只能删除树结构中的叶子节点(子的菜单的节点).

技术角度实现,在执行操作应先查询这个下有没有菜单,

通过对子元素进行统计实现.假如统计结果为没有子元素,这样

可以对菜单进行删除操作了.查询要删除的菜单是否有子菜单



selectcount()

fromsys_menus

whereparentId=#{menuId}



删除菜单按钮



deletefromsys_menuswhereid=#{id}

@Override

publicvoiddeleteObject(IntegermenuId){

if(menuId==null)

thrownewServiceException("删除菜单,菜单id不能为空!");

intcount=menuDao.hasChild(menuId);

if(count!=0)

thrownewServiceException("请先删除子菜单或按钮!");

inti=menuDao.deleteObject(menuId);

if(i!=1)thrownewServiceException("删除菜单失败!");

}@RequestMapping("doDeleteObject")

@ResponseBody

publicJsonResultdoDeleteObject(IntegermenuId){

menuService.deleteObject(menuId);

returnnewJsonResult();

}



客户端设计及实现



删除按钮事件注册

页面加载完成,采用如下语句注册事件



$(''.input-group-btn'').on(''click'',''.btn-delete'',doDeleteObject)



删除按钮事件处理



/获得选中的id值/

functiongetSelectedId(){

//1.1获得选中的对象,默认返回值为一个对象数组

varselections=$("#menuTable")

.bootstrapTreeTable("getSelections");

if(selections.length==0){

return-1;//表示没选择任何对象

}

//1.2获得选中数组中下标为0的元素id的值

returnselections[0].id;

}

//删除菜单项

functiondoDeleteObject(){

varmenuId=getSelectedId();

if(menuId==-1){

alert("请先选择");

return;

}

varparams={''menuId'':menuId};

varurl=''menu/doDeleteObject.do'';

$.post(url,params,function(result){

if(result.state==1){

alert(''删除成功!'');

doGetObjects();

}else{

alert(result.message);

}

});

}





菜单添加页面设计

业务描述

点击菜单列表页面的添加按钮





点击上级菜单时,弹出树结构,选择具体选项











页面呈现



Controller方法定义



@RequestMapping("editUI")

publicStringeditUI(){

return"sys/menu_edit";

}



定义添加页面

在WEB-INF/pages/sys/menu_edit.html,在对应div添加如下form元素







类型





菜单



按钮







菜单名称











上级菜单











菜单URL











授权标识:




placeholder="多个用逗号分隔,如:user:list,user:create"

class="form-control">







排序号:




class="form-control">











Cancel

Save











Js定义

在sys_menu.html文件中定义,页面加载事件



$(".input-group-btn").on("click",".btn-add",doLoadEditPage)



事件处理函数

functiondoLoadEditPage(){

vartitle="添加菜单"

varurl="menu/editUI.do";

$(".container-fluid").load(url,function(){

$(".box-title").html(title);

});

}一个值对象,用于封装zTree上节点信息

publicclassNode{

privateIntegerid;

privateIntegerparentId;

privateStringname;

//set/get

}



不写这个类可以吗?可以map都可以封装





DAO操作

在SysMenuDao中定义查询节点的方法



ListfindZtreeNodes();



Mapper操作

在SysUserMapper中定义查询节点的信息



select

id,

name,

parentId

from

sys_menus





Service操作



在SysUserService接口及实现类中定义查询节点的方。



@Override

publicListfindZtreeNodes(){

//TODOAuto-generatedmethodstub

returnmenuDao.findZtreeNodes();

}



Controller操作



@RequestMapping("treeUI")

@ResponseBody

publicJsonResulttreeUI(){

Listlist=

menuService.findZtreeNodes();

returnnewJsonResult(1,"ok",list);

}



客户端设计与实现



编辑页面添加DIV元素

在编辑页面menu_edit.html添加用于呈现树结构的div元素,例如


style="z-index:59891016;width:300px;height:450px;top:100px;left:500px;display:none">

选择菜单















确定

取消







在这个页面呈现数据时bower_components这个目录下.html页面引入CSS,在当前html页面引入js。

例如:


href="bower_components/layer/skin/default/layer.css">


href="bower_components/ztree/css/metroStyle/metroStyle.css"/>



在编辑页面后面


src="bower_components/layer/layer.js">



上级菜单选项注册事件

事件注册

$(''.form-horizontal'')

.on(''click'',''.load-sys-menu'',doLoadZTreeNodes);



上级菜单事件处理

定义配置信息varzTree;

varsetting={

data:{

simpleData:{

enable:true,

idKey:"id",//节点数据中保存唯一标识的属性名称

pIdKey:"parentId",//节点数据中保存其父节点唯一标识的属性名称

rootPId:null//根节点id

}

}

}

定义事件处理函数functiondoLoadZTreeNodes(){

$(''#menuLayer'').css(''display'',''block'');

varurl=''menu/treeUI.do'';

$.getJSON(url,function(result){

if(result.state==1){

zTree=$.fn.zTree.init($("#menuTree"),setting,result.data);

}else{

alert(result.message);

}

})

}



点击ZTree确定按钮,执行

functiondoSetSelectedNode(){

varselectedNodes=zTree.getSelectedNodes();

varnode=selectedNodes[0];

$(''#menuLayer'').css(''display'',''none'');

$(''#parentId'').val(node.name);

$(''.form-horizontal'').data(''parentId'',node.id);

}



菜单数据保存

与实现



在pojo包中定义SysMenu类,用于封装数据

publicclassSysMenuimplementsSerializable{

privatestaticfinallongserialVersionUID=6880195210216766454L;

privateIntegerid;

privateStringname;

privateStringurl;

privateinttype;

privateintsort;

privateStringnote;

privateIntegerparentId;

privateStringpermission;

privateDatecreatedTime;

privateDatemodifiedTime;

privateStringcreatedUser;

privateStringmodifiedUser;

//set/get

}



Dao方法定义实现



intinsertObject(SysUserentity);



方法定义实现

SysMenuService接口及实现类中定义Object方法

@Override

publicintsaveObject(SysMenuentity){

if(entity==null)

thrownewServiceException("保存的数据不能为空");

introws=sysMenuDao.insertObject(entity);

if(rows!=1)

thrownewServiceException("数据保存失败");

returnrows;

}方法定义实现

SysMenuController中定义SaveObject方法



@RequestMapping("doSaveObject")

@ResponseBody

publicJsonResultdoSaveObject(SysMenuentity){

sysMenuService.saveObject(entity);

returnnewJsonResult(1,"saveok");

}设计与实现



按钮事件注册



$(''.form-horizontal'') .on(''click'',''.btn-save'',doSaveOrUpdate)



保存按钮事件

获取表单数据

functiongetFormData(){

varparams={

type:$("input[name=''typeId'']:checked").val(),

name:$("#nameId").val(),

parentId:$(''.form-horizontal'').data(''parentId''),

url:$("#urlId").val(),

permission:$("#permissionId").val(),

sort:$("#sortId").val()

}

returnparams;

}



提交表单数据

functiondoSaveOrUpdate(){

//1.获取表单数据

varparams=getFormData();

//2.异步提交表单数据

varurl=menu/doSaveObject.do;

$.post(url,params,function(result){

if(result.state==1){

alert(result.message);

doCancel();

}else{

alert(result.message);

}

});

}



修改页面加载

时根据选择的id查询库,然后将结果填充在表单中.

实现

方法定义

根据id查询的方法

Map

findObjectById(Integerid);



Mapper元素定义

id查询菜单信息.
resultType="map">

selectm.,p.nameparentName

fromsys_menusmleftjoinsys_menusp

onm.parentId=p.id

wherem.id=#{id}





Service方法定义

id执行查询操作.@Override

publicMapfindObjectById(Integerid){

if(id==null||id<1)

thrownewServiceException("id的值无效");

Mapmap=

sysMenuDao.findObjectById(id);

returnmap;

}Controller方法定义



@RequestMapping("treeUI")

@ResponseBody

publicJsonResulttreeUI(){

Listlist=sysMenuService.findZtreeNodes();

returnnewJsonResult(1,"ok",list);

}实现

页面列表页面点击修改时编辑页面(添加一个)



按钮事件注册:





$(".input-group-btn")

.on("click",".btn-add,.btn-update",doLoadEditPage)



按钮事件处理:





functiondoLoadEditPage(){

vartitle;

if($(this).hasClass("btn-add")){

title="添加菜单";

}elseif($(this).hasClass("btn-update")){

title="修改菜单";

varid=getSelectedId();

if(id==-1){

alert("请先选择");

return;

}

$(".container-fluid").data("id",id);

}

varurl="menu/editUI.do";

$(".container-fluid").load(url,function(){

$(".box-title").html(title);

});



}



编辑页面操作页面加载完成以后根据id的值异步获取数据库

页面数据.



$(function(){

varid=$(".container-fluid").data("id");

//假如id有值说明是修改,然后根据id查找菜单信息

if(id){

doFindObjectById(id);

}

});

根据id查找functiondoFindObjectById(id){

varurl="menu/doFindObjectById.do";

varparams={"id":id};

$.getJSON(url,params,function(result){

if(result.state==1){

doInitFormData(result.data)

}else{

alert(result.message);

}

})

}



通过数据初始化表单



$(function(){

$(''.form-horizontal'')

.on(''click'',''.load-sys-menu'',doLoadZTreeNodes)

.on(''click'',''.btn-save'',doSaveOrUpdate)



$(''#menuLayer'')

.on(''click'',''.btn-confirm'',doSetSelectedNode)

.on(''click'',''.btn-cancle'',doHideTree);



varid=$(".container-fluid").data("id");

//假如id有值说明是修改,然后根据id查找菜单信息

if(id){

doFindObjectById(id);

}

});



修改页面数据保存

设计与实现



方法定义

SysMenuDao接口中定义修改数据



intupdateObject(SysMenuentity);



Mapper元素定义

SysMenuMapper中元素





updatesys_menus

set

name=#{name},type=#{type},url=#{url},

sort=#{sort},parentId=#{parentId},

permission=#{permission}

whereid=#{id}



Service方法定义



SysMenuService接口及实现类中定义修改方法



@Override

publicintupdateObject(SysMenuentity){

if(entity==null)

thrownewServiceException("更新的数据不能为空");

introws=sysMenuDao.updateObject(entity);

if(rows!=1)

thrownewServiceException("数据更新失败");

returnrows;

}



Controller方法定义

SysMenuController中定义修改方法

@RequestMapping("doUpdateObject")

@ResponseBody

publicJsonResultdoUpdateObject(SysMenuentity){

sysMenuService.updateObject(entity);

returnnewJsonResult(1,"updateok");

}



客户端设计及实现

表单数据异步更新



functiondoSaveOrUpdate(){

//1.获取表单数据

varparams=getFormData();

varid=$(".container-fluid").data("id");

if(id)params.id=id;

console.log(params);

//2.异步提交表单数据

varinsertUrl="menu/doSaveObject.do";

varupdateUrl="menu/doUpdateObject.do";

varurl=id?updateUrl:insertUrl;

$.post(url,params,function(result){

if(result.state==1){

alert(result.message);

doCancel();

}else{

alert(result.message);

}

});

}



退出时移除绑定的id





functiondoCancel(){

$(".container-fluid").load("menu/listUI.do");

$(".container-fluid").removeData("id")

}





















1-2

齐雷(qilei@tedu.cn)







献花(0)
+1
(本文系金银宝100首藏)
类似文章 更多
发表评论: