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

如何基于表格分组行添加自定义<th>实现分组名称与计数展示

表格分组自定义表头实现方案

核心修改逻辑:

  • 单独生成分组头行,不再复用分组内第一条数据行
  • 分组头默认展示分组ID(首个内容)与当前分组内条目总数
  • 折叠按钮固定在分组头末尾,优化可见性
  • 原有子行数据展示、折叠交互逻辑保持不变

完整修改后代码

// 生成timesheet表格内容
fetch(timehsheetUrl + date)
    .then(response => response.json())
    .then(data => makeTable(data.contracts))
    .catch(error => console.log(`Oh no! ${error}`))

const makeTable = (contracts) => {
    console.log(contracts);
    const body = document.getElementById('tsdata');
    let counter = 0; // 补充原代码缺失的counter变量定义
    contracts.forEach((person, index) => {
        person.details.forEach((entry) => {
            const dateString = entry.timesheetDate;
            const dateObject = new Date(dateString);
            const dd = dateObject.getDate();
            const mm = dateObject.toLocaleString('en-us', {
                month: 'short'
            });
            const yyyy = dateObject.getFullYear();
            const chartDate = `${dd}-${mm}-${yyyy}`;

            const htmlTemplate = `
                <tr class="testDeleteTimesheet subrow">
                  <td>${entry.contractCode}</td>
                  <td class="timesheetDetailsID" style="display:none;">${entry.timesheetDetailsId}</td>
                  <td>${entry.activityCode}</td>
                  <td>${entry.otFlag}</td>
                  <td>${entry.notes}</td>
                  <td>${chartDate}</td>
                  <td class="totalHours">${entry.hours}</td>
                  <td>
                    <button id="edit-${counter}" class="btn editRow btnStyle btn-primary btn-sm"><span class="bi bi-pencil"></span></button> 
                    <button id="delete-${counter}" class="btn delRow btnStyle btn-danger btn-sm"><span class="bi bi-eraser"></span></button>
                  </td>
                </tr>
            `;
            body.innerHTML += htmlTemplate;
            counter++;
        });

        const tables = $('table')[0];
        const rowGroups = {};
        // 遍历所有行(跳过表头)
        while(tables.rows.length > 1){
            const row = tables.rows[1];
            const id = $(row.cells[0]).text();
            if(!rowGroups[id]) rowGroups[id] = [];
            rowGroups[id].push(row);
            tables.deleteRow(1);
        }
        // 遍历分组生成新表格结构
        for(let id in rowGroups){
            const group = rowGroups[id];
            const groupLen = group.length;
            // 生成自定义分组头行
            const groupHeaderRow = document.createElement('tr');
            groupHeaderRow.className = 'group-header';
            // 跨列显示分组名称与数量,最后一列放折叠按钮
            groupHeaderRow.innerHTML = `
                <td colspan="${tables.rows[0].cells.length - 1}"><strong>${id}(共${groupLen}条)</strong></td>
                <td><span class='collapsed' style="cursor: pointer; font-size: 16px;">+</span></td>
            `;
            // 绑定折叠点击事件
            $(groupHeaderRow).find('.collapsed').click(plusClick);
            tables.tBodies[0].appendChild(groupHeaderRow);
            // 插入所有子行
            group.forEach(row => {
                $(row).hide(); // 默认折叠隐藏
                tables.tBodies[0].appendChild(row);
            });
        }
        // 折叠点击处理函数
        function plusClick(e){
            const collapsed = $(this).hasClass('collapsed');
            $(this).text(collapsed ? '-' : '+');
            $(this).closest('tr').nextUntil('.group-header').slideToggle(400);
            $(this).toggleClass('collapsed');
        }
    });
};

可选样式优化

可以添加以下CSS让分组头更醒目:

.group-header {
    background-color: #f5f5f5;
    font-weight: 500;
}
.group-header td {
    padding: 8px 12px;
}
.collapsed {
    user-select: none;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 17:54:03