extjs 的权限问题 要求控制的对象是 菜单,按钮,URL


Posted in Javascript onMarch 09, 2010

解题思路1 : 重载Connection类
由于extjs和server端交互全都是 json格式的数据交互,server端不会控制页面的跳转,页面跳转,提示功能全都有extjs来完成。
extjs和server端的交互方法全都是继承自 Ext.data.Connection,这个类中可以拦截所有和server端交互的方法。
server端的权限控制用acegi做的,如果没通过acegi的验证,没有授权会返回到403.jsp,需要重登录会返回到 login.jsp。
因此重载Connection类,并改写其中的 handleResponse 方法,判断返回的结果是否是 403.jsp,login.jsp, 如果是就进行相应的控制,如果是正常的返回数据就继续向下执行。
我个人在403.jsp 和login.jsp 的第一行加上了 注释代码<!--权限控制自定义关键字-->,就是靠这个关键字来工作的
,代码如下:

//此处重载了Cunnection方法,用来拦截client与Server的交 互, 
//后台acegi拦截用户请求后,如果无权限,返回403.jsp;如果没登录,返回login.jsp; 
//通过Acegi拦截 后,才返回用户想要的Json结果 
Ext.override(Ext.data.Connection, { 
handleResponse : Ext.data.Connection.prototype.handleResponse.createInterceptor( 
function(response) { 
var resText=response.responseText; 
if (resText.length>10) { 
resText=resText.substr(0,9); 
} 
if (resText=='<!--login'){ 
window.top.location.href = topURL+"/login.jsp"; 
} else if (resText=='<!--deny-'){ 
if (resText=='<!--deny-'){ 
Ext.Msg.show({ 
title : '错误提示', 
msg : '禁止访问此功能,请和系统管理员联系', 
buttons : Ext.Msg.OK, 
icon : Ext.Msg.INFO 
}); 
}; 
} else if (resText=='<!--404--'){ 
Ext.Msg.show({ 
title : '错误提示', 
msg : '页面未找到', 
buttons : Ext.Msg.OK, 
icon : Ext.Msg.INFO 
}); 
} 
}) 
});

解题思路2: server端返回菜单json数据
我的菜单用tree来做的,在初始化主页面时先初始化菜单,
loader : new Ext.tree.TreeLoader({ 
dataUrl : 'getJsonMenus.do' 
}), 
这个'getJsonMenus.do'返回菜单json数据,在strut2中的配置为: 
<action name="getJsonMenus" class="jsonSystemAction" method="getJsonMenus"> 
<result type="json"> 
<param name="root">menus</param> 
</result> 
</action>

