国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

在ABP框架中使用BootstrapTable組件的方法

2019-11-19 15:56:18
字體:
供稿:網(wǎng)友

一、關(guān)于ABP

ABP是“ASP.NET Boilerplate Project (ASP.NET樣板項(xiàng)目)”的簡稱,它是一個(gè)成熟的開源框架,基于DDD+Repository模式,自帶Zero權(quán)限和認(rèn)證模塊,避免了從零開始搭建框架的煩惱。關(guān)于ABP的框架優(yōu)勢(shì)就此打住,因?yàn)檫@樣說下去要說三天三夜,脫離文本主題。

關(guān)于ABP的入門,博主不想說太多,園子里面tkb至簡和陽光銘睿有很多入門級(jí)的文章,有興趣的可以了解下,還是給出它的官網(wǎng)和開源地址。

ABP官方網(wǎng)站:http://www.aspnetboilerplate.com

ABP開源項(xiàng)目:https://github.com/aspnetboilerplate

PS:如果你不愿意去看它的源碼,可以直接查看ABP官網(wǎng)上面的演示地址:https://aspnetzero.com/?ref=abptmplpage

點(diǎn)擊CREATE MY DEMO按鈕,系統(tǒng)會(huì)自動(dòng)為你生成演示地址

進(jìn)入對(duì)應(yīng)的Demo URL

使用演示的用戶名和密碼登陸進(jìn)去

可以看到Zero模塊的實(shí)現(xiàn)效果。

二、jTable在ABP中的運(yùn)用

如果你下載ABP的源碼,并且選擇的是混合開發(fā)模式(ABP提供了兩種開發(fā)模式,一種是基于MVVM的Angular.js的模式;另一種就是MVC+jQuery的混合開發(fā)模式),如下圖:

當(dāng)你Down下來源碼之后你就會(huì)發(fā)現(xiàn),ABP的源碼里面的UI部分的表格都是使用jTable去實(shí)現(xiàn)的。為什么會(huì)用jTable?原因很簡單,jTable是ABP的作者kalkan寫的一款開源插件,自己寫的肯定用自己的東西嘍。下面jTable的效果來一發(fā)。

來一個(gè)jtable的父子表:

如果是不帶父子表的簡單表格,其實(shí)jTable的效果其實(shí)還行,可是加上一些復(fù)雜的功能之后,那一片片藍(lán)色的區(qū)域不忍直視,并且jTable的api還有待完善,很多需要的功能都需要自己去實(shí)現(xiàn),于是就接到了將所有的表格組件換成BootstrapTable的需求,才有了今天的主題:在ABP中封裝BootstrapTable。

三、Bootstrap Table在ABP中的封裝

接到需求,博主各種百度、各種谷歌,都找不到Bootstrap Table組件在ABP中的封裝,有的只是在ABP的項(xiàng)目里面簡單的用傳統(tǒng)的方式去初始化組件,這并不是博主想要的。說到這里不得不說一下,如果你使用ABP開發(fā)的過程中遇到一些難題,你會(huì)發(fā)現(xiàn)很難從百度里面搜索到相關(guān)答案,谷歌里面有時(shí)能找到,但大部分都是英文社區(qū),所以如果你英文較弱,在查找資料上面會(huì)很吃虧,有時(shí)一個(gè)簡單的配置問題需要折騰很久。

1、jTable在ABP項(xiàng)目里面的初始化

首先來看看jTable在一般的ABP項(xiàng)目里面是如何初始化的。比如我們?cè)贏pplication里面有一個(gè)如下的接口和實(shí)現(xiàn)

 public interface IRequisitionAppService : IApplicationService {  Task<PagedResultDto<RequisitionListDto>> GetRequisitionListAsync(GetRequisitionListInput input); }  [AbpAuthorize(OrderAppPermissions.Pages_Order_Requisition)] public class RequisitionAppService : AbpZeroTemplateAppServiceBase, IRequisitionAppService {  private readonly IRepository<Requisition, long> _requisitionRepository;  public RequisitionAppService(IRepository<Requisition, long> requisitionRepository)  {   _requisitionRepository = requisitionRepository;  }     public async Task<PagedResultDto<RequisitionListDto>> GetRequisitionListAsync(GetRequisitionListInput input)  {   var query = _requisitionRepository.GetAll()             .WhereIf(input.Status != null, w => (int)w.Status == input.Status.Value)             .WhereIf(              !input.Filter.IsNullOrWhiteSpace(),              u =>               u.No.Contains(input.Filter) ||               u.Remark.Contains(input.Filter)             );   var count = await query.CountAsync();   var list = await query   .OrderBy(input.Sorting)   .PageBy(input)   .ToListAsync();   var dtos = list.MapTo<List<RequisitionListDto>>();   return new PagedResultDto<RequisitionListDto>(    count,    dtos    );  } }

