You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中实现多子行金额批量更新与自动计算需求

多子行金额自动均分解决方案

场景背景

  • 存在包含**名称(Name)和金额(Amount)**的父行(Parent Row)
  • 子行(Sub rows)是父行的细分项,同样包含名称和金额

需求问题

实现更新多个子行金额后,自动计算剩余未编辑子行的均分金额。
示例:父行总金额为5000,修改Jan为2000、Feb为1000后,剩余3个子行自动计算为666.66。

当前已实现效果

仅支持修改单个子行金额,其余所有子行自动重置为均分金额。
示例:修改Jan为2000后,其余4个子行自动设为750。


修改后的代码

import { useState } from 'react';
import './App.css';

function App() {
  // 记录已手动修改的子行名称
  const [editedMonths, setEditedMonths] = useState<Set<string>>(new Set());
  const [data, setData] = useState([
    {
      name: 'Admission Fee',
      amount: 5000,
      months: [
        { name: 'Jan', amount: 1000 },
        { name: 'Feb', amount: 1000 },
        { name: 'Mar', amount: 1000 },
        { name: 'Apr', amount: 1000 },
        { name: 'May', amount: 1000 }
      ]
    }
  ]);

  const handleSubRowChange = (totalAmount: number, newSubAmount: string, monthName: string) => {
    const row = data[0];
    // 标记当前修改的子行为已编辑
    const newEditedMonths = new Set(editedMonths);
    newEditedMonths.add(monthName);
    
    // 计算所有已编辑子行的总金额
    const editedTotal = row.months
      .filter(month => newEditedMonths.has(month.name))
      .reduce((sum, month) => {
        return sum + (month.name === monthName ? Number(newSubAmount) : month.amount);
      }, 0);
    
    // 剩余可分配金额 = 父行总金额 - 已编辑子行总金额
    const remainingAmount = totalAmount - editedTotal;
    // 未编辑子行的数量
    const uneditedCount = row.months.length - newEditedMonths.size;
    // 未编辑子行的均分金额(避免除以0的异常)
    const exactAmount = uneditedCount > 0 ? remainingAmount / uneditedCount : 0;

    const updatedMonths = row.months.map(month => {
      if (month.name === monthName) {
        return {
          ...month,
          amount: Number(newSubAmount)
        };
      } else if (newEditedMonths.has(month.name)) {
        // 已编辑过的子行保持用户设置的金额
        return { ...month };
      } else {
        // 未编辑子行使用均分金额,保留两位小数
        return {
          ...month,
          amount: Number(exactAmount.toFixed(2))
        };
      }
    });

    setEditedMonths(newEditedMonths);
    setData([{ ...row, months: updatedMonths }]);
  };

  return (
    <>
      {data?.map(e => (
        <div key={e.name}>
          <div style={{ display: 'flex', flexDirection: 'row', margin: '8px 0' }}>
            <span style={{ fontWeight: 'bold' }}>{e.name}</span>
            &nbsp;&nbsp;
            <span>总金额: {e.amount}</span>
          </div>
          <div style={{ marginLeft: '20px' }}>
            {e.months.map(m => (
              <div key={m.name} style={{ display: 'flex', flexDirection: 'row', margin: '4px 0' }}>
                <span style={{ width: '40px' }}>{m.name}</span>
                &nbsp;&nbsp;
                <input
                  type='number'
                  step="0.01"
                  value={m.amount}
                  onChange={(event) => {
                    handleSubRowChange(e.amount, event.target.value, m.name);
                  }}
                  style={{ width: '100px' }}
                />
              </div>
            ))}
          </div>
        </div>
      ))}
    </>
  );
}

export default App;

核心修改说明

  • 新增editedMonths状态,用Set存储用户手动修改过的子行名称,避免覆盖已编辑的金额
  • 重构金额计算逻辑:
    1. 先统计所有已编辑子行的总金额
    2. 用父行总金额减去已编辑金额,得到剩余可分配金额
    3. 仅对未编辑过的子行进行均分计算,已编辑子行保持用户设置值
  • 优化输入体验:将输入框改为number类型并设置step="0.01",支持小数金额输入
  • 对均分金额保留两位小数,符合金额展示规范

内容的提问来源于stack exchange,提问作者Nawaz Pasha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 19:22:54