menus是个list<JsonMenu>,
JsonMenu的属性为:
private String text;
private boolean expanded;
private String id;
private boolean leaf;
private List<JsonMenu> children;
getJsonMenus.do 返回的格式是可以满足tree的格式要求的。
js代码如下
Ext.onReady(function() { 
setTimeout(function() { 
Ext.get('loading').remove(); 
Ext.getDom('header').style.visibility = 'visible'; 
var vp = new Ext.Viewport({ 
layout : 'border', 
defaults : { 
collapsible : true, 
split : true 
}, 
items : [{ 
xtype : 'box', 
region : 'north', 
applyTo : 'header', 
height : 30, 
split : false 
}, { 
title : currentUser, 
id : 'accordion-panel', 
layout : 'border', 
region : 'west', 
margins : '2 0 5 5', 
width : 200, 
minSize : 200, 
maxSize : 250, 
bodyStyle : 'background-color:#DFE8F6', 
defaults : { 
border : false 
}, 
bbar : [{ 
text : '开始', 
iconCls : 'icon-plugin', 
menu : new Ext.menu.Menu({ 
items : [{ 
text : '关于系统', 
iconCls : 'icon-info', 
handler : function() { 
new Ext.Window({ 
closeAction : 'close', 
resizable : false, 
bodyStyle : 'padding: 7', 
modal : true, 
title : '关于本系统', 
html : '本系统采用目前较为流行的技术实现,<br>前台使用了ExtJs技术,所以实现了跨浏览器<br>' + 
' 本程序在IE6,IE7,FireFox3均测试通过!<br><br>主要技术: Struts2 + Spring + iBatis + ExtJs<br><br>' 
+ '数  据  库: Oracle 9i', 
width : 300, 
height : 200 
}).show(); 
} 
}, { 
text : '退出系统', 
iconCls : 'icon-delete', 
handler : function() { 
Ext.Msg.confirm('操作提示', '您确定要退出本系统?', function(btn) { 
if ('yes' == btn) { 
Ext.Ajax.request({ 
url : 'logout.do', 
success : function() { 
location = '/'; 
}, 
failure : function() { 
Ext.Msg.show({ 
title : '错误提示', 
msg : '退出系统失败!', 
icon : Ext.Msg.ERROR, 
buttons : Ext.Msg.OK 
}); 
} 
}); 
} 
}); 
} 
}] 
}) 
}], 
items : [{ 
layout : 'accordion', 
region : 'center', 
items : [{ 
title : '导航菜单', 
iconCls : 'icon-nav', 
border : false, 
items : [{ 
xtype : 'treepanel', 
border : false, 
rootVisible : false, 
autoScroll : true, 
loader : new Ext.tree.TreeLoader({ 
dataUrl : 'getJsonMenus.do' 
}), 
root : new Ext.tree.AsyncTreeNode(), 
listeners : { 
'click' : function(n) { 
try { 
var sn = this.selModel.selNode || {}; 
if (n.leaf && n.id != sn.id) { 
Ext.getCmp('content-panel').layout.setActiveItem(n.id.substring(0, n.id 
.indexOf('-')) 
+ '-panel'); 
} 
} catch (e) { 
} 
} 
} 
}] 
},{ 
title : '系统设置', 
iconCls : 'icon-nav' 
}] 
}] 
}, { 
id : 'content-panel', 
region : 'center', 
layout : 'card', 
margins : '2 5 5 0', 
activeItem : 0, 
border : false, 
items : [start, p_company, p_user, p_dept, p_system, p_subject, p_category, p_resource] 
}] 
}); 
}, 250); 
});

这样就得到了菜单,还有网友提出了异步菜单解决方法,我也把它列到下面
解题思路3 : 同步加载所有的TAG,用hidden属性控制显示
所有的tag必须要同步加载后才可以控制component的hidden属性,异步加载不好用。
同步加载的方法如下:
//FUTURE_TAG全局的TAG控制类, 控制的组件的hidden属性,key=TAG的名字,value=true(组件隐藏),false(组件显示) 
var FUTURE_TAG={tbar1: false, tbar2: true}; 
var conn = Ext.lib.Ajax.getConnectionObject().conn; 
conn.open("GET", 'getJsonTags.do',false); 
conn.send(null); 
future_tag= eval('(' + conn.responseText + ')');

在js中TAG的用法如下:
var btn_add_system = new Ext.Button({ 
text : '添加', 
iconCls : 'icon-add', 
hidden: FUTURE_TAG.system_add, 
handler : function() { 
window_add_system.show(); 
} 
});

getJsonTags.do 返回一个Map对象,key是TAG名字,value是boolean
java的写法如下:
tagMap=new HashMap<String,Boolean>(); 
for (int i=0;i<allTagList.size();i++){ 
tagMap.put(allTagList.get(i).getResString(), true); 
}

strut2配置如下:
<action name="getJsonTags" class="jsonSystemAction" method="getJsonTags"> 
<result type="json"> 
<param name="root">tagMap</param> 
</result> 
</action>

