React Antd 实现表格合计功能

思路:首先拿到 表格数组对象,然后写一个工具类,然后向数组对象最后插入一条数据,这条数据的字段时根据表格数组里合计算出来的。

代码如下,需根据各自业务稍作改动:

html 复制代码
 <Table dataSource={tableData}
                   columns={columns}
                   pagination={false}
            />
javascript 复制代码
    const columns = [
        {
            title: 'xxx',
            dataIndex: 'name',
            key: 'name',
            align: 'center',
        },
        {
            title: 'yyy',
            dataIndex: 'yyy',
            key: '',
            align: 'center',
            render: (text, record, rowIndex) => {
                return (<InputNumber min={0} value={text}
                                         onChange={(e) => handleCellChange(rowIndex, 'yyy', e)} />);
            },

    ]
}
javascript 复制代码
    // 每次数据变更计算一次合计
    const handleCellChange = (rowIndex, dataIndex, value) => {
        const newTableData = _.cloneDeep(tableData);
        newTableData[rowIndex][dataIndex] = value;
        countSum(newTableData, '', 'project');
        setTableData(newTableData);
    };


    // 第一次进来计算一次合计
    React.useEffect(() => {
        const newTableData = _.cloneDeep(tableData);
        countSum(newTableData, '', 'project');
        setTableData(newTableData);
    }, []);

合计工具类

javascript 复制代码
/**
 * 用于表格的合计计算
 *
 * @param arr 要计算的数组
 * @param prefix 要计算的数组的对象的前缀
 * @param sumField 合计字段名字放到哪个字段上
 * @param accuracy 合计精度
 * @returns {*}
 */
export function countSum(arr, prefix, sumField, accuracy = 4) {
  if (arr.length === 0) {
    // 没数据,直接返回
    return;
  }

  // 求和对象
  let sumObj = {};

  // 获取到最后一个数据
  let last = arr[arr.length - 1];
  if (prefix) {
    if (last[prefix][sumField] === '合计') {
      // 已经存在合计了
      sumObj = last;
      // 把 sum 的值清空,重新计算
      sumObj[prefix] = {};
      sumObj[prefix][sumField] = '合计';
    } else {
      sumObj[prefix] = {};
      sumObj[prefix][sumField] = '合计';
      arr.push(sumObj); // 在数组末尾添加合计对象
    }
  } else {
    if (last[sumField] === '合计') {
      // 已经存在合计了
      last = {};
      last[sumField] = '合计';
      arr[arr.length - 1] = last;
      sumObj = last;
    } else {
      sumObj[sumField] = '合计';
      arr.push(sumObj); // 在数组末尾添加合计对象
    }
  }


  let attrNames;
  if (prefix) {
    attrNames = Object.keys(arr[0][prefix]); // 获取数组中所有对象的属性名
  } else {
    attrNames = Object.keys(arr[0]); // 获取数组中所有对象的属性名
  }

  // -1 代表不累计合计本身的值
  for (let i = 0; i < attrNames.length - 1; i++) {
    const attrName = attrNames[i];

    for (let j = 0; j < arr.length - 1; j++) {
      let attrValue;
      if (prefix) {
        attrValue = arr[j][prefix][attrName];
      } else {
        attrValue = arr[j][attrName];
      }

      if (typeof attrValue == 'number') {

        // 只合计数值类型
        // 将属性值转换为数值类型
        let attrValueNumber = Number(attrValue).toFixed(4);

        if (prefix) {
          sumObj[prefix][attrName] = Number(parseFloat(Number(sumObj[prefix][attrName] || 0) + Number(attrValueNumber)).toFixed(accuracy)); // 求和
        } else {
          sumObj[attrName] = Number(parseFloat(Number(sumObj[attrName] || 0) + Number(attrValueNumber)).toFixed(accuracy)); // 求和
        }
      }
    }
  }
}
相关推荐
林涧泣9 分钟前
【Uniapp-Vue3】下拉刷新
前端·vue.js·uni-app
浪遏17 分钟前
Langchain.js | Memory | LLM 也有记忆😋😋😋
前端·llm·aigc
luoganttcc1 小时前
华为升腾算子开发(一) helloword
java·前端·华为
九月十九2 小时前
AviatorScript用法
java·服务器·前端
_.Switch3 小时前
Python Web开发:使用FastAPI构建视频流媒体平台
开发语言·前端·python·微服务·架构·fastapi·媒体
菜鸟阿康学习编程3 小时前
JavaWeb 学习笔记 XML 和 Json 篇 | 020
xml·java·前端
索然无味io4 小时前
XML外部实体注入--漏洞利用
xml·前端·笔记·学习·web安全·网络安全·php
ThomasChan1234 小时前
Typescript 多个泛型参数详细解读
前端·javascript·vue.js·typescript·vue·reactjs·js
爱学习的狮王4 小时前
ubuntu18.04安装nvm管理本机node和npm
前端·npm·node.js·nvm
东锋1.34 小时前
使用 F12 查看 Network 及数据格式
前端