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

如何让可折叠表格中折叠行的单元格与展开行单元格对齐

问题原因

你的代码中折叠行的结构不符合HTML表格规范:非首条taskAction对应的行里,你用一个设置了colSpan={9}的TableCell占满整行后,直接把9个TableCell放在Collapse组件内,这些单元格没有父级TableRow,也不属于外层表格的行结构,浏览器不会按外层表头的列宽进行排版,因此出现对齐错乱。

修复方案

这里提供两种常用实现方式,按需选择即可:

方案1:保留展开/收起动画(推荐)

参考MUI官方可折叠表格的实现逻辑,在Collapse内部嵌套一个和外层表头结构完全一致的内部表格,自动继承外层列宽实现对齐,修改后的代码如下:

function Task(props: { task: taskProps }) {  
  const { task } = props;  
  const [open, setOpen] = React.useState(false);
  // 拆分首条展示action和剩余折叠action,避免map中判断索引
  const [firstAction, ...restActions] = task.tasksActions;

  return (
    <>
      {/* 首行可展开头部,逻辑保持不变 */}
      <TableRow>
        <TableCell>
            <IconButton
                aria-label="expand row"
                size="small"
                onClick={() => setOpen(!open)}
            >
                {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
            </IconButton>
        </TableCell>
        <TableCell>{task.taskId}</TableCell>
        <TableCell>{firstAction.actionId}</TableCell>
        <TableCell>{firstAction.templateStepId}</TableCell>
        <TableCell>{firstAction.templateStepName}</TableCell>
        <TableCell>100</TableCell>
        <TableCell>{firstAction.startedAt}</TableCell>
        <TableCell>{firstAction.endedAt}</TableCell>
        <TableCell>{firstAction.status}</TableCell>
      </TableRow>
      {/* 折叠内容容器行 */}
      <TableRow>
        <TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={9}>
          <Collapse in={open} timeout="auto" unmountOnExit>
            {/* 内部表格结构和外层表头完全对应,保证对齐 */}
            <Table size="small" sx={{ border: 0 }}>
              <TableBody>
                {restActions.map((taskAction, index) => (
                  <TableRow key={index} sx={{ '&:last-child td, &:last-child th': { border: 0 } }}>
                    <TableCell padding="none">{/* 对应外层展开按钮列,留空对齐 */}</TableCell>
                    <TableCell>{task.taskId}</TableCell>
                    <TableCell>{taskAction.actionId}</TableCell>
                    <TableCell>{taskAction.templateStepId}</TableCell>
                    <TableCell>{taskAction.templateStepName}</TableCell>
                    <TableCell>100</TableCell>
                    <TableCell>{taskAction.startedAt}</TableCell>
                    <TableCell>{taskAction.endedAt}</TableCell>
                    <TableCell>{taskAction.status}</TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </Collapse>
        </TableCell>
      </TableRow>
    </>
  );
}

// 外层MetricsTable组件无需修改

代码中新增的sx样式用于移除内部表格的多余边框,保证和外层表格视觉统一。

方案2:无动画,对齐最精准

如果不需要展开收起的过渡动画,可以直接把剩余的action渲染为外层表格的直接子行,通过display属性控制显示隐藏,天然继承外层表格的列宽,对齐效果最完美:

function Task(props: { task: taskProps }) {  
  const { task } = props;  
  const [open, setOpen] = React.useState(false);
  const [firstAction, ...restActions] = task.tasksActions;

  return (
    <>
      {/* 首行可展开头部 */}
      <TableRow>
        <TableCell>
            <IconButton
                aria-label="expand row"
                size="small"
                onClick={() => setOpen(!open)}
            >
                {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
            </IconButton>
        </TableCell>
        <TableCell>{task.taskId}</TableCell>
        <TableCell>{firstAction.actionId}</TableCell>
        <TableCell>{firstAction.templateStepId}</TableCell>
        <TableCell>{firstAction.templateStepName}</TableCell>
        <TableCell>100</TableCell>
        <TableCell>{firstAction.startedAt}</TableCell>
        <TableCell>{firstAction.endedAt}</TableCell>
        <TableCell>{firstAction.status}</TableCell>
      </TableRow>
      {/* 剩余action直接渲染为普通行,控制显示隐藏 */}
      {restActions.map((taskAction, index) => (
        <TableRow key={index} style={{ display: open ? 'table-row' : 'none' }}>
          <TableCell>{/* 对应外层展开按钮列,留空对齐 */}</TableCell>
          <TableCell>{task.taskId}</TableCell>
          <TableCell>{taskAction.actionId}</TableCell>
          <TableCell>{taskAction.templateStepId}</TableCell>
          <TableCell>{taskAction.templateStepName}</TableCell>
          <TableCell>100</TableCell>
          <TableCell>{taskAction.startedAt}</TableCell>
          <TableCell>{taskAction.endedAt}</TableCell>
          <TableCell>{taskAction.status}</TableCell>
        </TableRow>
      ))}
    </>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 07:27:04