这样就可以在后台控制前台的组件是否显示了,从而达到了我们的目的。
解决思路4:
通过ajax读取服务器端的权限值,返回这样的数据:
{tbar1: false, tbar2: true}
然后在extjs中:
var vResult = eval('(' + ajaxText + ')'); //得到{tbar1: false, tbar2: true}
这样就可以直接给tbar赋值了
disabled: vResult.tbar1
disabled: vResult.tbar2
解决思路5:
设置模块权限用于设置用户可以操作的权限。允许设置用户对模块的可操作与不可操作。
弹出设置权限子窗体
设置权限之前须选择一个用户。
Js代码
var row = grid_user.getSelectionModel().getSelected(); 
if(!row){ 
alert('对不起,您还未选择数据!'); 
return; 
} 
var row = grid_user.getSelectionModel().getSelected(); 
if(!row){ 
alert('对不起,您还未选择数据!'); 
return; 
}

创建一棵树,树放置在弹出窗体的中央。
Js代码
var root=new Ext.tree.TreeNode({ 
id:"root", 
text:"所有操作", 
checked:false, 
iconCls:'task-folder' 
}); 
var tree=new Ext.tree.TreePanel({ 
frame:false, 
region:'center', 
root:root, 
animate:true, 
enableDD:false, 
border:false, 
rootVisible:true, 
autoScroll:true 
}); 
var root=new Ext.tree.TreeNode({ 
id:"root", 
text:"所有操作", 
checked:false, 
iconCls:'task-folder' }); 
var tree=new Ext.tree.TreePanel({ 
frame:false, 
region:'center', 
root:root, 
animate:true, 
enableDD:false, 
border:false, 
rootVisible:true, 
autoScroll:true 
});

创建弹出子窗体。
Js代码
var win = new Ext.Window({ 
title:'设置模块权限', 
closable:true, 
width:300, 
height:500, 
plain:true, 
layout:'border', 
modal:true, 
items:[tree] 
}); 
win.show(this); 
var win = new Ext.Window({ 
title:'设置模块权限', 
closable:true, 
width:300, 
height:500, 
plain:true, 
layout:'border', 
modal:true, 
items:[tree] 
}); 
win.show(this);

在加载数据期间,给予提示。
Js代码
Ext.MessageBox.show({ 
title:'请稍候', 
msg:'正在加载数据,请耐心等待...', 
progress:true 
}); 
Ext.MessageBox.show({ 
title:'请稍候', 
msg:'正在加载数据,请耐心等待...', 
progress:true 
});

