• extjs+MVC4+PetaPoco+AutoFac+AutoMapper后台管理系统(附源码)


    前言

    本项目使用的开发环境及技术列举如下:
    1、开发环境
    IDE:VS2010+MVC4
    数据库:SQLServer2008
    2、技术
    前端:Extjs
    后端:
    (1)、数据持久层:轻量级ORM框架PetaPoco
    (2)、依赖注入:AutoFac
    (3)、对象关系映射:AutoMapper
    (4)、数据验证(MVC自带的验证封装使用)
    (5)、SQL翻译机
    (6)、缓存

    以上使用都参考或直接借鉴使用了园子内牛人们的代码,只是学习交流使用而已,还请勿怪,我为了简便,没有分多个类库,而是以文
    件夹的形式分的,大家可以根据文件夹分成类库也是一样的。好了,废话不多说,还是先上几张图大家看看吧,如果有兴趣再往下看

     

    项目截图

    要点一:Extjs

    本项目虽然功能不多,但是基本已经涵盖了extjs的所有基本用法了,对于一般的extjs初学者或是简单应用的开发应该是足够了,后
    台开发主要在tab、grid、treegrid的用法比较多,也是比较麻烦的地方,下面直接上代码,大家看看

    首页布局:

      1 /**
      2 * 程序主入口
      3 */
      4 Ext.onReady(function () {
      5     /**
      6     * 上,panel.Panel
      7     */
      8     this.topPanel = Ext.create('Ext.panel.Panel', {
      9         region: 'north',
     10         height: 55
     11     });
     12     /**
     13     * 左,panel.Panel
     14     */
     15     this.leftPanel = Ext.create('Ext.panel.Panel', {
     16         region: 'west',
     17         title: '主菜单',
     18         iconCls: 'House',
     19          200,
     20         layout: 'accordion',
     21         collapsible: true
     22     });
     23     /**
     24     * 右,tab.Panel
     25     */
     26     this.rightPanel = Ext.create('Ext.tab.Panel', {
     27         region: 'center',
     28         layout: 'fit',
     29         id: 'mainContent',
     30         collapisble: true,
     31         tabWidth: 120,   
     32         items: [{ title: '首页', html: ' <iframe scrolling="auto" frameborder="0" width="100%" height="100%" src="' + DefaultUrl + '"> </iframe>'}]
     33     });
     34     /**
     35     * 下,panel.Panel
     36     */
     37     this.bottomPanel = Ext.create('Ext.panel.Panel', {
     38         region: 'south',
     39         layout: 'fit',
     40         id: 'foot',
     41         collapisble: true,
     42         height: 30,
     43         html:'<div>欢迎您光临!</div>'
     44     });
     45     /**
     46     * 组建树
     47     */
     48     Ext.define('TreeModelExtension', {
     49         extend: 'Ext.data.Model',
     50         //当Model实体类模型被用在某个TreeStore上,并且第一次实例化的时候 ,这些个属性会添加到Model实体类的的原型(prototype )上 (至于上述代码,则是通过把他设置为根节点的时候触发实例化处理的)
     51         fields: [
     52             {name: 'text',  type: 'string'},
     53             {name: 'url',  type: 'string'}
     54         ],
     55     });
     56     var buildTree = function (json) {
     57         return Ext.create('Ext.tree.Panel', {
     58             rootVisible: false,
     59             border: false,
     60             store: Ext.create('Ext.data.TreeStore', {
     61                 model:'TreeModelExtension',
     62                 root: {
     63                     expanded: true,
     64                     children: json.children
     65                 }
     66             }),
     67             listeners: {
     68                 'itemdblclick': function (view, record, item,
     69                                         index, e) {
     70                     var id = record.get('id');
     71                     var text = record.get('text');
     72                     var iconCls = record.get('iconCls');
     73                     var leaf = record.get('leaf');
     74                     var url = record.get('url');
     75                     if (leaf) {      //没有子节点时才创建新的tab显示
     76                         var tabs = Ext.getCmp('mainContent');  //获取布局页的Tab组件
     77                         var Loadtab = Ext.getCmp(id);          //判断Tab是否已经加载
     78                         if(Loadtab==undefined){                  //未加载则加载                          
     79                             tabs.add({
     80                                 id:id,
     81                                 closable: true,
     82                                 //这种方式采取了加载多个iframe的方式,优化看如何采取一个iframe的方式
     83                                 html: ' <iframe scrolling="auto" frameborder="0" width="100%" height="100%" src="' + url + '"> </iframe>',
     84                                 iconCls: iconCls,
     85                                 title: text
     86                             }).show()
     87                         }else{                                           //已加载则设置为活动页
     88                             //tabs.setActiveTab(id);           //适合于数据量较大,但是不需要实时改变得情况下,直接将已打开的tab设置为活动tab
     89 
     90                             //适合于需要实时展示最新数据的情况,先移除已打开的此tab,然后再重新加载
     91                             tabs.remove(id);
     92                             tabs.add({
     93                                 id: id,
     94                                 closable: true,
     95                                 //这种方式采取了加载多个iframe的方式,优化看如何采取一个iframe的方式
     96                                 html: ' <iframe scrolling="auto" frameborder="0" width="100%" height="100%" src="' + url + '"> </iframe>',
     97                                 iconCls: iconCls,
     98                                 title: text
     99                             }).show()
    100                         }
    101                     }
    102                 },
    103                 scope: this
    104             }
    105         });
    106     };
    107     /**
    108     * 加载菜单树
    109     */
    110     Ext.Ajax.request({
    111         url: AjaxPath,
    112 
    113         success: function (response) {
    114             var json = Ext.JSON.decode(response.responseText)
    115             Ext.each(json.data, function (el) {
    116                 var panel = Ext.create(
    117                                                 'Ext.panel.Panel', {
    118                                                     id: el.id,
    119                                                     title: el.text,
    120                                                     iconCls:el.iconCls,
    121                                                     layout: 'fit'
    122                                                 });
    123                 panel.add(buildTree(el));
    124                 leftPanel.add(panel);
    125             });
    126         },
    127         failure: function (request) {
    128             Ext.MessageBox.show({
    129                 title: '操作提示',
    130                 msg: "连接服务器失败",
    131                 buttons: Ext.MessageBox.OK,
    132                 icon: Ext.MessageBox.ERROR
    133             });
    134         },
    135         method: 'post'
    136     });
    137     /**
    138     * Viewport
    139     */
    140     Ext.create('Ext.container.Viewport', {
    141         layout: 'border',
    142         renderTo: Ext.getBody(),
    143         items: [this.topPanel, this.leftPanel, this.rightPanel, this.bottomPanel]
    144     });
    145 });
    View Code

    Grid行内增删改查:

      1 Ext.onReady(function () {
      2     //    ExtJS组件自适应浏览器大小改变,看还有没有其他实现方式
      3     Ext.EventManager.onWindowResize(function () {
      4         Ext.ComponentManager.each(function (cmpId, cmp, length) {
      5             if (cmp.hasOwnProperty("renderTo")) {
      6                 cmp.doLayout();
      7             }
      8         });
      9     });
     10     var toolbar = Ext.create('Ext.toolbar.Toolbar', {
     11         renderTo: document.body,
     12         items: [
     13         // 使用右对齐容器
     14         '->', // 等同 { xtype: 'tbfill' }
     15         {
     16         xtype: 'textfield',
     17         name: 'roleName',
     18         id: 'roleName',
     19         emptyText: '输入角色名关键字',
     20         listeners: {
     21             specialkey: function (field, e) {
     22                 if (e.getKey() == Ext.EventObject.ENTER) {
     23                     store.load({                //传递查询条件参数
     24                         params: {
     25                             roleName: Ext.getCmp('roleName').getValue()
     26                         }
     27                     });
     28                 }
     29             }
     30         }
     31     },
     32     {
     33         // xtype: 'button', // 默认的工具栏类型
     34         text: '查询',
     35         tooltip: '根据数据条件查询数据',
     36         iconCls: "Zoom",
     37         listeners: {
     38             click: function () {
     39                 store.load({                //传递查询条件参数
     40                     params: {
     41                         roleName: Ext.getCmp('roleName').getValue()
     42                     }
     43                 });
     44             }
     45         }
     46     },
     47     // 添加工具栏项之间的垂直分隔条
     48         '-', // 等同 {xtype: 'tbseparator'} 创建 Ext.toolbar.Separator
     49     {
     50     // xtype: 'button', // 默认的工具栏类型
     51     text: '重置',
     52     tooltip: '清空当前查询条件',
     53     iconCls: "Arrowrotateanticlockwise",
     54     handler: function () {                   //此事件可以代替click事件
     55         Ext.getCmp('roleName').setValue("");
     56     }
     57 },
     58     ]
     59 });
     60 //1.定义Model
     61 Ext.define("BeiDream.model.BeiDream_Role", {
     62     extend: "Ext.data.Model",
     63     fields: [
     64         { name: 'ID', type: 'int' },
     65         { name: 'Name', type: 'string' },
     66         { name: 'Description', type: 'string' },
     67         { name: 'IsUsed', type: 'boolean', defaultValue: true }
     68     ]
     69 });
     70 //2.创建store
     71 var store = Ext.create("Ext.data.Store", {
     72     model: "BeiDream.model.BeiDream_Role",
     73     autoLoad: true,
     74     pageSize: 10,
     75     proxy: {
     76         type: 'ajax',
     77         api: {
     78             read: RoleListUrl, //查询
     79             create: AddUrl, //创建
     80             update: UpdateUrl, //更新,必须真正修改了才会触发
     81             destroy: RemoveUrl //删除
     82         },
     83         reader: {
     84             type: 'json',
     85             root: 'data'
     86         },
     87         writer: {
     88             type: 'json',  //默认格式          //MVC下后台使用模型自动进行转换,如果是普通webform,则配置root:'data',encode:'true',这样之后就可以使用request【data】获取
     89             writeAllFields: true,   //false只提交修改过的字段
     90             allowSingle: false      //默认为true,为true时,一条数据不以数组形式提交,为false时,都以数组形式提交,这样避免了提交了一条数据时,后台是list模型无法接收到数据问题
     91         },
     92         listeners: {
     93             exception: function (proxy, response, operation) {
     94                 grid.store.load();    //删除失败,数据重新加载
     95                 var resText = Ext.decode(response.responseText);
     96                 Ext.MessageBox.show({
     97                     title: '服务器端异常',
     98                     msg: resText.msg,
     99                     icon: Ext.MessageBox.ERROR,
    100                     buttons: Ext.Msg.OK
    101                 });
    102             }
    103         }
    104     }
    105     //    sorters: [{
    106     //        //排序字段。  
    107     //        property: 'id'
    108     //    }] 
    109 });
    110 store.on('beforeload', function (store, options) {
    111     var params = { roleName: Ext.getCmp('roleName').getValue() };
    112     Ext.apply(store.proxy.extraParams, params);
    113 });
    114 var Gridtoolbar = Ext.create('Ext.toolbar.Toolbar', {
    115     renderTo: document.body,
    116     items: [{
    117         text: '新增',
    118         tooltip: '新增一条数据',
    119         iconCls: 'Add',
    120         handler: function () {
    121             RowEditing.cancelEdit();
    122             // Create a model instance
    123             var r = new BeiDream.model.BeiDream_Role();
    124             Ext.getCmp('RoleGrid').getStore().insert(0, r);
    125             RowEditing.startEdit(0, 0);
    126         }
    127     }, '-', {
    128         text: '编辑',
    129         tooltip: '编辑当前选择行数据',
    130         iconCls: 'Pencil',
    131         handler: function () {
    132             RowEditing.cancelEdit();
    133             var data = Ext.getCmp("RoleGrid").getSelectionModel().getSelection();
    134             RowEditing.startEdit(data[0].index, 0);
    135         },
    136         disabled: true
    137     }, '-', {
    138         itemId: 'removeUser',
    139         text: '删除',
    140         tooltip: '可以多选删除多条数据',
    141         iconCls: 'Delete',
    142         handler: function () {
    143             Ext.MessageBox.confirm('提示', '确定删除该记录?', function (btn) {
    144                 if (btn != 'yes') {
    145                     return;
    146                 }
    147                 var sm = Ext.getCmp('RoleGrid').getSelectionModel();
    148                 RowEditing.cancelEdit();
    149 
    150                 var store = Ext.getCmp('RoleGrid').getStore();
    151                 store.remove(sm.getSelection());
    152                 store.sync(); //根据状态执行对应的服务器方法,delete,放在remove后才能成功执行服务器方法
    153                 if (store.getCount() > 0) {
    154                     sm.select(0);
    155                 }
    156             });
    157         },
    158         disabled: true
    159     }, '-', {
    160         itemId: 'gridSync',
    161         text: '保存',
    162         tooltip: '保存到服务器',
    163         iconCls: 'Disk',
    164         handler: function () {
    165             grid.store.sync();
    166             grid.store.commitChanges();   //执行commitChanges()提交数据修改。
    167         }
    168     }, '-', {
    169         itemId: 'gridCancel',
    170         text: '取消',
    171         tooltip: '取消所有的已编辑数据',
    172         iconCls: 'Decline',
    173         handler: function () {
    174             Ext.MessageBox.confirm('提示', '确定取消已编辑数据吗?', function (btn) {
    175                 if (btn != 'yes') {
    176                     return;
    177                 }
    178                 grid.store.rejectChanges();   //执行rejectChanges()撤销所有修改,将修改过的record恢复到原来的状态
    179             });
    180         }
    181     }, '-', {
    182         itemId: 'gridrefresh',
    183         text: '刷新',
    184         tooltip: '重新加载数据',
    185         iconCls: 'Arrowrefresh',
    186         handler: function () {
    187             grid.store.load();
    188         }
    189     }, '->', {
    190         itemId: 'ImportExcel',
    191         text: '导入Excel',
    192         tooltip: '导入角色数据',
    193         iconCls: 'Pageexcel',
    194         handler: function () {
    195             Ext.MessageBox.show({
    196                 title: '暂未开放',
    197                 msg: '即将开放',
    198                 icon: Ext.MessageBox.ERROR,
    199                 buttons: Ext.Msg.OK
    200             });
    201         }
    202     }, '-', {
    203         itemId: 'ExportExcel',
    204         text: '导出Ecxel',
    205         tooltip: '角色数据导出Excel',
    206         iconCls: 'Pageexcel',
    207         handler: function () {
    208             Ext.MessageBox.show({
    209                 title: '暂未开放',
    210                 msg: '即将开放',
    211                 icon: Ext.MessageBox.ERROR,
    212                 buttons: Ext.Msg.OK
    213             });
    214         }
    215     }
    216     ]
    217 });
    218 var RowEditing = Ext.create('Ext.grid.plugin.RowEditing', { // 行编辑模式
    219     clicksToEdit: 2,   //双击进行修改  1-单击   2-双击   
    220     autoCancel: false,
    221     saveBtnText: '确定',
    222     cancelBtnText: '取消',
    223     errorsText: '错误',
    224     dirtyText: '你要确认或取消更改',
    225     listeners: {
    226         cancelEdit: function (rowEditing, context) {
    227             // Canceling editing of a locally added, unsaved record: remove it
    228             if (context.record.phantom) {    //服务器上是否有此条记录的标志,true为没有
    229                 store.remove(context.record);
    230             }
    231         },
    232         Edit: function (rowEditing, context) {
    233             //store.sync();     //根据状态执行对应的服务器方法,Add/Edit
    234             var IsValidate = ValidateInput(context.record.data, context.record.phantom);
    235             if (!IsValidate) {
    236                 grid.store.rejectChanges();
    237             }
    238         },
    239         validateedit: function (rowEditing, context) {
    240 
    241         }
    242     }
    243 });
    244 function ValidateInput(data, IsAdd) {
    245     var IsValidate;
    246     Ext.Ajax.request({
    247         url: ValidateInputUrl,
    248         method: 'POST',
    249         jsonData: data,
    250         params: { IsAdd: IsAdd },
    251         async: false,
    252         success: function (response) {
    253             var resText = Ext.decode(response.responseText);
    254             if (resText.success) {
    255                 Ext.MessageBox.alert('警告', resText.msg);
    256                 IsValidate = false;
    257             } else {
    258                 IsValidate = true;
    259             }
    260         },
    261         failure: function (response, options) {
    262             Ext.MessageBox.alert('服务器异常', response.status);
    263         }
    264     });
    265     return IsValidate;
    266 }
    267 //多选框变化
    268 function selectchange() {
    269     var count = this.getCount();
    270     //删除
    271     if (count == 0) {
    272         Gridtoolbar.items.items[2].disable();
    273         Gridtoolbar.items.items[4].disable();
    274     }
    275     else {
    276         Gridtoolbar.items.items[2].enable();
    277         Gridtoolbar.items.items[4].enable();
    278     }
    279 }
    280 //3.创建grid
    281 var grid = Ext.create("Ext.grid.Panel", {
    282     id: "RoleGrid",
    283     xtype: "grid",
    284     store: store,
    285     columnLines: true,
    286     renderTo: Ext.getBody(),
    287     selModel: {
    288         injectCheckbox: 0,
    289         listeners: {
    290             'selectionchange': selectchange
    291         },
    292         mode: "MULTI",     //"SINGLE"/"SIMPLE"/"MULTI"
    293         checkOnly: false     //只能通过checkbox选择
    294     },
    295     selType: "checkboxmodel",
    296     columns: [
    297         { xtype: "rownumberer", text: "序号",  40, align: 'center' },
    298         { id: "id", text: "ID",  40, dataIndex: 'ID', sortable: true, hidden: true },
    299         { text: '角色名称', dataIndex: 'Name', flex: 1, editor: "textfield" },
    300         { text: '角色描述', dataIndex: 'Description', flex: 1, editor: "textfield" },
    301         { text: '是否启用', dataIndex: 'IsUsed', flex: 1, xtype: 'checkcolumn', editor: { xtype: 'checkbox', cls: 'x-grid-checkheader-editor'} }
    302     ],
    303     plugins: [RowEditing],
    304     listeners: {
    305         itemdblclick: function (me, record, item, index, e, eOpts) {
    306             //双击事件的操作
    307         }
    308     },
    309     tbar: Gridtoolbar,
    310     bbar: { xtype: "pagingtoolbar", store: store, displayInfo: true, emptyMsg: "没有记录" }
    311 });
    312 });

    TreeGrid展示:前台代码和后台模型结合

    Ext.onReady(function () {
        //    ExtJS组件自适应浏览器大小改变,看还有没有其他实现方式
        Ext.EventManager.onWindowResize(function () {
            Ext.ComponentManager.each(function (cmpId, cmp, length) {
                if (cmp.hasOwnProperty("renderTo")) {
                    cmp.doLayout();
                }
            });
        });
    Ext.create('Ext.container.Viewport', {
        layout: 'border',
        renderTo: Ext.getBody(),
        items: [{
            title: '主菜单模块',
            region: 'west',
            xtype: 'panel',
            margins: '5 0 0 5',
             200,
            collapsible: true,   // 可折叠/展开
            id: 'NavigationMenucontainer',
            layout: 'fit'
        }, {
            title: '子菜单列表',
            region: 'center',     // 必须指定中间区域
            xtype: 'panel',
            layout: 'fit',
            id: 'Gridcontainer',
            margins: '5 5 0 0'
        }]
    });
    
        var NavigationMenu=Ext.getCmp('NavigationMenucontainer');
        /**
        * 加载菜单树
        */
        Ext.Ajax.request({
            url: AjaxPath,
            success: function (response) {
                var json = Ext.JSON.decode(response.responseText)
                Ext.each(json.data, function (el) {
                    var panel = Ext.create(
                                                    'Ext.panel.Panel', {
                                                        id: el.id,
                                                        layout: 'fit'
                                                    });
                    var ShowGrid=CreateGrid(el.id);
                    Gridcontainer.add(ShowGrid);    //初始化,加载主菜单下的菜单
                    panel.add(buildTree(el));
                    NavigationMenu.add(panel);
                });
            },
            failure: function (request) {
                Ext.MessageBox.show({
                    title: '操作提示',
                    msg: "连接服务器失败",
                    buttons: Ext.MessageBox.OK,
                    icon: Ext.MessageBox.ERROR
                });
            },
            method: 'post'
        });
        var Gridcontainer=Ext.getCmp('Gridcontainer');
       /**
        * 组建树
        */
        Ext.define('TreeModelExtension', {
            extend: 'Ext.data.Model',
            //当Model实体类模型被用在某个TreeStore上,并且第一次实例化的时候 ,这些个属性会添加到Model实体类的的原型(prototype )上 (至于上述代码,则是通过把他设置为根节点的时候触发实例化处理的)
            fields: [
                {name: 'text',  type: 'string'},
                {name: 'url',  type: 'string'}
            ],
        });
        var buildTree = function (json) {
            return Ext.create('Ext.tree.Panel', {
                id:'MenuTree',
                rootVisible: true,
                border: false,
                store: Ext.create('Ext.data.TreeStore', {
                    model:'TreeModelExtension',
                    root: {
                        id:json.id,
                        text:json.text,
                        iconCls: json.iconCls,
                        expanded: json.expanded,
                        children: json.children
                    }
                }),
                listeners: {
                    'itemclick': function (view, record, item,
                                            index, e) {
                            var ParentID = record.get('id');
                            var ShowGrid=CreateGrid(ParentID);
                            Gridcontainer.add(ShowGrid);
                        },
                    scope: this
                }
            });
        };
    
    function CreateGrid(ParentID) {
    var Gridtoolbar = Ext.create('Ext.toolbar.Toolbar', {
        renderTo: document.body,
        items: [{
            text: '新增',
            tooltip: '新增一条数据',
            iconCls: 'Add',
            handler: function () {
                RowEditing.cancelEdit();
                // Create a model instance
                var r = new BeiDream.model.BeiDream_NavigationMenu();
                Ext.getCmp('NavigationMenuGrid').getStore().insert(0, r);
                RowEditing.startEdit(0, 0);
            }
        }, '-', {
            text: '编辑',
            tooltip: '编辑当前选择行数据',
            iconCls: 'Pencil',
            handler: function () {
                RowEditing.cancelEdit();
                var data = Ext.getCmp("NavigationMenuGrid").getSelectionModel().getSelection();
                RowEditing.startEdit(data[0].index, 0);
            },
            disabled: true
        }, '-', {
            itemId: 'removeUser',
            text: '删除',
            tooltip: '可以多选删除多条数据',
            iconCls: 'Delete',
            handler: function () {
                Ext.MessageBox.confirm('提示', '确定删除该记录?', function (btn) {
                    if (btn != 'yes') {
                        return;
                    }
                    var sm = Ext.getCmp('NavigationMenuGrid').getSelectionModel();
                    RowEditing.cancelEdit();
    
                    var store = Ext.getCmp('NavigationMenuGrid').getStore();
                    store.remove(sm.getSelection());
                    store.sync(); //根据状态执行对应的服务器方法,delete,放在remove后才能成功执行服务器方法
                    if (store.getCount() > 0) {
                        sm.select(0);
                    }
                });
            },
            disabled: true
        }, '-', {
            itemId: 'gridSync',
            text: '保存',
            tooltip: '保存到服务器',
            iconCls: 'Disk',
            handler: function () {
                var grid=Ext.getCmp('NavigationMenuGrid');
                grid.store.sync();
                grid.store.commitChanges();   //执行commitChanges()提交数据修改。
            }
        }, '-', {
            itemId: 'gridCancel',
            text: '取消',
            tooltip: '取消所有的已编辑数据',
            iconCls: 'Decline',
            handler: function () {
                Ext.MessageBox.confirm('提示', '确定取消已编辑数据吗?', function (btn) {
                    if (btn != 'yes') {
                        return;
                    }
                    var grid=Ext.getCmp('NavigationMenuGrid');
                    grid.store.rejectChanges();   //执行rejectChanges()撤销所有修改,将修改过的record恢复到原来的状态
                });
            }
        }, '-', {
            itemId: 'gridrefresh',
            text: '刷新',
            tooltip: '重新加载数据',
            iconCls: 'Arrowrefresh',
            handler: function () {
                 var grid=Ext.getCmp('NavigationMenuGrid');
                grid.store.load();
            }
        }
        ]
    });
    
    var RowEditing = Ext.create('Ext.grid.plugin.RowEditing', { // 行编辑模式
        clicksToEdit: 2,   //双击进行修改  1-单击   2-双击   
        autoCancel: false,
        saveBtnText: '确定',
        cancelBtnText: '取消',
        errorsText: '错误',
        dirtyText: '你要确认或取消更改',
        listeners: {
    //        beforeedit: function (rowEditing,e,context) {
    //            if(e.colldx==2 && e.record.data.IsLeaf==false){
    //                return false;
    //            }else{
    //               return true;
    //            }
    //        },
            cancelEdit: function (rowEditing, context) {
                // Canceling editing of a locally added, unsaved record: remove it
                if (context.record.phantom) {    //服务器上是否有此条记录的标志,true为没有
                    store.remove(context.record);
                }
            },
            Edit: function (rowEditing, context) {
                //store.sync();     //根据状态执行对应的服务器方法,Add/Edit
                //var IsValidate = ValidateInput(context.record.data, context.record.phantom);
    //            if (!IsValidate) {
    //                grid.store.rejectChanges(); 
    //            }
            }
        }
    });
    function ValidateInput(data, IsAdd) {
        var IsValidate;
        Ext.Ajax.request({
            url: ValidateInputUrl,
            method: 'POST',
            jsonData: data,
            params: { IsAdd: IsAdd },
            async: false,
            success: function (response) {
                var resText = Ext.decode(response.responseText);
                if (resText.success) {
                    Ext.MessageBox.alert('警告', resText.msg);
                    IsValidate = false;
                } else {
                    IsValidate = true;
                }
            },
            failure: function (response, options) {
                Ext.MessageBox.alert('服务器异常', response.status);
            }
        });
        return IsValidate;
    }
    //多选框变化
    function selectchange() {
        var count = this.getCount();
        //删除
        if (count == 0) {
            Gridtoolbar.items.items[2].disable();
            Gridtoolbar.items.items[4].disable();
        }
        else {
            Gridtoolbar.items.items[2].enable();
            Gridtoolbar.items.items[4].enable();
        }
    }
    //1.定义Model
    Ext.define("BeiDream.model.BeiDream_NavigationMenu", {
        extend: "Ext.data.Model",
        fields: [
            { name: 'ID', type: 'int' },
            { name: 'ParentID', type: 'int' },
            { name: 'ShowName', type: 'string', defaultValue: '名称......' },
            { name: 'IsLeaf', type: 'boolean', defaultValue: true },
            { name: 'url', type: 'string' },
            { name: 'OrderNo', type: 'int', defaultValue: 1 },
            { name: 'iconCls', type: 'string' },
            { name: 'Expanded', type: 'boolean', defaultValue: false }
        ]
    });
    //2.创建store
    var store = Ext.create("Ext.data.Store", {
        model: "BeiDream.model.BeiDream_NavigationMenu",
        autoLoad: true,
        pageSize: 15,
        proxy: {
            type: 'ajax',
            api: {
                read: MenuListUrl, //查询
                create: AddUrl, //创建
                update: UpdateUrl, //更新,必须真正修改了才会触发
                destroy: RemoveUrl //删除
            },
            reader: {
                type: 'json',
                root: 'data'
            },
            writer: {
                type: 'json',  //默认格式          //MVC下后台使用模型自动进行转换,如果是普通webform,则配置root:'data',encode:'true',这样之后就可以使用request【data】获取
                writeAllFields: true,   //false只提交修改过的字段
                allowSingle: false      //默认为true,为true时,一条数据不以数组形式提交,为false时,都以数组形式提交,这样避免了提交了一条数据时,后台是list模型无法接收到数据问题
            },
            listeners: {
                exception: function (proxy, response, operation) {
    //                 var grid=Ext.getCmp('NavigationMenuGrid');
    //                grid.store.load();    //删除失败,数据重新加载
                    var resText = Ext.decode(response.responseText);
                    Ext.MessageBox.show({
                        title: '服务器端异常',
                        msg: resText.msg,
                        icon: Ext.MessageBox.ERROR,
                        buttons: Ext.Msg.OK
                    });
                }
            }
        }
    });
    store.on('beforeload', function (store, options) {
        var params = { ParentID: ParentID };
        Ext.apply(store.proxy.extraParams, params);
    });
            return Ext.create("Ext.grid.Panel", {
            id: "NavigationMenuGrid",
            xtype: "grid",
            store: store,
            columnLines: true,
            selModel: {
                injectCheckbox: 0,
                listeners: {
                    'selectionchange': selectchange
                },
                mode: "SINGLE",     //"SINGLE"/"SIMPLE"/"MULTI"
                checkOnly: false     //只能通过checkbox选择
            },
            selType: "checkboxmodel",
            columns: [
                { xtype: "rownumberer", text: "序号",  40, align: 'center' },
                { id: "id", text: "ID",  40, dataIndex: 'ID', sortable: true, hidden: true },
                { id: "id", text: "ParentID",  40, dataIndex: 'ParentID', sortable: true, hidden: true },
                { text: '名称', dataIndex: 'ShowName', flex: 1, editor: {
                    xtype: 'textfield',
                    allowBlank: false
                }  },
                { text: '是否为模块', dataIndex: 'IsLeaf', flex: 1, xtype: 'checkcolumn', editor: { xtype: 'checkbox', cls: 'x-grid-checkheader-editor'} },
                { text: '控制器路径', dataIndex: 'url', flex: 1, editor : {
                        xtype: 'combobox',
                        editable:false,    
                        listeners: {
                            //点击下拉列表事件
                            expand: function (me, event, eOpts) {
                                var grid=Ext.getCmp('NavigationMenuGrid');
                                var record = grid.getSelectionModel().getLastSelected();
                                if(record!=null){
                                   if(record.data.IsLeaf==true){
                                          currentComboBox = me;
                                          f_openSelectControllerWin();
                                   }else{
                                        Ext.MessageBox.alert('警告', '只有模块才拥有控制器!');
                                   }
                                }                          
    
                            }
                        }
                }  },
                { text: '排序号', dataIndex: 'OrderNo',align:"center",  48, flex: 1,editor: {
                    xtype: 'numberfield',
                    allowBlank: false,
                    minValue: 1,
                    maxValue: 150000
                } },
                { text: '图标', dataIndex: 'iconCls',align:"center",  48,renderer : function(value) {
                        return "<div Align='center' style='height:16px;16px' class="+value+"></div>";
                   } ,editor : {
                        xtype: 'combobox',
                        editable:false,    
                        listeners: {
                            //点击下拉列表事件
                            expand: function (me, event, eOpts) {
                                currentComboBox = me;
                                f_openIconsWin();
                            }
                        }
                } },
                { text: '是否展开', dataIndex: 'Expanded', flex: 1, xtype: 'checkcolumn', editor: { xtype: 'checkbox', cls: 'x-grid-checkheader-editor'} }
            ],
            plugins: [RowEditing],
            tbar: Gridtoolbar,
            bbar: { xtype: "pagingtoolbar", store: store, displayInfo: true, emptyMsg: "没有记录" }
        });
      };
    });

    要点二:后台MVC的传参绑定,返回值自定义

    MVC方便了Ajax的异步实现,并且方便的模型传参,代码如下

     1         /// <summary>
     2         /// 返回数据库新增后的实体,供前台的extjs的 grid的store更新数据,这样就不需要进行重新加载store了,删,改类似
     3         /// </summary>
     4         /// <param name="Roles"></param>
     5         /// <returns></returns>
     6         [Anonymous]
     7         [HttpPost]
     8         public ActionResult Add(List<BeiDream_Role> Roles)
     9         {
    10             List<BeiDream_Role> AddRoles = new List<BeiDream_Role>();
    11             List<Object> ListObj = RoleService.Add(Roles);
    12             if (ListObj.Count == 0)
    13             {
    14                 List<string> msg = new List<string>();
    15                 msg.Add("添加角色失败!");
    16                 return this.ExtjsJsonResult(false, msg);
    17             }
    18             else
    19             {
    20                 foreach (var item in ListObj)
    21                 {
    22                     AddRoles.Add(RoleService.GetModelByID(item));
    23                 }
    24                 List<string> msg = new List<string>();
    25                 msg.Add("添加角色成功!");
    26                 return this.ExtjsJsonResult(true, AddRoles, msg);
    27             }
    28 
    29         }

    可以看到我直接通过后台模型来接收前台传递过来的参数,而不需要去一一解析参数值

    返回值自定义:重写了ActionResult,实现了extjs需要的返回值

     1    /// <summary>
     2     /// 扩展的jsonResult模型,适用于extjs需要的json数据类型
     3     /// </summary>
     4     public class JsonResultExtension:ActionResult
     5     {
     6         public bool success { get; set; }
     7         public string msg { get; set; }
     8         public object data { get; set; }
     9         public long? total { get; set; }
    10         public Dictionary<string, string> errors { get; set; }
    11         /// <summary>
    12         /// 是否序列化为extjs需要的json格式,否则进行普通序列化
    13         /// </summary>
    14         public bool ExtjsUISerialize { get; set; }
    15         public override void ExecuteResult(ControllerContext context)
    16         {
    17 
    18             if (context == null)
    19             {
    20                 throw new ArgumentNullException("context");
    21             }
    22             HttpResponseBase response = context.HttpContext.Response;
    23             response.ContentType = "application/json";
    24 
    25             StringWriter sw = new StringWriter();
    26             //IsoDateTimeConverter timeFormat = new IsoDateTimeConverter();
    27             //timeFormat.DateTimeFormat = "yyyy-MM-dd HH:mm:ss";
    28             IsoDateTimeConverter timeFormat = new IsoDateTimeConverter();
    29             timeFormat.DateTimeFormat = "yyyy-MM-dd";
    30             JsonSerializer serializer = JsonSerializer.Create(
    31                 new JsonSerializerSettings
    32                 {
    33                     Converters = new JsonConverter[] { timeFormat },
    34                     ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
    35                     NullValueHandling = NullValueHandling.Ignore    //忽略为null的值序列化
    36 
    37                 }
    38                 );
    39 
    40 
    41             using (JsonWriter jsonWriter = new JsonTextWriter(sw))
    42             {
    43                 jsonWriter.Formatting = Formatting.Indented;
    44 
    45                 if (ExtjsUISerialize)
    46                     serializer.Serialize(jsonWriter, this);
    47                 else
    48                     serializer.Serialize(jsonWriter, data);
    49             }
    50             response.Write(sw.ToString());
    51 
    52         }
    53     }

    特性标注及权限验证,代码如下

     1     /// <summary>
     2     /// 权限拦截
     3     /// </summary>
     4     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
     5     public class PermissionFilterAttribute : ActionFilterAttribute
     6     {
     7         /// <summary>
     8         /// 权限拦截
     9         /// </summary>
    10         /// <param name="filterContext"></param>
    11         public override void OnActionExecuting(ActionExecutingContext filterContext)
    12         {
    13             if (!this.CheckAnonymous(filterContext))
    14             {
    15                 //未登录验证
    16                 if (SessionHelper.Get("UserID") == null)
    17                 {
    18                     //跳转到登录页面
    19                     filterContext.RequestContext.HttpContext.Response.Redirect("~/Admin/User/Login");
    20                 }
    21             }
    22         }
    23         /// <summary>
    24         /// [Anonymous标记]验证是否匿名访问
    25         /// </summary>
    26         /// <param name="filterContext"></param>
    27         /// <returns></returns>
    28         public bool CheckAnonymous(ActionExecutingContext filterContext)
    29         {
    30             //验证是否是匿名访问的Action
    31             object[] attrsAnonymous = filterContext.ActionDescriptor.GetCustomAttributes(typeof(AnonymousAttribute), true);
    32             //是否是Anonymous
    33             var Anonymous = attrsAnonymous.Length == 1;
    34             return Anonymous;
    35         }
    36     }

    通过写一个BaseController来进行权限的验证,这样就不需要所有需要验证的Controller加标注了,当然BaseController还可以增加其他通用的处理

    1     /// <summary>
    2     /// Admin后台系统公共控制器(需要验证的模块)
    3     /// </summary>
    4     [PermissionFilter]
    5     public class BaseController:Controller
    6     {
    7 
    8     }

     要点三:轻量级ORM框架PetaPoco  

      非侵入性ORM框架,只需要一个PetaPoco.cs文件就OK了,不过我对其进行了再次封装,实现了工作单元,还是上代码吧

          一:封装

     1    public interface IDataRepository<TEntity> : IDependency where TEntity : class
     2         {
     3             #region 属性
     4 
     5             /// <summary>
     6             ///     获取 当前实体的查询数据集
     7             /// </summary>
     8             Database PetaPocoDB { get; }
     9 
    10             #endregion
    11 
    12             #region 公共方法
    13 
    14             /// <summary>
    15             ///     插入实体记录
    16             /// </summary>
    17             /// <param name="entity"> 实体对象 </param>
    18             /// <returns> 操作影响的行数 </returns>
    19             bool Add(TEntity entity);
    20 
    21             /// <summary>
    22             ///     批量插入实体记录集合
    23             /// </summary>
    24             /// <param name="entities"> 实体记录集合 </param>
    25             /// <returns> 操作影响的行数 </returns>
    26             List<object> Add(IEnumerable<TEntity> entities);
    27 
    28             /// <summary>
    29             ///     删除实体记录
    30             /// </summary>
    31             /// <param name="entity"> 实体对象 </param>
    32             /// <returns> 操作影响的行数 </returns>
    33             int Delete(TEntity entity);
    34 
    35             /// <summary>
    36             ///     删除实体记录集合
    37             /// </summary>
    38             /// <param name="entities"> 实体记录集合 </param>
    39             /// <returns> 操作影响的行数 </returns>
    40             bool Delete(IEnumerable<TEntity> entities);
    41 
    42             /// <summary>
    43             ///     更新实体记录
    44             /// </summary>
    45             /// <param name="entity"> 实体对象 </param>
    46             /// <returns> 操作影响的行数 </returns>
    47             int Update(TEntity entity);
    48 
    49             /// <summary>
    50             ///     更新实体记录
    51             /// </summary>
    52             /// <param name="entity"> 实体对象 </param>
    53             /// <returns> 操作影响的行数 </returns>
    54             bool Update(IEnumerable<TEntity> entities);
    55             /// <summary>
    56             /// 根据主键ID获取实体
    57             /// </summary>
    58             /// <param name="KeyID">主键ID</param>
    59             /// <returns>实体</returns>
    60             TEntity GetModelByID(object KeyID);
    61 
    62             /// <summary>
    63             /// 动态查询,返回dynamic类型的列表
    64             /// 请使用标准SQL语句进行查询(SELECT ... FROM ...)
    65             /// </summary> 
    66             /// <returns></returns>
    67             PagedList<dynamic> DynamicPagedList(int pageIndex, int pageSize, Sql sql);
    68 
    69             PagedList<TEntity> PagedList(int pageIndex, int pageSize, string sql, params object[] args);
    70 
    71             PagedList<TEntity> PagedList(int pageIndex, int pageSize, Sql sql);
    72 
    73             PagedList<TDto> PagedList<TDto>(int pageIndex, int pageSize, string sql, params object[] args);
    74 
    75             PagedList<TDto> PagedList<TDto>(int pageIndex, int pageSize, Sql sql);
    76             #endregion
    77         }
    View Code

         二:使用,具体封装和使用,大家还是去下载源码看吧

     1     public class NavigationMenuService : DbContextBase<BeiDream_NavigationMenu>, INavigationMenuService, IDependency
     2     {
     3         public NavigationMenuService(IUnitOfWork unitOfWork)
     4             : base(unitOfWork)
     5         { }
     6         public List<NavigationMenu> GetNavigationMenu(int id)
     7         {
     8             var sql = Sql.Builder.Where("ParentID=@0",id);
     9             sql.OrderBy("OrderNo ASC");   //默认ASC升序,降序为DESC
    10             List<BeiDream_NavigationMenu> List = this.PetaPocoDB.Fetch<BeiDream_NavigationMenu>(sql);
    11             return AutoMapperHelper.GetMapper(List);
    12         }
    13         public List<NavigationMenu> GetNavigationMenuNoLeaf(int id)
    14         {
    15             var sql = Sql.Builder.Where("ParentID=@0", id);
    16             sql.Where("IsLeaf=@0", false);
    17             sql.OrderBy("OrderNo ASC");   //默认ASC升序,降序为DESC
    18             List<BeiDream_NavigationMenu> List = this.PetaPocoDB.Fetch<BeiDream_NavigationMenu>(sql);
    19             return AutoMapperHelper.GetMapper(List);
    20         }
    21         /// <summary>
    22         /// 递归查询产品分类列表
    23         /// </summary>
    24         /// <param name="list">父级产品分类列表</param>
    25         public void GetNavigationMenus(ref List<NavigationMenu> list)
    26         {
    27             foreach (NavigationMenu season in list)
    28             {
    29                 List<NavigationMenu> lstSeason = GetNavigationMenu(season.id);
    30                 season.children = lstSeason;
    31                 if (list.Count > 0)
    32                 {
    33                     GetNavigationMenus(ref lstSeason);
    34                 }
    35             }
    36         }
    37         /// <summary>
    38         /// 递归查询产品分类列表
    39         /// </summary>
    40         /// <param name="list">父级产品分类列表</param>
    41         public void GetNavigationMenusNoLeaf(ref List<NavigationMenu> list)
    42         {
    43             foreach (NavigationMenu season in list)
    44             {
    45                 List<NavigationMenu> lstSeason = GetNavigationMenuNoLeaf(season.id);
    46                 season.children = lstSeason;
    47                 if (list.Count > 0)
    48                 {
    49                     GetNavigationMenusNoLeaf(ref lstSeason);
    50                 }
    51             }
    52         }
    53     }
    View Code

    要点四:依赖注入框架Autofac

    目前使用心得最大的好处就是不需要配置即实现了面向接口编程,特别是和MVC结合,实现构造函数注入就更加方便了,当然它还有其他
    功能,比如生命周期唯一实例,单例啊等等,暂时还研究不深,只是简单应用,大家看看具体实现吧

     1         private static void AutofacMvcRegister()
     2         {
     3             ContainerBuilder builder = new ContainerBuilder();
     4             builder.RegisterGeneric(typeof(DbContextBase<>)).As(typeof(IDataRepository<>));
     5             Type baseType = typeof(IDependency);
     6             Assembly[] assemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies()
     7                 .Select(Assembly.Load).ToArray();
     8             assemblies = assemblies.Union(new[] { Assembly.GetExecutingAssembly() }).ToArray();
     9             builder.RegisterAssemblyTypes(assemblies)
    10                 .Where(type => baseType.IsAssignableFrom(type) && !type.IsAbstract)
    11                 .AsImplementedInterfaces().InstancePerLifetimeScope();//InstancePerLifetimeScope 保证生命周期基于请求
    12 
    13             //无效
    14             //builder.RegisterType<DefaultCacheAdapter>().PropertiesAutowired().As<ICacheStorage>();
    15 
    16             builder.RegisterControllers(Assembly.GetExecutingAssembly());
    17             builder.RegisterFilterProvider();
    18             IContainer container = builder.Build();
    19             DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    20         }

    要点五;对象关系映射AutoMapper

    目前也只是简单应用,先看代码,它是如何简化我们的工作量的

     1         public static List<NavigationMenu> GetMapper(List<BeiDream_NavigationMenu> List)
     2         {
     3             List<NavigationMenu> NavigationMenuList = new List<NavigationMenu>();
     4             foreach (var item in List)
     5             {
     6                 //NavigationMenu DaoModel = new NavigationMenu();
     7                 //DaoModel.id = item.ID;
     8                 //DaoModel.text = item.ShowName;
     9                 //DaoModel.leaf = item.IsLeaf;
    10                 //DaoModel.url = item.url;
    11                 //DaoModel.Expanded = item.Expanded;
    12                 //DaoModel.children = null;
    13                 NavigationMenu DaoModel = item.ToDestination<BeiDream_NavigationMenu, NavigationMenu>();
    14                 NavigationMenuList.Add(DaoModel);
    15             }
    16             return NavigationMenuList;
    17         }

    注释掉的是不使用automapper之前的代码,没注释掉的是使用automapper,扩展了方法直接一句代码实现转化,是不是很easy,当然实
    现这些之前,我们需要给他定义规则,然后还要注册,代码如下,具体的请看源码

     1     public class NavigationMenuProfile : Profile
     2     {
     3         protected override void Configure()
     4         {
     5             CreateMap<BeiDream_NavigationMenu, NavigationMenu>()
     6                 .ForMember(dest => dest.id, opt => opt.MapFrom(src => src.ID))
     7                 .ForMember(dest => dest.text, opt => opt.MapFrom(src => src.ShowName))
     8                 .ForMember(dest => dest.leaf, opt => opt.MapFrom(src => src.IsLeaf));
     9         }
    10     }

    要点六:数据验证

    extjs前台验证我们已经做了,但是客户端传来的东西我们不能完全相信,后台需要再次验证,我们看到mvc的官方demo。一句话就实现
    了验证,我们是不是可以自己做验证呢,看代码

     1         [Anonymous]
     2         public ActionResult SaveUser(BeiDream_User model, List<int> Roles)
     3         {
     4             var ValidateResult = Validation.Validate(model);//服务器端的验证
     5             if (ValidateResult.IsValid)     //验证成功
     6             {
     7                 bool IsExitUser = UserService.PetaPocoDB.Exists<BeiDream_User>(model.ID);
     8                 if (!IsExitUser)
     9                 {
    10                     FilterGroup userRoleGroup = new FilterGroup();
    11                     FilterHelper.CreateFilterGroup(userRoleGroup, null, "UserName", model.UserName, GroupOperatorQueryEnum.and, RuleOperatorQueryEnum.equal);
    12                     bool IsExist = UserService.IsExist(userRoleGroup);
    13                     if (IsExist)
    14                     {
    15                         List<string> errorName=new List<string>();
    16                         errorName.Add("UserName");
    17                         ValidationResult error = new ValidationResult("已存在相同的用户名", errorName);
    18                         ValidateResult.Add(error);
    19                          return this.ExtjsFromJsonResult(false,ValidateResult); 
    20                     }
    21                     else
    22                     {
    23                         bool IsSaveSuccess = TransactionService.AddUserAndUserRole(model, Roles);
    24                         List<string> msg = new List<string>();
    25                         msg.Add(IsSaveSuccess ? "用户信息保存成功!" : "用户信息保存失败!");
    26                         return this.ExtjsFromJsonResult(true, null, msg); 
    27                     }
    28                 }
    29                 else
    30                 {
    31                     FilterGroup userRoleGroup = new FilterGroup();
    32                     FilterHelper.CreateFilterGroup(userRoleGroup, null, "UserName", model.UserName, GroupOperatorQueryEnum.and, RuleOperatorQueryEnum.equal);
    33                     FilterHelper.CreateFilterGroup(userRoleGroup, null, "ID", model.ID, GroupOperatorQueryEnum.and, RuleOperatorQueryEnum.notequal);
    34                     bool IsExist = UserService.IsExist(userRoleGroup);
    35                     if (IsExist)
    36                     {
    37                         List<string> errorName = new List<string>();
    38                         errorName.Add("UserName");
    39                         ValidationResult error = new ValidationResult("已存在相同的用户名", errorName);
    40                         ValidateResult.Add(error);
    41                         return this.ExtjsFromJsonResult(false, ValidateResult); 
    42                     }
    43                     else
    44                     {
    45                         bool IsSaveSuccess = TransactionService.UpdateUserAndUserRole(model, Roles);
    46                         List<string> msg = new List<string>();
    47                         msg.Add(IsSaveSuccess ? "用户信息保存成功!" : "用户信息保存失败!");
    48                         return this.ExtjsFromJsonResult(true, null, msg); 
    49                     }
    50                 }
    51             }
    52             else
    53             {
    54                 return this.ExtjsFromJsonResult(false,ValidateResult);   //验证失败,返回失败的验证结果,给出前台提示信息
    55             }          
    56         }

    大家可以看到前台传进来的参数,我们先进行验证 var ValidateResult = Validation.Validate(model),验证的条件我们是在模型上定义好的,然后判断验证是否通过,通过进行下一步动作,不通过,把验证的结果信息返回前台,提示给用户

    要点七:SQL翻译机

    这个只能算是一个简单的东西吧,并且感觉用起来麻烦,但是我觉得用的熟练了,还是很不错的,只是省了手拼SQL的问题嘛,减少了出
    错几率,具体使用还是看代码吧

     1         [Anonymous]
     2         public ActionResult GetUserList(int page, int start, int limit, string UserKeyName, string RoleID)
     3         {
     4             RemoveSelectId();
     5             PagedList<BeiDream_User> PageList = null;
     6             FilterGroup userGroup = GetQueryConditions(UserKeyName, RoleID);
     7             PageList = UserService.GetPagedList(page, limit, userGroup);
     8             return this.ExtjsGridJsonResult(PageList, PageList.TotalItemCount);
     9         }
    10         private FilterGroup GetQueryConditions(string UserKeyName, string RoleID)
    11         {
    12             FilterGroup userGroup = new FilterGroup();
    13             if (!string.IsNullOrEmpty(RoleID))             //用户角色不为空时
    14             {
    15                 FilterGroup userRoleGroup = new FilterGroup();
    16                 FilterHelper.CreateFilterGroup(userRoleGroup, null, "RoleID", RoleID, GroupOperatorQueryEnum.and, RuleOperatorQueryEnum.equal);
    17                 //先根据用户角色查出对应的用户ID
    18                 List<BeiDream_User_Role> List = UserRoleService.GetList(userRoleGroup);
    19                 if (List.Count != 0)             //todo,此角色信息为空情况下,查到的用户也应该为空,目前未处理
    20                 {
    21                     if (string.IsNullOrEmpty(UserKeyName))
    22                     {
    23                         //再根据此用户角色下的用户ID,因为查出所以用户ID,查询条件是或的关系GroupOperatorQueryEnum.or,翻译出对应用户的查询条件,最后查出对应用户
    24                         foreach (var item in List)
    25                         {
    26                             FilterHelper.CreateFilterGroup(userGroup, null, "ID", item.UserID, GroupOperatorQueryEnum.or, RuleOperatorQueryEnum.equal);
    27                         }
    28                     }
    29                     else
    30                     {
    31                         //先翻译出用户名查询条件,与其他查询条件是与的关系GroupOperatorQueryEnum.and
    32                         FilterHelper.CreateFilterGroup(userGroup, null, "UserName", UserKeyName, GroupOperatorQueryEnum.and, RuleOperatorQueryEnum.like);
    33                         //因为第二个查询条件是多个查询条件的结合组成再与第一个查询条件结合,故放到子FilterGroup中
    34                         List<FilterGroup> filterGroups = new List<FilterGroup>();
    35                         FilterGroup userIDGroup = new FilterGroup();
    36                         //再根据此用户角色下的用户ID,因为查出所以用户ID,查询条件是或的关系GroupOperatorQueryEnum.or,翻译出对应用户的查询条件,最后查出对应用户
    37                         foreach (var item in List)
    38                         {
    39                             FilterHelper.CreateFilterGroup(userIDGroup, null, "ID", item.UserID, GroupOperatorQueryEnum.or, RuleOperatorQueryEnum.equal);
    40                         }
    41                         filterGroups.Add(userIDGroup);
    42                         userGroup.groups = filterGroups;
    43                     }
    44                 }
    45             }
    46             else
    47             {
    48                 if (!string.IsNullOrEmpty(UserKeyName))
    49                 {
    50                     //先翻译出用户名查询条件,与其他查询条件是与的关系GroupOperatorQueryEnum.and
    51                     FilterHelper.CreateFilterGroup(userGroup, null, "UserName", UserKeyName, GroupOperatorQueryEnum.and, RuleOperatorQueryEnum.like);
    52                 }
    53             }
    54             return userGroup;
    55         } 
    View Code

    要点八:缓存

     缓存也就简单应用Helper级别,主要用了.net自带缓存和分布式Memcached缓存,一个接口,两个实现

     1     /// <summary>
     2     /// 缓存接口
     3     /// </summary>
     4    public interface ICacheStorage
     5     {
     6         #region 缓存操作
     7         /// <summary>
     8         /// 添加缓存
     9         /// </summary>
    10         /// <param name="key"></param>
    11         /// <param name="value"></param>
    12         void Insert(string key, object value);
    13         /// <summary>
    14         /// 添加缓存(默认滑动时间为20分钟)
    15         /// </summary>
    16         /// <param name="key">key</param>
    17         /// <param name="value">value</param>
    18         /// <param name="expiration">绝对过期时间</param>
    19         void Insert(string key, object value, DateTime expiration);
    20         /// <summary>
    21         /// 添加缓存
    22         /// </summary>
    23         /// <param name="key">key</param>
    24         /// <param name="value">value</param>
    25         /// <param name="expiration">过期时间</param>
    26         void Insert(string key, object value, TimeSpan expiration);
    27         /// <summary>
    28         /// 获得key对应的value
    29         /// </summary>
    30         /// <param name="key"></param>
    31         /// <returns></returns>
    32         object Get(string key);
    33         /// <summary>
    34         /// 根据key删除缓存
    35         /// </summary>
    36         /// <param name="key"></param>
    37         void Remove(string key);
    38         /// <summary>
    39         /// 缓存是否存在key的value
    40         /// </summary>
    41         /// <param name="key">key</param>
    42         /// <returns></returns>
    43         bool Exist(string key);
    44         /// <summary>
    45         /// 获取所有的缓存key
    46         /// </summary>
    47         /// <returns></returns>
    48         List<string> GetCacheKeys();
    49         /// <summary>
    50         /// 清空缓存
    51         /// </summary>
    52         void Flush();
    53         
    54         #endregion
    55     }

    写在最后

      写博客真的是很累人的事,很敬佩那些能写连载博客的牛人们,虽然自己做的项目很小,但是觉得写成博客,要写的要点还是很多的
    ,上面我讲的很粗略,但是主要的知识点都讲出来了,这个项目其实没有做完,不打算再继续了,打算换了,接下来打算使用easyui
    +knockout+ef来写一个完整的权限管理系统,涉及菜单权限、按钮权限、字段权限等等吧,路很长.....任重而道远

    最后,大家如果觉得有帮助,请点推荐哦!源码下载地址:

    猛戳这里BeiDream.part1.rar!

    猛戳这里BeiDream.part2.rar!

  • 相关阅读:
    C# 设计模式-抽象工厂模式
    C# 设计模式-工厂方法模式
    C# 设计模式-简单工厂模式
    C# 设计原则-迪米特法则(最少知识原则)
    C# 设计原则-接口隔离原则
    阻止右击事件并更改为自定义导航栏;
    今日头条滚动新闻版块特效
    抓包工具
    查看页面加载速度
    插件那点事
  • 原文地址:https://www.cnblogs.com/beimeng/p/4453142.html
Copyright © 2020-2023  润新知