table 增加参数 footer-data

This commit is contained in:
xuliangzhan
2024-03-20 17:54:53 +08:00
parent fdecfc4985
commit b4f8d33e1b
8 changed files with 79 additions and 323 deletions

View File

@@ -12,7 +12,7 @@
highlight-hover-row
show-footer
max-height="400"
:footer-method="footerMethod1"
:footer-data="footerData1"
:data="tableData1">
<vxe-column type="seq" width="60"></vxe-column>
<vxe-column field="name" title="Name" sortable></vxe-column>
@@ -21,13 +21,6 @@
<vxe-column field="amount" title="Amount"></vxe-column>
</vxe-table>
<p class="demo-code">{{ $t('app.body.button.showCode') }}</p>
<pre>
<pre-code class="xml">{{ demoCodes[0] }}</pre-code>
<pre-code class="javascript">{{ demoCodes[1] }}</pre-code>
</pre>
<p class="tip">还可以配合 <table-api-link prop="footer-cell-class-name"/> 自定义不同列颜色</p>
<vxe-table
@@ -45,14 +38,6 @@
<vxe-column field="amount" title="Amount"></vxe-column>
</vxe-table>
<p class="demo-code">{{ $t('app.body.button.showCode') }}</p>
<pre>
<pre-code class="xml">{{ demoCodes[2] }}</pre-code>
<pre-code class="javascript">{{ demoCodes[3] }}</pre-code>
<pre-code class="css">{{ demoCodes[4] }}</pre-code>
</pre>
<p class="tip">还可以固定列</p>
<vxe-toolbar>
@@ -80,14 +65,6 @@
<vxe-column field="date" title="Date" min-width="600"></vxe-column>
<vxe-column field="amount" title="Amount" width="200" fixed="right"></vxe-column>
</vxe-table>
<p class="demo-code">{{ $t('app.body.button.showCode') }}</p>
<pre>
<pre-code class="xml">{{ demoCodes[5] }}</pre-code>
<pre-code class="javascript">{{ demoCodes[6] }}</pre-code>
<pre-code class="javascript">{{ demoCodes[7] }}</pre-code>
</pre>
</div>
</template>
@@ -106,7 +83,7 @@ export default {
{ id: 10006, name: 'Test6', role: 'Designer', sex: '0', age: 21, amount: 998, address: 'test abc' }
],
footerData1: [
['合计', '2', '44', '67', '-']
{ name: 11, sex: 44 }
],
tableData2: [
{ id: 10001, name: 'Test1', role: 'Develop', sex: '0', age: 28, amount: 888, address: 'test abc' },
@@ -127,265 +104,6 @@ export default {
{ id: 10006, name: 'Test6', role: 'Designer', sex: '0', age: 21, amount: 998, address: 'test abc' },
{ id: 10007, name: 'Test7', role: 'Test', sex: '1', age: 29, amount: 2000, address: 'test abc' },
{ id: 10008, name: 'Test8', role: 'Develop', sex: '1', age: 35, amount: 999, address: 'test abc' }
],
demoCodes: [
`
<vxe-table
class="mytable-footer"
border
highlight-hover-row
show-footer
max-height="400"
:footer-method="footerMethod1"
:data="tableData1">
<vxe-column type="seq" width="60"></vxe-column>
<vxe-column field="name" title="Name" sortable></vxe-column>
<vxe-column field="sex" title="Sex"></vxe-column>
<vxe-column field="age" title="Age"></vxe-column>
<vxe-column field="amount" title="Amount"></vxe-column>
</vxe-table>
`,
`
export default {
data () {
return {
tableData1: [
{ id: 10001, name: 'Test1', role: 'Develop', sex: '0', age: 28, amount: 888, address: 'test abc' },
{ id: 10002, name: 'Test2', role: 'Test', sex: '1', age: 22, amount: 666, address: 'Guangzhou' },
{ id: 10003, name: 'Test3', role: 'PM', sex: '1', age: 32, amount: 89, address: 'Shanghai' },
{ id: 10004, name: 'Test4', role: 'Designer', sex: '0', age: 23, amount: 1000, address: 'test abc' },
{ id: 10005, name: 'Test5', role: 'Develop', sex: '0', age: 30, amount: 999, address: 'Shanghai' },
{ id: 10006, name: 'Test6', role: 'Designer', sex: '0', age: 21, amount: 998, address: 'test abc' }
],
footerData1: [
['合计', '2', '44', '67', '-']
]
}
},
methods: {
footerMethod1 () {
// 返回一个二维数组的表尾合计
return this.footerData1
}
}
}
`,
`
<vxe-table
class="mytable-footer"
border
show-footer
height="400"
:footer-method="footerMethod"
:footer-cell-class-name="footerCellClassName2"
:data="tableData2">
<vxe-column type="seq" width="60"></vxe-column>
<vxe-column field="name" title="Name" sortable></vxe-column>
<vxe-column field="sex" title="Sex"></vxe-column>
<vxe-column field="age" title="Age"></vxe-column>
<vxe-column field="amount" title="Amount"></vxe-column>
</vxe-table>
`,
`
export default {
data () {
return {
tableData2: [
{ id: 10001, name: 'Test1', role: 'Develop', sex: '0', age: 28, amount: 888, address: 'test abc' },
{ id: 10002, name: 'Test2', role: 'Test', sex: '1', age: 22, amount: 666, address: 'Guangzhou' },
{ id: 10003, name: 'Test3', role: 'PM', sex: '1', age: 32, amount: 89, address: 'Shanghai' },
{ id: 10004, name: 'Test4', role: 'Designer', sex: '0', age: 23, amount: 1000, address: 'test abc' },
{ id: 10005, name: 'Test5', role: 'Develop', sex: '0', age: 30, amount: 999, address: 'Shanghai' },
{ id: 10006, name: 'Test6', role: 'Designer', sex: '0', age: 21, amount: 998, address: 'test abc' },
{ id: 10007, name: 'Test7', role: 'Test', sex: '1', age: 29, amount: 2000, address: 'test abc' },
{ id: 10008, name: 'Test8', role: 'Develop', sex: '1', age: 35, amount: 999, address: 'test abc' }
]
}
},
methods: {
footerCellClassName2 ({ $rowIndex, column, columnIndex }) {
if (columnIndex === 0) {
if ($rowIndex === 0) {
return 'col-blue'
} else {
return 'col-red'
}
}
},
meanNum (list, field) {
let count = 0
list.forEach(item => {
count += Number(item[field])
})
return count / list.length
},
sumNum (list, field) {
let count = 0
list.forEach(item => {
count += Number(item[field])
})
return count
},
footerMethod ({ columns, data }) {
const means = []
const sums = []
const others = []
columns.forEach((column, columnIndex) => {
if (columnIndex === 0) {
means.push('平均')
sums.push('和值')
others.push('其他')
} else {
let meanCell = null
let sumCell = null
let otherCell = '-'
switch (column.property) {
case 'age':
case 'amount':
meanCell = this.meanNum(data, column.property)
sumCell = this.sumNum(data, column.property)
break
case 'sex':
otherCell = '无'
break
}
means.push(meanCell)
sums.push(sumCell)
others.push(otherCell)
}
})
// 返回一个二维数组的表尾合计
return [means, sums, others]
}
}
}
`,
`
.mytable-footer .col-blue {
background-color: #2db7f5;
color: #fff;
}
.mytable-footer .col-red {
background-color: red;
color: #fff;
}
`,
`
<vxe-toolbar>
<template #buttons>
<vxe-button @click="showHeader = !showHeader">显示/隐藏表头</vxe-button>
<vxe-button @click="showFooter = !showFooter">显示/隐藏表尾</vxe-button>
</template>
</vxe-toolbar>
<vxe-table
class="mytable-footer"
border
height="400"
show-overflow
:show-header="showHeader"
:show-footer="showFooter"
:footer-method="footerMethod"
:footer-cell-class-name="footerCellClassName3"
:data="tableData3">
<vxe-column type="seq" width="60" fixed="left"></vxe-column>
<vxe-colgroup title="基本信息">
<vxe-column field="name" title="Name" min-width="600" sortable></vxe-column>
<vxe-column field="age" title="Age" min-width="600"></vxe-column>
</vxe-colgroup>
<vxe-column field="date" title="Date" min-width="600"></vxe-column>
<vxe-column field="rate" title="Rate" width="200" fixed="right"></vxe-column>
</vxe-table>
`,
`
export default {
data () {
return {
showFooter: true,
tableData3: [
{ id: 10001, name: 'Test1', role: 'Develop', sex: '0', age: 28, amount: 888, address: 'test abc' },
{ id: 10002, name: 'Test2', role: 'Test', sex: '1', age: 22, amount: 666, address: 'Guangzhou' },
{ id: 10003, name: 'Test3', role: 'PM', sex: '1', age: 32, amount: 89, address: 'Shanghai' },
{ id: 10004, name: 'Test4', role: 'Designer', sex: '0', age: 23, amount: 1000, address: 'test abc' },
{ id: 10005, name: 'Test5', role: 'Develop', sex: '0', age: 30, amount: 999, address: 'Shanghai' },
{ id: 10006, name: 'Test6', role: 'Designer', sex: '0', age: 21, amount: 998, address: 'test abc' },
{ id: 10007, name: 'Test7', role: 'Test', sex: '1', age: 29, amount: 2000, address: 'test abc' },
{ id: 10008, name: 'Test8', role: 'Develop', sex: '1', age: 35, amount: 999, address: 'test abc' }
]
}
},
methods: {
footerCellClassName3 ({ $rowIndex, column }) {
if (column.type === 'seq') {
if ($rowIndex === 0) {
return 'col-blue'
} else {
return 'col-red'
}
} else if (column.property === 'age') {
if ($rowIndex === 1) {
return 'col-red'
}
}
},
meanNum (list, field) {
let count = 0
list.forEach(item => {
count += Number(item[field])
})
return count / list.length
},
sumNum (list, field) {
let count = 0
list.forEach(item => {
count += Number(item[field])
})
return count
},
footerMethod ({ columns, data }) {
const means = []
const sums = []
const others = []
columns.forEach((column, columnIndex) => {
if (columnIndex === 0) {
means.push('平均')
sums.push('和值')
others.push('其他')
} else {
let meanCell = null
let sumCell = null
let otherCell = '-'
switch (column.property) {
case 'age':
case 'amount':
meanCell = this.meanNum(data, column.property)
sumCell = this.sumNum(data, column.property)
break
case 'sex':
otherCell = '无'
break
}
means.push(meanCell)
sums.push(sumCell)
others.push(otherCell)
}
})
// 返回一个二维数组的表尾合计
return [means, sums, others]
}
}
}
`,
`
.mytable-footer .col-blue {
background-color: #2db7f5;
color: #fff;
}
.mytable-footer .col-red {
background-color: red;
color: #fff;
}
`
]
}
},

