Skip to content

feat: support rowspan expanded #1276

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

crazyair
Copy link
Contributor

@crazyair crazyair commented May 19, 2025

Summary by CodeRabbit

  • 新功能

    • 表格支持可展开行的自定义跨行(rowSpan)合并,展开行时单元格跨行数动态调整。
    • 新增示例演示结合可展开行与跨行合并的使用场景。
  • 文档

    • 增加了“expandedRowSpan”功能的示例文档和演示页面。
  • 修复

    • 优化数据结构,确保每条数据包含唯一的 rowKey,提升表格渲染准确性。

PixPin_2025-05-20_07-17-56

Copy link

vercel bot commented May 19, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
table ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 20, 2025 10:23pm

Copy link

coderabbitai bot commented May 19, 2025

Walkthrough

本次更新主要扩展了表格行和单元格的属性,支持根据行展开状态动态调整单元格的 rowSpan。通过在数据结构中加入 rowKey,并将所有行的 rowKeys 传递给 BodyRow 和 getCellProps,实现了更灵活的合并单元格逻辑。同时新增了相关文档和示例。

Changes

文件/文件组 变更摘要
src/Body/BodyRow.tsx BodyRowProps 接口新增 rowKeys 属性;getCellProps 增加 rowKeys 参数,支持根据 expandedKeys 动态调整 rowSpan。
src/Body/index.tsx 使用 useFlattenRecords 生成 rowKeys 数组,传递给每个 BodyRow 组件,BodyRow 渲染时直接使用 rowKey 属性。
src/hooks/useFlattenRecords.ts FlattenData 接口新增 rowKey 属性,所有扁平化数据结构均包含唯一 rowKey。
docs/examples/expandedRowSpan.tsx 新增 Demo 组件,演示可展开行与自定义 rowSpan 的表格用法。
docs/demo/expandedRowSpan.md 新增文档页面,嵌入 expandedRowSpan 示例,展示合并单元格与展开行的功能。
src/VirtualTable/VirtualCell.tsx getCellProps 调用新增空数组参数以适配新签名,无其他逻辑变动。

Sequence Diagram(s)

sequenceDiagram
    participant Table
    participant Body
    participant BodyRow
    participant getCellProps

    Table->>Body: 生成 flattenData, rowKeys
    Body->>BodyRow: 传递 rowKey, rowKeys, 及其他 props
    BodyRow->>getCellProps: 传递 rowInfo, column, rowIndex, rowKeys
    getCellProps->>getCellProps: 根据 expandedKeys 和 rowKeys 计算 rowSpan
    getCellProps-->>BodyRow: 返回 cellProps
    BodyRow-->>Body: 渲染单元格
Loading

Suggested reviewers

  • zombieJ
  • afc163

Poem

一行行表格兔儿跳,
合并单元格展新貌。
rowKey 传递不迷路,
展开折叠随心调。
示例文档来助阵,
代码如画乐逍遥!
🐇✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

docs/examples/expandedRowSpan.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the config "prettier" to extend from. Please check that the name of the config is correct.

The config "prettier" was referenced from the config file in "/.eslintrc.js".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.

src/Body/BodyRow.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the config "prettier" to extend from. Please check that the name of the config is correct.

The config "prettier" was referenced from the config file in "/.eslintrc.js".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e606eed and 1cb0013.

