Bootstrap

antd 表格合计栏

用的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>
    );
}
;