一、前言
权限系统设计中,授权代码是用来控制数据访问权限的。授权代码说白了只是一树型结构的数据,没有什么其它的业务意义。那么这个页面的功能也就非常简单授权代码维护:新增、修改、删除授权代码数据。

二、正文
我们实际上就是要实现一个treegrid的增删改的功能,技术上很容易实现。
1、新建控制器 PermissionControlle.cs

public class PermissionController : Controller
{
public ActionResult Index()
{
return View();
}
}

mvc控制器中不需要写任何的代码,就这样就ok

2、创建view

@{
ViewBag.Title = "授权代码";
Layout = "~/Views/Shared/_Layout.cshtml";
} @section scripts{
<script src="~/Areas/Sys/ViewModels/Permission.js"></script>
<script type="text/javascript">
using(['combotree'],easyuifix.datagrid_editor_extend);
ko.bindingViewModel(new viewModel());
var formatterParent = function (value, row) { return row.ParentName };
</script>
}
<div class="z-toolbar">
<a id="a_refresh" href="#" plain="true" class="easyui-linkbutton" icon="icon-arrow_refresh" title="刷新" data-bind="click:refreshClick">刷新</a>
<a id="a_add" href="#" plain="true" class="easyui-linkbutton" icon="icon-add" title="新增" data-bind="click:addClick">新增</a>
<a id="a_edit" href="#" plain="true" class="easyui-linkbutton" icon="icon-edit" data-bind="click:editClick" title="编辑">编辑</a>
<a id="a_del" href="#" plain="true" class="easyui-linkbutton" icon="icon-cross" title="删除" data-bind="click:deleteClick">删除</a>
<a id="a_save" href="#" plain="true" class="easyui-linkbutton" icon="icon-save" data-bind="click:saveClick" title="保存">保存</a>
</div> <table data-bind="treegrid:grid">
<thead>
<tr>
<th field="_id" hidden="true"></th>
<th field="PermissionName" align="left" width="150" editor="{type:'validatebox',options:{required: true }}">授权名称 </th>
<th field="PermissionCode" align="left" width="80" editor="{type:'validatebox',options:{required: true }}">授权代码 </th>
<th field="ParentCode" align="left" width="150" editor="combotree" formatter="formatterParent">上级授权 </th>
</tr>
</thead>
</table>

这个view相对于其它页面来说也是相当的简洁了

3、前端的实现,主要是实现easyui treegrid的在线编辑功能及按钮的交互逻辑

/**
* 模块名:mms viewModel
* 程序名: Permission.js
* Copyright(c) 2013-2015 liuhuisheng [ liuhuisheng.xm@gmail.com ]
**/ function viewModel() {
var self = this;
this.grid = {
size: { w: 4, h: 40 },
url: '/api/sys/permission',
idField: '_id',
queryParams: ko.observable(),
treeField: 'PermissionName',
loadFilter: function (d) {
d = utils.copyProperty(d.rows || d, ["PermissionCode"], ["_id"], false);
return utils.toTreeData(d, '_id', 'ParentCode', "children");
}
};
this.refreshClick = function () {
window.location.reload();
};
this.addClick = function () {
if (self.grid.onClickRow()) {
var row = { _id: utils.uuid(), PermissionCode: '', PermissionName: '' };
self.grid.treegrid('append', { parent: '', data: [row] });
self.grid.treegrid('select', row._id);
self.grid.$element().data("datagrid").insertedRows.push(row);
self.editClick();
}
};
this.editClick = function () {
var row = self.grid.treegrid('getSelected');
if (row) {
//取得父节点数据
var treeData = JSON.parse(JSON.stringify(self.grid.treegrid('getData')).replace(/_id/g, "id").replace(/PermissionName/g, "text"));
treeData.unshift({ "id": 0, "text": "" }); //设置上级菜单下拉树
var gridOpt = $.data(self.grid.$element()[0], "datagrid").options;
var col = $.grep(gridOpt.columns[0], function (n) { return n.field == 'ParentCode' })[0];
col.editor = { type: 'combotree', options: { data: treeData } };
col.editor.options.onBeforeSelect = function (node) {
var isChild = utils.isInChild(treeData, row._id, node.id);
com.messageif(isChild, 'warning', '不能将自己或下级设为上级节点');
return !isChild;
}; //开始编辑行数据
self.grid.treegrid('beginEdit', row._id);
self.edit_id = row._id;
}
}; this.grid.OnBeforeDestroyEditor = function (editors, row) {
row.ParentName = editors['ParentCode'].target.combotree('getText');
};
this.deleteClick = function () {
var row = self.grid.treegrid('getSelected');
if (row) {
self.grid.$element().treegrid('remove', row._id);
self.grid.$element().data("datagrid").deletedRows.push(row);
}
};
this.grid.onDblClickRow = self.editClick;
this.grid.onClickRow = function () {
var edit_id = self.edit_id;
if (!!edit_id) {
if (self.grid.treegrid('validateRow', edit_id)) { //通过验证
self.grid.treegrid('endEdit', edit_id);
self.edit_id = undefined;
}
else { //未通过验证
self.grid.treegrid('select', edit_id);
return false;
}
}
return true;
};
this.saveClick = function () {
self.grid.onClickRow();
var post = {};
post.list = new com.editTreeGridViewModel(self.grid).getChanges(['_id', 'PermissionCode', 'PermissionName', 'ParentCode']);
if (self.grid.onClickRow() && post.list._changed) {
com.ajax({
url: '/api/sys/permission/edit',
data: ko.toJSON(post),
success: function (d) {
com.message('success', '保存成功!');
self.grid.treegrid('acceptChanges');
self.grid.queryParams({});
}
});
} };
}