将根节点,所选择的用户行,父节点标志作为参数调用方法。
Js代码
getNodes(row,root,'root');
getNodes(row,root,'root');
从后台中取得数据并以树形式在客户端展现
方法定义与方法内容。
Js代码
function getNodes(row,root,parent){ 
//... 
} 
function getNodes(row,root,parent){ //...}

JSON 数据的定义。
Js代码
var record_pri = new Ext.data.Record.create([ 
{name:'modelId'}, 
{name:'modelName'}, 
{name:'sort'}, 
{name:'canUse'}, 
{name:'privilegeId'} 
]); 
var store_pri = new Ext.data.Store({ 
proxy: new Ext.data.HttpProxy({url:'../'}), 
reader: new Ext.data.JsonReader({root:'rows'},record_pri) 
}); 
var record_pri = new Ext.data.Record.create([ 
{name:'modelId'}, 
{name:'modelName'}, 
{name:'sort'}, 
{name:'canUse'}, 
{name:'privilegeId'} 
]); var store_pri = new Ext.data.Store({ 
proxy: new Ext.data.HttpProxy({url:'../'}), 
reader: new Ext.data.JsonReader({root:'rows'},record_pri) 
});

无刷新请求,获取数据并展现出来;并添加事件监听。当点击树某一节点时,判断是否已经从后台取得数据,如果还没有取则从后台获取数据,再根据返回的数据判断是叶子节点还是非叶子节点。然后以不同的方式展现与处理。
叶子节点和非叶子节点展现时,使用的图标不同。叶子节点没有添加单击事件,而非叶子节点添加了单击事件。
Js代码
Ext.Ajax.request({ 
url:'http://www.cnblogs.com/../privilegeAction.do?method=list', 
params:{ 
userId:row.get('userId'), 
parentId:parent 
}, 
success:function(response, request){ 
Ext.MessageBox.hide(); 
var res = Ext.util.JSON.decode(response.responseText); 
store_pri.loadData(res); 
for(var i=0;i<store_pri.getCount();i++){ 
var rec = store_pri.getAt(i); 
var canuse = (rec.get('canUse')=='是'?true:false); 
var modid = rec.get('privilegeId') + '-id-' + rec.get('modelId'); 
var node; 
if(rec.get('sort')=='菜单'){ 
node = new Ext.tree.TreeNode({ 
text:rec.get('modelName'), 
id:modid, 
checked:canuse, 
iconCls:'task-folder' 
}); 
node.on('click',function(node){ 
if(node.firstChild==null){ 
getNodes(row,node,get_mod_id(node.id)); 
} 
}); 
} else { 
node = new Ext.tree.TreeNode({ 
text:rec.get('modelName'), 
id:modid, 
checked:canuse, 
iconCls:'task' 
}); 
} 
node.on('checkchange',function(node,check){ 
Ext.Ajax.request({ 
url:'http://www.cnblogs.com/../privilegeAction.do?method=save2', 
params:{ 
privilegeId:get_rec_id(node.id), 
canuse:(check?'是':'否') 
}, 
success:function(response, request){ }, 
failure:function(){ 
Ext.MessageBox.hide(); 
alert('sorry!'); 
} 
}); 
}); 
root.appendChild(node); 
} 
root.expand(); 
}, 
failure:function(){ 
Ext.MessageBox.hide(); 
alert('sorry!'); 
} 
}); 
Ext.Ajax.request({ 
url:'http://www.cnblogs.com/../privilegeAction.do?method=list', 
params:{ 
userId:row.get('userId'), 
parentId:parent 
}, 
success:function(response, request){ 
Ext.MessageBox.hide(); 
var res = Ext.util.JSON.decode(response.responseText); 
store_pri.loadData(res); 
for(var i=0;i<store_pri.getCount();i++){ 
var rec = store_pri.getAt(i); 
var canuse = (rec.get('canUse')=='是'?true:false); 
var modid = rec.get('privilegeId') + '-id-' + rec.get('modelId'); 
var node; 
if(rec.get('sort')=='菜单'){ 
node = new Ext.tree.TreeNode({ 
text:rec.get('modelName'), 
id:modid, 
checked:canuse, 
iconCls:'task-folder' 
}); 
node.on('click',function(node){ 
if(node.firstChild==null){ 
getNodes(row,node,get_mod_id(node.id)); 
} 
}); 
} else { 
node = new Ext.tree.TreeNode({ 
text:rec.get('modelName'), 
id:modid, 
checked:canuse, 
iconCls:'task' 
}); 
} 
node.on('checkchange',function(node,check){ 
Ext.Ajax.request({ 
url:'https://3water.com/../privilegeAction.do?method=save2', 
params:{ 
privilegeId:get_rec_id(node.id), 
canuse:(check?'是':'否') 
}, 
success:function(response, request){ 
}, 
failure:function(){ 
Ext.MessageBox.hide(); 
alert('sorry!'); 
} 
}); 
}); 
root.appendChild(node); 
} 
root.expand(); 
}, 
failure:function(){ 
Ext.MessageBox.hide(); 
alert('sorry!'); 
} });

当非叶子节点被点击时,递归地调用方法来获取孩子节点。
获取行的ID和模块的ID。树的节点将行的ID和模块的ID一起取出来了。不然的话,如果只取得模块ID,而不取行ID,那么在修改的时候,则不能进行正确的修改。
Js代码
function get_rec_id(str){ 
var arr = str.split('-id-'); 
return arr[0]; 
} 
function get_mod_id(str){ 
var arr = str.split('-id-'); 
return arr[1]; 
}
Javascript 相关文章推荐
JavaScript的eval JSON object问题
Nov 15 Javascript
分享20款好玩的jQuery游戏
Apr 17 Javascript
JS 去除Array中的null值示例代码
Nov 20 Javascript
jquerydom对象的事件隐藏显示和对象数组示例
Dec 10 Javascript
angularJS中router的使用指南
Feb 09 Javascript
JavaScript实现的链表数据结构实例
Apr 02 Javascript
jQuery使用siblings获取某元素所有同辈(兄弟姐妹)元素用法示例
Jan 30 Javascript
浅谈Vue.js应用的四种AJAX请求数据模式
Aug 30 Javascript
详解浏览器缓存和webpack缓存配置
Jul 06 Javascript
微信小程序sessionid不一致问题解决
Aug 30 Javascript
JavaScript 面向对象基础简单示例
Oct 02 Javascript
浅谈vue 锚点指令v-anchor的使用
Nov 13 Javascript
javascript 简单抽屉效果的实现代码
Mar 09 #Javascript
Javascript常考语句107条收集
Mar 09 #Javascript
风吟的小型JavaScirpt库 (FY.JS).
Mar 09 #Javascript
Jquery实现无刷新DropDownList联动实现代码
Mar 08 #Javascript
JavaScript this调用规则说明
Mar 08 #Javascript
javascript 放大镜 v1.0 基于Yui2 实现的放大镜效果
Mar 08 #Javascript
JavaScript中的闭包原理分析
Mar 08 #Javascript
You might like
CPU步进是什么意思?i3-9100F B0步进和U0步进区别知识科普
2020/03/17 数码科技
PHP cron中的批处理
2008/09/16 PHP
在PHP中使用反射技术的架构插件使用说明
2010/05/18 PHP
Php图像处理类代码分享
2012/01/19 PHP
Codeigniter通过SimpleXML将xml转换成对象的方法
2015/03/19 PHP
PHP获取类私有属性的3种方法
2020/09/10 PHP
漂亮的widgets,支持换肤和后期开发新皮肤(2007-4-27已更新1.7alpha)
2007/04/27 Javascript
jQuery 动画基础教程
2008/12/25 Javascript
JQuery 风格的HTML文本转义
2009/07/01 Javascript
原生javascript实现图片轮播效果代码
2010/09/03 Javascript
jQuery 对Select的操作备忘记录
2011/07/04 Javascript
jQuery动画显示和隐藏效果实例演示(附demo源码下载)
2015/12/31 Javascript
浅析AMD CMD CommonJS规范--javascript模块化加载学习心得总结
2016/03/16 Javascript
JQuery手速测试小游戏实现思路详解
2016/09/20 Javascript
jQuery扩展+xml实现表单验证功能的方法
2016/12/25 Javascript
详解Angular的数据显示优化处理
2016/12/26 Javascript
利用JS做网页特效_大图轮播(实例讲解)
2017/08/09 Javascript
JS实现登录页密码的显示和隐藏功能
2017/12/06 Javascript
详解webpack打包后如何调试的方法步骤
2018/11/07 Javascript
js遍历详解(forEach, map, for, for...in, for...of)
2019/08/28 Javascript
[26:40]DOTA2上海特级锦标赛A组资格赛#1 Secret VS MVP.Phx第一局
2016/02/25 DOTA
Python的Django框架中forms表单类的使用方法详解
2016/06/21 Python
Python读写Json涉及到中文的处理方法
2016/09/12 Python
Python+matplotlib绘制不同大小和颜色散点图实例
2018/01/19 Python
mvc框架打造笔记之wsgi协议的优缺点以及接口实现
2018/08/01 Python
python3.6、opencv安装环境搭建过程(图文教程)
2019/11/05 Python
pandas中ix的使用详细讲解
2020/03/09 Python
如何在python中处理配置文件代码实例
2020/09/27 Python
最新PyCharm 2020.2.3永久激活码(亲测有效)
2020/11/26 Python
法国最大电子商务平台:Cdiscount
2018/03/13 全球购物
英国最受欢迎的价格比较网站之一:MoneySuperMarket
2018/12/19 全球购物
北美最大的参茸药食商城:德成行
2020/12/06 全球购物
小学校园活动策划
2014/01/30 职场文书
竞聘演讲稿开场白
2014/08/25 职场文书
努力学习保证书
2015/02/26 职场文书
vue使用watch监听属性变化
2022/04/30 Vue.js