# bootstrap table 重构 queryParams
queryParams:function(params){ | |
let filter = JSON.parse(params.filter); | |
let op = JSON.parse(params.op); | |
// 重构搜索条件 | |
filter['game.game_mode'] = 0; | |
filter['game.play_mode'] = 0; | |
op['game.game_mode'] = '='; | |
op['game.play_mode'] = '='; | |
params.filter = JSON.stringify(filter); | |
params.op = JSON.stringify(op); | |
console.log(params); | |
return params; | |
} |
# table 页脚统计和按钮复制到剪贴板等小功能
- 给 Table.api.init 内增加 showFooter:true 配置,开启页脚
- columns {field} 增加 footerFormatter:totalTextFormatter,作为统计表头
- 需要统计的列 添加代码 footerFormatter:function (rows){
return sumFormatter(rows,this.field)
} - 添加 js 方法和监听滚动条代码 (如果有滚动条可使页脚跟随滚动条滚动)
- 进阶 通过监听 checkbox, 页面只统计勾选的数据,用到 checkData 和 table.bootstrapTable ('resetFooter')
define(['jquery', 'bootstrap', 'backend', 'table', 'form','layui'], function ($, undefined, Backend, Table, Form) { | |
var Controller = { | |
index: function () { | |
// 初始化表格参数配置 | |
Table.api.init({ | |
showFooter:true, // 此处配置项有效 | |
extend: {} | |
}); | |
var table = $("#table"); | |
// 修改弹出框大小 | |
$('.btn-edit').data('area',["75%","75%"]) | |
// 初始化表格 | |
table.bootstrapTable({ | |
columns: [ | |
[ | |
{checkbox: true}, | |
{field: 'id', title: __('Id')}, | |
{field: 'operate', title: __('Operate'), table: table, | |
buttons: [ | |
{ | |
name: 'pwd', | |
text: __('Copy Account'), | |
icon: 'fa fa-copy', | |
classname: 'btn btn-xs btn-primary btn-ajax', | |
url: 'auth/admin/pwd?u={accname}', | |
success: function (data, ret) { | |
let info = '后台地址:' + data.url + '\n账号:' + data.username + '\n密码:' + data.pass; | |
// 使用方法 | |
var ct =new copy_txt(); | |
ct.copy(info);// 把 "xxx" 复制到粘贴板 | |
}, | |
error: function (data, ret) { | |
console.log(data, ret); | |
Layer.alert(ret.msg); | |
return false; | |
}, | |
visible: function (row) { | |
// 返回 true 时按钮显示,返回 false 隐藏 | |
if (row.account){ | |
return true; | |
}else{ | |
return false; | |
} | |
} | |
} | |
], events: Table.api.events.operate, formatter: Table.api.formatter.operate}, | |
{field: 'userName', title: __('Nickname'), operate: 'LIKE',footerFormatter:totalTextFormatter}, | |
{field: 'balance', title: __('Balance'),operate:false,operate:false,footerFormatter:function(rows){ | |
return sumFormatter(rows,this.field) | |
}}, | |
{field: 'frozen', title: __('Frozen Balance'),operate:false,operate:false,footerFormatter:function(rows){ | |
return sumFormatter(rows,this.field) | |
}}, | |
] | |
] | |
}); | |
// 监听 checkbox | |
table.on('check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table post-body.bs.table', function (e) { | |
checkData = Table.api.selecteddata(table); | |
table.bootstrapTable('resetFooter'); | |
}) | |
// 可以隐藏某一个列 | |
if (!Config.show) { | |
table.bootstrapTable('hideColumn','statmidday.platformFee'); | |
table.bootstrapTable('hideColumn','platformFee'); | |
table.bootstrapTable('hideColumn','frozenPlatformFee'); | |
} | |
// 修改表格内的按钮 | |
table.on('post-body.bs.table',function () { | |
$('.btn-editone').data('area',["75%","75%"]) | |
}) | |
var copy_txt=function(){// 无组件复制到剪贴板 | |
var _this =this; | |
this.copy=function(txt){ | |
$("#input_copy_txt_to_board").val(txt);// 赋值 | |
$("#input_copy_txt_to_board").removeClass("hide");// 显示 | |
$("#input_copy_txt_to_board").focus();// 取得焦点 | |
$("#input_copy_txt_to_board").select();// 选择 | |
document.execCommand("Copy"); | |
$("#input_copy_txt_to_board").addClass("hide");// 隐藏 | |
} | |
//----------- | |
let html ='<textarea class="hide" id="input_copy_txt_to_board" /></textarea>';// 添加一个隐藏的元素 可换行 | |
//let html ='<input type class="hide" id="input_copy_txt_to_board" value="" />';// 添加一个隐藏的元素 | |
$("body").append(html); | |
} | |
// 监听滚动条 | |
$(".fixed-table-body").on("scroll",function(){ | |
var sl=this.scrollLeft; | |
$(this).next()[0].scrollLeft = sl; | |
}) | |
// 为表格绑定事件 | |
Table.api.bindevent(table); | |
}, | |
// 页面弹出编辑框,提交修改后台刷新当前页面 | |
keepamount: function () { | |
Form.api.bindevent("form[role='form']", function(res){ | |
parent.location.reload();// 这里刷新父页面,可以换其他代码 | |
}); | |
}, | |
api: { | |
bindevent: function () { | |
Form.api.bindevent($("form[role=form]")); | |
} | |
} | |
}; | |
return Controller; | |
}); | |
// 页脚统计 js begin | |
function totalTextFormatter() { | |
return '总计:'; | |
} | |
let checkData = []; | |
function sumFormatter(rows,value,format= false) { | |
if (checkData.length) { | |
rows = checkData; | |
} | |
var sum = 0; | |
for (var i=0;i<rows.length;i++) { | |
sum += Number(rows[i][value]) | |
} | |
let result = 0; | |
if (format){ | |
result = sum.toString(); | |
}else { | |
result = toDecimal2(sum) | |
} | |
return result; | |
} | |
function toDecimal2(x) { | |
var f = Math.round(x * 100) / 100; | |
var s = f.toString(); | |
var rs = s.indexOf('.'); | |
if (rs < 0) { | |
rs = s.length; | |
s += '.'; | |
} | |
while (s.length <= rs + 2) { | |
s += '0'; | |
} | |
return s; | |
} | |
// 页脚统计 js end |
# 进阶 根据 checkbox 勾选,只页脚统计,勾选内容
通过 checkData 和 table.bootstrapTable ('resetFooter'); 实现
// 监听 checkbox | |
table.on('check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table post-body.bs.table', function (e) { | |
checkData = Table.api.selecteddata(table); | |
table.bootstrapTable('resetFooter'); | |
}) | |
let checkData = []; | |
function sumFormatter(rows,value,format= false) { | |
if (checkData.length) { | |
rows = checkData; | |
} | |
var sum = 0; | |
for (var i=0;i<rows.length;i++) { | |
sum += Number(rows[i][value]) | |
} | |
let result = 0; | |
if (format){ | |
result = sum.toString(); | |
}else { | |
result = toDecimal2(sum) | |
} | |
return result; | |
} |
注意
public/assets/libs/bootstrap-table/dist/bootstrap-table.js 中的 resetFooter 默认不开放
需要修改代码 大致 3016 行,把 resetFooter ,追加写在末尾
var allowedMethods = [... 省略其他方法名,'resetFooter']
改好后需要压缩 js, 并且复制到同目录下的 bootstrap-table.min.js 中
最后执行
php think min -m backend -r all
# table 页脚 bug - 页脚统计与列无法对齐
看起来就像页脚,每个单元格都多了一个像素,整的对不齐
后来我就找到这个页脚生成的 js, 做了些修改
public/assets/libs/bootstrap-table/dist/bootstrap-table.js 差不多在 2288 行
下面代码 注释的就是原来的 上面那行是我修改的
$footerTd.eq(i).find(".fht-cell").width($this[0].getBoundingClientRect().width - 1) | |
//$footerTd.eq(i).find(".fht-cell").width($this.innerWidth()) |
改好后需要压缩 复制到同目录下的 bootstrap-table.min.js
在线压缩工具
所以最后还要执行
php think min -m backend -r all
# table 页脚 bug - 页脚和固定列 css 问题
页脚和固定列同时开启时,固定列会多一块,可以用 css 样式去掉
<style> | |
.fixed-table-container .fixed-columns { | |
height: calc(100% - 116px) !important; | |
} | |
</style> | |
#table 开启固定列 | |
table.bootstrapTable({ | |
url: $.fn.bootstrapTable.defaults.extend.index_url, | |
pk: 'id', | |
sortName: 'id', | |
searchFormVisible: true, | |
toolbar: '#toolbar', | |
fixedColumns: true, //开启固定列 | |
fixedNumber: 2, //左边列固定 | |
#省略.. | |
}) |
# public/assets/libs/bootstrap-table/dist/bootstrap-table.js
BootstrapTable.prototype.fitFooter = function () { | |
//.... | |
//todo $this.innerWidth () 这个版本 js 无法获取精度数字 改好后压缩下 bootstrap-table.min.js | |
this.$body.find('>tr:first-child:not(.no-records-found) > *').each(function (i) { | |
var $this = $(this); | |
$footerTd.eq(i).find(".fht-cell").width($this[0].getBoundingClientRect().width - 1) | |
//$footerTd.eq(i).find(".fht-cell").width($this.innerWidth()) | |
}); | |
}; |
# tab 分页 多表 table
<div class="panel panel-default panel-intro"> | |
{:build_heading()} | |
<ul class="nav nav-tabs main"> | |
{foreach name="typeList" item="vo" index="i"} | |
<li {if $i==1}class="active"{/if}><a href="#{$key}" data-toggle="tab">{$vo}</a></li> | |
{/foreach} | |
</ul> | |
<div class="panel-body"> | |
<div id="myTabContent" class="tab-content"> | |
<div class="tab-pane fade active in" id="one"> | |
<div class="widget-body no-padding"> | |
<div id="toolbar" class="toolbar"> | |
{:build_toolbar('refresh,add,delete')} | |
</div> | |
<table id="table" class="table table-striped table-bordered table-hover" | |
data-operate-edit=false | |
width="100%"> | |
</table> | |
</div> | |
</div> | |
<div class="tab-pane fade" id="two"> | |
<div class="widget-body no-padding"> | |
<div id="toolbar2" class="toolbar"> | |
{:build_toolbar('refresh,add,delete')} | |
</div> | |
<table id="table2" class="table table-striped table-bordered table-hover" | |
data-operate-edit=false | |
width="100%"> | |
</table> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> |
对应 js
index: function () { | |
Table.api.init(); | |
// 绑定事件 | |
$('.main a[data-toggle="tab"]').on('shown.bs.tab', function (e) { | |
var panel = $($(this).attr("href")); | |
console.log(panel) | |
if (panel.size() > 0) { | |
Controller.table[panel.attr("id")].call(this); | |
$(this).on('click', function (e) { | |
console.log(1) | |
$($(this).attr("href")).find(".btn-refresh").trigger("click"); | |
}); | |
} | |
// 移除绑定的事件 | |
$(this).unbind('shown.bs.tab'); | |
}); | |
// 必须默认触发 shown.bs.tab 事件 | |
$('ul.nav-tabs li.active a[data-toggle="tab"]').trigger("shown.bs.tab"); | |
}, | |
table: { | |
one: function () { | |
var table = $("#table"); | |
// 初始化表格 | |
table.bootstrapTable({ | |
url: '', | |
extend: { | |
index_url: '', | |
add_url: '', | |
del_url: '', | |
table: '', | |
}, | |
pk: 'id', | |
sortName: 'weigh', | |
toolbar:'#toolbar', | |
columns: [ | |
[ | |
{checkbox: true}, | |
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate} | |
] | |
], | |
sidePagination: "client", // 客户端分页 | |
}); | |
// 为表格绑定事件 | |
Table.api.bindevent(table); | |
}, | |
two: function () { | |
var table = $("#table2"); | |
// 初始化表格 | |
table.bootstrapTable({ | |
url: '', | |
extend: { | |
index_url: '', | |
add_url: ', | |
del_url: '', | |
table: '', | |
}, | |
pk: 'id', | |
sortName: 'weigh', | |
toolbar:'#toolbar2', | |
columns: [ | |
[ | |
{checkbox: true}, | |
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate} | |
] | |
], | |
sidePagination: "client", // 客户端分页 | |
}); | |
// 为表格绑定事件 | |
Table.api.bindevent(table); | |
}, | |
}, |
# btn-group 按钮组 dropdown
当按钮太多时,把几个按钮合并到按钮组中
buttons: [ | |
{ | |
name: '', | |
text: '', | |
title: '', | |
classname: 'btn btn-xs btn-info btn-dialog', | |
icon: 'fa fa-list-alt', | |
url: '', | |
extend: 'data-area=\'["650px", "450px"]\'', | |
dropdown:__('Operate'), // 需要放一起的按钮都加上 dropdown | |
callback: function (data) { | |
}, | |
visible: function (row) { | |
// 返回 true 时按钮显示,返回 false 隐藏 | |
return true; | |
} | |
} | |
] |
由于 btn-group 按钮组 显示的不太友好 自己瞎搞调整了下 css 样式
.dropdown-menu.pull-right { | |
right: auto; | |
top: auto; | |
margin-top: 24px; | |
} | |
.dropdown-menu > li > a { | |
text-align: left; | |
} | |
.btn-group { | |
position: inherit; | |
display: inline-flex; | |
} |
# btn-group 多个按钮组中间有个逗号
require-table.js html.unshift (dropdownHtml) 修改 html.unshift (dropdownHtml.join (' '))
if (!$.isEmptyObject(dropdowns)) { | |
var dropdownHtml = []; | |
$.each(dropdowns, function (i, j) { | |
dropdownHtml.push('<div class="btn-group"><button type="button" class="btn btn-primary dropdown-toggle btn-xs" data-toggle="dropdown">' + i + '</button><button type="button" class="btn btn-primary dropdown-toggle btn-xs" data-toggle="dropdown"><span class="caret"></span></button><ul class="dropdown-menu dropdown-menu-right"><li>' + j.join('</li><li>') + '</li></ul></div>'); | |
}); | |
html.unshift(dropdownHtml.join(' ')); | |
} | |
return html.join(' '); |
# 表格显示列,全选与全不选
参考链接
https://ask.fastadmin.net/question/9304.html
index: function () { | |
// 初始化表格参数配置 | |
var table = $("#table"); | |
table.on('post-common-search.bs.table', function (e, settings, json, xhr) { | |
$("ul.dropdown-menu", settings.$toolbar).prepend("<li role='menucheckall'><label><input type='checkbox' checked> 全选/反选</label></li>"); | |
$(document).on("click", "ul.dropdown-menu li[role='menucheckall'] input", function (e) { | |
e.stopPropagation(); | |
var that = settings; | |
var checked = $(this).prop('checked'); | |
$("ul.dropdown-menu li[role='menuitem'] input").each(function () { | |
that.toggleColumn($(this).val(), checked, false); | |
that.trigger('column-switch', $(this).data('field'), checked); | |
$(this).prop("checked", checked); | |
}); | |
}); | |
}); | |
// 为表格绑定事件 | |
Table.api.bindevent(table); | |
} |
# 单日期 day 自定义搜索
bootstrap table 的搜索样式 单个日期搜索
参考链接
https://ask.fastadmin.net/question/28226.html
[ | |
{field: 'day', title: __('Day'), addclass:'datetimepicker', data: 'data-date-format="YYYYMMDD"'}, | |
] |
显示有 bug
.bootstrap-table .form-commonsearch .form-group { | |
white-space: normal; | |
} |
# bulid_checkboxs 增加全选 / 反选
bulid_checkboxs 构建的多选框 没有全选 / 反选
这里通过在数组开头增加 ['' => ' 全选 / 反选 ']
bulid_checkboxs ('status []',['' => ' 全选 / 反选 ',... 其他元素])
再配合 js 达成 全选 / 反选的效果
// 初始化 checkbox 是否勾选全选 / 反选 | |
function init(name) { | |
let elem = $('input[name="' + name + '"]'); | |
// 当前列 checkbox 除了全选 / 反选的 元素数量 | |
let len = elem.length - 1; | |
let chk = $('input[name="' + name + '"]:checked'); | |
let chklen = chk.length; | |
// 排除全选 | |
if (elem.first().prop("checked")) { | |
chklen = chk.length - 1; | |
} | |
if (len == chklen && chklen != 0){ | |
elem.first().prop("checked",true); | |
}else { | |
elem.first().prop("checked",false); | |
} | |
} | |
init('status'); | |
$(":checkbox").on('click',function(){ | |
// 获取当前 name | |
let name = $(this).attr('name'); | |
let elem = $('input[name="' + name + '"]'); | |
// 当前列 checkbox 除了全选 / 反选的 元素数量 | |
let len = elem.length - 1; | |
// 判断全选 / 反选 | |
let checked = $(this).prop('checked'); | |
let key = $(this).val(); | |
if (key == '') { | |
if (checked) { | |
elem.prop("checked",true); | |
} else { | |
elem.prop("checked",false); | |
} | |
} | |
// 如果有一个未选中则取消全选按钮的选中状态 / 全都选择设置全选按钮为选中状态 | |
let chk = $('input[name="' + name + '"]:checked'); | |
let chklen = chk.length; | |
// 排除全选 | |
if (elem.first().prop("checked")) { | |
chklen = chk.length - 1; | |
} | |
if (len == chklen && chklen != 0){ | |
elem.first().prop("checked",true); | |
}else { | |
elem.first().prop("checked",false); | |
} | |
}) |
如果不选 checkbox ,php 后台接收参数不是 [] 而是 [0 => '']
可用 array_filter 过滤
status);
# 实用的表格列表字段显示优化,采用 cookie 记忆隐藏字段功能。
参考链接
https://ask.fastadmin.net/article/9464.html
define(['jquery', 'bootstrap', 'backend', 'table', 'form','cookie'], function ($, undefined, Backend, Table, Form) { | |
var Controller = { | |
index: function () { | |
// 初始化表格参数配置 | |
var table = $("#table"); | |
// 选择隐藏字段事件,使用cookie存入 | |
table.on('column-switch.bs.table', function (e, json) { | |
var myColumns = []; | |
$.each(table.bootstrapTable('getHiddenColumns'), function (i, item) { | |
myColumns.push(item.field); | |
}); | |
let cookieName = 'fa_<!--swig0-->' //fa_\{%table%\} 反斜杆去掉 | |
$.cookie(cookieName, JSON.stringify(myColumns), {expires: 365, path: '/'}); | |
}); | |
if ($.cookie(cookieName)) { | |
//读取cookie隐藏字段 | |
$.each(JSON.parse($.cookie(cookieName)), function (i, item) { | |
table.bootstrapTable('hideColumn', item); | |
}); | |
} | |
// 为表格绑定事件 | |
Table.api.bindevent(table); | |
} | |
} | |
}) |
# 记录当前窗体内的确认框触发
$('.btn-release').on('click',function () { | |
event.preventDefault(); | |
Layer.confirm(__('Confirm Release?'), { | |
title: __('Confirm Release?'), | |
}, function (index) { | |
Fast.api.ajax({ | |
url: "", | |
}, function (data) { | |
Layer.closeAll('dialog'); // 关闭确认框 | |
Fast.api.close(1); // 关闭窗体并回传数据 | |
parent.$(".btn-refresh").trigger("click"); // 触发窗体的父页面刷新 | |
},function () { | |
}); | |
}, function (index) { | |
}); | |
}); |
# 自定义搜索 (下拉框搜索)
fastAdmin 有个开发实例的插件,包括一些实用的技巧,如下
var table = $("#table"); | |
// 在普通搜索渲染后 | |
table.on('post-common-search.bs.table', function (event, table) { | |
var form = $("form", table.$commonsearch); | |
$("input[name='bankID']", form).addClass("selectpage").data("source", "bank/bank/index").data("primaryKey", "id").data("field", "account").data("orderBy", "id desc"); | |
Form.events.cxselect(form); | |
Form.events.selectpage(form); | |
}); | |
let col = [ | |
{checkbox: true}, | |
{field: 'id', title: __('Id')}, | |
{field: 'bankID', title: __('Account'),visible: false}, | |
{field: 'bank.account', title: __('Account'), operate: false}, | |
] |
# 固定表格高度
<table data-height="500"></table> |
或
table.bootstrapTable({ | |
... | |
height: 500, | |
... | |
}) |
# 添加表格显示列的全选反选
// 添加表格显示列的全选反选 | |
table.on('post-common-search.bs.table', function (e, settings, json, xhr) { | |
$("ul.dropdown-menu", settings.$toolbar).prepend("<li role='menucheckall'><label><input type='checkbox' checked> 全选/反选</label></li>"); | |
$(document).on("click", "ul.dropdown-menu li[role='menucheckall'] input", function (e) { | |
e.stopPropagation(); | |
var that = settings; | |
var checked = $(this).prop('checked'); | |
$("ul.dropdown-menu li[role='menuitem'] input").each(function () { | |
that.toggleColumn($(this).val(), checked, false); | |
that.trigger('column-switch', $(this).data('field'), checked); | |
$(this).prop("checked", checked); | |
}); | |
}); | |
}); |
# 表格导出插件,日期自动转换问题
参考地址 https://www.cnblogs.com/darkestinblack/p/12557433.html
exportOptions: { | |
// 省略 | |
mso: { | |
//cell td 实例 | |
//row td 所在行 | |
//col td 所在列 | |
onMsoNumberFormat: function (cell, row, col) { | |
return '\\@'; | |
} | |
}, | |
}, |
# 非 weigh 字段如何排序
对应 js
// 初始化表格参数配置 | |
Table.api.init({ | |
showFooter:true, // 此处配置项有效 | |
extend: { | |
// 添加排序 url | |
dragsort_url: 'ajax/weigh', | |
... | |
} | |
}); | |
// 重新定义排序字段 | |
Table.config.dragsortfield = 'sort'; |
修改 application/admin/controller/Ajax.php 中的 weigh 方法
/** | |
* 通用排序 | |
*/ | |
public function weigh() | |
{ | |
... | |
// 限制更新的字段 | |
$field = in_array($field, ['weigh','sort']) ? $field : 'weigh'; | |
} |
# 搜索加载完成触发 tab 状态分页,并查询状态
table.on('post-common-search.bs.table', function (event, table) { | |
$('ul.nav-tabs li a[data-value="0"]').trigger('click'); | |
$(".form-commonsearch select[name=status]").val("0"); | |
}); |
# 表格列样式 cellStyle
{field: 'field', title: __('field'),operate:false,cellStyle: function (value, row, index) { | |
return {css: {"background-color": "rgb(24,188,156)"}}; | |
}}, |
# 表格公共搜索,带默认值,隐藏对应搜索框
// 在普通搜索渲染后 | |
table.on('post-common-search.bs.table', function (event, table) { | |
var form = $("form", table.$commonsearch); | |
var arr = ['day','type']; | |
for (let item of table.columns) { | |
if (arr.indexOf(item.field) >= 0 && item.defaultValue.length) { | |
$("input[name='" + item.field + "']", form).parent().parent().addClass('hide'); | |
} | |
} | |
}); |