ABP框架实战 1.基础信息维护

在之前的一个开发项目中,因为公司战略发展,引用了这个ABP开源框架作为新项目的基础版本,由于客户的要求需要迁移旧系统数据,以及其他的一些原因,数据库采用了Oracle数据库管理。所以引用了Dapper这个ORM框架作为数据访问的扩展,在前期的开发过程中,碰到过很多的坑,但是通过学习ABP框架实战 1.基础信息维护阳光铭睿ABP框架实战 1.基础信息维护tkb至简这两位博主写的一系列文章,以及其他同事的帮助下,慢慢的熟悉了ABP框架的一些原理以及思路。

下面简单介绍一下这个Abp框架以及一些学习的资料:

ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称。

ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个通用的WEB应用程序框架和项目模板。

ASP.NET Boilerplate 基于DDD的经典分层架构思想,实现了众多DDD的概念(但没有实现所有DDD的概念)。

ABP的官方网站http://www.aspnetboilerplate.com

ABP在Github上的开源项目https://github.com/aspnetboilerplate

ABP框架实战 1.基础信息维护

阳光铭睿:http://www.cnblogs.com/mienreal/p/4528470.html

ABP框架实战 1.基础信息维护

tkb至简:http://www.cnblogs.com/farb/p/ABPTheory.html

1.在历经了7个月(1607-1701)的时间,项目前两期的开发工作也算是全部的完成了,幸运的我一直留到了最后,负责后续功能以及App对接的开发,以及试运行问题过程中客户提出问题的维护。

2.在后面的某个日期中,全体这个项目的参与人员进行了一次会议总结,总体来说还算不错吧。

3.在后来的某一天,自己想要在最基础的框架上面弄一个基础的框架管理,关于简单的用户-部门-角色-权限管理这一块,可能还有很多地方没有弄完善的地方,目前还存在一部分的,但是简单来说也能满足一些简单的管理需求吧。(因为在这个项目开发过程中,这一块的数据管理是用的之前公司成熟的一套PMI框架,引用的单点登录,所以只能够参照他的思路来弄)

项目总体框架:

ABP框架实战 1.基础信息维护

这里链接一个同事写的一篇文章吧,上面有关于这个项目框架的一些详细介绍http://www.cnblogs.com/yuanbeier/articles/6394484.html

下面讲一下自己弄这个的开发过程吧。

a.建立PDM,数据对应关系

ABP框架实战 1.基础信息维护

b.生成数据库,以及实体,其实这里在ABP最初始的做法是采用Code First模式先建立实体在生成数据结构,个人觉得看自己习惯吧。

ABP框架实战 1.基础信息维护

c.创立对应的Application Services, Controller,View,Js

