.Net MVC&&datatables.js&&bootstrap作一個界面的CRUD有多簡單

    咱們在項目開發中,作得最多的可能就是CRUD,那麼咱們如何在ASP.NET MVC中來作CRUD呢?若是說只是單純實現功能,那天然是再簡單不過了,但是咱們要考慮如何來作得比較好維護比較好擴展,如何作得比較漂亮。作開發要有工匠精神,不要只求完成開發任務,那樣的話,永遠停留在只是簡單的寫業務邏輯代碼水平,咱們要作有追求的程序員。原本這麼簡單的東西,我真是懶得寫,可是看到即使是一些工做了好些年的人,作東西也是隻管實現功能,啥都無論,還有些界面css樣式要麼就硬編要麼就毫無規則的在頁面中進行穿插,遇到要設置間距甚至直接寫多個 ,我以爲仍是要寫出來給那些人看下。硬編的前提是隻有你這一個界面使用。php

    咱們先來看下咱們要實現的效果,功能須要:新增、修改、刪除、查詢、分頁、排序、導出excel、打印、上傳圖片、支持表單驗證,優雅的實現有多簡單?很是簡單。css

須要用到哪些UI組件?我都是基於bootstrap這種扁平化響應式風格的,jquery.dataTables.js、toastr.js、bootstrapValidator.js、bootstrap-confirmation.js、printThis.jshtml

因爲是演示用,因此控制器中直接調用了EF上下文操做,重點是看前端部分的渲染和交互,不要重複你的代碼!不要重複你的代碼!不要重複你的代碼!重要的事情說三遍!爲何沒有用mvc自帶的模型驗證?答:太傻逼!一、樣式改起來操蛋;二、每次要點擊提交表單才促發驗證。前端

這裏表數據量少,是直接一次性加載,而後內存中分頁的,若是表數據量多,那麼就要用服務器分頁,一樣很簡單。修改下配置項,以下所示:而後控制器中對應的方法稍微修改下便可。java

