zmdms-webui 3.2.6 → 3.2.7

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.
@@ -3,6 +3,7 @@ import { jsx, Fragment } from 'react/jsx-runtime';
3
3
 
4
4
  var HeaderOverlay = function (_a) {
5
5
  var overlays = _a.overlays;
6
+ var horizontalPadding = 16;
6
7
  return (jsx(Fragment, { children: overlays.map(function (overlay) { return (jsx("div", __assign({ className: "canvas-table-header-overlay", style: {
7
8
  position: "absolute",
8
9
  left: overlay.x,
@@ -12,11 +13,17 @@ var HeaderOverlay = function (_a) {
12
13
  pointerEvents: "none",
13
14
  display: "flex",
14
15
  alignItems: "center",
15
- paddingLeft: "16px",
16
- paddingRight: "16px",
16
+ paddingLeft: "".concat(horizontalPadding, "px"),
17
+ paddingRight: "".concat(horizontalPadding, "px"),
17
18
  boxSizing: "border-box",
18
19
  overflow: "hidden",
19
- } }, { children: jsx("div", __assign({ style: { pointerEvents: "auto" } }, { children: overlay.content })) }), overlay.columnKey)); }) }));
20
+ zIndex: overlay.isFixed ? 10 : 1,
21
+ } }, { children: jsx("div", __assign({ style: {
22
+ position: "absolute",
23
+ left: -overlay.offsetLeft + horizontalPadding,
24
+ width: Math.max(overlay.originalWidth - horizontalPadding * 2, 0),
25
+ pointerEvents: "auto",
26
+ } }, { children: overlay.content })) }), overlay.columnKey)); }) }));
20
27
  };
21
28
 
22
29
  export { HeaderOverlay as default };
@@ -10,33 +10,16 @@ import '../../node_modules/exceljs/dist/exceljs.min.js';
10
10
  import 'dayjs';
11
11
 
12
12
  /**
13
- * 覆盖层管理 Hook - 统一管理所有覆盖层相关逻辑
14
- *
15
- * 包含功能:
16
- * 1. 单元格覆盖层管理(useTableCellOverlay)
17
- * 2. 表头覆盖层管理(useHeaderOverlay)
18
- *
19
- * 覆盖层用于在 Canvas 表格上方渲染自定义的 DOM 内容,支持用户交互
20
- */
21
- // ==================== Hook 1: 单元格覆盖层管理 ====================
22
- /**
23
- * 单元格覆盖层管理 Hook
24
- *
25
- * 功能:
26
- * - 计算可见单元格的位置信息
27
- * - 处理边界裁剪(上下左右)
28
- * - 处理fixed列的遮挡
29
- * - 只渲染React元素类型的内容(字符串和数字在Canvas中直接绘制)
13
+ * 覆盖层管理 Hook
14
+ * 1. useTableCellOverlay: 单元格自定义 DOM 覆盖层
15
+ * 2. useHeaderOverlay: 表头 ReactNode 覆盖层
30
16
  */
