一.下载、安装zTree
zTree下载地址:http://code.google.com/p/jquerytree/downloads/list
这里我下载的是JQuery zTree v3.0。目前最新版是v3.1,一般不建议使用最新版。
下载完成后解压,可以看到其中有三个文件夹和一个更新日志文件。
Css文件夹 zTree的样式和图片存放位置
Demo文件夹 存放zTree的一些实例
Js文件夹 存放的是所有与zTree相关的js文件。这里min是压缩版,我们在开发的时候建议使用未压缩版的(不含min的)。
开发时建议将这些压缩包统一放在一个文件夹(比如zTree)下,这样,如果需要查看对应的实例,可直接在当前工程下访问并做修改,便于开发使用。当然,开发完成后可以删除demo内容。
二.编辑页面
001 |
<%@ page language="java" pageEncoding="UTF-8"%> |
002 |
<%@taglib uri="/struts-tags" prefix="s"%> |
003 |
<%@ include file="../common/header.jsp" %> |
004 |
005 |
<!DOCTYPE html> |
006 |
< HTML > |
007 |
< HEAD > |
008 |
< title >指派权限</ title > |
009 |
< meta http-equiv = "content-type" content = "text/html; charset=UTF-8" > |
010 |
|
011 |
< link rel = "stylesheet" type = "text/css" href = "${root}/css/dialogStyle.css" /> |
012 |
< link rel = "stylesheet" href = "${root}/js/zTree/css/zTreeStyle/zTreeStyle.css" type = "text/css" > |
013 |
< link rel = "stylesheet" type = "text/css" href = "${root}/js/jquery/themes/icon.css" /> |
014 |
< STYLE type = "text/css" > |
015 |
.btn { |
016 |
BACKGROUND: url(../images/bt_bg.gif); |
017 |
BORDER-RIGHT: #999999 1px solid; |
018 |
PADDING-RIGHT: 2px; |
019 |
BORDER-TOP: #CCCCCC 1px solid; |
020 |
PADDING-LEFT: 2px; FONT-SIZE: 12px; |
021 |
FILTER: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr=#ffffff, EndColorStr=#cecfde); |
022 |
BORDER-LEFT: #CCCCCC 1px solid; |
023 |
CURSOR: hand; COLOR: black; |
024 |
PADDING-TOP: 2px; |
025 |
BORDER-BOTTOM: #999999 1px solid; |
026 |
} |
027 |
</ STYLE > |
028 |
|
029 |
<!-- |
030 |
为提高效率,建议将1.4.4换成1.6.4版 |
031 |
<script type="text/javascript" src="${root}/js/zTree/js/jquery-1.4.4.min.js"></script> |
032 |
--> |
033 |
< script type = "text/javascript" src = "${root}/js/jquery/jquery-1.6.4.min.js" ></ script > |
034 |
< script type = "text/javascript" src = "${root}/js/jquery/jquery.easyui.min.js" ></ script > |
035 |
< script type = "text/javascript" src = "${root}/js/zTree/js/jquery.ztree.core-3.0.js" ></ script > |
036 |
< script type = "text/javascript" src = "${root}/js/zTree/js/jquery.ztree.excheck-3.0.js" ></ script > |
037 |
< script type = "text/javascript" src = "${root}/js/winutil.js" ></ script > |
038 |
039 |
<!-- |
040 |
<script type="text/javascript" src="${root}/js/js/jquery.ztree.exedit-3.0.js"></script> |
041 |
--> |
042 |
< SCRIPT type = "text/javascript" > |
043 |
<!-- |
044 |
var setting = { |
045 |
async: { |
046 |
enable: true,//异步处理 |
047 |
048 |
//contentType: "application/json",//提交参数方式,这里 JSON 格式,默认form格式 |
049 |
|
050 |
url: '${root}/sys/listoper.action?roleId=${roleId}',//异步获取json格式数据的路径 |
051 |
052 |
autoParam: ["id","name"]//异步加载时需要提交的参数,多个用逗号分隔 |
053 |
|
054 |
}, |
055 |
callback: {//回调函数,在这里可做一些回调处理 |
056 |
//beforeAsync: zTreeBeforeAsync |
057 |
}, |
058 |
check: {//设置 zTree 的节点上是否显示 checkbox / radio ,默认为false |
059 |
enable: true |
060 |
}, |
061 |
data: { |
062 |
simpleData: { |
063 |
/** |
064 |
如果设置为 true,请务必设置 setting.data.simpleData 内的其他参数: idKey / pIdKey / rootPId |
065 |
并且让数据满足父子关系。*/ |
066 |
enable: true,//true / false 分别表示 使用 / 不使用 简单数据模式 |
067 |
idKey: "id", |
068 |
pIdKey: "pId", |
069 |
rootPId: 0 |
070 |
} |
071 |
} |
072 |
}; |
073 |
074 |
var zNodes =[];//树节点,json格式,异步加载可设置为null或[] |
075 |
var zTreeObj;//树对象 |
076 |
|
077 |
$(document).ready(function(){ |
078 |
|
079 |
zTreeObj = $.fn.zTree.init($("#permission_tree"), setting, zNodes);//实例化后直接返回树对象 |
080 |
081 |
//异步提交表单 |
082 |
$('#permissionform').form({ |
083 |
url: '${root}/sys/PermissionManagerole.action', |
084 |
onSubmit: function() { |
085 |
//获取树对象中选中的节点 |
086 |
var nodes = zTreeObj.getCheckedNodes(); |
087 |
var s = '';//选中节点ids |
088 |
//遍历选中的节点,为s赋值 |
089 |
for(var i=0; i<nodes.length; i++){ |
090 |
if (s != '') s += ','; |
091 |
s += nodes[i].id; |
092 |
} |
093 |
document.all("roledto.permissionIds").value = s; |
094 |
}, |
095 |
success: function(data) { |
096 |
//操作成功,返回信息 |
097 |
var data = jQuery.parseJSON(data); |
098 |
if(data.success == false){ |
099 |
alert(data.msg); |
100 |
} |
101 |
m_close(); |
102 |
} |
103 |
}); |
104 |
|
105 |
}); |
106 |
107 |
//--> |
108 |
</ SCRIPT > |
109 |
</ HEAD > |
110 |
111 |
< BODY onunload = "m_close()" style = "background-color: #f7f7f7;" > |
112 |
< div style = "border: 0px ;width: 100%;height:100%;background-color: #f7f7f7;" > |
113 |
|
114 |
<!-- 树加载后存放的容器 --> |
115 |
< ul id = "permission_tree" class = "ztree" style = "border: 0px; background-color: #f7f7f7;" ></ ul > |
116 |
|
117 |
<!-- 提交授权操作表单 --> |
118 |
< form id = "permissionform" method = "post" > |
119 |
< table > |
120 |
< tr > |
121 |
< td >< input type = "hidden" name = "roledto.permissionIds" /></ td > |
122 |
< td >< input type = "hidden" name = "roledto.roleId" value = "${roleId}" /></ td > |
123 |
< td >< input type = "hidden" name = "orgid" value = "${orgId}" /></ td > |
124 |
</ tr > |
125 |
< tr > |
126 |
< td width = "100%" align = "right" > |
127 |
< input type = "submit" style = "width:60px;" class = "btn" value = "保存" /> |
128 |
< input type = "button" style = "width:60px;" class = "btn" value = "取消" onclick = "m_close()" /> |
129 |
</ td > |
130 |
</ tr > |
131 |
</ table > |
132 |
</ form > |
133 |
|
134 |
</ div > |
135 |
136 |
</ BODY > |
137 |
</ HTML > |
三.后台Action
01 |
private String id; |
02 |
|
03 |
private String roleId; |
04 |
|
05 |
/** |
06 |
* 显示权限栏目树 |
07 |
* 这里采用一次加载所有树节点的方式 |
08 |
* 当然也可以换成逐级动态加载的方式 |
09 |
* @return |
10 |
* @throws IOException |
11 |
*/ |
12 |
@SuppressWarnings ( "unchecked" ) |
13 |
public String list() throws IOException{ |
14 |
|
15 |
/** |
16 |
* 再次查询时直接返回,这里采用所有节点一次加载的方式 |
17 |
* @param id 点击树的节点时传递到后台的属性id |
18 |
*/ |
19 |
if (ValidateUtil.validateString(id)){ |
20 |
return SUCCESS; |
21 |
} |
22 |
//根据角色找到对应的操作权限id |
23 |
String operationids = this .getOperationIdsByRoleId(roleId); |
24 |
//查询所有的权限分类,如系统管理、订单管理、采购管理等等,作为树的一级节点 |
25 |
List<OperationClass> list =operationClassServiceImpl.getAllOperationClass(); |
26 |
//存放树节点信息 |
27 |
List<Map<String,Object>> items = new ArrayList<Map<String,Object>>(); |
28 |
//当前角色对应的操作 |
29 |
List<RoleOperation> rolist = this .roleServiceImpl.getRoleOperationByRoleId(roleId); |
30 |
|
31 |
for (OperationClass node: list){ //第一级遍历,遍历所有的权限分类 |
32 |
|
33 |
Map<String,Object> item = new HashMap<String,Object>(); //最外层,父节点 |
34 |
item.put( "id" , node.getOperationClassId()); //id属性 ,数据传递 |
35 |
item.put( "name" , node.getClassName()); //name属性,显示节点名称 |
36 |
item.put( "isParent" , true ); //设置为父节点,这样所有最外层节点都是统一的图标,看起来会舒服些 |
37 |
//item.put("iconSkin", "diy02");//设置节点的图标皮肤, diy02在zTreeStyle.css中进行设置 |
38 |
|
39 |
/** |
40 |
* 如果当前节点(权限分类)有对应的操作(权限),添加操作权限作为该节点的子节点 |
41 |
*/ |
42 |
if (node.getOperations()!= null &&node.getOperations().size()> 0 ){ |
43 |
|
44 |
Iterator<Operation> it = node.getOperations().iterator(); |
45 |
//存放第一层子节点信息 |
46 |
List<Map<String,Object>> subitems = new ArrayList<Map<String,Object>>(); |
47 |
|
48 |
while (it.hasNext()){ //对操作进行遍历 |
49 |
|
50 |
Map<String,Object> subitem = new HashMap<String,Object>(); //第二层 |
51 |
Operation oper = (Operation) it.next(); |
52 |
subitem.put( "id" , oper.getOperationId()+ ":oper" ); //id属性 ,数据传递 |
53 |
subitem.put( "name" , oper.getOperationName()); //name属性,显示节点名称 |
54 |
|
55 |
/** |
56 |
* 如果操作中有多个选项,添加选项作为第二层的子节点 |
57 |
*/ |
58 |
if (oper!= null &&oper.getOptions()!= null ){ |
59 |
String uoption = "" ; //有操作权限的操作选项 |
60 |
for (RoleOperation ro : rolist){ |
61 |
if (ro.getOperation().getOperationId(). |
62 |
equals(oper.getOperationId())){ //如果当前角色有对应的操作 |
63 |
uoption = ro.getOptions(); |
64 |
} |
65 |
} |
66 |
String[] suboper = oper.getOptions().split( "," ); |
67 |
List<Map<String,Object>> items3 = new ArrayList<Map<String,Object>>(); //第三层 |
68 |
for ( int i= 0 ;i<suboper.length;i++){ |
69 |
Map<String,Object> item3 = new HashMap<String,Object>(); |
70 |
item3.put( "id" , "opt:" +oper.getOperationId()+ ":" +suboper[i]); //id属性 ,数据传递 |
71 |
item3.put( "name" , suboper[i]); //name属性,显示节点名称 |
72 |
73 |
if (uoption!= null &&! "" .equals(uoption)){ //如果操作中有操作选项 |
74 |
if (uoption.contains(suboper[i]+ "," )){ //如果当前角色有此操作选项 |
75 |
item3.put( "checked" , true ); //将此选项选中 |
76 |
} |
77 |
} |
78 |
items3.add(item3); //添加到树的第三层 |
79 |
} |
80 |
subitem.put( "children" , items3); //添加第二层子节点 |
81 |
|
82 |
} else { //如果操作没有选项 |
83 |
if (operationids.contains(oper.getOperationId())){ //当前角色有此操作 |
84 |
subitem.put( "checked" , true ); //将此操作选中 |
85 |
} |
86 |
} |
87 |
subitems.add(subitem); //添加到树的第二层 |
88 |
} |
89 |
item.put( "children" , subitems); //添加第一层子节点 |
90 |
|
91 |
} |
92 |
items.add(item); //添加到树的第一层 |
93 |
|
94 |
} |
95 |
JSONArray json = JSONArray.fromObject(items); //转成json格式 |
96 |
jsonString = json.toString(); //json格式字符串 |
97 |
|
98 |
return SUCCESS; |
99 |
} |
四.编后语
公司之前用的jQuery dTree。dTree也是比较好用的,跟zTree的区别不是很大。但有一点比较让人难以忍受,dTree在页面的解析效率比较低。在权限操作这一块儿换成zTree后速度提高了好几倍。
zTree的具体使用已在页面和action模块做了细致的说明,如果对其中的用法比较有疑问可以查看官方的api,中文api地址如下: http://www.baby666.cn/v3/api.php