antdvue实现Table末尾增加合计行
前言: 本文主要解决在
Ant Design Vue
中的table
组件末尾增加合计行的需求。 遇到的问题点有如下几个:
- table中的合计行如何添加?
- table中不是所有列都需要合计,如何处理?
- 有的是 “时分秒(hh:mm:ss)” 的合计,有的是数量的合计,有的是百分数的合计,需要前端自行计算,如何处理?
- 合计行的数据如何居中?
一、背景
最近后台管理系统的项目中有个新需求,在统计列表中,需要在末尾展示有些数据列的合计。原型图如下:
二、table中的合计行如何添加?
官网的Table表格中给出了“总结栏”的案例参考:
按照官网的示例,可以按照如下步骤实现:
在table中加入下图这部分代码,即#summary
设置合计栏,a-table-summary-row
和a-table-summary-cell
代码行列:
<template #summary v-if="dataSource && dataSource.length">
<a-table-summary-row align="center">
<a-table-summary-cell>合计</a-table-summary-cell>
<a-table-summary-cell>-</a-table-summary-cell>
<a-table-summary-cell v-for="(item, index) in columns.slice(2)" :key="index">
<a-typography-text>{{ combinedNums(item.dataIndex, item.type) }}</a-typography-text>
</a-table-summary-cell>
</a-table-summary-row>
</template>
三、table中不是所有列都需要合计,如何处理?
如我这边的原型图所示:
- 第一列是“合计”的文案,第二列是“姓名”的文案,处理方式如下图:
- 其余列用
for
循环统一处理:
// columns.slice(2):前两列不参与循环
<a-table-summary-cell v-for="(item, index) in columns.slice(2)" :key="index">
<a-typography-text>{{ combinedNums(item.dataIndex, item.type) }}</a-typography-text>
</a-table-summary-cell>
四、进行合计的数据类型不只是number
如原型图所示,我这边需要进行合计的有:时分秒、百分比、数量,下面分别列举解决方案。
- “时分秒(hh:mm:ss)” 的累加合计实现方案:
sumDurations(durations) {
let totalSeconds = durations.reduce((total, duration) => {
// 将时间字符串转换成时间组件
let parts = duration.split(':').map(Number);
// 将小时、分钟和秒转换为总秒数
let seconds = parts[0] * 3600 + parts[1] * 60 + parts[2];
// 累加总秒数
return total + seconds;
}, 0);
// 将总秒数转换回时间格式
let hours = Math.floor(totalSeconds / 3600);
totalSeconds %= 3600;
let minutes = Math.floor(totalSeconds / 60);
let seconds = totalSeconds % 60;
// 格式化为HH:MM:SS字符串
return [hours, minutes, seconds]
.map(num => num.toString().padStart(2, '0'))
.join(':');
}
// 示例使用
let durations = ['01:30:00', '02:15:00', '00:45:00'];
let totalDuration = sumDurations(durations);
console.log(totalDuration); // 输出累加后的时间 "04:30:00"
- 百分数的合计实现方案:
接口返回的是纯数字,不带百分号的值,所以需要前端进行手动拼接。
另外看需求限制保留几位小数。
ps:我这边百分数的合计是求的平均数,所以除以了数组的长度。
const total = this.dataSource.reduce((prev: number, next: { [x: string]: any }) => {
return prev + next[field]
}, 0)
return `${(total / this.dataSource.length).toFixed(2)}%`
- 数量的合计实现方案:
this.dataSource.reduce((prev: number, next: { [x: string]: any }) => {
return prev + next[field]
}, 0)
五、整理思路,实现结果
- 首先在
columns
数组中用type
区分类型:
combinedNums
方法接受两个参数,分别是字段名称
和type
类型:
具体实现方法如下:
combinedNums(field: string, type: any) {
if (type === 'num') {
return this.dataSource.reduce((prev: number, next: { [x: string]: any }) => {
return prev + next[field]
}, 0)
} else if (type === 'rate') {
const total = this.dataSource.reduce((prev: number, next: { [x: string]: any }) => {
return prev + next[field]
}, 0)
return `${(total / this.dataSource.length).toFixed(2)}%`
} else {
const sumTime = this.dataSource.map((item) => {
return item[field]
})
return this.sumDurations(sumTime)
}
},
六、合计行中的文案如何居中
在<a-table-summary-row>
标签中加上align="center"
即可:
以上,希望对大家有帮助!
转载自:https://juejin.cn/post/7361687968519340066