31
17
  var useTableCellOverlay = function (params) {
32
18
  var processedDataSource = params.processedDataSource, columnRenderInfos = params.columnRenderInfos, scrollState = params.scrollState, containerWidth = params.containerWidth, containerHeight = params.containerHeight, headerHeight = params.headerHeight, rowHeight = params.rowHeight, needHorizontalScrollbar = params.needHorizontalScrollbar, needVerticalScrollbar = params.needVerticalScrollbar, scrollbarSize = params.scrollbarSize, fixedRowsCount = params.fixedRowsCount, fixedRowsConfig = params.fixedRowsConfig, _a = params.hasSummaryRow, hasSummaryRow = _a === void 0 ? false : _a, _b = params.summaryFixed, summaryFixed = _b === void 0 ? false : _b;
33
- // 计算可见的单元格覆盖层信息
34
19
  var cellOverlays = useMemo(function () {
35
20
  var overlays = [];
36
- // 计算固定行数量
37
21
  var fixedTopRowsCount = fixedRowsCount || (fixedRowsConfig === null || fixedRowsConfig === void 0 ? void 0 : fixedRowsConfig.topCount) || 0;
38
22
  var fixedBottomRowsCount = (fixedRowsConfig === null || fixedRowsConfig === void 0 ? void 0 : fixedRowsConfig.bottomCount) || 0;
39
- // 计算fixed列的右边界,用于裁剪非fixed列的覆盖层
40
23
  var fixedColumnsRightEdge = columnRenderInfos.reduce(function (maxEdge, info) {
41
24
  if (info.fixed) {
42
25
  var rightEdge = info.fixedLeft + info.width;
@@ -44,18 +27,13 @@ var useTableCellOverlay = function (params) {
44
27
  }
45
28
  return maxEdge;
46
29
  }, 0);
47
- // 计算有效容器尺寸
48
30
  var effectiveWidth = needVerticalScrollbar
49
31
  ? containerWidth - scrollbarSize
50
32
  : containerWidth;
51
- // 计算可用高度,需要为固定合计行预留空间
52
33
  var fixedSummaryHeight = summaryFixed && hasSummaryRow ? rowHeight : 0;
53
34
  var effectiveHeight = (needHorizontalScrollbar
54
35
  ? containerHeight - scrollbarSize
55
36
  : containerHeight) - fixedSummaryHeight;
56
- /**
57
- * 通用的单元格覆盖层处理函数
58
- */
59
37
  var processCell = function (rowIndex, y, isFixedRow) {
60
38
  if (isFixedRow === void 0) { isFixedRow = false; }
61
39
  var record = processedDataSource[rowIndex];
@@ -63,110 +41,88 @@ var useTableCellOverlay = function (params) {
63
41
  return;
64
42
  columnRenderInfos.forEach(function (info, colIndex) {
65
43
  var column = info.column, x = info.x, width = info.width, fixed = info.fixed, fixedLeft = info.fixedLeft;
66
- // 跳过选择框列
67
44
  if (column.key === "__selection__") {
68
45
  return;
69
46
  }
70
- // 检查该列是否有 render 函数
71
47
  if (!column.render) {
72
48
  return;
73
49
  }
74
- // 跳过合计行的 render 函数处理
75
50
  if (record[IS_SUMMARY]) {
76
51
  return;
77
52
  }
78
53
  var drawX = fixed ? fixedLeft : x - scrollState.scrollLeft;
79
- // 跳过不在可视区域的列
80
54
  if (!fixed && (drawX + width < 0 || drawX > effectiveWidth)) {
81
55
  return;
82
56
  }
83
- // 对于非fixed列,检查是否被fixed列完全遮挡
84
57
  if (!fixed &&
85
58
  fixedColumnsRightEdge > 0 &&
86
59
  drawX < fixedColumnsRightEdge) {
87
- // 如果完全被遮挡,跳过
88
60
  if (drawX + width <= fixedColumnsRightEdge) {
89
61
  return;
90
62
  }
91
63
  }
92
- // 需要处理左右边界的裁剪
93
64
  var effectiveCellWidth = width;
94
65
  var effectiveDrawX = drawX;
95
- var offsetLeft = 0; // 记录左侧被裁剪的宽度
66
+ var offsetLeft = 0;
96
67
  if (!fixed) {
97
- // 处理左边界:如果单元格部分在左边界外
98
68
  if (drawX < 0) {
99
- offsetLeft = -drawX; // 左侧被裁剪的宽度
100
- effectiveCellWidth = width + drawX; // 减少宽度
101
- effectiveDrawX = 0; // 从容器左边界开始绘制
69
+ offsetLeft = -drawX;
70
+ effectiveCellWidth = width + drawX;
71
+ effectiveDrawX = 0;
102
72
  if (effectiveCellWidth <= 0)
103
73
  return;
104
74
  }
105
- // 处理被fixed列遮挡的情况
106
75
  if (fixedColumnsRightEdge > 0 &&
107
76
  effectiveDrawX < fixedColumnsRightEdge) {
108
77
  var overlap = fixedColumnsRightEdge - effectiveDrawX;
109
78
  if (overlap < effectiveCellWidth) {
110
- offsetLeft += overlap; // 增加左侧裁剪量
111
- effectiveCellWidth -= overlap; // 减少宽度
112
- effectiveDrawX = fixedColumnsRightEdge; // 从fixed列右边界开始绘制
79
+ offsetLeft += overlap;
80
+ effectiveCellWidth -= overlap;
81
+ effectiveDrawX = fixedColumnsRightEdge;
113
82
  }
114
83
  }
115
84
  }
116
- // 处理右边界:如果单元格部分在右边界外(fixed 和非 fixed 列都需要处理)
117
85
  if (effectiveDrawX + effectiveCellWidth > effectiveWidth) {
118
86
  effectiveCellWidth = effectiveWidth - effectiveDrawX;
119
87
  if (effectiveCellWidth <= 0)
120
88
  return;
121
89
  }
122
- // 获取单元格值
123
90
  var dataIndex = column.dataIndex || column.key;
124
91
  var cellValue = record[dataIndex];
125
- // 调用 render 函数获取内容
126
92
  var renderedContent = column.render(cellValue, record, rowIndex);
127
- // 只有返回的不是字符串或数字时,才需要渲染到覆盖层
128
- // 字符串和数字会在 Canvas 中直接绘制
129
93
  if (typeof renderedContent !== "string" &&
130
94
  typeof renderedContent !== "number" &&
131
95
  renderedContent !== null &&
132
96
  renderedContent !== undefined) {
133
- // 处理 y 轴的边界裁剪,类似于 x 轴的处理
134
97
  var effectiveCellHeight = rowHeight;
135
98
  var effectiveDrawY = y;
136
- var offsetTop = 0; // 记录上方被裁剪的高度
137
- // 处理上边界:根据行类型进行不同的边界检查
138
- var minTopY = headerHeight; // 默认最小Y为表头高度
99
+ var offsetTop = 0;
100
+ var minTopY = headerHeight;
139
101
  if (!isFixedRow) {
140
- // 非固定行还需要避开固定顶部行区域
141
102
  minTopY = headerHeight + fixedTopRowsHeight;
142
103
  }
143
104
  if (y < minTopY) {
144
- offsetTop = minTopY - y; // 上方被裁剪的高度
145
- effectiveCellHeight = rowHeight - offsetTop; // 减少高度
146
- effectiveDrawY = minTopY; // 从允许的最小Y开始绘制
105
+ offsetTop = minTopY - y;
106
+ effectiveCellHeight = rowHeight - offsetTop;
107
+ effectiveDrawY = minTopY;
147
108
  if (effectiveCellHeight <= 0)
148
109
  return;
149
110
  }
150
- // 处理下边界:根据行类型进行不同的边界检查
151
111
  var maxBottomY = void 0;
152
112
  if (isFixedRow) {
153
- // 固定行使用完整的容器高度(减去滚动条)
154
113
  maxBottomY = needHorizontalScrollbar
155
114
  ? containerHeight - scrollbarSize
156
115
  : containerHeight;
157
116
  }
158
117
  else {
159
- // 非固定行需要严格避开所有固定行区域
160
118
  var currentFixedBottomHeight = fixedBottomRowsCount * rowHeight;
161
119
  var currentFixedSummaryHeight = summaryFixed && hasSummaryRow ? rowHeight : 0;
162
- // 计算可滚动区域的严格边界
163
120
  var scrollableAreaBottom = containerHeight -
164
121
  (needHorizontalScrollbar ? scrollbarSize : 0) -
165
122
  currentFixedBottomHeight -
166
123
  currentFixedSummaryHeight;
167
124
  maxBottomY = Math.min(effectiveHeight, scrollableAreaBottom);
168
125
  }
169
- // 如果单元格部分在底部边界外
170
126
  if (effectiveDrawY + effectiveCellHeight > maxBottomY) {
171
127
  effectiveCellHeight = maxBottomY - effectiveDrawY;
172
128
  if (effectiveCellHeight <= 0)
@@ -193,58 +149,45 @@ var useTableCellOverlay = function (params) {
193
149
  }
194
150
  });
195
151
  };
196
- // 1. 处理固定顶部行
197
152
  if (fixedTopRowsCount > 0) {
198
153
  for (var i = 0; i < fixedTopRowsCount; i++) {
199
154
  var y = headerHeight + i * rowHeight;
200
155
  processCell(i, y, true);
201
156
  }
202
157
  }
203
- // 2. 处理可滚动区域的行
204
158
  var fixedTopRowsHeight = fixedTopRowsCount * rowHeight;
205
159
  var fixedBottomRowsHeight = fixedBottomRowsCount * rowHeight;
206
- // 计算可滚动数据区域的高度
207
160
  var scrollableAreaHeight = containerHeight -
208
161
  headerHeight -
209
162
  fixedTopRowsHeight -
210
163
  fixedBottomRowsHeight -
211
164
  fixedSummaryHeight -
212
165
  (needHorizontalScrollbar ? scrollbarSize : 0);
213
- // 计算可见的滚动行范围
214
166
  var scrollStartRow = Math.floor(scrollState.scrollTop / rowHeight);
215
- var scrollEndRow = Math.min(Math.ceil((scrollState.scrollTop + scrollableAreaHeight) / rowHeight), processedDataSource.length - fixedBottomRowsCount
216
- // 注意:不再减去合计行数量,因为合计行的空间已在 scrollableAreaHeight 中考虑
217
- );
218
- // 调整行索引,从固定顶部行之后开始
167
+ var scrollEndRow = Math.min(Math.ceil((scrollState.scrollTop + scrollableAreaHeight) / rowHeight), processedDataSource.length - fixedBottomRowsCount);
219
168
  var adjustedStartRow = fixedTopRowsCount + scrollStartRow;
220
169
  var adjustedEndRow = fixedTopRowsCount + scrollEndRow;
221
170
  for (var rowIndex = adjustedStartRow; rowIndex < adjustedEndRow; rowIndex++) {
222
171
  if (rowIndex < 0 || rowIndex >= processedDataSource.length)
223
172
  continue;
224
- // 计算相对于滚动区域的位置
225
173
  var relativeRowIndex = rowIndex - fixedTopRowsCount;
226
174
  var y = headerHeight +
227
175
  fixedTopRowsHeight +
228
176
  relativeRowIndex * rowHeight -
229
177
  scrollState.scrollTop;
230
- // 检查是否在可见区域内,并确保不会与固定行重叠
231
178
  var minVisibleY = headerHeight + fixedTopRowsHeight;
232
179
  var maxVisibleY = minVisibleY + scrollableAreaHeight;
233
- // 额外检查:确保不会延伸到固定底部行或固定合计行区域
234
180
  var maxAllowedY = containerHeight -
235
181
  (needHorizontalScrollbar ? scrollbarSize : 0) -
236
182
  fixedBottomRowsHeight -
237
183
  fixedSummaryHeight;
238
- // 可见性检查:允许部分可见的行(被固定行遮挡的情况)
239
184
  if (y + rowHeight <= minVisibleY ||
240
185
  y >= maxVisibleY ||
241
- y >= maxAllowedY // 只检查行顶部是否超出边界,允许底部被遮挡
242
- ) {
186
+ y >= maxAllowedY) {
243
187
  continue;
244
188
  }
245
189
  processCell(rowIndex, y, false);
246
190
  }
247
- // 3. 处理固定底部行
248
191
  if (fixedBottomRowsCount > 0) {
249
192
  var bottomRowsStartIndex = processedDataSource.length -
250
193
  fixedBottomRowsCount -
@@ -259,7 +202,6 @@ var useTableCellOverlay = function (params) {
259
202
  processCell(rowIndex, y, true);
260
203
  }
261
204
  }
262
- // 4. 处理固定合计行
263
205
  if (summaryFixed && hasSummaryRow) {
264
206
  var summaryRowIndex = processedDataSource.length - 1;
265
207
  var summaryY = containerHeight -
@@ -267,25 +209,22 @@ var useTableCellOverlay = function (params) {
267
209
  rowHeight;
268
210
  processCell(summaryRowIndex, summaryY, true);
269
211
  }
270
- // 排序覆盖层:优先级顺序 - 确保固定合计行有最高优先级
271
212
  return overlays.sort(function (a, b) {
272
- // 计算优先级(数值越大优先级越高)
273
213
  var getPriority = function (overlay) {
274
- // 检查是否是固定合计行(最后一行且固定合计行开启)
275
214
  var isSummaryRow = summaryFixed &&
276
215
  hasSummaryRow &&
277
216
  overlay.rowIndex === processedDataSource.length - 1;
278
217
  if (isSummaryRow && overlay.isFixed)
279
- return 6; // 固定合计行固定列(最高优先级)
218
+ return 6;
280
219
  if (isSummaryRow && !overlay.isFixed)
281
- return 5; // 固定合计行非固定列
220
+ return 5;
282
221
  if (overlay.isFixedRow && overlay.isFixed)
283
- return 4; // 其他固定行固定列
222
+ return 4;
284
223
  if (overlay.isFixedRow && !overlay.isFixed)
285
- return 3; // 其他固定行非固定列
224
+ return 3;
286
225
  if (!overlay.isFixedRow && overlay.isFixed)
287
- return 2; // 非固定行固定列
288
- return 1; // 非固定行非固定列(最低优先级)
226
+ return 2;
227
+ return 1;
289
228
  };
290
229
  return getPriority(a) - getPriority(b);
291
230
  });
@@ -310,15 +249,6 @@ var useTableCellOverlay = function (params) {
310
249
  cellOverlays: cellOverlays,
311
250
  };
312
251
  };
313
- // ==================== Hook 2: 表头覆盖层管理 ====================
314
- /**
315
- * 表头覆盖层管理 Hook
316
- *
317
- * 功能:
318
- * - 计算需要渲染为 React 组件的表头位置信息
319
- * - 只处理 title 为 React 元素的列
320
- * - 支持列宽调整时的临时宽度
321
- */
322
252
  var useHeaderOverlay = function (params) {
323
253
  var columnRenderInfos = params.columnRenderInfos, scrollLeft = params.scrollLeft, headerHeight = params.headerHeight, containerWidth = params.containerWidth, needVerticalScrollbar = params.needVerticalScrollbar, scrollbarSize = params.scrollbarSize, getColumnWidth = params.getColumnWidth;
324
254
  var headerOverlays = useMemo(function () {
@@ -326,26 +256,62 @@ var useHeaderOverlay = function (params) {
326
256
  var displayWidth = needVerticalScrollbar
327
257
  ? containerWidth - scrollbarSize
328
258
  : containerWidth;
259
+ var fixedColumnsRightEdge = columnRenderInfos.reduce(function (maxEdge, info, index) {
260
+ if (!info.fixed) {
261
+ return maxEdge;
262
+ }
263
+ var currentWidth = getColumnWidth ? getColumnWidth(index) : info.width;
264
+ return Math.max(maxEdge, info.fixedLeft + currentWidth);
265
+ }, 0);
329
266
  columnRenderInfos.forEach(function (info, index) {
330
267
  var column = info.column, x = info.x, fixed = info.fixed, fixedLeft = info.fixedLeft;
331
- // 只处理 title 为 React 元素的列
332
268
  if (!isValidElement(column.title)) {
333
269
  return;
334
270
  }
335
- // 使用 getColumnWidth 获取列宽(考虑拖拽时的临时宽度)
336
271
  var width = getColumnWidth ? getColumnWidth(index) : info.width;
337
272
  var drawX = fixed ? fixedLeft : x - scrollLeft;
338
- // 跳过不在可视区域的列
339
273
  if (!fixed && (drawX + width < 0 || drawX > displayWidth)) {
340
274
  return;
341
275
  }
276
+ var effectiveWidth = width;
277
+ var effectiveDrawX = drawX;
278
+ var offsetLeft = 0;
279
+ if (!fixed) {
280
+ if (drawX < 0) {
281
+ offsetLeft = -drawX;
282
+ effectiveWidth = width + drawX;
283
+ effectiveDrawX = 0;
284
+ if (effectiveWidth <= 0) {
285
+ return;
286
+ }
287
+ }
288
+ if (fixedColumnsRightEdge > 0 &&
289
+ effectiveDrawX < fixedColumnsRightEdge) {
290
+ var overlap = fixedColumnsRightEdge - effectiveDrawX;
291
+ if (overlap >= effectiveWidth) {
292
+ return;
293
+ }
294
+ offsetLeft += overlap;
295
+ effectiveWidth -= overlap;
296
+ effectiveDrawX = fixedColumnsRightEdge;
297
+ }
298
+ }
299
+ if (effectiveDrawX + effectiveWidth > displayWidth) {
300
+ effectiveWidth = displayWidth - effectiveDrawX;
301
+ if (effectiveWidth <= 0) {
302
+ return;
303
+ }
304
+ }
342
305
  overlays.push({
343
306
  columnKey: column.key,
344
- x: drawX,
307
+ x: effectiveDrawX,
345
308
  y: 0,
346
- width: width,
309
+ width: effectiveWidth,
347
310
  height: headerHeight,
348
311
  content: column.title,
312
+ isFixed: fixed || false,
313
+ offsetLeft: offsetLeft,
314
+ originalWidth: width,
349
315
  });
350
316
  });
351
317
  return overlays;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zmdms-webui",
3
- "version": "3.2.6",
3
+ "version": "3.2.7",
4
4
  "private": false,
5
5
  "main": "dist/index.es.js",
6
6
  "module": "dist/index.es.js",