ASP.NET MVC搭建項目後臺UI框架—七、統計報表

  1. ASP.NET MVC搭建項目後臺UI框架—一、後臺主框架
  2. ASP.NET MVC搭建項目後臺UI框架—二、菜單特效
  3. ASP.NET MVC搭建項目後臺UI框架—三、面板摺疊和展開
  4. ASP.NET MVC搭建項目後臺UI框架—四、tab多頁籤支持
  5. ASP.NET MVC搭建項目後臺UI框架—五、Demo演示Controller和View的交互
  6. ASP.NET MVC搭建項目後臺UI框架—六、客戶管理(添加、修改、查詢、分頁)
  7. ASP.NET MVC搭建項目後臺UI框架—七、統計報表
  8. ASP.NET MVC搭建項目後臺UI框架—八、將View中選擇的數據行中的部分數據傳入到Controller中
  9. ASP.NET MVC搭建項目後臺UI框架—九、服務器端排序

本節,我將經過一個Demo,演示Datatables 和ASP.NET MVC的完美結合,能夠這麼說,若是這樣的界面都能作出來,後臺系統90%的界面功能均可以開發出來了。javascript

用jquery Datatables 來開發確實是件比較蛋疼的事情(和Jquery EasyUI、MiniUI、ExtJs相比),用其它的第三方UI框架來實現相同的功能真是很是很是的簡單,但是使用Datatables倒是那麼的吃力,至少我這麼以爲,多是由於我對這個控件使用得還不夠純熟。在官網,datatables默認使用的是bootstraps的樣式,這裏我已經把樣式重寫了一部分。css

看見公司原有的系統,一樣是使用ASP.NET MVC作的,在頁面隨便點擊個東東,整個界面就刷新了,刷得我本身都受不了,更別期望固定表頭啊什麼什麼的了,徹底不存在用戶體驗啊!因而我就本身寫了UI框架(也能夠說是組裝,可是我重寫了許多東西)。html

技術點:一、服務器端分頁。二、查詢(模糊查詢)三、界面操做刷新後依舊保留當前分頁 四、固定表頭、表尾 五、動態控制列的隱藏和顯示 六、全選、反選(數據行中複選框所有選中時,全選按鈕自動選中,我發現不少程序員這個功能一直沒作,但是說是bug麼?)  七、服務器排序(功能我已經開發出來了,可是這裏我沒有寫上去,這個網上我尚未看到實現的Demo) 八、特殊字段標紅顯示 九、滑動變色 十、單擊行選中變色 ....java

先看下效果:jquery

點擊圖片,摺疊或展開列程序員

新建Reconciliation控制器ajax

using Core.CostFlow;
using Core.Filters;
using Core.Reconciliation;
using Data.Reconciliation;
using ProjectBase.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ProjectBase.Utils.Entities;

namespace Site.Controllers
{
    public class ReconciliationController : Controller
    {
        //運單對帳
        public ActionResult WayBill()
        {
            return View();
        }