d.然后就是具体的编码业务完成了,这个前段采用最快速的easyui开发,在这里参考了之前一个同事写的一个基类,然后在其思路上重新了写了一个基类,在这里的思路也正是考虑到ABP的约定大于规范的开发思路

 var TopeveryBase = Base.extend({
/*构造方法*/
constructor: function () {
},
/*初始化表格*/
initGrid: function (options) {
options = $.extend({}, { id: "grid", width: "100%", height: "600", method: "post", singleSelect: true }, options || {});
if (options.url == null) {
options.url = $("#" + options.id).attr("url");
}
if (typeof (options.url) == "undefined") {
options.url = $("#" + options.id).attr("turl");
}
if ($("#" + options.id).attr("singleSelect") === "false") {
options.singleSelect = true;
}
var gridParm = {
idField: "id",
fitColumns: true,
loadMsg: false,
nowrap: false,
queryParams: options.queryParams,
method: options.method,
singleSelect: options.singleSelect,
iconCls: "icon-save",
striped: true,
height: options.height,
animate: true,
collapsible: true,
border: true,
rownumbers: true, //行号
pagination: options.pagination || true, //分页控件
pageSize: 10,
pageList: [1, 10, 20, 50, 100, 250, 500, 1000],
sortName: "Id",
sortOrder: "desc",
toolbar: '#toolbarWrap',
onLoadSuccess: function (data) {
$(this).datagrid('doCellTip', { 'max-width': '400px', 'delay': 500 });
$(this).datagrid("clearSelections").datagrid("clearChecked");
},
loader: function (param, success, error) {
if (typeof (param.sort) == "undefined") {
param.sort = "Id";
}
if (typeof (param.order) == "undefined") {
param.order = "desc";
}
var postParm = {
PageIndex: param.page,
PageCount: param.rows,
sort: param.sort,
order: param.order
};
if (options.queryParams != null) {
postParm = $.extend({}, postParm, options.queryParams);
}
postParm = $.extend({}, postParm);
var formpostdata = topevery.form2Json("selectFrom");
postParm = $.extend({}, postParm, formpostdata);
/* 获取详情*/
easyuiBase.ajax({
type: "post",
url: options.url,
data: JSON.stringify(postParm),
loading: false
}, function (data) {
if (data.Success) {
var array = new Object();
array.rows = data.Result.Rows;
array.total = data.Result.Total;
success(array);
} else {
error();
}
}, true);
}
};
for (var i = 0; i < $(".easyui-textbox").length; i++) {
$("#" + $('.easyui-textbox').eq(i)[0].id + "").textbox({
inputEvents: $.extend({}, $.fn.textbox.defaults.inputEvents, {
keyup: function (event) {
if (event.keyCode === 13) {
User.loadInfo();
}
}
})
});
};
if (options.columns != null) {
gridParm.columns = options.columns;
}
$("#" + options.id).datagrid(gridParm);
},
/**
*
* @param {} id 修改时所用查询编号
* @param {} 加载修改查看 callback 回调函数
* @param {} 新增修改之后 callback1 回调函数
* @param {} options 参数集合
* @returns {}
*/
View: function (id, callback, callback1, options) {
if (id > 0) {
options = $.extend({}, { id: "edit", btn: "save", sumbit: "sumbitForm", grid: "grid" }, options || {});
} else {
options = $.extend({}, { id: "add", btn: "save", sumbit: "sumbitForm", grid: "grid" }, options || {});
}
var urlstring = $("#" + options.id).attr("url").split(',');
//geturl 获取修改需要加载信息
if (options.geturl == null) {
if (urlstring.length > 0) {
options.geturl = urlstring[1];
}
}
///新增or修改url
if (options.url == null) {
options.url = urlstring[0];
}
$("#" + options.sumbit).form("reset");
if (id !== "undefined" && id != null) {
//修改时 数据加载到页面
easyuiBase.ajax({
type: "POST",
url: options.geturl,
data: JSON.stringify({ Id: id }),
loading: false
}, function (data) {
if (data.Success) {
var row = data.Result;
$("#" + options.sumbit).form("load", row);
callback(row);
} else {
error();
}
});
}
//弹出层dialog Id
if (options.name == null) {
options.name = $("#" + options.id).attr("name");
}
$("#" + options.name).dialog('open');
$("#" + options.btn).click(function () {
if ($("#" + options.sumbit).form('validate') === false) {
return;
}
easyuiBase.ajax({
type: "post",
url: options.url,
data: JSON.stringify(easyuiBase.form2Json(options.sumbit)),
loading: false
}, function (data) {
if (data.Success) {
if (data.Result.IsSuccess) {
$("#" + options.name).dialog('close');
try {
topeveryMessage.show(data.Result.Message);
} catch (e) {
}
$("#" + options.sumbit).form("reset");
$("#" + options.grid).datagrid("load");
$("#" + options.btn).unbind();
if (callback1 !== "undefined" && callback1 != null) {
callback1(data.Result);
}
} else {
try {
topeveryMessage.show(data.Result.Message);
} catch (e) { }
}
} else {
error();
}
});
});
},
//删除
delData: function (options, callback) {
options = $.extend({}, { id: "delete", grid: "grid" }, options || {});
var urlstring = $("#" + options.id).attr("url");
///删除url
if (options.url == null) {
options.url = urlstring;
}
var arrRows = $('#' + options.grid).datagrid('getSelections');
if (arrRows.length === 0) {
$.messager.alert('提示', '请选择一条需要删除的记录!', 'info');
} else {
var ids = [];
$.each(arrRows, function () {
ids.push(this.Id);
});
easyuiBase.ajax({
type: "post",
url: options.url,
data: JSON.stringify({ "Ids": ids.join() }),
contentType: "application/json",
loading: false
}, function (data) {
if (data.Success) {
if (data.Result.IsSuccess) {
try {
$("#" + options.grid).datagrid('reload');
} catch (e) { }
callback();
topeveryMessage.show(data.Result.Message);
} else {
try {
topeveryMessage.show(data.Result.Message);
} catch (e) { }
}
} else {
error();
}
}, true);
}
},
///搜索
loadInfo: function (options) {
options = $.extend({}, { grid: "grid" }, options || {});
$('#' + options.grid).datagrid('load'); //点击搜索
},
//清空
empty: function (options) {
options = $.extend({}, { sumbit: "selectFrom", grid: "grid", tree: "tree" }, options || {});
$("#" + options.sumbit).form("reset");
$("#" + options.grid).datagrid("load");
$('#' + options.tree).find('.tree-node-selected').removeClass('tree-node-selected');
}
});