4、现在大家看我的东西都觉得是在看前端文章,实际上我在后台框架也做的很强大。现在重点放在后台,请大家注意我后端的写法,我们现在看web api中的处理。我这里用到了两个web api

1、取得授权代码数据:                                            GET    /api/sys/permission

2、保存treegrid中的修改(包括新增、修改、删除的数据)   POST  /api/sys/permission

大家注意下WebApi实现,超级简洁的代码实现

public class PermissionApiController : ApiController
{
//创建数据服务实例
sys_permissionService service = new sys_permissionService(); public IEnumerable<dynamic> Get()
{
//构建查询参数
var pQuery = ParamQuery.Instance()
.Select("A.*,B.PermissionName as ParentName")
.From(@"sys_permission A left join sys_permission B on B.PermissionCode = A.ParentCode"); //调用服务基类中的共通方法返回查询结果
return service.GetDynamicList(pQuery);
} [HttpPost]
public void Edit(dynamic data)
{
//构建编辑的参数 传入的数据结构为data={deleted:[...],inserted:[...],updated:[...]};
var listWrapper = RequestWrapper.Instance().LoadSettingXmlString(@"
<settings>
<table>sys_permission</table>
<where>
<field name='PermissionCode' cp='equal' variable='_id'></field>
</where>
</settings>"); //调用服务基类中的共通方法处理保存
service.Edit(null, listWrapper, data);
}
}

以上的两个方法就已经实现了全部的功能了,这里我们好像觉得都是调用service中的方法,那我们再看看service类

public class sys_permissionService : ServiceBase<sys_permission>
{ }

这个数据服务类是空的,没有任何方法,只是继承了我的service基类,拥有了基类中定义的方法。
这里再简单的介绍下我的服务基类,只要服务类继承了服务基类后,就拥有以下方法

//服务构造函数
public ServiceBase();
public ServiceBase(string moduleName); //查询方法:
public List<dynamic> GetDynamicList(ParamQuery param = null); //取得动态数据列表
public dynamic GetDynamicListWithPaging(ParamQuery param = null); //取得动态数据列表(带分页) public List<T> GetModelList(ParamQuery param = null); //取得Model列表数据
public dynamic GetModelListWithPaging(ParamQuery param = null); //取得Model列表数据(带分页) public T GetModel(ParamQuery param); //取得单model数据
public dynamic GetDynamic(ParamQuery param); //取得动态对象 public TField GetField<TField>(ParamQuery param); //取得字段的值 //数据插入:提供数据插入前后事件定义
protected virtual bool OnBeforeInsert(InsertEventArgs arg);
public int Insert(ParamInsert param);
protected virtual void OnAfterInsert(InsertEventArgs arg); //数据更新:
protected virtual bool OnBeforeUpdate(UpdateEventArgs arg);
public int Update(ParamUpdate param);
protected virtual void OnAfterUpdate(UpdateEventArgs arg); //数据删除:
protected virtual bool OnBeforeDelete(DeleteEventArgs arg);
public int Delete(ParamDelete param);
protected virtual void OnAfterDelete(DeleteEventArgs arg); //存储过程执行:
public int StoredProcedure(ParamSP param); //数据编辑(主从表在同一个事务中保存):
protected virtual bool OnBeforEdit(EditEventArgs arg);
protected virtual bool OnBeforEditMaster(EditEventArgs arg);
protected virtual bool OnBeforEditDetail(EditEventArgs arg);
public int Edit(RequestWrapper formWrapper, RequestWrapper listWrapper, JObject data);
protected virtual void OnAfterEdit(EditEventArgs arg);
protected virtual void OnAfterEditMaster(EditEventArgs arg);
protected virtual void OnAfterEditDetail(EditEventArgs arg);

查询、新增、修改、删除、存储过程等每一个对象我都对应一个参数构造器,查询对应的是ParamQuery,每一个写法都可以像linq一样,比较方简洁。
好了,回过头再看看我的webapi中的代码,是不是每个方法只有两行代码,而且已经实现了很复杂的操作。

正是得利于我框架的这一点,才把我从后台中解放出来,有更多的时间精力去研究前端。

三、效果图

简单的几句代码就搞定了这个功能,我们来看看实现的效果

新增、修改、删除测试都ok

五、后述

如果你觉得不错就帮我【推荐】一下吧,你的支持才是我能坚持写完这个系列文章的动力。

技术交流QQ群:群一:328510073(已满),群二:167813846,欢迎大家来交流。

系列博客链接:

我的权限系统设计实现MVC4 + WebAPI + EasyUI + Knockout(三)图形化机构树

我的权限系统设计实现MVC4 + WebAPI + EasyUI + Knockout(二)菜单导航

我的权限系统设计实现MVC4 + WebAPI + EasyUI + Knockout(一)

我的权限系统设计实现MVC4 + WebAPI + EasyUI + Knockout(四)授权代码维护的更多相关文章

