用的Antd 的 UI 框架。
场景:table 中后面想添加一行合计。合计的值前端计算得到。目前想到两种方法。
第一种:比较好维护。
第二种:使用antd4中summary
方法一:把合计行插入到数组中
需要对每列求和,然后插入到数组中
import React, { useEffect, useState } from 'react';
import { PageContainer } from '@ant-design/pro-layout';
import { Form, Input, Button, Card, Table } from 'antd';
/**
* 单元格合并处理
* @param text 当前单元格的值
* @param data 当前分页所有数据
* @param key 当前列的dataIndex
* @param index 当前数据所在下标
* @returns {number} 待合并单元格数量
*/
const mergeCells = (text, data, key, index) => {
// 上一行该列数据是否一样
if (index !== 0 && text === data[index - 1][key]) {
return 0
}
let rowSpan = 1
// 判断下一行是否相等
for (let i = index + 1; i < data.length; i++) {
if (text !== data[i][key]) {
break
}
rowSpan++
}
return rowSpan
}
export default () => {
const list = [
{
id: '1',
group: '组一',
age: 32,
age1: 32,
user: '用户1',
select: true,
},
{
id: '1',
group: '组一',
age: 32,
age1: 32,
user: '用户1',
select: true,
},
{
id: '1',
group: '组二',
age: 32,
age1: 32,
user: '用户1',
select: true,
},
{
id: '1',
group: '组二',
age: 32,
age1: 32,
user: '用户1',
select: true,
},
{
id: '1',
group: '组三',
age: 32,
age1: 32,
user: '用户1',
select: true,
},
{
id: '1',
group: '组四',
age: 32,
age1: 32,
user: '用户1',
select: true,
},
{
id: '1',
group: '组五',
age: 32,
age1: 8,
user: '用户1',
select: true,
},
{
id: '1',
group: '组五',
age: 32,
age1: 32,
user: '用户1',
select: true,
},
];
//定义获取求和方法
const getSummaries = (columns, data) => {
const sums = [];
let sumsInfo = {};
columns?.forEach((column, index) => {
if (index === 0) {
sums[index] = '总价';
sumsInfo = { total: '合计' }
return;
}
const values = data?.map(item => item[column.dataIndex]);
if (!values.every(value => isNaN(value))) {
let sum = values.reduce((prev, curr) => {
const value = Number(curr);
if (!isNaN(value)) {
return prev + curr;
} else {
return prev;
}
}, 0);
sums[index] = sum
sumsInfo = { ...sumsInfo, [column.dataIndex]: sum }
sums[index] += ' 元';
} else {
sums[index] = 'N/A';
}
});
return { sumsInfo, sums };
}
const getTotal = (columns, currentData) => {
const sums = {
index: '',
group: '',
age: 0,
age1: 0,
user: '合计',
}
let sumObj = getSummaries(columns, currentData).sumsInfo
return { ...sums, ...sumObj }
}
const columns = [
{
title: 'group',
dataIndex: 'group',
key: 'group',
render: (text, record, index) => {
const obj = {
children: text !== null ? text : '',
props: {}
}
obj.props.rowSpan = mergeCells(text, dataSource, 'group', index)
return obj
}
},
{
title: '用户',
dataIndex: 'user',
key: 'user',
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
},
{
title: '年龄',
dataIndex: 'age1',
key: 'age1',
},
{
title: '住址',
dataIndex: 'address',
key: 'address',
},
];
let sums = getTotal(columns, list)
const dataSource = list && list.length > 0 ? [...list, sums] : [];
console.log("getTotal", getTotal(columns, list))
return (
<PageContainer>
<Card title="Default size card">
<Table dataSource={dataSource} columns={columns} rowKey={record => record.id} bordered
/>
</Card>
</PageContainer>
);
}
方法二、使用antd4中summary
import React, { useEffect, useState } from 'react';
import { PageContainer } from '@ant-design/pro-layout';
import { Form, Input, Button, Card, Table } from 'antd';
/**
* 单元格合并处理
* @param text 当前单元格的值
* @param data 当前分页所有数据
* @param key 当前列的dataIndex
* @param index 当前数据所在下标
* @returns {number} 待合并单元格数量
*/
const mergeCells = (text, data, key, index) => {
// 上一行该列数据是否一样
if (index !== 0 && text === data[index - 1][key]) {
return 0
}
let rowSpan = 1
// 判断下一行是否相等
for (let i = index + 1; i < data.length; i++) {
if (text !== data[i][key]) {
break
}
rowSpan++
}
return rowSpan
}
export default () => {
const dataSource = [
{
id: '1',
group: '组一',
age: 32,
user: '用户1',
select: true,
},
{
id: '1',
group: '组一',
age: 32,
user: '用户1',
select: true,
},
{
id: '1',
group: '组二',
age: 32,
user: '用户1',
select: true,
},
{
id: '1',
group: '组二',
age: 32,
user: '用户1',
select: true,
},
{
id: '1',
group: '组三',
age: 32,
user: '用户1',
select: true,
},
{
id: '1',
group: '组四',
age: 32,
user: '用户1',
select: true,
},
{
id: '1',
group: '组五',
age: 32,
user: '用户1',
select: true,
},
{
id: '1',
group: '组五',
age: 32,
user: '用户1',
select: true,
},
];
const columns = [
{
title: 'group',
dataIndex: 'group',
key: 'group',
render: (text, record, index) => {
const obj = {
children: text !== null ? text : '',
props: {}
}
obj.props.rowSpan = mergeCells(text, dataSource, 'group', index)
return obj
}
},
{
title: '用户',
dataIndex: 'user',
key: 'user',
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
},
{
title: '年龄',
dataIndex: 'age2',
key: 'age2',
},
{
title: '住址',
dataIndex: 'address',
key: 'address',
},
];
/**
* @fun self-define summery.
* @param currentData
* @returns {*}
*/
const onSummary = (currentData) => {
const a = {
index: '总计',
user: "总计",
age: 0,
};
console.log(currentData);
const data = currentData.reduce((total, currentValue, currentIndex, arr) => {
return {
...a,
age: total.age + currentValue.age,
}
}, a)
return <>
<Table.Summary.Row>
{columns
.map((i, j) =>
<Table.Summary.Cell key={j + 1} index={j + 1}>
{data[i.dataIndex]}
</Table.Summary.Cell>
)
}
</Table.Summary.Row>
</>
}
return (
<PageContainer>
<Card title="Default size card">
<Table dataSource={dataSource} columns={columns} rowKey={record => record.id} bordered
summary={(currentData) => onSummary(currentData)}
/>
</Card>
</PageContainer>
);
}