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 Zifa FormValid 0.1表单验证 代码打包下载
Jun 08 Javascript
javascript 闭包详解
Jul 02 Javascript
Jquery幻灯片特效代码分享--鼠标点击按钮时切换(1)
Aug 15 Javascript
jQuery 移动端拖拽(模块化开发,触摸事件,webpack)
Oct 28 Javascript
如何用JS/HTML将时间戳转换为“xx天前”的形式
Feb 06 Javascript
AngularJs+Bootstrap实现漂亮的计算器
Aug 10 Javascript
webpack手动配置React开发环境的步骤
Jul 02 Javascript
vue.js实现格式化时间并每秒更新显示功能示例
Jul 07 Javascript
vue 实现边输入边搜索功能的实例讲解
Sep 16 Javascript
详解vuex之store源码简单解析
Jun 13 Javascript
Node.js系列之发起get/post请求(2)
Aug 30 Javascript
使用next.js开发网址缩短服务的方法
Jun 17 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
fleaphp crud操作之findByField函数的使用方法
2011/04/23 PHP
PHP获取服务器端信息的方法
2014/11/28 PHP
PHP 实现判断用户是否手机访问
2015/01/21 PHP
PHP常见漏洞攻击分析
2016/02/21 PHP
YII2框架中excel表格导出的方法详解
2017/07/21 PHP
在laravel-admin中列表中禁止某行编辑、删除的方法
2019/10/03 PHP
js解决弹窗问题实现班级跳转DIV示例
2014/01/06 Javascript
基于jQuery通过jQuery.form.js插件实现异步上传
2015/12/13 Javascript
javascript实现禁止复制网页内容汇总
2015/12/30 Javascript
基于javascript实现精确到毫秒的倒计时限时抢购
2016/04/17 Javascript
Extjs4.0 ComboBox如何实现三级联动
2016/05/11 Javascript
jQuery stop()用法实例详解
2016/07/28 Javascript
Javascript 对cookie操作详解及实例
2016/12/29 Javascript
vue2.0多条件搜索组件使用详解
2020/03/26 Javascript
vue移动端微信授权登录插件封装的实例
2018/08/28 Javascript
Vue中控制v-for循环次数的实现方法
2018/09/26 Javascript
Node.js如何对SQLite的async/await封装详解
2019/02/14 Javascript
解决layui弹出层layer的area过大被遮挡的问题
2019/09/21 Javascript
Element Carousel 走马灯的具体实现
2020/07/26 Javascript
antd-日历组件,前后禁止选择,只能选中间一部分的实例
2020/10/29 Javascript
Python编程语言的35个与众不同之处(语言特征和使用技巧)
2014/07/07 Python
使用python绘制常用的图表
2016/08/27 Python
Python爬虫包 BeautifulSoup  递归抓取实例详解
2017/01/28 Python
Python编程使用*解包和itertools.product()求笛卡尔积的方法
2017/12/18 Python
Python基础学习之类与实例基本用法与注意事项详解
2019/06/17 Python
Python-opencv 双线性插值实例
2020/01/17 Python
python中用ctypes模拟点击的实例讲解
2020/11/26 Python
美国宠物商店:Wag.com
2016/10/25 全球购物
Michael Kors加拿大官网:购买设计师手袋、手表、鞋子、服装等
2019/03/16 全球购物
美国鲜花递送:UrbanStems
2021/01/04 全球购物
大学本科毕业生的自我鉴定
2013/11/26 职场文书
银行主办会计岗位职责
2014/08/13 职场文书
部队反四风对照检查材料
2014/09/26 职场文书
小学感恩主题班会
2015/08/12 职场文书
领导激励员工的演讲稿,各种会上用得到,建议收藏
2019/08/13 职场文书
深入理解 Golang 的字符串
2022/05/04 Golang