  1. 我的权限系统设计实现MVC4 + WebAPI + EasyUI + Knockout(三)图形化机构树

    一.前言 组织机构是国内管理系统中很重要的一个概念,以前我们基本都是采用数据列表的形式展现,最多只是采用树形列表展现.虽然够用,但是如果能做成图形化当然是最好不过了.这里我不用任何图形控件,就用最原始 ...

  2. 我的权限系统设计实现MVC4 + WebAPI + EasyUI + Knockout(二)菜单导航

    一.前言 上篇博客中已经总体的说了一下权限系统的思路和表结构设计,那接下来我们就要进入正文了,先从菜单导航这个功能开始. 二.实现 这个页面基本不用什么需求分析了,大家都很明白,不过在这个页面要多维护 ...

  3. 我的权限系统设计实现MVC4 + WebAPI + EasyUI + Knockout(一)

    一.前言 之前的博客一直都还没写到框架的实现及权限系统,今天开始写我的权限系统,我以前做过的项目基本上都有权限管理这个模块,但各个系统都会有一些不太一样,有些简单点,有些稍微复杂一点,一句话,我们做的 ...

  4. 我的权限系统设计实现MVC4 + WebAPI + EasyUI + Knockout(五)框架及Web项目的组件化

    一.组件化印象 1.先给大家看一张截图 如果我告诉大家,这就是一个web管理系统发布后的所有内容,你们会不会觉得太简洁了,只有一个web.config.一个Global.asax文件,其它的都是dll ...

  5. 权限系统设计实现MVC4 + WebAPI + EasyUI + Knouckout

