@gmfe/table-x 2.14.30-beta.2 → 2.14.30-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gmfe/table-x",
3
- "version": "2.14.30-beta.2",
3
+ "version": "2.14.30-beta.4",
4
4
  "description": "",
5
5
  "author": "liyatang <liyatang@qq.com>",
6
6
  "homepage": "https://github.com/gmfe/gmfe#readme",
@@ -80,13 +80,16 @@ export function rebuildNestedColumnsFromFlat(flatColumns) {
80
80
  }
81
81
  })
82
82
 
83
- // 特殊列(select、diy、expand)必须放在最后
83
+ // 特殊列(select、diy、expand)的处理
84
84
  // 从 flatColumns 中提取特殊列,保持它们在 flatColumns 中的相对顺序
85
85
  const specialCols = flatColumns.filter(col =>
86
86
  specialColumnIds.includes(col.id)
87
87
  )
88
- // 确保特殊列在最后
89
- nested.push(...specialCols)
90
-
91
- return nested
88
+
89
+ // 分离 fixed: 'left' 的特殊列和其他特殊列
90
+ const leftFixedSpecialCols = specialCols.filter(col => col.fixed === 'left')
91
+ const otherSpecialCols = specialCols.filter(col => col.fixed !== 'left')
92
+
93
+ // 按顺序:fixed: 'left' 的特殊列 -> 普通列 -> 其他特殊列
94
+ return [...leftFixedSpecialCols, ...nested, ...otherSpecialCols]
92
95
  }
@@ -6,12 +6,64 @@ import React from 'react'
6
6
  // cell.render('Cell') 是一个react组件,如果这个组件return undefined,那就就会报错
7
7
  // 这里是为了兼容 cell.render('Cell') 返回undefined的情况
8
8
  class TdCatchErr extends React.Component {
9
+ state = {
10
+ hasError: false
11
+ }
12
+
13
+ static getDerivedStateFromError(error) {
14
+ // 捕获子组件树中的错误,返回新的 state
15
+ return { hasError: true }
16
+ }
17
+
18
+ componentDidCatch(error, errorInfo) {
19
+ // 静默处理错误,不打印日志
20
+ }
21
+
22
+ render() {
23
+ if (this.state.hasError) {
24
+ return null
25
+ }
26
+ const children = this.props.children
27
+ // 如果 children 是 undefined 或 null,返回 null(React 允许返回 null)
28
+ if (children === undefined || children === null) {
29
+ return null
30
+ }
31
+ return children
32
+ }
33
+ }
34
+
35
+ // 创建一个包装组件,用于包装 Cell 组件的 type,确保它总是返回有效值
36
+ // 这个组件会包装原始的 Cell 组件,如果原始组件返回 undefined,就返回 null
37
+ const SafeCellWrapper = OriginalComponent => {
38
+ return function WrappedCell(props) {
39
+ try {
40
+ const result = OriginalComponent(props)
41
+ // 如果原始组件返回 undefined,返回 null
42
+ return result === undefined ? null : result
43
+ } catch (error) {
44
+ return null
45
+ }
46
+ }
47
+ }
48
+
49
+ // 错误边界组件,专门用于捕获 Cell 组件返回 undefined 的错误
50
+ class SafeCellErrorBoundary extends React.Component {
51
+ state = {
52
+ hasError: false
53
+ }
54
+
55
+ static getDerivedStateFromError(error) {
56
+ return { hasError: true }
57
+ }
58
+
9
59
  componentDidCatch(error, errorInfo) {
10
- console.warn(error)
11
- console.warn(errorInfo.componentStack)
60
+ // 静默处理错误
12
61
  }
13
62
 
14
63
  render() {
64
+ if (this.state.hasError) {
65
+ return null
66
+ }
15
67
  return this.props.children
16
68
  }
17
69
  }
@@ -40,12 +92,26 @@ const Td = ({ cell, totalWidth }) => {
40
92
  }
41
93
 
42
94
  // 如果 Cell 返回 undefined,转换为 null(null 不会报错,undefined 会)
43
- const cellContent = cell.render('Cell')
44
- const safeCellContent = cellContent === undefined ? null : cellContent
95
+ let cellContent = cell.render('Cell')
96
+
97
+ // cellContent 是一个 React 元素,但它的 type(组件)在渲染时可能返回 undefined
98
+ // 我们需要用一个包装组件来替换原始的 type,确保总是返回有效值
99
+ if (cellContent && React.isValidElement(cellContent)) {
100
+ // 创建一个新的 React 元素,用包装组件替换原始的 type
101
+ const OriginalComponent = cellContent.type
102
+ const WrappedComponent = SafeCellWrapper(OriginalComponent)
103
+ cellContent = React.createElement(
104
+ SafeCellErrorBoundary,
105
+ null,
106
+ React.createElement(WrappedComponent, cellContent.props)
107
+ )
108
+ } else if (cellContent === undefined || cellContent === null) {
109
+ cellContent = null
110
+ }
45
111
 
