ExtJs4实战流量统计系统----权限该怎么实现&自定义ToolBar(五)
抱歉,最近比较忙,更新的比较慢~
=========================分隔线====================================
流量系统,是开放给内部所有用户使用,用于查询网站相关流量数据。
Boss们需要能看到所有栏目的所有流量数据,而普通编辑们,则只能查看自己负责栏目的流量数据;
管理员需要给所有人设置权限的权限;
。。。。。。
对于普通的Web应用程序或MVC来说,可以通过控制html元素的显示与否、可用与否来实现权限。
而对于ExtJs来说,如何实现就是另一回事了。
=========================分隔线====================================
先来看看有哪些地方需要配置权限吧。
左边手风琴有三个部分,Accordion控件不像Tree一样,可以从服务端加载数据生成控件,它只能手动的逐个添加子项。
所以要实现权限控制,只好从服务端加载完权限信息后,再来控制各部分显示与否。
另外,如果手风琴的子项内,也就是内部的Tree控件,没有任何节点的话,则自动将该子项隐藏。
Ext.define('Yiqi.Main.SysSetTree', { extend: 'Ext.tree.Panel', requires: ['Yiqi.Common.Model.FunctionMenu'], parentId: 2, loadUrl: '', initComponent: function () { this.loadMask = new Ext.LoadMask(this, { msg: '加载中...' }); this.buildStore(); var me = this; Ext.apply(this, { rootVisible: false, lines: false, store: this.dataStore, listeners: { itemclick: this.onItemClick, beforeitemexpand: function () { me.loadMask.show(); }, itemexpand: function () { me.loadMask.hide(); }, load: function (store, obj, records, eOpts) { if (!me.loadMask.isHidden()) { me.loadMask.hide(); } if (records.length <= 0) { me.ownerCt.remove(me);//--如果没有子项,则隐藏 } } } }); this.callParent(arguments); } });
各部分里边的内容,都是Tree控件,这个不用多说也能想到,直接在服务端返回可用的就行。
权限配置功能也比较简单。
=========================分隔线====================================
左侧手风琴比较简单。
而下边这个,就比较麻烦了。
这是哪?这是流量数据显示界面顶部的工具条(Toolbar),用于切换数据显示。
是的,并非所有栏目的功能都一样。
比如:某些栏目才有地理信息统计,某些栏目才有访问排行。。。。。。
如果在左侧加一个Tree控件来显示所有功能的话,那么就简单多了,对吧。
但这样的话,就严重挤压了图表的空间,对于这样一个系统,图表及数据的展示,才是重点。
而在顶部以一个工具条的方式显示菜单的话,似乎就简洁多了。。。
好吧,那就这么干吧。。。
=========================分隔线====================================
一般Toolbar都是固定的,而基于服务端数据的Toolbar则是灵活的。
对Toolbar子组件的类型,有三种要求:
1、纯分组用,就像文件夹一样;
2、带功能的分组,即有子组件的按钮,在ExtJs里,叫SplitButton。
3、就是纯按钮了。
先看一下用来加载Toolbar的数据是什么样的。
功能地址:就是点击按钮后,会加载的功能地址,也是功能对应的js文件路径。这个在之前的文章里也说过。
可以看到,有些项目的功能地址是空的,没错,就是用这个字段来区别类型。
有子项目,功能地址为空,则说明是纯分组用的;有子项目,功能地址也不为空,则说明是带分组的功能按钮;没有子项目的就是纯按钮咯。
=========================分隔线====================================
从服务端加载好这些数据后,逐一循环,根据这个规则来决定ExtJs需要创建的类型,创建完成,再add到Toolbar里。
当然,理论上支持无限级子菜单。
Ext.define('Yiqi.Show.Catagory.FunctionToolBar', { extend: 'Ext.toolbar.Toolbar', alias: 'widget.functionbar', catagoryId: 1, loadStatics: function (path, scope) { }, handlerScope: null, initComponent: function () { Ext.apply(this, { items: [ //--一加载就显示Loading,提高用户体验 { xtype: 'displayfield', value: '<img src="/Scripts/ext4.2/resources/themes/images/default/grid/loading.gif"/> 菜单加载中......' } ] }); this.callParent(arguments); }, afterRender: function () { //--渲染完成后,再从服务端加载数据,并创建Toolbar this.loadEnabledMenu(); this.callParent(arguments); }, loadEnabledMenu: function () { var me = this; Ext.Ajax.request({ url: '/FunctionMenu/GetEnabledList', params: { catagoryId: me.catagoryId }, method: 'POST', success: function (response, opts) { Yiqi.Common.Tools.IsLogin(response); var result = Ext.decode(response.responseText); var menu = me.buildMenu(result); me.removeAll(true); me.add(menu); }, failure: function (response, opts) { Ext.Msg.alert("提示", "保存失败(报错)~!"); } }); }, buildMenu: function (list) { var me = this; var menu = []; //--循环所有 Ext.Array.each(list, function (m) { menu.push(me.createSingle(m)); }); return menu; }, createSingle: function (data) { var me = this; var menu = {}; //--功能地址不为空 if (!Ext.isEmpty(data.LoadPath, true) && Ext.String.trim(data.LoadPath).length > 0) { if (data.Children.length > 0) { menu.xtype = 'splitbutton'; } if (me.handlerScope) { menu.scope = me.handlerScope; } menu.handler = function () { this.createItem(data.LoadPath, menu); //me.loadStatics(data.LoadPath, menu); } } menu.text = data.text; menu.iconCls = data.iconCls; //--有子菜单,则继续循环 if (data.Children.length > 0) { var childMenu = me.buildMenu(data.Children); menu.menu = { items: childMenu }; } return menu; } });