一、关于ABP
ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称,它是一个成熟的开源框架,基于DDD+Repository模式,自带Zero权限和认证模块,避免了从零开始搭建框架的烦恼。关于ABP的框架优势就此打住,因为这样说下去要说三天三夜,脱离文本主题。
关于ABP的入门,博主不想说太多,园子里面tkb至简和阳光铭睿有很多入门级的文章,有兴趣的可以了解下,还是给出它的官网和开源地址。
ABP官方网站:http://www.aspnetboilerplate.com
ABP开源项目:https://github.com/aspnetboilerplate
PS:如果你不愿意去看它的源码,可以直接查看ABP官网上面的演示地址:https://aspnetzero.com/"text-align: center">
点击CREATE MY DEMO按钮,系统会自动为你生成演示地址
进入对应的Demo URL
使用演示的用户名和密码登陆进去
可以看到Zero模块的实现效果。
二、jTable在ABP中的运用
如果你下载ABP的源码,并且选择的是混合开发模式(ABP提供了两种开发模式,一种是基于MVVM的Angular.js的模式;另一种就是MVC+jQuery的混合开发模式),如下图:
当你Down下来源码之后你就会发现,ABP的源码里面的UI部分的表格都是使用jTable去实现的。为什么会用jTable?原因很简单,jTable是ABP的作者kalkan写的一款开源插件,自己写的肯定用自己的东西喽。下面jTable的效果来一发。
来一个jtable的父子表:
如果是不带父子表的简单表格,其实jTable的效果其实还行,可是加上一些复杂的功能之后,那一片片蓝色的区域不忍直视,并且jTable的api还有待完善,很多需要的功能都需要自己去实现,于是就接到了将所有的表格组件换成BootstrapTable的需求,才有了今天的主题:在ABP中封装BootstrapTable。
三、Bootstrap Table在ABP中的封装
接到需求,博主各种百度、各种谷歌,都找不到Bootstrap Table组件在ABP中的封装,有的只是在ABP的项目里面简单的用传统的方式去初始化组件,这并不是博主想要的。说到这里不得不说一下,如果你使用ABP开发的过程中遇到一些难题,你会发现很难从百度里面搜索到相关答案,谷歌里面有时能找到,但大部分都是英文社区,所以如果你英文较弱,在查找资料上面会很吃亏,有时一个简单的配置问题需要折腾很久。
1、jTable在ABP项目里面的初始化
首先来看看jTable在一般的ABP项目里面是如何初始化的。比如我们在Application里面有一个如下的接口和实现
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
);
}
}
然后我们前端有一个页面的列表数据从这个接口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="/UploadFiles/2021-04-02/list_metro.png">
得到如下效果:
代码释疑:
(1) var _service = abp.services.app.requisition; 这一句声明当前页面需要使用哪个服务。
(2) _service.getRequisitionListAsync 这一句对应的是服务调用的方法,你会发现在后台方法名是GetRequisitionListAsync(),而在js里面却变成了getRequisitionListAsync(),我们暂且称之为“潜规则”。
2、bootstrapTable在ABP项目里面的封装
通过上述代码你会发现,ABP在application层里面定义的方法,最终会生成某一些js对应的function,这里难点来了。我们找遍了bootstrapTable组件的api,都没有通过某一个function去获取数据的啊。这可如何是好?为这个问题,博主折腾了两天。最开始博主想,function最终还不是要换成http请求的,我们只要拿到http请求的url,然后将function转换为url不就行了么:
我们使用bootstrapTable组件初始化的时候声明 {url:'/api/services/app/requisition/GetRequisitionListAsync'} 这样不就行了么?呵呵,经过测试,这样确实能正确取到数据。但是不够理想,因为这前面的前缀是ABP给我们生成的,是否会变化我们尚且不说,给每一个url加上这么一长串着实看着很不爽,于是进一步想,是否我们的bootstrapTable也可以使用function去初始化呢,组件没有,难道我们就不能给他扩展一个吗?我们不用url获取数据,通过调用这个function取到数据,然后将数据渲染到组件不就行了。思路有了,那么这里有两个难题:一是如何将原来url的方式变成这里的调用function的方式呢?二是参数的封装。经过查看组件的源码发现,如果是服务端分页,组件最终是进入到initServer()这个方法去获取数据,然后渲染到页面上面的,组件原始的initServer()方法如下:
BootstrapTable.prototype.initServer = function (silent, query) {
var that = this,
data = {},
params = {
pageSize: this.options.pageSize === this.options.formatAllRows() "htmlcode">
(function ($) {
'use strict';
//debugger;
//通过构造函数获取到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) {
//构造自定义参数
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() "htmlcode">
//选取界面上要先数据的表格
var _$SendOrdersTable = $('#SendOrdersTable');
//获取服务层方法
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'),
},
]
});
得到如下效果
总结
以上所述是小编给大家介绍的在ABP框架中使用BootstrapTable组件的方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]










