我的权限系统设计实现MVC4 + WebAPI + EasyUI + Knockout(四)授权代码维护

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

二、正文 
我们实际上就是要实现一个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(一)

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 小程序大智慧,sqlserver 注释提取工具

    原文:小程序大智慧,sqlserver 注释提取工具 开篇背景 我习惯在写表的创建脚本时将注释直接写在脚本里,比如 /*账套*/ CREATE TABLE [dbo].[AccountingBook] ...

  2. 《剑指offer》 相应 在线测试地址

    <剑指Offer>面试题集收录汇总 面试题1 赋值运算符函数 不适合在线模式 面试题2 实现Singleton模式 不适合在线模式 面试题3 二维数组中的查找 已收录 面试题4 替换空格 ...

  3. Jenkins master在windows

    Jenkins master在windows上安装 1 Jenkins Jenkins由以前的hudson更名而来.Jenkins的主要功能是监视重复工作的执行,例如软件工程的构建或在cron下设置的 ...

  4. [ Bubble Sort ]& block

    [ Bubble Sort ] 冒泡排序!“预处理.block.预编译”!<环境:Terminal的gcc编译器> 简述:冒泡排序就是把小的元素往前调或者把大的元素往后调.比较是相邻的两个 ...

  5. Oracle分区表转换

    Oracle普通表—>分区表转换(9亿数据量) 背景介绍: 环境:Linux 5.5 + Oracle 10.2.0.4 某普通表T,由于前期设计不当没有分区,如今几年来的数据量已达9亿+, 空 ...

  6. 关于tasklet的一点小小的解释

    大概有一些同学对tasklet的串行化还有点困惑,其实在单处理器上最好理解,所以本帖主要讨论多处理器上tasklet如何实现串行化:同一个tasklet对象同一时刻只能在一个处理器上运行. 在 驱动程 ...

  7. The Swift Programming Language-官方教程精译Swift(9) 枚举-- --Enumerations

    枚举定义了一个通用类型的一组相关的值,使你可以在你的代码中以一个安全的方式来使用这些值.   如果你熟悉 C 语言,你就会知道,在 C 语言中枚举指定相关名称为一组整型值.Swift 中的枚举更加灵活 ...

  8. NET 2015

    .NET 2015 英文原文:Understanding .NET 2015 Understanding 翻译为了解或理解,对于 .NET 来说,2015 年注定会更加精彩,所以标题就用了“精彩”这个 ...

  9. 使用Row_Number()分页优化

    记一次SQLServer的分页优化兼谈谈使用Row_Number()分页存在的问题   最近有项目反应,在服务器CPU使用较高的时候,我们的事件查询页面非常的慢,查询几条记录竟然要4分钟甚至更长,而且 ...

  10. 在windows server里,对于同一个账号,禁止或允许多个用户使用该账户,同时登录

    开始 -> 运行 -> gpedit.msc -> 本地计算机 策略 -> 计算机配置 -> 管理模板 -> Windows 组件 -> 远程桌面服务 -&g ...