📒 Files selected for processing (2)
  • docs/examples/expandedRowSpan.tsx (1 hunks)
  • src/Body/BodyRow.tsx (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • docs/examples/expandedRowSpan.tsx
  • src/Body/BodyRow.tsx
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Commit Unit Tests in branch support-row-span-expanded
  • Post Copyable Unit Tests in Comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/Body/BodyRow.tsx (3)

74-87: 优化 addChildrenRowSpan 函数的可读性

函数实现了正确的递归逻辑来计算行合并单元格的 rowSpan 值,但有几点可以改进:

  1. 变量名 ddddd 缺乏描述性,难以理解其用途
  2. 中文注释应替换为英文,保持代码风格一致性

建议如下修改:

-  const addChildrenRowSpan = (rowSpan: number, index2: number) => {
-    const _index = index2 + 1;
-    let _rowSpan = rowSpan;
-    // 下面如果是 0 的,增加 +1 逻辑
-    const dd = column.onCell(record, _index);
-    if (dd.rowSpan === 0) {
-      const ddd = expandedKeys.has(getRowKey(_index));
-      if (ddd) {
-        _rowSpan = _rowSpan + 1;
-      }
-      return addChildrenRowSpan(_rowSpan, _index);
-    }
-    return _rowSpan;
+  const addChildrenRowSpan = (rowSpan: number, index2: number) => {
+    const nextIndex = index2 + 1;
+    let newRowSpan = rowSpan;
+    // If next row has rowSpan=0, increment rowSpan if row is expanded
+    const nextRowCellProps = column.onCell(record, nextIndex);
+    if (nextRowCellProps.rowSpan === 0) {
+      const isNextRowExpanded = expandedKeys.has(getRowKey(nextIndex));
+      if (isNextRowExpanded) {
+        newRowSpan = newRowSpan + 1;
+      }
+      return addChildrenRowSpan(newRowSpan, nextIndex);
+    }
+    return newRowSpan;

92-99: 移除生产环境中的调试日志

第99行的 console.log 应当被移除,避免在生产环境中输出调试信息。

    if (additionalCellProps.rowSpan > 0) {
      // 本身展开 +1
      if (expanded) {
        additionalCellProps.rowSpan = additionalCellProps.rowSpan + 1;
      }
      additionalCellProps.rowSpan = addChildrenRowSpan(additionalCellProps.rowSpan, index);
    }
-    console.log('additionalCellProps.rowSpan', additionalCellProps.rowSpan);

110-112: 更正重复的注释块

这个注释块与第25-27行完全相同,两者都标记为 "getCellProps",但此处应该是对 BodyRow 组件的注释。

-// ==================================================================================
-// ==                                 getCellProps                                 ==
-// ==================================================================================
+// ==================================================================================
+// ==                                   BodyRow                                    ==
+// ==================================================================================
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 92dbe91 and 8565bfa.

📒 Files selected for processing (4)
  • docs/demo/colspan-rowspan-expanded.md (1 hunks)
  • docs/examples/colspan-rowspan-expanded.tsx (1 hunks)
  • src/Body/BodyRow.tsx (6 hunks)
  • src/Body/index.tsx (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/Body/BodyRow.tsx (2)
src/interface.ts (1)
  • Key (21-21)
src/hooks/useRowInfo.tsx (1)
  • useRowInfo (8-123)
🔇 Additional comments (8)
docs/demo/colspan-rowspan-expanded.md (1)

1-8: 新文档页面内容已确认

文档结构清晰,成功创建了一个新的演示页面,展示了 colspan、rowspan 与 expanded 功能的结合使用案例。

src/Body/index.tsx (1)

70-75: 传递 getRowKey 函数实现以索引获取行键值的功能

这个更改为 BodyRow 组件提供了一种通过索引动态获取行键的方法,是支持 rowspan 与 expanded 功能结合的关键实现。代码实现正确,安全地处理了边缘情况。

docs/examples/colspan-rowspan-expanded.tsx (3)

6-33: 示例中的表格列定义实现了合并单元格功能

列配置正确实现了单元格合并:

  • "手机号"列设置了 colSpan: 2 以水平合并
  • 基于行索引的不同 rowSpan 设置实现了垂直合并
  • "电话"列设置了 colSpan: 0 表示被前一列合并

示例清晰地展示了这些功能,便于用户理解如何使用。


35-41: 数据结构与列定义匹配,支持展示功能

表格数据结构符合要求,正确匹配了列定义,并包含了必要的 key 属性以支持行展开功能。


43-55: 组件示例完整实现了列合并、行合并与展开行功能

组件实现清晰简洁,成功展示了关键功能的组合使用:

  • 通过 columns 配置实现列跨度
  • 通过 onCell 返回的属性实现行跨度
  • 通过 expandable 配置实现行展开

这个示例对用户理解这些功能的组合使用非常有帮助。

src/Body/BodyRow.tsx (3)

22-22: 新增 getRowKey 属性支持行扩展功能

这个新增的属性是实现行合并与展开行兼容的关键,为组件提供了通过索引获取行键的能力。


34-34: getCellProps 函数添加 getRowKey 参数

函数签名的更新正确地接收了新的 getRowKey 参数,使其能在计算单元格属性时使用。


184-184: 正确传递 getRowKey 参数

已正确地将 getRowKey 函数传递给 getCellProps 函数,确保了行合并和行展开功能的兼容。

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
docs/examples/expandedRowSpan.tsx (2)

6-33: 列定义中的 rowSpan 处理逻辑

列定义中通过 onCell 属性实现了行合并的功能。第一列设置了 rowSpan,使多行合并为一个单元格,这是一个很好的示例。

但是,当前的实现方式有些冗长,可以考虑优化。

您可以考虑将 onCell 函数的逻辑简化:

  onCell: (_, index) => {
    const props: React.TdHTMLAttributes<HTMLTableCellElement> = {};
-   if (index === 0) {
-     props.rowSpan = 4;
-   } else if (index === 1) {
-     props.rowSpan = 0;
-   } else if (index === 2) {
-     props.rowSpan = 0;
-   } else if (index === 3) {
-     props.rowSpan = 0;
-   } else if (index === 4) {
-     props.rowSpan = 1;
-   }
+   if (index === 0) {
+     props.rowSpan = 4;
+   } else if (index >= 1 && index <= 3) {
+     props.rowSpan = 0;
+   }
    
    return props;
  },

43-54: 组件实现清晰

Demo 组件实现简洁明了,正确使用了 Table 组件的 expandable 属性来实现行展开功能,并将其与 rowSpan 功能相结合。标题也清晰地表明了示例的目的。

不过,考虑添加一些注释来解释这个示例如何演示 rowSpan 与展开行的交互。

建议在组件前添加简短说明:

// 这个示例展示了如何在表格中同时使用行合并(rowSpan)和行展开(expandable)功能
// 注意观察展开行时行合并的效果
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 532e524 and b5fc268.

📒 Files selected for processing (5)
  • docs/demo/expandedRowSpan.md (1 hunks)
  • docs/examples/expandedRowSpan.tsx (1 hunks)
  • src/Body/BodyRow.tsx (6 hunks)
  • src/Body/index.tsx (2 hunks)
  • src/hooks/useFlattenRecords.ts (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • docs/demo/expandedRowSpan.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/Body/index.tsx
  • src/Body/BodyRow.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/hooks/useFlattenRecords.ts (1)
src/interface.ts (1)
  • Key (21-21)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test / react component workflow
🔇 Additional comments (5)
src/hooks/useFlattenRecords.ts (3)

18-18: 添加了正确的 rowKey 属性

通过在 fillRecords 函数中从 getRowKey 获取并保存 rowKey,确保了每条扁平化记录都包含唯一标识符,这对于后续的行渲染和 rowSpan 计算至关重要。


45-45: 接口更新与实现一致

FlattenData 接口添加了 rowKey 字段,与实现部分保持一致,这有助于确保类型安全和代码可维护性。


85-85: 非展开状态的数据也添加了 rowKey

在非递归展开的情况下也正确添加了 rowKey 属性,确保了 API 一致性,无论是否有展开的行,每条记录都有唯一标识符。

docs/examples/expandedRowSpan.tsx (2)

1-5: 示例文件导入完整

导入了必要的依赖和样式文件,包括 React、Table 组件以及相关类型定义,便于示例代码的正确运行和类型检查。


35-41: 数据结构设计合理

测试数据设计合理,前四条数据的手机号相同,最后一条不同,与 rowSpan 设置相匹配。每条数据都有唯一的 key 属性,符合 React 列表渲染的最佳实践。

Copy link

codecov bot commented May 20, 2025

Codecov Report

Attention: Patch coverage is 72.72727% with 9 lines in your changes missing coverage. Please review.

Project coverage is 97.92%. Comparing base (92dbe91) to head (7b26a22).

Files with missing lines Patch % Lines
src/Body/BodyRow.tsx 47.05% 9 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1276      +/-   ##
==========================================
- Coverage   98.03%   97.92%   -0.12%     
==========================================
  Files          76       76              
  Lines        7435     7462      +27     
  Branches     1147     1149       +2     
==========================================
+ Hits         7289     7307      +18     
- Misses        140      149       +9     
  Partials        6        6              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0b53334 and d91920e.

📒 Files selected for processing (2)
  • docs/examples/expandedRowSpan.tsx (1 hunks)
  • src/Body/BodyRow.tsx (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/examples/expandedRowSpan.tsx
🧰 Additional context used
🪛 GitHub Check: codecov/patch
src/Body/BodyRow.tsx

[warning] 83-83: src/Body/BodyRow.tsx#L83
Added line #L83 was not covered by tests


[warning] 85-92: src/Body/BodyRow.tsx#L85-L92
Added lines #L85 - L92 were not covered by tests

🔇 Additional comments (1)
src/Body/BodyRow.tsx (1)

22-23: rowKeys 参数缺乏使用契约说明,易引发越界或长度不一致问题

rowKeys 现在是必填,但仅在行合并逻辑中读取 rowKeys[index + offset]
在虚拟滚动场景(VirtualCell)里被强制传入空数组,会直接导致读取 undefined,虽目前被 expandedKeys.has(undefined) “吞掉”,却隐藏了潜在 bug。

建议:

  1. BodyRowProps 注释中明确 rowKeys 必须与 flattenData 数组长度一致的契约;
  2. getCellProps 内部访问增加越界保护;
  3. 考虑将 rowKeys 参数改为可选,并在缺失或长度不匹配时跳过扩展计算,减少误用。

是否需要我提供更完整的守卫代码?

Also applies to: 35-35


// For expandable row with rowSpan,
// We should increase the rowSpan if the row is expanded
if (expandable && rowSpan > offset) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rowSpanoffset 没有关系,rowSpan !== 0 并且当前列 columnIndex < offset

@crazyair crazyair closed this by deleting the head repository May 21, 2025
@crazyair
Copy link
Contributor Author

被删除仓库关闭了,迁移到 #1278

@crazyair
Copy link
Contributor Author

test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants