日期:2014-05-16  浏览次数:20453 次

ExtJS4.1+MVC3+Spring.NET1.3+EF5 整合十:TreePanel 之 管理菜单

很遗憾,过去将近一年的时间里一直在学习,工作之中涉及到Java和Flex,业余时间在和朋友搞Android,实际开发中遇到很多问题都需要学习,偶而挤出来那么一点时间自己也在了解一些新的东西,感觉太多的东西想学,只是时间少的可怜。

从今天开始,计划每周不低于一篇文章,把《ExtJS4.1+MVC3+Spring.NET1.3+EF5 整合》写完,下一系列准备写个SSH2.0+EasyUI的框架,我还是依旧那么的喜欢开源技术。


Tree结构应该说是Web开发中必会的对象之一,在关系型数据库中体现为一种“一对多”的父子表,最为典型的就是系统“管理菜单”和角色“权限”,在本篇之中,“菜单”和“权限”实际上是一张数据表,“菜单”仅涉及到显示数据,“权限”涉及到更多的ExtJS API操作,正面分别讲解这两种情况下的使用。


1 ExtJS 代码

理论上说“管理菜单”应该根据当前登录用户(所属角色)的权限,显示相应的菜单结构,这个可以通过继承System.Web.Mvc.AuthorizeAttribute来实现,在需要验证权限的Controller或方法上添加“特性(Attribute)”即可。权限的实现过程准备单独写一篇说明。

本文章的“管理菜单”涉及到以下几个js文件:

app/controller/menu.js
app/store/menu.js
app/view/menu/tree.js


1.1 先看一下控制器类(app/controller/menu.js)代码

Ext.define('Manage.controller.Menu', {
    extend: 'Ext.app.Controller',
    stores: ['Menu'],
    views: ['menu.Tree'],
    init: function() {
		this.control({
		    'menuTree': {
	            itemclick: this.selectItem
	        }
	    });
    },
    selectItem: function (view, record, item, index) {
        Ext.Ajax.request({
            url: '/Manage/Category/Query.aspx?id=' + record.data.id,
            success: function (response) {
                var menu = Ext.JSON.decode(response.responseText);
                var url = menu.children.MenuUrl;
                if (url.length > 0) {
                    var body = Ext.getCmp('bodyID');
                    body.removeAll();
                    body.add({
                        xtype: url
                    });
                }
            }
        });
    }
});


该控制器类很简单,仅仅是涉及到了store和view,这里selectItem方法的作用是选择节点的事件,即向id为bodyID的元素中添加一个新的子元素,其实就是点击左侧菜单时,在右侧打开相应的菜单模块。


1.2 看下store(app/store/menu.js)中的定义

Ext.define('Manage.store.Menu', {
	extend: 'Ext.data.TreeStore',
	autoLoad: true,
	sorters: [{
	    property: 'leaf',
	    direction: 'ASC'
	}],
	root: {
	    nodeType: 'async',
	    expanded: true
	},
    proxy: {
        type: 'ajax',
        api: {
            read: '/Manage/Authorize/Menu.aspx'
		},
		reader: {
            type: 'json',
            root: 'children'
        }
    }
});

“管理菜单”仅涉及到“读”操作,所以这里的proxy只设置了一个read URL:/Manage/Authorize/Menu.aspx,先把view代码看完再回过头看这个URL返回的值。


1.3 view(app/view/menu/tree.js)代码

Ext.define('Manage.view.menu.Tree', {
    extend: 'Ext.tree.Panel',
    alias: 'widget.menuTree',
    header : false,
    border : 0,
    store: 'Menu',
    rootVisible: false
});

视图代码很简单,定义了不显示header,边框为0,以及不显示根节点。


2 C# 代码

ExtJS 中相应的controll、store、view代码都很简单,而C#返回的结果也很简单,“管理菜单”所请求的URL是:/Manage/Authorize/Menu.aspx,打开Areas/Manage/Controllers/AuthorizeController.cs文件:

public class AuthorizeController : Controller
{
    public IRoleService RoleService { get; set; }
    public IAuthorizeService AuthorizeService { get; set; }

    public ActionResult Menu()
    {
        Role role = this.RoleService.Read("12");
        var childs = this.MenuChildrens(ref role, null);
        var root = new
        {
            id = 0,
            text = "根",
            expanded = true,
            leaf = !childs.Any(),
            children = childs
        };

        return Json(root, JsonRequestBehavior.AllowGet);
    }