likes
comments
collection
share

antdvue实现Table末尾增加合计行

作者站长头像
站长
· 阅读数 4

前言: 本文主要解决在Ant Design Vue中的table组件末尾增加合计行的需求。 遇到的问题点有如下几个:

  1. table中的合计行如何添加?
  2. table中不是所有列都需要合计,如何处理?
  3. 有的是 “时分秒(hh:mm:ss)” 的合计,有的是数量的合计,有的是百分数的合计,需要前端自行计算,如何处理?
  4. 合计行的数据如何居中?

一、背景

最近后台管理系统的项目中有个新需求,在统计列表中,需要在末尾展示有些数据列的合计。原型图如下:

antdvue实现Table末尾增加合计行

二、table中的合计行如何添加?

官网的Table表格中给出了“总结栏”的案例参考:

antdvue实现Table末尾增加合计行

按照官网的示例,可以按照如下步骤实现: 在table中加入下图这部分代码,即#summary设置合计栏,a-table-summary-rowa-table-summary-cell代码行列:

antdvue实现Table末尾增加合计行

<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中不是所有列都需要合计,如何处理?

如我这边的原型图所示:

  1. 第一列是“合计”的文案,第二列是“姓名”的文案,处理方式如下图:

antdvue实现Table末尾增加合计行

  1. 其余列用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

如原型图所示,我这边需要进行合计的有:时分秒、百分比、数量,下面分别列举解决方案。

  1. “时分秒(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"
  1. 百分数的合计实现方案:

接口返回的是纯数字,不带百分号的值,所以需要前端进行手动拼接。

另外看需求限制保留几位小数。

ps:我这边百分数的合计是求的平均数,所以除以了数组的长度。

const total = this.dataSource.reduce((prev: number, next: { [x: string]: any }) => {
  return prev + next[field]
}, 0)
return `${(total / this.dataSource.length).toFixed(2)}%`
  1. 数量的合计实现方案:
this.dataSource.reduce((prev: number, next: { [x: string]: any }) => {
  return prev + next[field]
}, 0)

五、整理思路,实现结果

  1. 首先在columns数组中用type区分类型:

antdvue实现Table末尾增加合计行

  1. combinedNums方法接受两个参数,分别是字段名称type类型:

antdvue实现Table末尾增加合计行

具体实现方法如下:

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"即可:

antdvue实现Table末尾增加合计行

以上,希望对大家有帮助!