目录
- ASP.NET MVC搭建项目后台UI框架—1、后台主框架
- ASP.NET MVC搭建项目后台UI框架—2、菜单特效
- ASP.NET MVC搭建项目后台UI框架—3、面板折叠和展开
- ASP.NET MVC搭建项目后台UI框架—4、tab多页签支持
- ASP.NET MVC搭建项目后台UI框架—5、Demo演示Controller和View的交互
- ASP.NET MVC搭建项目后台UI框架—6、客户管理(添加、修改、查询、分页)
- ASP.NET MVC搭建项目后台UI框架—7、统计报表
- ASP.NET MVC搭建项目后台UI框架—8、将View中选择的数据行中的部分数据传入到Controller中
- ASP.NET MVC搭建项目后台UI框架—9、服务器端排序
接着之前未写完的继续,本篇,我将讲解在此UI框架中和ASP.NET MVC4进行结合开发。效果如下:
这里,我将添加和修改用了两个不同的视图,当然也可以把添加和修改放到同一个视图中,但是要写一些业务逻辑代码来区分当前调用的是修改还是添加,根据添加和修改的不同,而对界面进行不同的操作。
添加控制器Customer,关于更新操作,我就不得不想吐槽一下NHibernate,他妹的,每次都要先load一次,然后再Update()一次,如果你直接save,它就把你表中有,但是界面上没有传过来的值全部更新为null了,相比之下EF就好多了。
public class CustomerController : Controller
{
private string message = "<script>frameElement.api.opener.hidePublishWin('{0}', '{1}','{2}'); </script>"; //消息,是否关闭弹出窗,是否停留在当前分页(0,1)
#region 客户管理主页
public ActionResult Index()
{
return View();
}
/// <summary>
/// 客户列表
/// </summary>
/// <param name="filter"></param>
/// <returns></returns>
[HttpPost]
public JsonResult List(CustomerFilter filter)
{
filter.PageSize = int.MaxValue;
var dataSource = CustomerInfo.GetByFilter(filter);
List<CustomerInfo> queryData = dataSource.ToList();
var data = queryData.Select(u => new
{
ID = u.ID,
CusCode = u.CusCode,
CusName = u.CusName,
BusssinessType = u.BusssinessType.GetDescription(false),
Balance = u.Balance,
CreditAmount = u.CreditAmount,
Status = u.Status.GetDescription(false),
Country = u.Country,
CompanyName = u.CompanyName,
Delivery = GetDeliveryList(u.ExpressCurInfoBy)
});
//构造成Json的格式传递
var result = new { iTotalRecords = queryData.Count, iTotalDisplayRecords = 10, data = data };
return Json(result, JsonRequestBehavior.AllowGet);
}
#region 添加客户
/// <summary>
/// 添加客户
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public ActionResult AddCustomer()
{
ViewBag.Title = "添加客户";
return View();
}
/// <summary>
/// 添加客户
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
[HttpPost]
public ActionResult AddCustomer(CustomerInfo info)
{
string msg = string.Empty;
if (ModelState.IsValid)
{
try
{
info.Save();
msg = "添加客户成功。";
}
catch (Exception ex)
{
msg = "添加客户失败!" + ex.Message;
ViewBag.Msg = string.Format(message, msg, false,"0");
}
ViewBag.Msg = string.Format(message, msg, true,"0");
}
return View();
}
#endregion
#region 修改客户
/// <summary>
/// 修改客户
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public ActionResult UpdateCustomer(int id)
{
ViewBag.Title = "修改客户";
var result = CustomerInfo.Load(id);
return View(result);
}
/// <summary>
/// 修改客户
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
[HttpPost]
public ActionResult UpdateCustomer(CustomerInfo info)
{
string msg = string.Empty;
if (ModelState.IsValid)
{
try
{
info.Update();
msg = "修改客户成功。";
}
catch (Exception ex)
{
msg = "修改客户失败!" + ex.Message;
ViewBag.Msg = string.Format(message, msg, false,"1");
}
ViewBag.Msg = string.Format(message, msg, true,"1");
}
return View();
}
#endregion
}
添加视图Index
@{
ViewBag.Title = "客户信息";
}
<link href="~/libs/DataTables-1.10.6/media/css/jquery.dataTablesNew.css" rel="stylesheet" />
<script src="~/libs/DataTables-1.10.6/media/js/jquery.dataTables.min.js"></script>
<script src="~/Scripts/DataTablesExt.js"></script>
<script type="text/javascript">
//弹出框
var addDG, updateDG, matchDG;
var w = 424, h = 520; //宽,高
//添加记录
function showPublishWin() {
addDG = new $.dialog({
id: "AddChannel",
title: "添加客户",
content: "url:/Customer/AddCustomer",
width: w,
height: h,
max: false,
min: false,
lock: true,
close: true,
btnBar: false
});
addDG.show();
}
//修改记录
function modifyRecord(id) {
updateDG = new $.dialog({
id: "UpdateCustomer",
title: "修改客户",
content: "url:/Customer/UpdateCustomer/" + id,
width: w,
height: h,
max: false,
min: false,
lock: true,
close: true,
btnBar: false
});
updateDG.show();
}
//隐藏弹出框
function hidePublishWin(msg, result, isStay) {
var icon = "success.gif";
if (result == "False") {
icon = "error.gif";
}
$.dialog({
title: "提示",
icon: icon,
titleIcon: 'lhgcore.gif',
content: msg,
lock: true,
ok: true
});
if (result != "False") {
if (addDG) {
addDG.close();
}
if (updateDG) {
updateDG.close();
}
if (matchDG) {
matchDG.close();
}
if (isStay == 0) {
reloadList();
}
else {
reloadListNew();
}
}
}
function matchDelivery(id) {
matchDG = new $.dialog({
id: "UpdateCustomer",
title: "客户匹配",
content: "url:/Customer/DeliveryMatching/" + id,
width: 800,
height: h,
max: false,
min: false,
lock: true,
close: true,
btnBar: false
});
matchDG.show();
}
//刷新,但是停留在当前分页
function reloadListNew() {
var tables = $('#table_local').dataTable().api();//获取DataTables的Api,详见 http://www.datatables.net/reference/api/
tables.ajax.reload(null,false);
}
</script>
<script type="text/javascript">
$(function () {
var h = $(document).height() - 258;
var table = $("#table_local").dataTable({
bProcessing: true,
"scrollY": h,
"scrollCollapse": "true",
"dom": 'ftr<"bottom"lip><"clear">',
"bServerSide": false, //指定从服务器端获取数据
sServerMethod: "POST",
sAjaxSource: "@Url.Action("List", "Customer")",
"fnServerParams": function (aoData) { //查询条件
aoData.push(
{ "name": "CusCode", "value": $("#CusCode").val() },
{ "name": "CusName", "value": $("#CusName").val() }
);
},
columns: [{ title: "1", "visible": false, "data": "ID" },
{ "data": "CusCode", title: "客户代码" },
{ "data": "CusName", title: "客户名称" },
{ "data": "BusssinessType", title: "业务类型", width: "100" },
{ "data": "Country", title: "国家", width: "200" },
{ "data": "CompanyName", title: "公司名称", width: "200" },
{ "data": "Delivery", title: "收货商", width: "150" },
{ "data": "Balance", title: "账户余额", width: "150" },
{ "data": "CreditAmount", title: "信用额度", width: "150" },
{ "data": "Status", title: "是否启用", width: "100" },
{
"data": "ID", orderable: false, title: "操作", width: "140", "render": function (data, type, row, meta) { //自定义列
var re = "<div style='text-align:center'><a style='visibility:visible' onclick='modifyRecord(" + data + ")'>修改</a> ";
re = re + "<a style='visibility:visible' onclick='matchDelivery(" + data + ")'>匹配</a></div>";
return re;
}
}
],
paging: true,//分页
ordering: true,//是否启用排序
searching: true,//搜索
language: {
"sProcessing": "处理中...",
lengthMenu: '每页显示:<select class="form-control input-xsmall">' + '<option value="5">5</option>' + '<option value="10">10</option>' + '<option value="15">15</option>'
+ '<option value="20">20</option>' + '<option value="25">25</option>' + '<option value="30">30</option>' + '<option value="35">35</option>' + '<option value="40">40</option>',//左上角的分页大小显示。
search: '<span class="label label-success">搜索:</span>',//右上角的搜索文本,可以写html标签
paginate: {//分页的样式内容。
previous: "上一页",
next: "下一页",
first: "",
last: ""
},
zeroRecords: "暂无记录",//table tbody内容为空时,tbody的内容。
//下面三者构成了总体的左下角的内容。
info: "总共 <span class='pagesStyle'>(_PAGES_) </span>页,显示 _START_ -- _END_ ,共<span class='recordsStyle'> (_TOTAL_)</span> 条",//左下角的信息显示,大写的词为关键字。初始_MAX_ 条
infoEmpty: "0条记录",//筛选为空时左下角的显示。
infoFiltered: ""//筛选之后的左下角筛选提示,
},
pagingType: "full_numbers"//分页样式的类型
});
//设置选中行样式
$('#table_local tbody').on('click', 'tr', function () {
if ($(this).hasClass('selected')) {
$(this).removeClass('selected');
}
else {
table.$('tr.selected').removeClass('selected');
$(this).addClass('selected');
}
});
});
//查询 刷新
function reloadList() {
var tables = $('#table_local').dataTable().api();//获取DataTables的Api,详见 http://www.datatables.net/reference/api/
tables.ajax.reload();
}
</script>
<div class="areabx clear">
@using (Html.BeginForm("List", null, FormMethod.Get, new { @clase = "form-inline", @role = "form" }))
{
<div class="areabx_header">客户信息</div>
<ul class="formod mgt10">
<li><span>客户代码:</span>@Html.TextBox("CusCode", "", new { @class = "trade-time wid153" })</li>
<li><span>客户名称:</span>@Html.TextBox("CusName", "", new { @class = "trade-time" })</li>
<li></li>
</ul>
<div class="botbtbx pdb0" style="margin-bottom: -30px;">
<input type="button" value="添加客户" class="btn btn-primary" onclick="showPublishWin()" />
<input type="button" value="查询" onclick="reloadList();" class="btn btn-primary">
</div>
}
<div class="tob_box mgt15">
<table id="table_local" class="display" cellspacing="0" cellpadding="0" border="0" style="width: 100%">
</table>
</div>
</div>
添加AddCustomer视图,之前公司ASP.NET MVC的项目没有启用模型验证,界面验证代码都是自己js写的,我晕,那用ASP.NET MVC干嘛呢?使用框架就是要充分发挥框架优良的功能,尽可能高效快速的开发,并减少开发人员的代码量。
@model Core.Customer.CustomerInfo
@using ProjectBase.Utils
@Html.Raw(ViewBag.Msg)
<div class="areabx clear">
@* <div class="areabx_header">@ViewBag.Title</div>*@
<div class="tian_xi">
@using (Html.BeginForm("AddCustomer", "Customer", FormMethod.Post, new { @clase = "form-inline", @role = "form", name = "from1" }))
{
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr style="height: 40px;">
<td style="width: 120px; text-align: right;">客户代码:</td>
<td>
@Html.TextBoxFor(x => x.CusCode, new { @class = "trade-timen", @id = "cusCode" })<span class="wtps">* @Html.ValidationMessageFor(m => m.CusCode)</span></td>
</tr>
<tr style="height: 40px;">
<td align="right">客户名称:</td>
<td>
@Html.TextBoxFor(x => x.CusName, new { @class = "trade-timen", @id = "cusName" })<span class="wtps">* @Html.ValidationMessageFor(m => m.CusName)</span></td>
</tr>
<tr style="height: 40px;">
<td align="right">手机:</td>
<td>
@Html.TextBoxFor(x => x.Phone, new { @class = "trade-timen" })</td>
</tr>
<tr style="height: 40px;">
<td align="right">电话:</td>
<td>
@Html.TextBoxFor(x => x.Tel, new { @class = "trade-timen" })</td>
</tr>
<tr style="height: 40px;">
<td align="right">邮箱:</td>
<td>
@Html.TextBoxFor(x => x.Email, new { @class = "trade-timen", @id = "email" })<span class="wtps">@Html.ValidationMessageFor(m => m.Email)</span></td>
</tr>
<tr style="height: 40px;">
<td align="right">传真:</td>
<td>
@Html.TextBoxFor(x => x.Fax, new { @class = "trade-timen" })</td>
</tr>
<tr style="height: 40px;">
<td align="right">国家:</td>
<td>
@Html.TextBoxFor(x => x.Country, new { @class = "trade-timen" })</td>
</tr>
<tr style="height: 40px;">
<td align="right">地址:</td>
<td>
@Html.TextBoxFor(x => x.Address, new { @class = "trade-timen" })</td>
</tr>
<tr style="height: 40px;">
<td align="right">公司名称:</td>
<td>
@Html.TextBoxFor(x => x.CompanyName, new { @class = "trade-timen" })</td>
</tr>
<tr style="height: 40px;">
<td align="right">业务类型:</td>
<td>
@Html.DropDownListFor(x => x.BusssinessType, @Html.EnumToList(typeof(Core.Customer.Busssiness), false), new { @class = "trade-timen", style = "width:180px" })
</tr>
<tr style="height: 40px;">
<td align="right">是否启用:</td>
<td>是 @Html.RadioButtonFor(x => x.Status, "0", new { Checked = "checked", @name = "status" })
<span class="radioMagin">否 @Html.RadioButtonFor(x => x.Status, "1", new { @name = "status" })</span></td>
</tr>
</tbody>
</table>
<input type="submit" value="确定" class="popbtn1 mg">
<input type="button" value="关闭" class="popbtn3 mg2" onclick="frameElement.api.opener.addDG.close();" />
}
</div>
</div>
添加UpdateCustomer视图
@model Core.Customer.CustomerInfo
@using ProjectBase.Utils
@Html.Raw(ViewBag.Msg)
<div class="areabx clear">
@* <div class="areabx_header">@ViewBag.Title</div>*@
<div class="tian_xi">
@using (Html.BeginForm("UpdateCustomer", "Customer", FormMethod.Post, new { @clase = "form-inline", @role = "form", name = "from1" }))
{
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr style="height: 40px;">
<td style="width: 120px; text-align: right;">客户代码:</td>
<td>
@Html.TextBoxFor(x => x.CusCode, new { @class = "trade-timen", @id = "cusCode", @readOnly = "readOnly" })<span class="wtps">* @Html.ValidationMessageFor(m => m.CusCode)</span></td>
@Html.HiddenFor(x => x.ID)
</tr>
<tr style="height: 40px;">
<td align="right">客户名称:</td>
<td>
@Html.TextBoxFor(x => x.CusName, new { @class = "trade-timen", @id = "cusName" })<span class="wtps">* @Html.ValidationMessageFor(m => m.CusName)</span></td>
</tr>
<tr style="height: 40px;">
<td align="right">手机:</td>
<td>
@Html.TextBoxFor(x => x.Phone, new { @class = "trade-timen" })</td>
</tr>
<tr style="height: 40px;">
<td align="right">电话:</td>
<td>
@Html.TextBoxFor(x => x.Tel, new { @class = "trade-timen" })</td>
</tr>
<tr style="height: 40px;">
<td align="right">邮箱:</td>
<td>
@Html.TextBoxFor(x => x.Email, new { @class = "trade-timen", @id = "email" }) <span class="wtps">@Html.ValidationMessageFor(m => m.Email)</span></td>
</tr>
<tr style="height: 40px;">
<td align="right">传真:</td>
<td>
@Html.TextBoxFor(x => x.Fax, new { @class = "trade-timen" })</td>
</tr>
<tr style="height: 40px;">
<td align="right">国家:</td>
<td>
@Html.TextBoxFor(x => x.Country, new { @class = "trade-timen" })</td>
</tr>
<tr style="height: 40px;">
<td align="right">地址:</td>
<td>
@Html.TextBoxFor(x => x.Address, new { @class = "trade-timen" })</td>
</tr>
<tr style="height: 40px;">
<td align="right">公司名称:</td>
<td>
@Html.TextBoxFor(x => x.CompanyName, new { @class = "trade-timen" })</td>
</tr>
<tr style="height: 40px;">
<td align="right">业务类型:</td>
<td>
@Html.DropDownListFor(x => x.BusssinessType, @Html.EnumToList(typeof(Core.Customer.Busssiness), false), new { @class = "trade-timen", style = "width:180px" })
</tr>
<tr style="height: 40px;">
<td align="right">是否启用:</td>
<td>是 @Html.RadioButtonFor(x => x.Status, "0", new { Checked = "checked", @name = "status" })
<span class="radioMagin">否 @Html.RadioButtonFor(x => x.Status, "1", new { @name = "status" })</span></td>
</tr>
</tbody>
</table>
<input type="submit" value="确定" class="popbtn1 mg">
<input type="button" value="关闭" class="popbtn3 mg2" onclick="frameElement.api.opener.updateDG.close();" />
}
</div>
</div>
客户实体CustomerInfo
/// <summary>
/// 客户信息
/// </summary>
public class CustomerInfo //: DomainObject<CustomerInfo, int, ICustomerInfoRepository>
{
#region property
/// <summary>
/// 客户代码
/// </summary>
[Required(ErrorMessage = "客户代码不能为空!")]
[StringLength(30, MinimumLength = 0, ErrorMessage = "客户代码最大长度为30个字符")]
public virtual string CusCode { get; set; }
/// <summary>
/// 客户名称
/// </summary>
[Required(ErrorMessage = "客户名称不能为空!")]
[StringLength(30, MinimumLength = 0, ErrorMessage = "客户名称最大长度为30个字符")]
public virtual string CusName { get; set; }
/// <summary>
/// 客户业务类型
/// </summary>
public virtual Busssiness BusssinessType { get; set; }
/// <summary>
/// 手机
/// </summary>
public virtual string Phone { get; set; }
/// <summary>
/// 电话
/// </summary>
public virtual string Tel { get; set; }
/// <summary>
/// 邮箱
/// </summary>
[RegularExpression(@"^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$", ErrorMessage="邮箱格式不正确!")]
public virtual string Email { get; set; }
/// <summary>
/// 传真
/// </summary>
public virtual string Fax { get; set; }
/// <summary>
/// 国家
/// </summary>
public virtual string Country { get; set; }
/// <summary>
/// 地址
/// </summary>
public virtual string Address { get; set; }
/// <summary>
/// 公司名称
/// </summary>
public virtual string CompanyName { get; set; }
/// <summary>
/// 金额
/// </summary>
public virtual decimal Balance { get; set; }
/// <summary>
/// 信用额度
/// </summary>
public virtual decimal CreditAmount { get; set; }
/// <summary>
/// 状态
/// </summary>
public virtual CustomerStatus Status { get; set; }
/// <summary>
/// 快件收货商信息
/// </summary>
public virtual IList<ExpressCurInfo> ExpressCurInfoBy { get; set; }
#endregion
#region common method
/// <summary>
/// 分页获取数据
/// </summary>
/// <param name="filter"></param>
/// <returns></returns>
public static IPageOfList<CustomerInfo> GetByFilter(CustomerFilter filter)
{
return Dao.GetByFilter(filter);
}
#endregion
}
查询类CustomerFilter
public class CustomerFilter : ParameterFilter
{
/// <summary>
/// 客户代码
/// </summary>
public virtual string CusCode { get; set; }
/// <summary>
/// 客户名称
/// </summary>
public virtual string CusName { get; set; }
/// <summary>
/// 生产NHQL查询语句
/// </summary>
/// <returns></returns>
public override string ToHql()
{
string hql = "";
if (!string.IsNullOrEmpty(CusCode))
{
hql += " and Cus_Code =:CusCode ";
}
if (!string.IsNullOrEmpty(CusName))
{
hql += " and Cus_Name =:CusName ";
}
return hql;
}
/// <summary>
/// 构造查询参数
/// </summary>
/// <returns></returns>
public override Dictionary<string, object> GetParameters()
{
var result = new Dictionary<string, object>();
if (!string.IsNullOrEmpty(CusCode))
{
result["CusCode"] = CusCode.Trim();
}
if (!string.IsNullOrEmpty(CusName))
{
result["CusName"] = CusName.Trim();
}
return result;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProjectBase.Utils.Entities;
namespace ProjectBase.Data
{
public abstract class ParameterFilter
{
public ParameterFilter()
{
HasQueryString = false;
PageSize = 10;
}
public string OrderBy { get;set; }
public abstract string ToHql();
public override string ToString()
{
return ToHql();
}
public abstract Dictionary<string, object> GetParameters();
public string GetOrderString()
{
if (OrderBy.HasValue())
return " Order By " + OrderBy;
return String.Empty;
}
protected string GetLike(string value)
{
return "%" + value + "%";
}
public int PageIndex { get; set; }
public int PageSize { get; set; }
/// <summary>
/// 标识此构造器是包含全部查询语句。
/// 若为 False,则ToHql() 只需要构造条件查询,系统会自动在前面加上<code>" from " + typeof(T).Name + " a where 1=1 "</code>
/// 若为 True, ToHql() 需要返回 连form在类的完整Hql语句
/// </summary>
public bool HasQueryString { get; set; }
protected static bool HasValue(string str)
{
return str.HasValue();
}
public static bool HasValue<T>(System.Nullable<T> value) where T:struct
{
return value.HasValue;
}
}
}
在这里,我只演示了控制器和视图的交互,至于Hhibernate和Unity等数据的操作,这里暂时不讲,因为你也可以使用其它的ORM框架和IOC框架,诸如EF、AutoFac等等。这里主要讲解jquery datatables和ASP.NET MVC的结合使用,但是这里只演示了客户端分页排序,后面我会讲服务器分页排序。我发现,网上都没有ASP.NET MVC和Datatables结合的完整的服务器分页、排序的Demo,只看到PHP的。于是我不断的尝试,皇天不负有心人,终于试验成功了,后面我会为大家讲述实现方式。