然后我們前端有一個(gè)頁面的列表數(shù)據(jù)從這個(gè)接口GetRequisitionListAsync()獲取

<div class="portlet-body"> <div id="dataListTable"></div></div>(function () { $(function () {  var _$dataListTable = $('#dataListTable');  var _service = abp.services.app.requisition;  _$dataListTable.jtable({   paging: true,   sorting: true,   selecting: true,   actions: {    listAction: {     method: _service.getRequisitionListAsync    }   },   fields: {    id: {     key: true,     list: false    },    details: {     width: '1%',     sorting: false,     edit: false,     create: false,     listClass: 'child-opener-image-column',     display: function (detailData) {      var $img = $('<img class="child-opener-image" src="/Common/Images/list_metro.png" title="申購明細(xì)" />');      $img.click(function () {       _$dataListTable.jtable('openChildTable',        $img.closest('tr'),        {         title: "申購明細(xì)",         showCloseButton: true,         actions: {          listAction: {           method: _service.getRequisitionDetailListByIdAsync          }         },         fields: {          materialClassParentNameAndName: {           title: app.localize('MaterialClassName'),           width: '8%'          },          materialInfoTypeNo: {           title: app.localize('TypeNo'),           width: '5%'          },          materialInfoLengthDisplayName: {           title: app.localize('LengthDisplayName'),           width: '3%'          },          materialInfoWeight: {           title: app.localize('Weight'),           width: '5%',           display: function (data) {            return data.record.materialInfoMinWeight + '-' + data.record.materialInfoMaxWeight;           }          },          materialInfoMouldTypeDisplayName: {           title: app.localize('MouldTypeDisplayName'),           width: '6%'          },          materialInfoProductionRemark: {           title: app.localize('ProductionRemark'),           width: '8%'          },          materialInfoBundleCountDisplayName: {           title: app.localize('BundleCountDisplayName'),           width: '3%'          },          materialInfoUnitDisplayName: {           title: app.localize('UnitDisplayName'),           width: '3%'          },          materialInfoProcessCost: {           title: app.localize('ProcessCost'),           width: '6%'          },          materialInfoProductRemark: {           title: app.localize('ProductRemark'),           width: '6%'          },          materialInfoRemark: {           title: app.localize('Remark'),           width: '6%'          },          count: {           title: app.localize('申購數(shù)量'),           width: '6%'          },          remark: {           title: app.localize('申購備注'),           width: '6%'          }         }        }, function (data) {         data.childTable.jtable('load',          { requisitionId: detailData.record.id }         );        });      });      return $img;     }    },    no: {     title: "申購單號(hào)",     width: '20%'    },    creatorUserName: {     title: "申購人",     width: '20%'    },    creationTime: {     title: "申購時(shí)間",     width: '10%',     display: function (data) {      return moment(data.record.creationTime).format('YYYY-MM-DD HH:mm:ss');     }    },    sumCount: {     title: "總數(shù)",     width: '10%'    },    status: {     title: "狀態(tài)",     width: '20%',     display: function (data) {      if (data.record.status === app.order.requisitionAuditStatus.audit)       return '<span class="label label-info">' + app.localize('Autdit') + '</span>'      else if (data.record.status === app.order.requisitionAuditStatus.auditPass)       return '<span class="label label-success">' + app.localize('Pass') + '</span>'      else if (data.record.status === app.order.requisitionAuditStatus.auditReject)       return '<span class="label label-danger">' + app.localize('Reject') + '</span>'      else if (data.record.status === app.order.requisitionAuditStatus.delete)       return '<span class="label label-danger">' + app.localize('Abandon') + '</span>'      else       return '<span class="label label-danger">' + app.localize('Unknown') + '</span>'     }    }   }  }); });})();

得到如下效果:

