前言:bootstrap-table默认的打印组件对于数据组合表头并不是很合适,打印组合列会出现各种各样的问题,于是对bootstrap-table-print进行升级。
/**
* @update sunck
*/
const Utils = $.fn.bootstrapTable.utils
function printPageBuilderDefault (table) {
return `
Print Table
${table}
`
}
$.extend($.fn.bootstrapTable.defaults, {
showPrint: false,
printAsFilteredAndSortedOnUI: true,
printSortColumn: undefined,
printSortOrder: 'asc',
printPageBuilder (table) {
return printPageBuilderDefault(table)
}
})
$.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, {
printFilter: undefined,
printIgnore: false,
printFormatter: undefined
})
$.extend($.fn.bootstrapTable.defaults.icons, {
print: {
bootstrap3: 'glyphicon-print icon-share',
'bootstrap-table': 'icon-printer'
}[$.fn.bootstrapTable.theme] || 'fa-print'
})
$.BootstrapTable = class extends $.BootstrapTable {
init (...args) {
super.init(...args)
if (!this.options.showPrint) {
return
}
this.mergedCells = []
}
initToolbar (...args) {
this.showToolbar = this.showToolbar || this.options.showPrint
super.initToolbar(...args)
if (!this.options.showPrint) {
return
}
const $btnGroup = this.$toolbar.find('>.columns')
let $print = $btnGroup.find('button.bs-print')
if (!$print.length) {
$print = $(`
`
).appendTo($btnGroup)
}
$print.off('click').on('click', () => {
this.doPrint(this.options.printAsFilteredAndSortedOnUI ?
this.getData() : this.options.data.slice(0))
})
}
mergeCells (options) {
super.mergeCells(options)
if (!this.options.showPrint) {
return
}
let col = this.getVisibleFields().indexOf(options.field)
if (Utils.hasDetailViewIcon(this.options)) {
col += 1
}
this.mergedCells.push({
row: options.index,
col,
rowspan: options.rowspan || 1,
colspan: options.colspan || 1
})
}
doPrint (data) {
const formatValue = (row, i, column) => {
const value = Utils.calculateObjectValue(column, column.printFormatter,
[row[column.field], row, i], row[column.field])
return typeof value === 'undefined' || value === null
? this.options.undefinedText : value
}
/**
* 格式化列
* @param columnsArray
*/
const formatColumnsArray = (columnsArray) =>{
let volimnsArray = [];
for (let i = 0; i < columnsArray[0].length; i++) {
let spanNum = columnsArray[0][i].colspan ? columnsArray[0][i].colspan : 1;
for (let j = 0; j < spanNum; j++) {
volimnsArray.push("");
}
}
for (let i = 0; i < columnsArray.length; i++) {
let volimnsArrayNum = 0;
for (let j = 0; j < columnsArray[i].length; j++) {
let column = columnsArray[i][j];
if(!column.printIgnore && column.field !=undefined && (i == columnsArray.length-1 || column.rowspan == columnsArray.length - i)){
if(volimnsArray.length > volimnsArrayNum ){
if(volimnsArray[volimnsArrayNum] == ""){
volimnsArray[volimnsArrayNum] = column;
console.log(column.title);
}else{
for (let k = volimnsArrayNum+1; k < volimnsArray.length; k++) {
if(volimnsArray[k] == ""){
volimnsArray[k] = column;
volimnsArrayNum = k;
break;
}
}
}
}
volimnsArrayNum++;
}else{
volimnsArrayNum =volimnsArrayNum + column.colspan
}
}
}
return volimnsArray;
}
const buildTable = (data, columnsArray) => {
const dir = this.$el.attr('dir') || 'ltr'
const html = [``]
for (const columns of columnsArray) {
html.push('')
for (let h = 0; h < columns.length; h++) {
if (!columns[h].printIgnore) {
html.push(
`${columns[h].title} `)
}
}
html.push(' ')
}
html.push('')
const dontRender = []
if (this.mergedCells) {
for (let mc = 0; mc < this.mergedCells.length; mc++) {
const currentMergedCell = this.mergedCells[mc]
for (let rs = 0; rs < currentMergedCell.rowspan; rs++) {
const row = currentMergedCell.row + rs
for (let cs = 0; cs < currentMergedCell.colspan; cs++) {
const col = currentMergedCell.col + cs
dontRender.push(row + ',' + col)
}
}
}
}
let columns = formatColumnsArray(columnsArray)//使用格式化后的数据操作
for (let i = 0; i < data.length; i++) {
html.push('')
for (let j = 0; j < columns.length; j++) {
let rowspan = 0
let colspan = 0
if (this.mergedCells) {
for (let mc = 0; mc < this.mergedCells.length; mc++) {
const currentMergedCell = this.mergedCells[mc]
if (currentMergedCell.col === j && currentMergedCell.row === i) {
rowspan = currentMergedCell.rowspan
colspan = currentMergedCell.colspan
}
}
}
if (
!columns[j].printIgnore && columns[j].field != undefined
&& (
!dontRender.includes(i + ',' + j)
|| (rowspan > 0 && colspan > 0)
)
) {
// console.log("处理当前的id+"+columns[j].title);
if (rowspan > 0 && colspan > 0) {
html.push(``, formatValue(data[i], i, columns[j]), ' ')
} else {
html.push('', formatValue(data[i], i, columns[j]), ' ')
}
}
}
html.push(' ')
}
html.push('')
if (this.options.showFooter) {
html.push('')
}
html.push('
')
return html.join('')
}
const sortRows = (data, colName, sortOrder) => {
if (!colName) {
return data
}
let reverse = sortOrder !== 'asc'
reverse = -((+reverse) || -1)
return data.sort((a, b) => reverse * (a[colName].localeCompare(b[colName])))
}
const filterRow = (row, filters) => {
for (let index = 0; index < filters.length; ++index) {
if (row[filters[index].colName] !== filters[index].value) {
return false
}
}
return true
}
const filterRows = (data, filters) => data.filter(row => filterRow(row, filters))
const getColumnFilters = columns => !columns || !columns[0] ? [] : columns[0].filter(col => col.printFilter).map(col => ({
colName: col.field,
value: col.printFilter
}))
data = filterRows(data, getColumnFilters(this.options.columns))
data = sortRows(data, this.options.printSortColumn, this.options.printSortOrder)
const table = buildTable(data, this.options.columns)
const newWin = window.open('')
newWin.document.write(this.options.printPageBuilder.call(this, table))
newWin.document.close()
newWin.focus()
newWin.print()
newWin.close()
}
}
将官方的文件替换即可。