View File

@@ -4,6 +4,7 @@ import vSize from '../../mixins/size'
import UtilTools, { getFuncText } from '../../tools/utils'
import DomTools from '../../tools/dom'
import { GlobalEvent } from '../../tools/event'
// import { warnLog } from '../../tools/log'
export default {
name: 'VxeButton',
@@ -45,6 +46,12 @@ export default {
}
},
created () {
// if (process.env.VUE_APP_VXE_TABLE_ENV === 'development') {
// if (props.type === 'text') {
// warnLog('vxe.error.delFunc', ['type=text', 'mode=text'])
// }
// }
GlobalEvent.on(this, 'mousewheel', this.handleGlobalMousewheelEvent)
},
beforeDestroy () {

View File

@@ -152,7 +152,22 @@ export default {
const columnIndex = $xetable.getColumnIndex(column)
const _columnIndex = $xetable.getVTColumnIndex(column)
const itemIndex = _columnIndex
const params = { $table: $xetable, $grid: $xetable.xegrid, _rowIndex, $rowIndex, column, columnIndex, $columnIndex, _columnIndex, itemIndex, items: list, fixed: fixedType, type: cellType, data: footerTableData }
const params = {
$table: $xetable,
$grid: $xetable.xegrid,
row: list,
_rowIndex,
$rowIndex,
column,
columnIndex,
$columnIndex,
_columnIndex,
itemIndex,
items: list,
fixed: fixedType,
type: cellType,
data: footerTableData
}
// 虚拟滚动不支持动态高度
if (scrollXLoad && !hasEllipsis) {
showEllipsis = hasEllipsis = true

View File

@@ -88,7 +88,7 @@ function renderTitleContent (h, params, content) {
}
function getFooterContent (h, params) {
const { $table, column, _columnIndex, items } = params
const { $table, column, _columnIndex, row, items } = params
const { slots, editRender, cellRender } = column
const renderOpts = editRender || cellRender
if (slots && slots.footer) {
@@ -100,7 +100,11 @@ function getFooterContent (h, params) {
return getSlotVNs(compConf.renderFooter.call($table, h, renderOpts, params))
}
}
return [UtilTools.formatText(items[_columnIndex], 1)]
// 兼容老模式
if (XEUtils.isArray(items)) {
return [UtilTools.formatText(items[_columnIndex], 1)]
}
return [UtilTools.formatText(XEUtils.get(row, column.field), 1)]
}
function getDefaultCellLabel (params) {

View File

@@ -4356,9 +4356,9 @@ const Methods = {
return !!rowExpandedMaps[rowid]
},
isExpandByRow (row) {
// if (process.env.VUE_APP_VXE_TABLE_ENV === 'development') {
// warnLog('vxe.error.delFunc', ['isExpandByRow', 'isRowExpandByRow'])
// }
if (process.env.VUE_APP_VXE_TABLE_ENV === 'development') {
warnLog('vxe.error.delFunc', ['isExpandByRow', 'isRowExpandByRow'])
}
// 即将废弃
return this.isRowExpandByRow(row)
},
@@ -5031,10 +5031,14 @@ const Methods = {
* 更新表尾合计
*/
updateFooter () {
const { showFooter, visibleColumn, footerMethod } = this
if (showFooter && footerMethod) {
this.footerTableData = visibleColumn.length ? footerMethod({ columns: visibleColumn, data: this.afterFullData, $table: this, $grid: this.$xegrid }) : []
const { showFooter, visibleColumn, footerData, footerMethod } = this
let footData = []
if (showFooter && footerData && footerData.length) {
footData = footerData.slice(0)
} else if (showFooter && footerMethod) {
footData = visibleColumn.length ? footerMethod({ columns: visibleColumn, data: this.afterFullData, $table: this, $grid: this.$xegrid }) : []
}
this.footerTableData = footData
return this.$nextTick()
},
/**

View File

@@ -134,6 +134,8 @@ export default {
highlightCell: Boolean,
// 是否显示表尾合计
showFooter: Boolean,
// 表尾数据
footerData: Array,
// 表尾合计的计算方法
footerMethod: Function,
// 给行附加 className
@@ -780,8 +782,8 @@ export default {
if (treeConfig && (treeOpts.showLine || treeOpts.line) && (!(this.rowKey || rowOpts.useKey) || !showOverflow)) {
warnLog('vxe.error.reqProp', ['row-config.useKey | show-overflow'])
}
if (this.showFooter && !this.footerMethod) {
warnLog('vxe.error.reqProp', ['footer-method'])
if (this.showFooter && !(this.footerMethod || this.footerData)) {
warnLog('vxe.error.reqProp', ['footer-data | footer-method'])
}
if (treeConfig && this.stripe) {
warnLog('vxe.error.noTree', ['stripe'])

57
types/footer.d.ts vendored
View File

@@ -16,31 +16,32 @@ export type ColumnFooterSlotParams = ColumnFooterRenderParams
*/
export interface ColumnFooterRenderParams extends TableRenderParams {
/**
* 列对象
*/
column: ColumnInfo;
/**
* 相对于 columns 中的索引
*/
columnIndex: number;
/**
* 相对于当前表格列中的索引
*/
_columnIndex: number;
/**
* 相对于可视区渲染中的列索引
*/
$columnIndex: number;
/**
* 相对于表尾行数据的索引
*/
$rowIndex: number;
/**
* 表尾项列表
*/
items: any[];
/**
* 表尾数据集
*/
data: any[][];
}
* 列对象
*/
column: ColumnInfo;
/**
* 相对于 columns 中的索引
*/
columnIndex: number;
/**
* 相对于当前表格列中的索引
*/
_columnIndex: number;
/**
* 相对于可视区渲染中的列索引
*/
$columnIndex: number;
row: any
/**
* 相对于表尾行数据的索引
*/
$rowIndex: number;
/**
* 表尾项列表
*/
items: any[];
/**
* 表尾数据集
*/
data: any[][];
}

5
types/table.d.ts vendored
View File

@@ -94,6 +94,10 @@ export declare class Table extends VXETableComponent {
* 是否显示表尾
*/
showFooter?: boolean;
/**
* 表尾数据
*/
footerData: any[]
/**
* 表尾数据获取的方法
*/
@@ -1198,6 +1202,7 @@ export interface TableOptions {
*/
highlightCell?: boolean;
showFooter?: boolean;
footerData?: any[];
footerMethod?: typeof TableFooterMethod;
rowClassName?: string | ((params: any) => any);
cellClassName?: string | ((params: any) => any);