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)); // 求和
        }
      }
    }
  }
}
相关推荐
siwangqishiq29 分钟前
Vulkan Tutorial 教程翻译(四) 绘制三角形 2.2 呈现
前端
李三岁_foucsli10 分钟前
js中消息队列和事件循环到底是怎么个事,宏任务和微任务还存在吗?
前端·chrome
尽欢i10 分钟前
HTML5 拖放 API
前端·html
PasserbyX26 分钟前
一句话解释JS链式调用
前端·javascript
1024小神27 分钟前
tauri项目,如何在rust端读取电脑环境变量
前端·javascript
Nano32 分钟前
前端适配方案深度解析:从响应式到自适应设计
前端
古夕37 分钟前
如何将异步操作封装为Promise
前端·javascript
小小小小宇37 分钟前
前端定高和不定高虚拟列表
前端
古夕1 小时前
JS 模块化
前端·javascript
wandongle1 小时前
HTML面试整理
前端·面试·html