    权限系统设计实现MVC4 + WebAPI + EasyUI + Knouckout (一) 一.前言 之前的博客一直都还没写到框架的实现及权限系统,今天开始写我的权限系统,我以前做过的项目基本上都有 ...

  6. MVC4 + WebAPI + EasyUI + Knockout-授权代码维护

    我的权限系统设计实现MVC4 + WebAPI + EasyUI + Knockout(四)授权代码维护 一.前言 权限系统设计中,授权代码是用来控制数据访问权限的.授权代码说白了只是一树型结构的数据 ...

  7. SNF快速开发平台3.0之BS页面展示和九大优点-部分页面显示效果-Asp.net+MVC4.0+WebAPI+EasyUI+Knockout

    一)经过多年的实践不断优化.精心维护.运行稳定.功能完善: 能经得起不同实施策略下客户的折腾,能满足各种情况下客户的复杂需求. 二)编码实现简单易懂.符合设计模式等理念: 上手快,见效快.方便维护,能 ...

  8. 建筑材料系统 ASP.NET MVC4.0 + WebAPI + EasyUI + Knockout 的架构设计开发

    框架介绍: 1.基于 ASP.NET MVC4.0 + WebAPI + EasyUI + Knockout 的架构设计开发 2.采用MVC的框架模式,具有耦合性低.重用性高.生命周期成本低.可维护性 ...

  9. SNF快速开发平台3.0之-界面个性化配置+10种皮肤+7种菜单-Asp.net+MVC4.0+WebAPI+EasyUI+Knockout

    一.个性配置-首页:可以进行拖动保存配置,下次登录时就会按配置的进行加载 二.个人配置页面 7种菜单用户可自定义配置,和预览效果 10种皮肤自定义配置,和预览效果 皮肤和菜单可以随意组合-部分截图: ...

随机推荐

  1. TreeSize工具介绍

    TreeSize Professional 工具是一个功能强大且灵活方便的硬盘空间管理工具,能在 Windows 8/7/Vista/XP 或 Windows Server 2012年/2008年/2 ...

  2. 最锋利的Visual Studio Web开发工具扩展:Web Essentials详解(转)

    Web Essentials是目前为止见过的最好用的VS扩展工具了,具体功能请待我一一道来. 首先,从Extension Manager里安装:最新版本是19号发布的2.5版 然后重启你的VS开发环境 ...

  3. Linux内核阅读相关

    一.likely()与unlikely()函数的意义 http://blog.chinaunix.net/uid-27665626-id-3506567.html 二.TSO.UFO.GSO.LRO. ...

  4. Bellman-Ford算法解决单源最短路问题

    #include<stdio.h> #include<stdlib.h> #include<stdbool.h> #define max 100 #define I ...

  5. windows下如何安装jira

    ---恢复内容开始--- 准备工作: 1.安装jdk,详细不在介绍 2.建立jira帐号:https://id.atlassian.com/login?application=mac&cont ...

  6. <a href="javascript:void(0)" onclick="ff()" ></a> 用法解析

    javascript:void(0) 仅仅表示一个死链接 如果是个# javascript:void(#),就会出现跳到顶部的情况,搜集了一下解决方法 1:<a href="####& ...

  7. bootstrap学习总结-js组件(四)

    这次我们来看下js组件的使用,本篇文章会有点长,希望大家可以耐心看,相信收获会有不少.不少园友加我好友,表示喜欢我写文字的风格,简单明了,这里,再次谢谢你们的支持.一方面,博主自身技术有限,写的东西都 ...

  8. JavaWeb学习----JSTL标签库

    一.JSTL简介: JSTL全名为JavaServer Pages Standard Tag Library,中文名称为JSP标准标签函数库,目前最新的版本为1.2.JSTL是由JCP(Java Co ...

  9. 在spring环境下集成ActiveMQ

    1.参考文献 Spring集成ActiveMQ配置 Spring JMS异步发收消息 ActiveMQ 2.环境 在前面的一篇ActiveMQ入门实例中我们实现了消息的异步传送,这篇博文将如何在spr ...

  10. Android Activity的生命周期

    一.为什么要了解Activity的生命周期 activity is directly affected by its association withother activities, its tas ...