代碼釋疑:

(1) var _service = abp.services.app.requisition; 這一句聲明當(dāng)前頁面需要使用哪個(gè)服務(wù)。

(2)  _service.getRequisitionListAsync 這一句對(duì)應(yīng)的是服務(wù)調(diào)用的方法,你會(huì)發(fā)現(xiàn)在后臺(tái)方法名是GetRequisitionListAsync(),而在js里面卻變成了getRequisitionListAsync(),我們暫且稱之為“潛規(guī)則”。

2、bootstrapTable在ABP項(xiàng)目里面的封裝

通過上述代碼你會(huì)發(fā)現(xiàn),ABP在application層里面定義的方法,最終會(huì)生成某一些js對(duì)應(yīng)的function,這里難點(diǎn)來了。我們找遍了bootstrapTable組件的api,都沒有通過某一個(gè)function去獲取數(shù)據(jù)的啊。這可如何是好?為這個(gè)問題,博主折騰了兩天。最開始博主想,function最終還不是要換成http請(qǐng)求的,我們只要拿到http請(qǐng)求的url,然后將function轉(zhuǎn)換為url不就行了么:

我們使用bootstrapTable組件初始化的時(shí)候聲明  {url:'/api/services/app/requisition/GetRequisitionListAsync'}  這樣不就行了么?呵呵,經(jīng)過測試,這樣確實(shí)能正確取到數(shù)據(jù)。但是不夠理想,因?yàn)檫@前面的前綴是ABP給我們生成的,是否會(huì)變化我們尚且不說,給每一個(gè)url加上這么一長串著實(shí)看著很不爽,于是進(jìn)一步想,是否我們的bootstrapTable也可以使用function去初始化呢,組件沒有,難道我們就不能給他擴(kuò)展一個(gè)嗎?我們不用url獲取數(shù)據(jù),通過調(diào)用這個(gè)function取到數(shù)據(jù),然后將數(shù)據(jù)渲染到組件不就行了。思路有了,那么這里有兩個(gè)難題:一是如何將原來url的方式變成這里的調(diào)用function的方式呢?二是參數(shù)的封裝。經(jīng)過查看組件的源碼發(fā)現(xiàn),如果是服務(wù)端分頁,組件最終是進(jìn)入到initServer()這個(gè)方法去獲取數(shù)據(jù),然后渲染到頁面上面的,組件原始的initServer()方法如下:

BootstrapTable.prototype.initServer = function (silent, query) {  var that = this,   data = {},   params = {    pageSize: this.options.pageSize === this.options.formatAllRows() ?     this.options.totalRows : this.options.pageSize,    pageNumber: this.options.pageNumber,    searchText: this.searchText,    sortName: this.options.sortName,    sortOrder: this.options.sortOrder   },   request;  if (!this.options.url && !this.options.ajax) {   return;  }  if (this.options.queryParamsType === 'limit') {   params = {    search: params.searchText,    sort: params.sortName,    order: params.sortOrder   };   if (this.options.pagination) {    params.limit = this.options.pageSize === this.options.formatAllRows() ?     this.options.totalRows : this.options.pageSize;    params.offset = this.options.pageSize === this.options.formatAllRows() ?: this.options.pageSize * (this.options.pageNumber - 1);   }  }  if (!($.isEmptyObject(this.filterColumnsPartial))) {   params['filter'] = JSON.stringify(this.filterColumnsPartial, null);  }  data = calculateObjectValue(this.options, this.options.queryParams, [params], data);  $.extend(data, query || {});  // false to stop request  if (data === false) {   return;  }  if (!silent) {   this.$tableLoading.show();  }  request = $.extend({}, calculateObjectValue(null, this.options.ajaxOptions), {   type: this.options.method,   url: this.options.url,   data: this.options.contentType === 'application/json' && this.options.method === 'post' ?    JSON.stringify(data) : data,   cache: this.options.cache,   contentType: this.options.contentType,   dataType: this.options.dataType,   success: function (res) {    res = calculateObjectValue(that.options, that.options.responseHandler, [res], res);    that.load(res);    that.trigger('load-success', res);   },   error: function (res) {    that.trigger('load-error', res.status, res);   },   complete: function () {    if (!silent) {     that.$tableLoading.hide();    }   }  });  if (this.options.ajax) {   calculateObjectValue(this, this.options.ajax, [request], null);  } else {   $.ajax(request);  } };

代碼不難讀懂,解析參數(shù),整合參數(shù),得到參數(shù),發(fā)送ajax請(qǐng)求,在success事件里面將得到的數(shù)據(jù)渲染到界面。讀懂了這段代碼,我們?cè)賮矸庋bfunction就容易多了。