TopeveryBase

 var DirectoryManageList;
var base;
var load;
var defaultDeptId;
var tree;
$(function () {
DirectoryManageList = TopeveryBase.extend({
});
load = function (row) {
$("#LoginPassword1").textbox("setValue", row.LoginPassword);
}
base = new DirectoryManageList();
var columns = [
[
{ field: "Id", checkbox: true },
{ width: 100, title: '用户名', field: 'Name', align: 'center' },
{ width: 100, title: '登录名', field: 'LoginName', align: 'center' },
{ width: 100, title: '电话', field: 'TelNum', align: 'center' },
{
width: 100, title: '默认部门', field: 'DefaultDeptName', align: 'center'
},
{ width: 100, title: '邮件', field: 'Email', align: 'center' },
{ width: 80, title: '手机', field: 'MobileNum', align: 'center' },
{
title: '操作',
field: 'Action',
width: '15%',
align: 'center',
formatter: function (value, row, index) {
var c = ' <a href="#" class="easyui-modifyoperate" onclick="base.View(' + row.Id + ',load)">修改</a>';
var d = ' <a href="#" class="easyui-modifyoperate" onclick="base.View(' + row.Id + ',load)">部门角色权限</a>';
return c + "&nbsp"+d;
}
}
]
];
base.initGrid({ columns: columns });
$('#DefaultDeptId').combotree({
url: "/Dept/GetDeptList",
panelHeight: 'auto',
panelMaxHeight: 150,
loadFilter: function (data) {
var object = new Array;
object.push({ id: 0, text: " ", children: data, state: "0", attributes: "" });
return object;
}
}),
$('#tree').tree({
url: "/Dept/GetDeptList",
loadFilter: function (data) {
var object = new Array;
object.push({ id: 0, text: "部门树", children: data, state: "0", attributes: "" });
return object;
},
onClick: function (node) { //单击事件
defaultDeptId = node.id;
$("#defaultDeptId").val(defaultDeptId);
base.loadInfo();
}
});
});

实例Js

