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

JavaScript合并同年份表格行问题:代码无报错但未生效

解决表格相同年份行合并及金额累加问题

嘿,作为JS新手碰到这种表格行合并+数据累加的需求确实容易踩坑,我来帮你捋清楚问题出在哪,再给你一套可行的实现方案~

首先,先揪出你代码里的一个致命问题:你的ERB模板里,每个表格行的年份单元格都用了id="pin",如果金额列也是id="price"的话,这完全违反了HTML的规则——同一个页面里id必须唯一!浏览器的querySelector只会返回第一个匹配该id的元素,后面的行根本拿不到年份和金额数据,这大概率就是你的代码没生效的核心原因!

先把ERB代码改了,把重复的id换成class:

<tr class="<%= payment_paid(f.paid)%> paidrow"> 
  <td> 
    <% if !f.paid %> 
      <%= check_box_tag "pin_number[]", f.id, checked= !f.paid? %> 
    <%end%> 
  </td> 
  <td class="pin"><%= f.year %></td>
  <!-- 假设你的金额列是下面这样,同样把id改成class -->
  <td class="price"><%= f.price %></td>
  <!-- 其他列... -->
</tr>

(顺便说一句:原来的tr用了id="paidrow",循环生成多行的话这个id也重复了,也得改成class哦)

接下来,我们写前端JS逻辑,核心思路是:先按年份把行分组,累加每组的金额,然后只保留每组的第一行,设置单元格的rowspan来实现合并,同时隐藏其他重复行。

把这段代码放在页面底部,或者用DOMContentLoaded确保DOM加载完成后再执行:

document.addEventListener('DOMContentLoaded', function() {
  // 获取所有目标表格行
  const rows = document.querySelectorAll('tr.paidrow');
  if (rows.length === 0) return;

  // 用对象分组,key是年份,value存总金额和对应的行集合
  const yearGroups = {};

  // 第一步:遍历所有行,分组并累加金额
  rows.forEach(row => {
    // 提取年份,注意去掉前后空格
    const year = row.querySelector('.pin').textContent.trim();
    // 提取金额,处理掉非数字字符后转成数字
    const priceStr = row.querySelector('.price').textContent.trim().replace(/[^0-9.]/g, '');
    const price = parseFloat(priceStr) || 0;

    // 初始化分组
    if (!yearGroups[year]) {
      yearGroups[year] = {
        total: 0,
        rows: []
      };
    }
    yearGroups[year].total += price;
    yearGroups[year].rows.push(row);
  });

  // 第二步:处理每组的行合并
  Object.values(yearGroups).forEach(group => {
    // 取出第一行和其他行
    const [firstRow, ...otherRows] = group.rows;
    // 设置年份单元格的rowspan为组内行数,实现合并
    const pinCell = firstRow.querySelector('.pin');
    pinCell.setAttribute('rowspan', group.rows.length);

    // 更新第一行的金额为累加后的总数,保留两位小数(格式可按需调整)
    const priceCell = firstRow.querySelector('.price');
    priceCell.textContent = `${group.total.toFixed(2)}`;

    // 隐藏其他重复的行
    otherRows.forEach(row => {
      row.style.display = 'none';
    });
  });
});

再补充几个注意点:

  • 如果你的表格是AJAX动态加载的(比如分页、筛选后重新渲染),那DOMContentLoaded事件已经触发过了,这时候要把这段JS代码放在表格渲染完成的回调里执行,或者用MutationObserver监听表格的变化。
  • 如果金额带千分位(比如1,200.00),可以在转数字前先去掉逗号:priceStr.replace(/,/g, '')。
  • 要是你需要合并其他列(比如和年份同组的其他单元格),可以参照年份单元格的方式设置rowspan。

这样改完之后,应该就能实现你想要的相同年份行合并、金额累加的效果啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:53:41