        [HttpPost]
        public JsonResult WayBillList(WayBillReconciliationFilter filter)
        {
            DataTablesRequest parm = new DataTablesRequest(this.Request);    //處理對象
            int pageIndex = parm.iDisplayStart / parm.iDisplayLength;
            filter.PageIndex = pageIndex;    //頁索引
            filter.PageSize = parm.iDisplayLength;    //頁行數
            var DataSource = WayBillReconciliation.GetByFilter(filter) as WRPageOfList<WayBillReconciliation>;

            int i = parm.iDisplayLength * pageIndex;

            List<WayBillReconciliation> queryData = DataSource.ToList();
            var data = queryData.Select(u => new
           {
               Index = ++i, //行號
               ID = u.ID,
               CusName = u.CusName, //客戶簡稱
               PostingTime =u.PostingTime==null?string.Empty: u.PostingTime.Value.ToStringDate(),//收寄日期
               ExpressNo = u.ExpressNo, //郵件號
               BatchNO = u.LoadBillNum, //提單號
               Weight = u.Weight==null ? 0m : u.Weight / 100, //重量
               WayBillFee = u.WayBillFee, //郵資
               ProcessingFee = u.ProcessingFee, //郵政郵件處理費
               InComeWayBillFee = u.ExpressFee, //客戶運費
               InComeOprateFee = u.OperateFee, //客戶操做費
               WayBillMargins = u.WayBillProfit, //運費毛利
               TotalMargins = u.ExpressFee + u.OperateFee + u.InComeOtherFee-(u.WayBillFee + u.ProcessingFee + u.CostOtherFee), //總毛利
               Margin = (u.ExpressFee + u.OperateFee + u.InComeOtherFee == 0 ? 0m : (u.ExpressFee + u.OperateFee + u.InComeOtherFee - (u.WayBillFee + u.ProcessingFee + u.CostOtherFee)) / (u.ExpressFee + u.OperateFee + u.InComeOtherFee) * 100) + "%", //毛利率 毛利率=(總收入-總的支出的成本)/總收入*100% 
                           
               ReconcileDate=DateTime.Now.ToString("yyyy-MM"), //對帳日期
               CostOtherFee = u.CostOtherFee, //成本 其餘費用
               CostTotalFee = u.WayBillFee + u.ProcessingFee+u.CostOtherFee, //成本 總費用
               CostStatus = u.CostStatus.ToChinese(),  //成本 狀態
               InComeOtherFee = u.InComeOtherFee, //收入 其餘費用
               InComeTotalFee = u.ExpressFee + u.OperateFee+u.InComeOtherFee, //收入 總費用
               InComeStatus = u.InComeStatus.ToChinese(),  //收入 狀態
               TotalStatus=""
           });
            decimal totalProfit = 0m;      //總毛利求和
            //構形成Json的格式傳遞
            var result = new
            {
                iTotalRecords = DataSource.Count,
                iTotalDisplayRecords = DataSource.RecordTotal,
                data = data,
                TotalWeight = DataSource.StatModelBy.TotalWeight/100,
                TotalWayBillFee = DataSource.StatModelBy.TotalWayBillFee,
                               TotalProcessingFee = DataSource.StatModelBy.TotalProcessingFee,
                               TotalExpressFee = DataSource.StatModelBy.TotalExpressFee,
                               TotalOperateFee = DataSource.StatModelBy.TotalOperateFee,
                               SumWayBillProfit = DataSource.StatModelBy.TotalWayBillProfit,
                               SumTotalProfit = totalProfit
            };
            return Json(result, JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// 提單對帳
        /// </summary>
        /// <returns></returns>
        public ActionResult LoadBill()
        {
            return View();
        }

        public JsonResult LoadBillList()
        {
            return Json(null, JsonRequestBehavior.AllowGet);
        }
    }
}
View Code

新建WayBill視圖json

@{
    ViewBag.Title = "運費對帳";
}
<style type="text/css">
    .numberColor {
        color:red;
    }
</style>
<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 src="~/libs/My97DatePicker/WdatePicker.js"></script>
<script type="text/javascript">
    $(function () {
        var h = $(document).height() - 312;
        var table = $("#table_local").dataTable({
            bProcessing: true,
            "scrollY": h,
            "scrollCollapse": "true",
            "dom": 'tr<"bottom"lip><"clear">',
            "bServerSide": true,                    //指定從服務器端獲取數據  
            sServerMethod: "POST",
            showRowNumber:true,
            sAjaxSource: "@Url.Action("WayBillList", "Reconciliation")",
            "initComplete": function (data, args) {
                //getTotal(args);
                var arr = new Array(7,8,9,12,13,14);
                controlColumnShow(table, arr,false);
            },
            "fnServerParams": function (aoData) {  //查詢條件
                aoData.push(
                    { "name": "CusShortName", "value": $("#CusShortName").val() },
                    { "name": "LoadBillNum", "value": $("#LoadBillNum").val() },
                    { "name": "ExpressNo", "value": $("#ExpressNo").val() },
                    { "name": "PostingTime", "value": $("#PostingTime").val() },
                    { "name": "PostingTimeTo", "value": $("#PostingTimeTo").val() }
                    // ,{ "name": "PostingTimeTo", "value": $("#sltMargin").val() }
                     );
            },
            //跟數組下標同樣,第一列從0開始,這裏表格初始化時,第四列默認降序
            "order": [[ 2, "asc" ]],
            columns: [
               {
                   "data": "ID", orderable: false,
                   "render": function (data, type, row, meta) {
                       return " <input id='cbx" + data + "' type='checkbox' onclick='controlSelectAll(" + data + ")' class='cbx' value='" + data + "'/>  " + row.Index;
                   }
               },                                                      
                { "data": "ReconcileDate",visible:false},//對帳日期
                { "data": "CusName" }, //客戶名稱
                { "data": "PostingTime"},//收寄日期
                { "data": "ExpressNo", orderable: false }, //郵件號
                { "data": "BatchNO"},//提單號
                { "data": "Weight"},//重量
                { "data": "WayBillFee"},//郵政郵資
                { "data": "ProcessingFee" },//郵政郵件處理費
                { "data": "CostOtherFee"},//其它費用
                { "data": "CostTotalFee" },//總成本
                { "data": "CostStatus", orderable: false },//狀態
                { "data": "InComeWayBillFee" },//客戶運費
                { "data": "InComeOprateFee"},//客戶操做費
                { "data": "InComeOtherFee"},//其它費用
                { "data": "InComeTotalFee" },//總收入
                { "data": "InComeStatus", orderable: false },//狀態
                 {
                     "data": "WayBillMargins", orderable: false, "render": function (data, type, row, meta) { //運費毛利
                         var css = "";
                         if (data < 0) {
                             css=" class='numberColor'";
                         }
                         var re = "<div"+css+">"+data+"</div>";
                         return re;
                     }
                 },
                  {
                      "data": "TotalMargins", orderable: false, "render": function (data, type, row, meta) { //總毛利
                          var css = "";
                          if (data < 0) {
                              css = " class='numberColor'";
                          }
                          var re = "<div" + css + ">" + data + "</div>";
                          return re;
                      }
                  },
                { "data": "Margin", orderable: false },//毛利率
                { "data": "TotalStatus", orderable: false },
                 {
                     "data": "ID", orderable: false, width: "80", "render": function (data, type, row, meta) { //操做
                         var re = "<div style='text-align:center'><a style='visibility:visible' onclick='openDetail(" + data + ")'>詳情</a>&nbsp;&nbsp;";
                         return re;
                     }
                 }
            ],
            paging: true,//分頁
            ordering: true,//是否啓用排序
            searching: true,//搜索
            language: {
                "sProcessing": "處理中...",
                lengthMenu: '每頁顯示:<select class="form-control input-xsmall">' + '<option value="10">10</option>' + '<option value="20">20</option>' + '<option value="30">30</option>'
                    + '<option value="50">50</option>' + '<option value="100">100</option>' + '<option value="150">150</option>' + '<option value="200">200</option>' + '<option value="250">250</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');
            }
        });
        //展開摺疊列
        $("#imgIncome").click(function () {
            var url = $("#imgIncome").attr("src");
            var arr = new Array(7, 8, 9);
            if (url == "/images/icon_9.png") {
                controlColumnShow(table, arr, true);
                $("#imgIncome").attr("src", "/images/icon_10.png");
            }
            else {
                controlColumnShow(table, arr, false);
                $("#imgIncome").attr("src", "/images/icon_9.png");
            }
            
        });
        //收入展開摺疊
        $("#imgCost").click(function () {
            var url = $("#imgCost").attr("src");
            var arr = new Array(12, 13, 14);
            if (url == "/images/icon_9.png") {
                controlColumnShow(table, arr, true);
                $("#imgCost").attr("src", "/images/icon_10.png");
            }
            else {
                controlColumnShow(table, arr, false);
                $("#imgCost").attr("src", "/images/icon_9.png");
            }
        });
    });
    function reloadList() {
        var tables = $('#table_local').dataTable().api();//獲取DataTables的Api,詳見 http://www.datatables.net/reference/api/
        tables.ajax.reload(function () {
            var json = tables.context[0].json;
            getTotal(json);
        }, false);
    }
    //統計
    function getTotal(json) {
        if (json) {
            if (json.TotalWeight) {
                $("#spnTotalWeight").html(json.TotalWeight);
                $("#spnTotalWayBillFee").html(json.TotalWayBillFee);
                $("#spnTotalProcessingFee").html(json.TotalProcessingFee);
                $("#spnTotalExpressFee").html(json.TotalExpressFee);
                $("#spnTotalOperateFee").html(json.TotalOperateFee);
                $("#spnSumWayBillProfit").html(json.SumWayBillProfit);
                $("#spnSumTotalProfit").html(json.SumTotalProfit);
            }
        }
    }
    //控制指定定列的隱藏和顯示(table,列索引數組,隱藏or顯示:true,false)
    function controlColumnShow(table, arr,tag) {
        for (var i = 0; i < arr.length; i++) {
            table.fnSetColumnVis(arr[i],tag);
        }
    }
</script>
<div class="areabx clear">
    @using (Html.BeginForm("List", null, FormMethod.Get, new { @clase = "form-inline", @role = "form" }))
    {
        <div class="areabx_header">@ViewBag.Title</div>
        <ul class="formod mgt10">
            <li><span>客戶簡稱:</span>@Html.TextBox("CusShortName","",new { @class = "trade-time wid153" })</li>
            <li><span>提單號:</span>@Html.TextBox("LoadBillNum","", new { @class = "trade-time" })</li>
        </ul>
        <ul class="formod mgt10">
            <li><span>運單號:</span>@Html.TextBox("ExpressNo","", new { @class = "trade-time wid153" })</li>
            <li><span>收寄日期:</span>@Html.TextBox("PostingTime", "", new { @class = "trade-time wid153", @onClick = "WdatePicker({maxDate:'#F{$dp.$D(\\'PostingTimeTo\\')}'})" })</li>
            <li><span style="text-align:left;width:25px;margin-left:-20px;"></span>  @Html.TextBox("PostingTimeTo", "", new { @class = "trade-time wid153", @onClick =  "WdatePicker({minDate:'#F{$dp.$D(\\'PostingTime\\')}'})"  })</li>
            <li><span>毛利:</span><select class="trade-time" id="sltMargin"><option value="" selected="selected">所有</option><option value="+">+</option><option value="-">-</option></select></li>
        </ul>
        <div class="botbtbx pdb0">
            <input type="button" value="查詢" id="btnSearch" 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%">
            <thead>
                <tr>
                    <th rowspan="2">
                     <input type='checkbox' id='chkAllColl' onclick='selectAll()' />序號</th>
                    <th rowspan="2">對帳日期</th>
                    <th rowspan="2">客戶簡稱</th>
                    <th rowspan="2">收寄日期</th>
                    <th rowspan="2">郵件號</th>
                    <th rowspan="2">提單號</th>
                    <th rowspan="2">重量(kg)</th>
                    <th colspan="5"><span>成本</span><span class="divIncome1"><img id="imgIncome" src="/images/icon_9.png"  alt="收起/展開"/></span></th>
                    <th colspan="5"><span>收入</span><span class="divIncome1"><img id="imgCost" src="/images/icon_9.png" alt="收起/展開"/></span></th>
                    <th colspan="3">毛利</th>
                    <th rowspan="2">狀態</th>
                    <th rowspan="2">操做</th>
                </tr>
                <tr>
                    <th>郵政郵資</th>
                    <th>郵政郵件處理費</th>
                    <th>其它費用</th>
                    <th>總成本</th>
                    <th>狀態</th>
                    <th>客戶運費</th>
                    <th>客戶操做費</th>
                    <th>其它費用</th>
                    <th>總收入</th>
                    <th>狀態</th>
                    <th>運費毛利</th>
                    <th>總毛利</th>
                    <th>毛利率</th>
                </tr>
            </thead>
            <tfoot>
                <tr>
                    <td>總計</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td><span id="spnTotalWeight"></span></td>
                    <td><span id="spnTotalWayBillFee"></span></td>
                    <td><span id="spnTotalProcessingFee"></span></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td><span id="spnTotalExpressFee"></span></td>
                    <td><span id="spnTotalOperateFee"></span></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td><span id="spnSumWayBillProfit"></span></td>
                    <td><span id="spnSumTotalProfit"></span></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
            </tfoot>
        </table>
    </div>
</div>
View Code

這裏面  table.fnSetColumnVis(arr[i], tag);這行代碼控制列動態隱藏和展現的時候,會從新加載數據,能夠在後面加一個false參數,取消刷新。 如: table.fnSetColumnVis(arr[i], tag,false);bootstrap

請求參數封裝類DataTablesRequest,這個類是從冠軍的博客下載的,它主要用於解析datatables的請求參數,因爲datatables支持多列排序,因此比較複雜。下載的這個類有點問題,那就是獲取的排序方式一直是asc,因而我進行了修改,修改後的代碼以下:api

/* ==============================================================================
   * 功能描述:DataTablesRequest  
   * 創 建 者:Zouqj
   * 建立日期:2015/4/21 17:47:35
   ==============================================================================*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ProjectBase.Utils
{
    // 排序的方向
    public enum SortDirection
    {
        Asc,    // 升序
        Desc    // 降序
    }

    // 排序列的定義
    public class SortColumn
    {
        public int Index { get; set; }                  // 列序號
        public SortDirection Direction { get; set; }    // 列的排序方向
    }

    // 列定義
    public class Column
    {
        public string Name { get; set; }        // 列名
        public bool Sortable { get; set; }      // 是否可排序
        public bool Searchable { get; set; }    // 是否可搜索
        public string Search { get; set; }      // 搜索串
        public bool EscapeRegex { get; set; }   // 是否正則
    }

    public class DataTablesRequest
    {
        private HttpRequestBase request;        // 內部使用的 Request 對象

        public DataTablesRequest(System.Web.HttpRequestBase request)    // 用於 MVC 模式下的構造函數
        {
            this.request = request;

            this.echo = this.ParseStringParameter(sEchoParameter);
            this.displayStart = this.ParseIntParameter(iDisplayStartParameter);
            this.displayLength = this.ParseIntParameter(iDisplayLengthParameter);
            this.sortingCols = this.ParseIntParameter(iSortingColsParameter);

            this.search = this.ParseStringParameter(sSearchParameter);
            this.regex = this.ParseStringParameter(bRegexParameter) == "true";

            // 排序的列
            int count = this.iSortingCols;
            this.sortColumns = new SortColumn[count];
            for (int i = 0; i < count; i++)
            {
                SortColumn col = new SortColumn();
                col.Index = this.ParseIntParameter(string.Format("iSortCol_{0}", i));

                if (this.ParseStringParameter(string.Format("sSortDir_{0}", i)) == "desc")
                {
                    col.Direction = SortDirection.Desc;
                }
                else
                {
                    col.Direction = SortDirection.Asc;
                }
                this.sortColumns[i] = col;
            }

            this.ColumnCount = this.ParseIntParameter(iColumnsParameter);

            count = this.ColumnCount;
            this.columns = new Column[count];

            if(this.ParseStringParameter(sColumnsParameter)==null||!this.ParseStringParameter(sColumnsParameter).Contains(','))
            {
                   return;
            }
            string[] names = this.ParseStringParameter(sColumnsParameter).Split(',');

            for (int i = 0; i < count; i++)
            {
                Column col = new Column();
                col.Name = names[i];
                col.Sortable = this.ParseStringParameter(string.Format("bSortable_{0}", i)) == "true";
                col.Searchable = this.ParseStringParameter(string.Format("bSearchable_{0}", i)) == "true";
                col.Search = this.ParseStringParameter(string.Format("sSearch_{0}", i));
                col.EscapeRegex = this.ParseStringParameter(string.Format("bRegex_{0}", i)) == "true";
                columns[i] = col;
            }
        }
        public DataTablesRequest(HttpRequest httpRequest)       // 標準的 WinForm 方式下的構造函數
            : this(new HttpRequestWrapper(httpRequest))
        { }

        #region
        private const string sEchoParameter = "sEcho";

        // 起始索引和長度
        private const string iDisplayStartParameter = "iDisplayStart";
        private const string iDisplayLengthParameter = "iDisplayLength";

        // 列數
        private const string iColumnsParameter = "iColumns";
        private const string sColumnsParameter = "sColumns";

        // 參與排序列數
        private const string iSortingColsParameter = "iSortingCols";
        private const string iSortColPrefixParameter = "iSortCol_";         // 排序列的索引
        private const string sSortDirPrefixParameter = "sSortDir_";         // 排序的方向 asc, desc

        // 每一列的可排序性
        private const string bSortablePrefixParameter = "bSortable_";

        // 全局搜索
        private const string sSearchParameter = "sSearch";
        private const string bRegexParameter = "bRegex";

        // 每一列的搜索
        private const string bSearchablePrefixParameter = "bSearchable_";
        private const string sSearchPrefixParameter = "sSearch_";
        private const string bEscapeRegexPrefixParameter = "bRegex_";
        #endregion

        private readonly string echo;
        public string sEcho
        {
            get { return echo; }
        }

        private readonly int displayStart;
        public int iDisplayStart
        {
            get { return this.displayStart; }
        }

        private readonly int displayLength;
        public int iDisplayLength
        {
            get { return this.displayLength; }
        }

        // 參與排序的列
        private readonly int sortingCols;
        public int iSortingCols
        {
            get { return this.sortingCols; }
        }

        // 排序列
        private readonly SortColumn[] sortColumns;
        public SortColumn[] SortColumns
        {
            get { return sortColumns; }
        }

        private readonly int ColumnCount;
        public int iColumns
        {
            get { return this.ColumnCount; }
        }

        private readonly Column[] columns;
        public Column[] Columns
        {
            get { return this.columns; }
        }

        private readonly string search;
        public string Search
        {
            get { return this.search; }
        }

        private readonly bool regex;
        public bool Regex
        {
            get { return this.regex; }
        }

        #region 經常使用的幾個解析方法
        private int ParseIntParameter(string name)          // 解析爲整數
        {
            int result = 0;
            string parameter = this.request[name];
            if (!string.IsNullOrEmpty(parameter))
            {
                int.TryParse(parameter, out result);
            }
            return result;
        }

        private string ParseStringParameter(string name)    // 解析爲字符串
        {
            return this.request[name];
        }

        private bool ParseBooleanParameter(string name)     // 解析爲布爾類型
        {
            bool result = false;
            string parameter = this.request[name];
            if (!string.IsNullOrEmpty(parameter))
            {
                bool.TryParse(parameter, out result);
            }
            return result;
        }
        #endregion
    }
}
View Code

本篇我不想作過多的說明,我寫了很是詳實的註釋,並且代碼很是通俗易懂,界面的功能仍是很是強大的,我相信,從這些犀利的代碼中,你必定會獲益良多。

相關文章
相關標籤/搜索