options.bServerSide = true;,
options.fnServerParams = function (aoData) { //查詢條件 aoData.push( { "name": "LogName", "value": $("#LogName").val() } ); };

 BaseController控制器基類jquery

    [PublicAuthorize]
    public class BaseController : Controller
    {
        HomeService _HomeService = new HomeService();
        #region 字段

        /// <summary>
        /// 新增
        /// </summary>
        protected string CText = "新增";
        /// <summary>
        /// 讀取
        /// </summary>
        protected string RText = "讀取";
        /// <summary>
        /// 更新
        /// </summary>
        protected string UText = "更新";
        /// <summary>
        /// 刪除
        /// </summary>
        protected string DText = "刪除";
        /// <summary>
        /// 數據有誤!
        /// </summary>
        protected string VoidText = "數據有誤!";

        #endregion

        #region 屬性
        /// <summary>
        /// 獲取點擊的菜單ID
        /// </summary>
        public string MenuId { get { return Request.QueryString["MenuId"]; } }
        /// <summary>
        /// 自動構建頁面標題導航
        /// </summary>
        public MvcHtmlString HeadString
        {
            get { return new MvcHtmlString(_HomeService.GetHead(int.Parse(MenuId))); }
        } 
        /// <summary>
        /// 構造非菜單頁的界面導航標題
        /// </summary>
        /// <param name="title">頁面標題</param>
        public void CreateSubPageHead(string title)
        {
            ViewBag.HeadString = HeadString;
            ViewBag.MenuId = MenuId;
            ViewBag.SubHeadString = title; 
        }
        #endregion
        [HttpGet]
        public virtual ActionResult Index()
        {
            if (!string.IsNullOrEmpty(MenuId))
            {
                ViewBag.MenuId = MenuId;
                ViewBag.HeadString = HeadString;
            }
            return View();
        }
        /// <summary>
        /// 操做成功
        /// </summary>
        /// <param name="message">提示文本</param>
        /// <returns></returns>
        protected virtual AjaxResult SuccessTip(string message)
        {
            return new AjaxResult { state = ResultType.success.ToString(), message = message };
        }
        /// <summary>
        /// 操做失敗
        /// </summary>
        /// <param name="message">提示文本</param>
        /// <returns></returns>
        protected virtual AjaxResult ErrorTip(string message)
        {
            return new AjaxResult { state = ResultType.error.ToString(), message = message };
        }
    }
View Code

控制器DefaultController程序員

    public class DefaultController : BaseController
    {
        private MyContext db = new MyContext();
        /// <summary>
        /// 客戶列表
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult List(Customer filter)
        {
            //filter.PageSize = int.MaxValue;
            IQueryable<Customer> dataSource = db.Customers;

            if (!string.IsNullOrEmpty(filter.Name))
            {
                dataSource = dataSource.Where(x => x.Name == filter.Name).OrderBy(x => x.CreateTime);
            }

            List<Customer> queryData = dataSource.ToList();

            var data = queryData.Select(u => new
            {
                ID = u.Id,
                Name = u.Name,
                CreateTime = u.CreateTime.ToDateStr(),
                Address = u.Address
            });

            //構形成Json的格式傳遞
            var result = new { iTotalRecords = queryData.Count, iTotalDisplayRecords = 10, data = data };
            return Json(result, JsonRequestBehavior.AllowGet);
        }
        #region CRUD
        [HttpGet]
        public ActionResult Create()
        {
            return View();
        }
        [HttpPost]
        public JsonResult Create([Bind(Include = "Name,Address,CreateTime,Msg,HeadsUrl")] Customer _Customer)
        {
            AjaxResult _AjaxResult = null;
            if (ModelState.IsValid)
            {
                db.Customers.Add(_Customer);
                _AjaxResult = db.SaveChanges() > 0 ? SuccessTip(string.Format("{0}成功!", CText)) : ErrorTip(string.Format("{0}失敗!", CText)); ;
            }
            else
            {
                _AjaxResult = ErrorTip(VoidText);
            }
            return Json(_AjaxResult, JsonRequestBehavior.AllowGet);
        }

        [HttpGet]
        public ActionResult Update(int Id)
        {
            var model = db.Customers.Where(x => x.Id == Id).FirstOrDefault();
            return View(model);
        }
        [HttpPost]
        public JsonResult Update([Bind(Include = "Id,Name,Address,CreateTime,Msg,HeadsUrl")] Customer _Customer)
        {
            AjaxResult _AjaxResult = null;
            if (ModelState.IsValid)
            {
                db.Entry(_Customer).State = EntityState.Modified;
                _AjaxResult = db.SaveChanges() > 0 ? SuccessTip(string.Format("{0}成功!", UText)) : ErrorTip(string.Format("{0}失敗!", UText));
            }
            else
            {
                _AjaxResult = ErrorTip(VoidText);
            }
            return Json(_AjaxResult, JsonRequestBehavior.AllowGet);
        }
        [HttpPost]
        public JsonResult Delete(int Id)
        {
            var model = db.Customers.Where(x => x.Id == Id).FirstOrDefault();
            db.Customers.Remove(model);
            AjaxResult _AjaxResult = db.SaveChanges() > 0 ? SuccessTip(string.Format("{0}成功!", DText)) : ErrorTip(string.Format("{0}失敗!", DText));

            return Json(_AjaxResult, JsonRequestBehavior.AllowGet);
        }
        [HttpPost]
        public JsonResult DeleteList(List<int> ids)
        {
            var list = db.Customers.Where(x => ids.Contains(x.Id)).ToList();
            db.Customers.RemoveRange(list);
            AjaxResult _AjaxResult = db.SaveChanges() > 0 ? SuccessTip(string.Format("{0}成功!", DText)) : ErrorTip(string.Format("{0}失敗!", DText));

            return Json(_AjaxResult, JsonRequestBehavior.AllowGet);
        }

        #endregion

        #region File handle
        /// <summary>
        /// 導出Excel
        /// </summary>
        /// <returns></returns>
        public FileResult ExportExcel()
        {
            string excelPath = Server.MapPath("~/Excel/用戶列表.xls");
            GenerateExcel genExcel = new GenerateExcel();
            genExcel.SheetList.Add(new UserListSheet(db.Customers.ToList(), "用戶列表"));
            genExcel.ExportExcel(excelPath);
            return File(excelPath, "application/ms-excel", "用戶列表.xls");
        }
        /// <summary>
        /// 上傳文件
        /// </summary>
        /// <returns></returns>
        public JsonResult ExportFile()
        {
            HttpPostedFileBase file = Request.Files["txt_file"];
            uploadFile _uploadFile = new uploadFile();

            if (file != null)
            {
                string str = DateTime.Now.ToString("yyyyMMddhhMMss");
                var fileFullName =string.Format("{0}{1}_{2}",Request.MapPath("~/Upload/"),str ,file.FileName);
                try
                {
                    file.SaveAs(fileFullName);
                    _uploadFile.state = 1;
                }
                catch
                {
                    _uploadFile.state = 0;
                }
                finally
                {
                    _uploadFile.name = str+"_"+file.FileName;
                    _uploadFile.fullName = fileFullName;
                }
            }
            else
            {
                _uploadFile.state = 0;
            }
            return Json(_uploadFile, JsonRequestBehavior.AllowGet);
        }
        /// <summary>
        /// 刪除文件
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public JsonResult DeleteFile(string key)
        {
            var fileFullName = Path.Combine(Request.MapPath("~/Upload"), key);
            int state = 0;
            try
            {
                state = FileHelper.DeleteFile(fileFullName) ? 1 : 0;
                //var model = db.Customers.Where(x => x.HeadsUrl == key).FirstOrDefault();
                //if(model!=null)
                //{
                //    db.Customers.Remove(model);
                //}
            }
            catch
            {
                state = 0;
            }
            return Json(state, JsonRequestBehavior.AllowGet);
        } 

        #endregion
    }
View Code

視圖頁面,razor、css、js都分離,不要放到一個文件中。ajax

Index視圖:json

@model List<Secom.Smp.Data.Models.Customer>
@{
    ViewBag.Title = "用戶列表";
    ViewBag.ParentTitle = "系統管理";
    Layout = "~/Views/Shared/_Page.cshtml";
}
<style type="text/css">
    .divModal {
        width: 700px;
    }
</style>
<div class="page-content-body">
    <div class="row">
        <div class="col-md-12">
            <!-- BEGIN EXAMPLE TABLE PORTLET-->
                <div class="portlet-title">
                    <div class="caption font-dark">
                        <i class="icon-settings font-dark"></i>
                        <span class="caption-subject bold uppercase">用戶列表</span>
                    </div>
                    <div class="actions">
                       
                    </div>
                </div>
                <div class="portlet-body">
                    <div class="table-toolbar">
                        <div class="row">
                            <div class="col-md-6">
                                <div class="btn-group">
                                    <button id="btnAdd" class="btn sbold green" onclick="DataTablesObj.doCreateModal('/Admin/Default/Create')" data-toggle="modal">添加用戶<i class="fa fa-plus"></i></button>
                                    <button id="btnDeleteList" title="肯定要刪除嗎?" class="btn sbold btn-danger deleteBtn" data-toggle="confirmation" data-placement="right" data-btn-ok-label="繼續" data-btn-ok-icon="icon-like" data-btn-ok-class="btn-success" data-btn-cancel-label="取消"
                                            data-btn-cancel-icon="icon-close" data-btn-cancel-class="btn-danger">
                                        批量刪除
                                        <i class="fa fa-minus"></i>
                                    </button>
                                </div>
                            </div>
                            <div class="col-md-6">
                                <div class="btn-group pull-right">
                                    <button class="btn green  btn-outline dropdown-toggle" data-toggle="dropdown">
                                        操做
                                        <i class="fa fa-angle-down"></i>
                                    </button>
                                    <ul class="dropdown-menu pull-right">
                                        <li>
                                            <a href="/Admin/Default/ExportExcel" target='_blank' class="fa fa-file-excel-o"><span style="margin-left:10px;"> 導出Excel </span></a>
                                        </li>
                                        <li>
                                            <a href="#" class="fa fa-file-excel-o" id="printView"><span style="margin-left:10px;"> 打印預覽</span></a>
                                        </li>
                                    </ul>
                                </div>

                            </div>
                        </div>
                    </div>
                    <table class="table table-striped table-bordered table-hover table-checkable order-column" id="table_local"></table>
                </div>
            <!--模態彈窗-->
            <div class="modal fade" id="defaultModal" tabindex="-1" role="dialog" aria-labelledby="defaultModalLabel" aria-hidden="true">
                <div class="modal-dialog divModal" role="document">
                    <div class="modal-content">
                    </div>
                </div>
            </div>
            <!-- END EXAMPLE TABLE PORTLET-->
        </div>       
        </div>
</div>
@section scripts
{
<script src="@Html.ScriptsPath("lib/printThis.js")"></script>
}
View Code

Create視圖:bootstrap

@model Secom.Smp.Data.Models.Customer
@{
    ViewBag.Title = "Create";
    Layout = "~/Views/Shared/_Form.cshtml";
}
<div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
    <h4 class="modal-title" id="defaultModalLabel">添加用戶</h4>
</div>
@using (Html.BeginForm("Create", "Default", new { area = "Admin" }, FormMethod.Post, new { @id = "defaultForm" }))
            {
    <div class="modal-body">
        <div class="row">
            <div class="col-md-5">
                    <div class="form-group">
                        @Html.LabelFor(x => x.HeadsUrl,new { @class = "control-label" }):
                        <input type="file" id="txt_file" name="txt_file" class="file-loading" accept="image/*" />
                        @Html.HiddenFor(x=>x.HeadsUrl,new { @id = "hidFileUrl" })
                    </div>
                </div>
            <div class="col-md-7">
                <div class="form-group">
                    @Html.LabelFor(x => x.Name, new { @class = "control-label" }):
                    @Html.TextBoxFor(x => x.Name, new { @id = "Name", @placeholder = "請輸入用戶名", @class = "form-control" })
                </div>
                <div class="form-group">
                    @Html.LabelFor(x => x.Address, new { @class = "control-label" }):
                    @Html.TextBoxFor(x => x.Address, new { @id = "Address", @placeholder = "請輸入地址", @class = "form-control" })
                </div>
                <div class="form-group">
                    @Html.LabelFor(x => x.CreateTime):
                    <div class="input-group input-medium date date-picker">
                        @Html.TextBoxFor(x => x.CreateTime, new { @class = "form-control", @readonly = true })
                        <span class="input-group-btn">
                            <button class="btn default" type="button">
                                <i class="fa fa-calendar"></i>
                            </button>
                        </span>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">關閉</button>
        <button type="submit" class="btn sbold green">提交</button>
    </div>
}
@section scripts
{

}
View Code

Update視圖:

@model Secom.Smp.Data.Models.Customer
@{
    ViewBag.Title = "Update";
    Layout = "~/Views/Shared/_Form.cshtml";
}
<div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
    <h4 class="modal-title" id="defaultModalLabel">修改用戶</h4>
</div>

    @using (Html.BeginForm("Update", "Default", new { area = "Admin" }, FormMethod.Post, new { @id = "updateForm" }))
    {
        @Html.HiddenFor(x=>x.Id)
        <div class="modal-body">
            <div class="row">
                <div class="col-md-5">
                    <div class="form-group">
                        @Html.LabelFor(x => x.HeadsUrl, new { @class = "control-label" }):
                        <input type="file" id="txt_file" name="txt_file" class="file-loading" accept="image/*" />
                        @Html.HiddenFor(x => x.HeadsUrl, new { @id = "hidFileUrl" })
                    </div>
                </div>
                <div class="col-md-7">
                    <div class="form-group">
                        @Html.LabelFor(x => x.Name, new { @class = "control-label" }):
                        @Html.TextBoxFor(x => x.Name, new { @id = "Name", @placeholder = "請輸入用戶名", @class = "form-control" })
                    </div>
                    <div class="form-group">
                        @Html.LabelFor(x => x.Address, new { @class = "control-label" }):
                        @Html.TextBoxFor(x => x.Address, new { @id = "Address", @placeholder = "請輸入地址", @class = "form-control" })
                    </div>
                    <div class="form-group">
                        @Html.LabelFor(x => x.CreateTime):
                        <div class="input-group input-medium date date-picker">
                            @Html.TextBoxFor(model => model.CreateTime,
           new { @type = "date", @class = "form-control", @readonly = true, @Value = Model.CreateTime.ToDateStr(),@id= "CreateTime" })
                            <span class="input-group-btn">
                                <button class="btn default" type="button">
                                    <i class="fa fa-calendar"></i>
                                </button>
                            </span>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">關閉</button>
            <button type="submit" class="btn sbold green">提交</button>
        </div>
    }
 @section scripts
{

}
View Code

_Form模板頁視圖

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
</head>
<body>
    @RenderBody()
    @RenderSection("scripts", required: false)
            @Html.AutoLoadPageJs()
</body>
</html>

看下這個自定義的擴展方法AutoLoadPageJs方法,其實就是模擬mvc的路由尋址方式去找指定目錄下面的js

        /// <summary>
        /// 根據mvc路由自動加載js文件(若是不存在則不加載)
        /// </summary>
        /// <param name="helper"></param>
        /// <returns></returns>
        public static MvcHtmlString AutoLoadPageJs(this HtmlHelper helper)
        {
            var areas = helper.ViewContext.RouteData.DataTokens["area"];
            var action = helper.ViewContext.RouteData.Values["action"];
            var controller = helper.ViewContext.RouteData.Values["controller"];
            string url = areas == null ? string.Format("views/{0}/{1}", controller, action) : string.Format("views/areas/{2}/{0}/{1}", controller, action, areas);

            return LoadJsString(helper,url);
        }
        /// <summary>
        /// 構造js加載的html字符串
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="url">js文件路徑</param>
        /// <returns></returns>
        public static MvcHtmlString LoadJsString(HtmlHelper helper, string url)
        {
            var jsBuilder = new StringBuilder();
            string jsLocation = "/content/release-js/";
#if DEBUG
            jsLocation = "/content/js/";
#endif
            string jsFullUrl = Path.Combine(jsLocation, url + ".js");

            if (File.Exists(helper.ViewContext.HttpContext.Server.MapPath(jsFullUrl)))
            {
                jsBuilder.AppendFormat("<script src=\"{0}\"></script>", jsFullUrl);
            }
            return new MvcHtmlString(jsBuilder.ToString());
        }

咱們看下View對應的js文件

index.js

$(function () {
    //-------------初始化datatable
    var obj = DataTablesObj;
    obj.showReadBtn = false;//顯示詳情按鈕
    obj.showDeleteBtn = true;//顯示刪除按鈕
    obj.showUpdateBtn = true;//顯示更新按鈕

    obj.updateUrl = "/Admin/Default/Update";
    obj.deleteUrl = "/Admin/Default/Delete";
    obj.batchDeleteUrl = "/Admin/Default/DeleteList";//批量刪除路徑

    obj.options.columns = [{ title: "", "visible": false, "data": "ID" },
           obj.checboxFied,
           { "data": "Name", title: "用戶名稱" },
           { "data": "Address", title: "用戶地址" },
           { "data": "CreateTime", title: "建立時間" },
           obj.opratorFiled
    ];
    obj.options.searching = true;
    obj.options.sAjaxSource = "/Admin/Default/List"; //數據源地址
    obj.init(obj.options);
    //表單驗證配置項
    FormValidatorObj.options.fields = {
        Name: {
            message: '用戶名驗證失敗',
            validators: {
                notEmpty: {
                    message: '用戶名不能爲空'
                }
            }
        },
        Address: {
            validators: {
                notEmpty: {
                    message: '地址不能爲空'
                }
            }
        }
    };
    //打印預覽
    $("#printView").on("click", function () {
        $("#table_local").printThis({
            debug: false,// 調試模式下打印文本的渲染狀態
            importCSS: true,
            importStyle: true,
            printContainer: true,
            //loadCSS: "/Content/bootstrap.css",
            pageTitle: "用戶列表",
            removeInline: false,
            printDelay: 333,
            header: null,
            formValues: true,
            header: "<h1>用戶列表</h1>",
            footer: null
        });
    })
})

create.js

$(function () {
    DatetimepickerObj.init('CreateTime');//(控件ID)
    //--------------表單驗證
    FormValidatorObj.init("defaultForm","defaultModal","table_local"); //(表單id,[modal容器Id],[datable容器ID])
    //初始化編輯界面的數據
    //--------------添加界面中的上傳控件
    FileInputObj.init(undefined,"txt_file", "hidFileUrl", "/Admin/Default/ExportFile",true);  //配置項,控件ID,存儲文件路徑的控件ID,上傳路徑,是否新增頁面
});

update.js

$(function () {
    DatetimepickerObj.init('CreateTime');//(控件ID)
    //--------------表單驗證
    FormValidatorObj.init("updateForm","defaultModal","table_local"); //(表單id,[modal容器Id],[datable容器ID])
    //初始化編輯界面的數據
    //([配置項],控件ID,存儲文件路徑的控件ID,圖片路徑,上傳路徑,刪除路徑)
    FileInputObj.initUpdateImg(undefined,"txt_file", "hidFileUrl", "/Admin/Default/ExportFile", "/Admin/Default/DeleteFile");
})

看上去比較多的界面功能,你看下,代碼就這麼點,並且各自職責很清晰。對datatables.js組件進行二次封裝,base-Datatable.js代碼以下:

// ajax加載調試用
//# sourceURL=base-Datatable.js

//DataTables表格組件擴展對象--created by zouqj 2017-7-03
var DataTablesObj = (function () {
    //------------------------------靜態全局屬性-------------------------------------
    var infoStr = "總共 <span class='pagesStyle'>(_PAGES_) </span>頁,顯示 _START_ -- _END_ ,共<span class='recordsStyle'> (_TOTAL_)</span> 條";

    var lengthMenuStr = '每頁顯示:<select class="form-control input-xsmall">' + '<option value="5">5</option>' + '<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>' + '<option value="500">500</option>';

    this.table_local = "table_local"; //table ID
    this.chkAllColl = "chkAllColl"; //全選按鈕ID
    this.modalId = "defaultModal"; //模態窗體ID
    this.batchDeleteBtn = "btnDeleteList"; //批量刪除按鈕ID
    this.deleteBtn = "btnDelete"; //刪除按鈕ID
    this.autoIncrement={'title': '序號', 'data': null, 'bSortable': false,'render': function (data, type, full, meta) {return meta.row + 1 + meta.settings._iDisplayStart;}}; // 序號
    //操做列
    this.opratorFiled = {
        "data": "ID", orderable: false, title: "操做", "render": function (data, type, row, meta) { //自定義列
            var re = "<div class='operatorDiv'></i>";
            if (DataTablesObj.showReadBtn) {
                var temp = DataTablesObj.detailModal == undefined ? data : data + ",'" + DataTablesObj.detailModal+"'";
                re += "<a class='' type='button' data-toggle='dropdown' aria-expanded='false' onclick=\"DataTablesObj.doReadModal(" + temp + ")\">詳情</a>";
            }
            if (DataTablesObj.showUpdateBtn) {
                var temp = DataTablesObj.updateModal == undefined ? data : data + ",'" + DataTablesObj.updateModal + "'";
                re += "<a class='' type='button' onclick='DataTablesObj.doUpdateModal(" + temp + ")'>編輯</a>";
            }
            if (DataTablesObj.showDeleteBtn) {
                re += "<a class='' title='肯定要刪除嗎?' data-toggle='confirmation' data-placement='left' data-btn-ok-label='繼續' data-btn-ok-icon='icon-like' data-btn-ok-class='btn-success toastrBtn' data-btn-cancel-label='取消' data-btn-cancel-icon='icon-close' data-btn-cancel-class='btn-danger' type='button' onclick='DataTablesObj.doDelete(this," + data + ")'>刪除</a>";
            }
            re += "</div>";
            return re;
        }
    };
    //複選框列
    this.checboxFied = {
        "data": "ID", title: "<input type='checkbox' id='chkAllColl' onclick='DataTablesObj.selectAll()'/>", orderable: false,
        "render": function (data, type, row, meta) {
            return "<input id='cbx" + data + "' name='chkItem' type='checkbox' onclick='DataTablesObj.controlSelectAll(" + data + ")' class='cbx' value='" + data + "'/>  ";
        }
    };
    //------------------------------變化部分的屬性-------------------------------------
    this.batchDeleteUrl = "";//批量刪除路徑
    this.deleteUrl = ""; //單條記錄刪除路徑
    this.showReadBtn = true;//默認不顯示詳情按鈕
    this.showDeleteBtn = false;//默認不顯示刪除按鈕
    this.showUpdateBtn = false;//默認顯示更新按鈕
    this.readUrl = ""; //單條記錄讀取路徑
    this.updateUrl = "";//更新界面URL地址
    this.detailModal = undefined; //詳情頁面的modalId
    this.updateModal = undefined;//修改頁面的modalId

    //------------------------------事件、方法-------------------------------------
    document.onkeydown = function (event) {
        var e = event || window.event || arguments.callee.caller.arguments[0];
        if (e && e.keyCode == 27) { // 按 Esc 
            //要作的事情
        }
        if (e && e.keyCode == 13) { // enter 鍵
            //要作的事情
            DataTablesObj.reloadList(DataTablesObj.table_local);
        }
    };
    ////對行單擊添加監聽事件
    //$('#table_local tbody').on('click', 'tr', function () {
    //    var tr = $(this).closest('tr');
    //    var checkbox = tr.find('td:first-child input:checkbox')[0];
    //    checkbox.checked = !checkbox.checked;
    //});
    //獲Ggridview中全部的複選框 sName: Gridview 的ID  
    this.getCheckbox = function (sName) {
        var aryCheckbox = new Array();
        var tb = document.getElementById(sName);
        if (tb == null)
            return;
        var objs = tb.getElementsByClassName("cbx");
        for (var i = 0; i < objs.length; i++) {
            if (objs[i].type == 'checkbox')
                aryCheckbox.push(objs[i]);
        }
        return aryCheckbox;
    };

    //監聽每一行的複選框,控制全選、反選按鈕  
    this.controlSelectAll = function (i) {
        var tblName, cbkAll; //Gridview ID ,全選框ID  
        var tblName = DataTablesObj.table_local;
        var cbkAll = DataTablesObj.chkAllColl;
        var id = "#cbx" + i;
        //點擊複選框選中行
        //if ($(id)[0].checked == true) {
        //    $(id).parent().parent().addClass('selected');
        //    $(id).parent().parent().siblings().removeClass('selected');
        //} else {
        //    $(id).parent().parent().siblings().removeClass('selected');
        //    $(id).parent().parent().removeClass('selected');
        //}
        var chks = DataTablesObj.getCheckbox(tblName);
        var count = 0;
        for (var i = 0; i < chks.length; i++) {
            if (chks[i].checked == true) {
                count++;
            }
        }
        if (count < chks.length) {
            document.getElementById(cbkAll).checked = false;
        }
        else {
            document.getElementById(cbkAll).checked = true;
        }
    };
    //全選反選
    this.selectAll = function () {
        var isChecked = $("#" + DataTablesObj.chkAllColl)[0].checked;
        $("input[name='chkItem']").prop("checked", isChecked);
    };
    //查詢刷新([datatable ID])
    this.reloadList = function (id) {
        var tableId = id == undefined ? DataTablesObj.table_local : id;
        var tables = $('#' + tableId).dataTable().api();//獲取DataTables的Api,詳見 http://www.datatables.net/reference/api/
        tables.ajax.reload();
    };
    //****************************************************************************************************************

    //新增記錄(異步請求界面url,[modal ID],[回調函數])
    this.doCreateModal = function (url, modalId, func) {
        var modalId = modalId == undefined ? DataTablesObj.modalId : modalId;
        $('#' + modalId).modal({ show: true, backdrop: 'static', remote: url });
        if (func != undefined) {
            func();
        }
    };
    //詳細記錄(主鍵ID,[modal ID],[異步請求界面url])
    this.doReadModal = function (id, modalId, readUrl) {
        var modalId = modalId == undefined ? DataTablesObj.modalId : modalId;
        var url = readUrl == undefined ? DataTablesObj.readUrl : readUrl;
        $('#' + DataTablesObj.modalId).modal({ show: true, backdrop: 'static', remote:url  + "?id=" + id });
    }
    //編輯記錄(主鍵ID,[異步請求界面url],[modal ID])
    this.doUpdateModal = function (id, modalId,updateUrl) {
        var modalId = modalId == undefined ? DataTablesObj.modalId : modalId;
        var url = updateUrl == undefined ? DataTablesObj.updateUrl : updateUrl;
        $('#' + modalId).modal({ show: true, backdrop: 'static', remote: url + "?id=" + id });
    };
    //刪除選中記錄(批量刪除url地址)
    this.doDeleteList = function (url) {
        var table = $('#' + DataTablesObj.table_local).dataTable();
        var nTrs = table.fnGetNodes();//fnGetNodes獲取表格全部行,nTrs[i]表示第i行tr對象
        var row;
        var strdid = '';
        var selectCounts = 0;
        for (var i = 0; i < nTrs.length; i++) {
            if ($(nTrs[i])[0].cells[0].children[0].checked) {
                row = table.fnGetData(nTrs[i]);//fnGetData獲取一行的數據        
                selectCounts++;
                strdid += "" + row.ID + ",";
            }
        }
        strdid = strdid.substring(0, strdid.length - 1);
        var ids = strdid.split(",");
        if (selectCounts < 1) {
            toastr.warning("請先選擇數據行!");
            return false;
        }
        $.ajax({
            type: 'POST',
            url: url,
            data: { 'ids': ids },
            dataType: 'json',
            success: function (result) {
                toastr.success(result.message);
                DataTablesObj.reloadList(DataTablesObj.table_local);
            }
        });
    }
    //刪除單條記錄(控件id,主鍵id)
    this.doDelete = function (btn, id) {
        $(btn).on('confirmed.bs.confirmation', function () {
            $.post(DataTablesObj.deleteUrl, { Id: id }, function (result) {
                toastr.success(result.message);
                DataTablesObj.reloadList(DataTablesObj.table_local);
            });
        });
        $(btn).confirmation('show');
    };
    this.options = {
        bProcessing: true,
        //"scrollY": table_h1,// 340,// 
        "scrollX": false,
        //"scrollCollapse": "true",
        //dom:"",//'ftr<"bottom"lip>',//<"clear">
        "bServerSide": false, //指定從服務器端獲取數據
        sServerMethod: "POST",
        sAjaxSource: "",
        autoWidth: false,
        fnServerParams: null,
        columns: null,
        paging: true,//分頁
        ordering: true,//是否啓用排序
        searching: false,//搜索
        language: {
            "sProcessing": "處理中...",
            lengthMenu: lengthMenuStr,//左上角的分頁大小顯示。
            search: '<span class="label label-success">搜索:</span>',//右上角的搜索文本,能夠寫html標籤

            //paginate: {//分頁的樣式內容。
            //    previous: "上一頁",
            //    next: "下一頁",
            //    first: "",
            //    last: ""
            //},
            "paginate": {
                "previous": "Prev",
                "next": "Next",
                "last": "Last",
                "first": "First"
            },

            zeroRecords: "",//table tbody內容爲空時,tbody的內容。--暫無記錄
            //下面三者構成了整體的左下角的內容。
            info: infoStr,//左下角的信息顯示,大寫的詞爲關鍵字。初始_MAX_ 條
            infoEmpty: "0條記錄",//篩選爲空時左下角的顯示。
            infoFiltered: ""//篩選以後的左下角篩選提示,
        },
        pagingType: "bootstrap_full_number"//分頁樣式的類型 "full_numbers"//
    };
    //監聽批量刪除按鈕事件(控件ID,url刪除地址)
    this.listenerDeleteEvent = function (ctrlId, url) {
        $('#' + ctrlId).on('confirmed.bs.confirmation', function () {
            DataTablesObj.doDeleteList(url);
        }).on("click", function () {
            $('#' + ctrlId).confirmation('show');
        });
    }
    //控件初始化(配置項,[table容器ID],[刪除對象])
    this.init = function (options, tableId,obj) {
        var tableId = tableId == undefined ? DataTablesObj.table_local : tableId;
        var opts = options == undefined ? DataTablesObj.options : options;
        $('#' + tableId).dataTable(opts);
        if (obj == undefined) {
            DataTablesObj.listenerDeleteEvent(DataTablesObj.batchDeleteBtn, DataTablesObj.batchDeleteUrl);
        } else {
            obj.listenerDeleteEvent(obj.batchDeleteBtn, obj.batchDeleteUrl);
        }      
        delete options.aoColumns;//同一個頁面多處使用時,要先刪除此對象,具體緣由不明
    };
    //批量初始化(options配置數組,tables id數組)-不添加監聽事件
    this.initList = function (opts, ids) {
        if (opts!=undefined &&opts!=null &&opts.length>0&& ids != undefined&& ids!=null && ids.length > 0) {
            var length = ids.length;
            for (var i = 0; i < length; i++) {
                $('#' + ids[i]).dataTable(opts[i]);
            }
        }
    }
    return this;
}).call({});
View Code

咱們進行二次封裝的UI組件對象,他們的options屬性,是複雜屬性,也就是相似與引用類型,要使用深拷貝而後再去修改,不然修改的是引用而不是副本。我這裏沒有去使用clone,而是直接在options對象上進行賦值了,那是由於我賦值的那些屬性每一個引用頁面都會去再賦值一遍,而js是運行在客戶端的,也就是說每一個客戶的電腦上面都會有一份完整的js文件副本,這和運行在服務器端的C#語言是不同的。其實使用  var options = clone(DataTablesObj.options);再去給options賦值是標準作法,可是會失去一部分性能。個人js水平太菜,因此封裝得不是特別好,可是至少頁面乾淨、方便維護。

js方法上面的註釋,我也是按照自定義的風格進行註釋,參數用()括起來,可選參數就用[],這些東西均可以當成約定或者規範,目的就是爲了讓全部的開發人員寫的代碼像一我的寫的。原本我想把方法的參數都封裝成一個對象的,只是以前以爲參數個數少,就沒有那樣去封裝了,參數用對象的好處就是能夠無序,並且更易擴展,全部這些進行二次封裝的UI組件,文件命名我都加了前綴base-,其實裏面的對象命名我是加的後綴Obj,你也能夠根據本身的愛好設定,好比說公司名稱簡寫做爲前綴,可是必定肯定了,就要團隊成員遵照約定。

日期組件一樣進行封裝base-Datetimepicker.js,這裏的打印我暫時就沒有去進行封裝了。在js中一般使用原型鏈的方式來實現繼承,我這裏沒有使用,緣由2點,一是自身對這塊掌握得很差,二是公司都是後端開發人員,就按照這種最簡單的方式進行封裝。

//ajax加載調試用
//# sourceURL=base-Datetimepicker.js

//Datetimepicker日期組件擴展對象--created by zouqj 2017-7-13
var DatetimepickerObj = (function () {
    this.options = {
        language: 'zh-CN',//顯示中文
        format: 'yyyy-mm-dd',//顯示格式
        minView: "month",//設置只顯示到月份
        initialDate: new Date(),//初始化當前日期
        autoclose: true,//選中自動關閉
        todayBtn: true//顯示今日按鈕
    };
    this.init= function (ctrlId) {
        $("#" + ctrlId).datetimepicker(DatetimepickerObj.options);
    }
    //(開始日期控件,結束日期控件)
    this.initStartEnd = function (startCtrl, endCtrl) {
        var startCtrl = $("#" + startCtrl);
        var endCtrl = $("#" + endCtrl);
        startCtrl.datetimepicker({
            format: 'yyyy-mm-dd',
            minView: 'month',
            language: 'zh-CN',
            autoclose: true,
            startDate: new Date()
        }).on("click", function () {
            startCtrl.datetimepicker("setEndDate", endCtrl.val())
        });
        endCtrl.datetimepicker({
            format: 'yyyy-mm-dd',
            minView: 'month',
            language: 'zh-CN',
            autoclose: true,
            startDate: new Date()
        }).on("click", function () {
            endCtrl.datetimepicker("setStartDate", startCtrl.val())
        });
    }
    return this;
}).call({});
   
View Code

那麼其實咱們界面上真正本身要寫的就3個View,3個js,一個控制器提供對應的方法調用,其它的不論是C#仍是js都去進行封裝,css樣式統統按照規範寫成皮膚文件。項目中能夠有一個皮膚css,一個佈局css,一個自定義css。

因此說.net作東西就是這麼簡單,看似複雜的功能界面,一會兒就搞定了,只要把東西都封裝好了,作一個這樣的功能最多大半天就搞定,仔細看下js總共就寫幾十行左右,還算上了複製粘貼修改下的,哪裏須要去常常加班?加班應該是php程序員和java程序員的專利,作不加班的.net程序員~

相關文章
相關標籤/搜索