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> <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> <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存储用户手动修改过的子行名称,避免覆盖已编辑的金额 - 重构金额计算逻辑:
- 先统计所有已编辑子行的总金额
- 用父行总金额减去已编辑金额,得到剩余可分配金额
- 仅对未编辑过的子行进行均分计算,已编辑子行保持用户设置值
- 优化输入体验:将输入框改为
number类型并设置step="0.01",支持小数金额输入 - 对均分金额保留两位小数,符合金额展示规范
内容的提问来源于stack exchange,提问作者Nawaz Pasha
相关产品推荐
相关产品推荐