@using System.Web.Optimization
<div style="width: 10%; float: left; height: 100%; background-color: #fff;">
<ul id="tree"></ul>
</div>
<table style="width: 90%!important; float: left;" singleSelect="false" id="grid" url="UserR/GetListAsync"></table>
<div id="toolbarWrap">
<div class="toolbar-area">
<div class="searching-area">
<form name="selectFrom" id="selectFrom">
<table>
<tr>
<td>
<input class="easyui-textbox" style="width: 120px; height: 30px;" id="Name1" name="Name" data-options="prompt:'用户名'" />
<input class="easyui-textbox" style="width: 120px; height: 30px;" id="LoginName1" name="LoginName" data-options="prompt:'登录名'" />
<input id="defaultDeptId" name="defaultDeptId" style="display: none;" />
<a href="#" class="search-btn easyui-normalyellowbutton" onclick="base.loadInfo();">查询</a>
<a href="#" class="search-btn easyui-normalyellowbutton" onclick="base.empty();">清空</a>
</td>
</tr>
</table>
</form>
</div>
</div>
<div id="toolbar" class="toolbar operate-area-new">
<a href="#" onclick="base.View();" class="easyui-normalbluebutton">新增用户</a>
<a href="#" onclick="base.delData();" class="easyui-normalbluebutton">删除用户</a>
<input type="hidden" id="edit" name="NewModifView" url="UserW/UserAddEditAsync,UserR/GetOneAsync">
<input type="hidden" id="add" name="NewModifView" url="UserW/UserAddEditAsync">
<input type="hidden" id="delete" url="UserW/DeleteUserAsync">
</div>
</div>
<div class="easyui-dialog" title="新增" data-options="iconCls:'pag-list',modal:true,collapsible:false,minimizable:false,maximizable:false,resizable:false,closed:true" id="NewModifView" style="width: 700px; height: 380px; display: none;">
<form id="sumbitForm" name="sumbitForm">
<div class="house-lost-register-form">
<input id="Id" name="Id" style="display: none;" />
<p>
<label>用户名:</label>
<input type="text" class="easyui-textbox" maxlength="20" style="width: 215px; height: 30px;" id="Name" name="Name" required="required" missingMessage="用户名不能为空" />
<label>登录名:</label>
<input type="text" class="easyui-textbox" style="width: 215px; height: 30px;" id="LoginName" name="LoginName" required="required" missingMessage="登录名不能为空" />
</p>
<p>
<label>登录密码:</label>
<input type="text" class="easyui-textbox" style="width: 215px; height: 30px;" id="LoginPassword" name="LoginPassword" required="required" missingMessage="登录密码不能为空" />
<label>重复登录密码:</label>
<input type="text" class="easyui-textbox" style="width: 215px; height: 30px;" id="LoginPassword1" name="LoginPassword1" required="required" missingMessage="重复登录密码不能为空" validType="equalTo['#LoginPassword']" invalidMessage="两次输入密码不匹配" />
</p>
<p>
<label>默认部门:</label>
<input type="text" class="easyui-combotree" style="width: 215px; height: 30px;" id="DefaultDeptId" name="DefaultDeptId" />
<label>电话:</label>
<input type="text" class="easyui-textbox" style="width: 215px; height: 30px;" id="TelNum" name="TelNum" />
</p>
<p>
<label>邮件:</label>
<input type="text" class="easyui-textbox" style="width: 215px; height: 30px;" id="Email" name="Email" />
<label>手机:</label>
<input type="text" class="easyui-textbox" style="width: 215px; height: 30px;" id="MobileNum" name="MobileNum" />
</p>
<div style="padding-top: 20px; text-align: center;" id="ToView">
<a href="#" class="easyui-normalbluebutton" id="save">确认</a>
</div>
</div>
</form>
</div> @Scripts.Render("~/js/User/IndexTest.js")

View

如果是简单的增删改查,就能够通过简单的一个页面就可以完成了。

 /// <summary>
/// 去掉集合2中Id集合2中的数据
/// </summary>
/// <typeparam name="TF"></typeparam>
/// <returns></returns>
public IQueryable<TF> NotShorthand<TF>(List<IdInput> list, IRepository<TF> iRepository) where TF : class, IEntity<int>
{
var idlist = new int[list.Count];
for (var i = ; i < list.Count; i++)
{
idlist.SetValue(list[i].Id, i);
}
var query = from t in iRepository.GetAll()
where !(idlist).Contains(t.Id)
select t;
return query;
} /// <summary>
/// 排序 分页封装
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TF"></typeparam>
/// <returns></returns>
public async Task<PagedResultOutputDto<TF>> GetListAsync<T,TF>(IQueryable<T> query,int pageIndex,int pageCount,string sort)
{
query = !string.IsNullOrWhiteSpace(sort) ? query.OrderBy(sort) : query.OrderBy("Id desc");
var count = query.Count();
query = query.Skip((pageIndex - ) * pageCount).Take(pageCount);
var row = await query.ToListAsync();
var data = row.MapTo<List<TF>>();
return new PagedResultOutputDto<TF>(count, data);
}
 /// <summary>
/// 根据部门Id获取可以调入的人员
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public async Task<PagedResultOutputDto<UserListOutputDto>> GetNotUserAsync(DeptListInput input)
{
var query1 = (from userDept in _userDeptRepository.GetAll()
join dept in _deptRepository.GetAll() on userDept.DeptId equals dept.Id
where userDept.DeptId == input.DeptId
select new IdInput { Id = userDept.UserId }).ToList();
var query = NotShorthand(query1, _userRepository);
if (!string.IsNullOrWhiteSpace(input.Name))
{
query = query.Where(x => x.Name.Contains(input.Name));
}
var list = await GetListAsync<Zero.Core.Authorization.User, UserListOutputDto>(query, input.PageIndex, input.PageCount, input.Sorting);
return list;
}

4.最后总结是,也许我自己也不知道我的目的是什么,弄这个的意义是什么,但是做自己想做的,想到了就去做吧。

5.发现问题,然后思考问题,最后去解决这个问题!

百度云地址:http://pan.baidu.com/s/1c2cjpLm  提取码:4b66

上一篇:Android Studio 100 tips and tricks


下一篇:【Luogu】P3317重建(高斯消元+矩阵树定理)