46
112
  return (
47
113
  <td {...tdProps}>
48
- <TdCatchErr>{safeCellContent}</TdCatchErr>
114
+ <TdCatchErr>{cellContent}</TdCatchErr>
49
115
  </td>
50
116
  )
51
117
  }
@@ -174,7 +174,12 @@ const TwoLevelTHead = ({ headerGroups, firstLevelHeaders, totalWidth }) => {
174
174
  }
175
175
  }
176
176
  }
177
- const { colSpan: hpColSpan, rowSpan: hpRowSpan, ...restHp } = hp || {}
177
+ const {
178
+ colSpan: hpColSpan,
179
+ rowSpan: hpRowSpan,
180
+ key: hpKey,
181
+ ...restHp
182
+ } = hp || {}
178
183
  const finalRowSpan =
179
184
  rowSpan !== undefined ? Number(rowSpan) : undefined
180
185
  const finalColSpan =
@@ -201,8 +206,12 @@ const TwoLevelTHead = ({ headerGroups, firstLevelHeaders, totalWidth }) => {
201
206
  style: cellStyle
202
207
  }
203
208
 
209
+ // 生成唯一的 key:结合 id/accessor 和索引,确保即使 id/accessor 相同,key 也是唯一的
210
+ // 如果有 hpKey,也加上索引以确保唯一性(因为 hpKey 可能也会重复)
211
+ const baseKey = hpKey || header.id || header.accessor
212
+ const headerKey = baseKey ? `${baseKey}-${idx}` : `header-${idx}`
204
213
  return (
205
- <th key={idx} {...thProps}>
214
+ <th key={headerKey} {...thProps}>
206
215
  {typeof header.Header === 'function' ? (
207
216
  <header.Header />
208
217
  ) : (
@@ -248,9 +257,15 @@ const TwoLevelTHead = ({ headerGroups, firstLevelHeaders, totalWidth }) => {
248
257
  ) {
249
258
  return null
250
259
  }
260
+ // 生成唯一的 key:结合 id/accessor 和索引,确保即使 id/accessor 相同,key 也是唯一的
261
+ const columnKey = column.id
262
+ ? `${column.id}-${idx}`
263
+ : column.accessor
264
+ ? `${column.accessor}-${idx}`
265
+ : `col-${idx}`
251
266
  return (
252
267
  <Th
253
- key={idx}
268
+ key={columnKey}
254
269
  column={{
255
270
  ...column,
256
271
  // column.fixed 已经在 transformColumnsForTwoLevel 中正确设置
@@ -51,11 +51,16 @@ export function transformColumnsForTwoLevel(columns) {
51
51
 
52
52
  // 分离普通列和特殊列
53
53
  const normalColumns = []
54
- const specialColumns = []
54
+ const leftFixedSpecialColumns = [] // fixed: 'left' 的特殊列(如 diy)
55
+ const otherSpecialColumns = [] // 其他特殊列(如 select、expand)
55
56
 
56
57
  columns.forEach(column => {
57
58
  if (specialColumnIds.includes(column.id)) {
58
- specialColumns.push(column)
59
+ if (column.fixed === 'left') {
60
+ leftFixedSpecialColumns.push(column)
61
+ } else {
62
+ otherSpecialColumns.push(column)
63
+ }
59
64
  } else {
60
65
  normalColumns.push(column)
61
66
  }
@@ -125,10 +130,21 @@ export function transformColumnsForTwoLevel(columns) {
125
130
  }
126
131
  })
127
132
 
128
- // 最后处理特殊列(select、diy、expand)放在最后
133
+ // 处理 fixed: 'left' 的特殊列(如 diy),放在最前面
134
+ leftFixedSpecialColumns.forEach(column => {
135
+ transformedColumns.unshift(column)
136
+ firstLevelHeaders.unshift({
137
+ ...column,
138
+ hasSubColumns: false,
139
+ subColumnCount: 1,
140
+ isSpecialColumn: true
141
+ })
142
+ })
143
+
144
+ // 最后处理其他特殊列(select、expand)放在最后
129
145
  // 注意:移除特殊列的 fixed 属性,让它们按数组顺序显示在最后(不固定)
130
146
  // 如果用户需要特殊列固定在右边,可以手动设置 fixed: 'right'
131
- specialColumns.forEach(column => {
147
+ otherSpecialColumns.forEach(column => {
132
148
  const { fixed, ...columnWithoutFixed } = column
133
149
  const adjustedColumn = {
134
150
  ...columnWithoutFixed,