最終我們封裝的代碼如下:

(function ($) { 'use strict'; //debugger; //通過構(gòu)造函數(shù)獲取到bootstrapTable里面的初始化方法 var BootstrapTable = $.fn.bootstrapTable.Constructor,  _initData = BootstrapTable.prototype.initData,  _initPagination = BootstrapTable.prototype.initPagination,  _initBody = BootstrapTable.prototype.initBody,  _initServer = BootstrapTable.prototype.initServer,  _initContainer = BootstrapTable.prototype.initContainer; //重寫 BootstrapTable.prototype.initData = function () {  _initData.apply(this, Array.prototype.slice.apply(arguments)); }; BootstrapTable.prototype.initPagination = function () {  _initPagination.apply(this, Array.prototype.slice.apply(arguments)); }; BootstrapTable.prototype.initBody = function (fixedScroll) {  _initBody.apply(this, Array.prototype.slice.apply(arguments)); }; BootstrapTable.prototype.initServer = function (silent, query) {  //構(gòu)造自定義參數(shù)  for (var key in this.options.methodParams) {   $.fn.bootstrapTable.defaults.methodParams[key] = this.options.methodParams[key];  }  //如果傳了url,則走原來的邏輯  if (this.options.url) {   _initServer.apply(this, Array.prototype.slice.apply(arguments));   return;  }  //如果定義了abpMethod,則走abpMethod的邏輯  if (!this.options.abpMethod) {   return;  }  var that = this,   data = {},   params = {    pageSize: this.options.pageSize === this.options.formatAllRows() ?     this.options.totalRows : this.options.pageSize,    pageNumber: this.options.pageNumber,    searchText: this.searchText,    sortName: this.options.sortName,    sortOrder: this.options.sortOrder   },   request;  //debugger;  if (this.options.queryParamsType === 'limit') {   params = {    search: params.searchText,    sort: params.sortName,    order: params.sortOrder   };   if (this.options.pagination) {    params.limit = this.options.pageSize === this.options.formatAllRows() ?     this.options.totalRows : this.options.pageSize;    params.offset = this.options.pageSize === this.options.formatAllRows() ?     0 : this.options.pageSize * (this.options.pageNumber - 1);   }  }  if (!($.isEmptyObject(this.filterColumnsPartial))) {   params['filter'] = JSON.stringify(this.filterColumnsPartial, null);  }  data = $.fn.bootstrapTable.utils.calculateObjectValue(this.options, this.options.queryParams, [params], data);  $.extend(data, query || {});  // false to stop request  if (data === false) {   return;  }  if (!silent) {   this.$tableLoading.show();  }  this.options.abpMethod(data).done(function (result) {   result = $.fn.bootstrapTable.utils.calculateObjectValue(that.options, that.options.responseHandler, [result], result);   that.load(result);   that.trigger('load-success', result);  });  request = $.extend({}, $.fn.bootstrapTable.utils.calculateObjectValue(null, this.options.ajaxOptions), {   type: this.options.method,   url: this.options.url,   data: this.options.contentType === 'application/json' && this.options.method === 'post' ?    JSON.stringify(data) : data,   cache: this.options.cache,   contentType: this.options.contentType,   dataType: this.options.dataType,   success: function (res) {    debugger;    res = $.fn.bootstrapTable.utils.calculateObjectValue(that.options, that.options.responseHandler, [res], res);    that.load(res);    that.trigger('load-success', res);   },   error: function (res) {    that.trigger('load-error', res.status, res);   },   complete: function () {    if (!silent) {     that.$tableLoading.hide();    }   }  });  if (this.options.ajax) {   $.fn.bootstrapTable.utils.calculateObjectValue(this, this.options.ajax, [request], null);  } else {   $.ajax(request);  } } BootstrapTable.prototype.initContainer = function () {  _initContainer.apply(this, Array.prototype.slice.apply(arguments)); }; abp.bootstrapTableDefaults = {  striped: false,  classes: 'table table-striped table-bordered table-advance table-hover',  pagination: true,  cache: false,  sidePagination: 'server',  uniqueId: 'id',  showRefresh: false,  search: false,  method: 'post',  //toolbar: '#toolbar',  pageSize: 10,  paginationPreText: '上一頁',  paginationNextText: '下一頁',  queryParams: function (param) {   //$.fn.bootstrapTable.defaults.methodParams.propertyIsEnumerable()   var abpParam = {    Sorting: param.sort,    filter: param.search,    skipCount: param.offset,    maxResultCount: param.limit   };   for (var key in $.fn.bootstrapTable.defaults.methodParams) {    abpParam[key] = $.fn.bootstrapTable.defaults.methodParams[key];   }   return abpParam;  },  responseHandler: function (res) {   if (res.totalCount)    return { total: res.totalCount, rows: res.items };   else    return { total: res.result.totalCount, rows: res.result.items };  },  methodParams: {},  abpMethod: function () { } }; $.extend($.fn.bootstrapTable.defaults, abp.bootstrapTableDefaults);})(jQuery);

代碼釋疑:增加兩個(gè)參數(shù) methodParams: {},abpMethod: function () { } 來獲取abp的function和參數(shù),然后獲取數(shù)據(jù)的時(shí)候如果定義了abpMethod,則通過function獲取數(shù)據(jù),否則還是走原來的邏輯。

然后我們調(diào)用就簡單了

//選取界面上要先數(shù)據(jù)的表格  var _$SendOrdersTable = $('#SendOrdersTable');  //獲取服務(wù)層方法  var _SendOrderService = abp.services.app.sendOrder;  _$SendOrdersTable.bootstrapTable({   abpMethod: _SendOrderService.getSendOrderListAsync,   detailView: true,   onExpandRow: function (index, row, $detail) {    var cur_table = $detail.html('<table></table>').find('table');    $(cur_table).bootstrapTable({     showRefresh: false,     search: false,     pagination: false,     abpMethod: _SendOrderService.getSendOrderDetailListAsync,     methodParams: { SendOrderId: row.id },     columns: [      {       field: 'materialClassName',       title: app.localize('MaterialClassName'),       width: '8%'      },      {       field: 'typeNo',       title: app.localize('TypeNo'),       width: '8%'      }     ]    });   },   columns: [{    field: 'no',    title: app.localize('SendOrderNO'),    align: 'center'   },   {    field: 'supplierName',    title: app.localize('SupplierName'),    align: 'center'   },   {    title: app.localize('SendOrderTime'),    align: 'center',    field: 'createdDate',    formatter: function (data) {     return moment(data).format('YYYY-MM-DD HH:mm:ss');    }   },   {    field: 'status',    align: 'center',    title: app.localize('SendOrderStatus'),    formatter: function (data) {     var value = "";     if (data == 1) {      value = '<span class="label label-info">' + app.localize('Autdit') + '</span>';     }     else if (data == 2) {      value = '<span class="label label-success">' + app.localize('Pass') + '</span>';     }     else if (data == 3) {      value = '<span class="label label-default">' + app.localize('Reject') + '</span>';     }     else      value = '<span class="label label-default">' + app.localize('Abandon') + '</span>';     return value;    }   },   {    field: 'createName',    align: 'center',    title: app.localize('SendOrderCreator'),   },   {    field: 'sumCount',    align: 'center',    title: app.localize('SendOrderTotalCount'),   },   ]  });

得到如下效果

總結(jié)

以上所述是小編給大家介紹的在ABP框架中使用BootstrapTable組件的方法,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)武林網(wǎng)網(wǎng)站的支持!

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 寿宁县| 南涧| 资阳市| 西乌珠穆沁旗| 汕尾市| 怀安县| 普格县| 陇川县| 二连浩特市| 余江县| 同心县| 深州市| 郓城县| 建始县| 河南省| 屏东市| 雅江县| 巨野县| 延庆县| 韶山市| 凤台县| 道孚县| 武邑县| 平潭县| 墨玉县| 青冈县| 油尖旺区| 红河县| 石嘴山市| 鞍山市| 扬州市| 吉安市| 嘉禾县| 武穴市| 韶关市| 阳泉市| 洪江市| 江华| 平遥县| 浏阳市| 常州市|