zmdms-webui 2.2.9 → 2.3.1
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/dist/es/canvastable/canvasTable.js +367 -0
- package/dist/es/canvastable/components/BadgePopover.js +27 -0
- package/dist/es/canvastable/components/CanvasTableMenu.js +74 -0
- package/dist/es/canvastable/components/CellOverlay.js +49 -0
- package/dist/es/canvastable/components/ColumnDynamic.js +12 -0
- package/dist/es/canvastable/components/EmptyPlaceholder.js +20 -0
- package/dist/es/canvastable/components/FilterPopover.js +274 -0
- package/dist/es/canvastable/components/HeaderOverlay.js +22 -0
- package/dist/es/canvastable/components/Tooltip.js +27 -0
- package/dist/es/canvastable/hooks/useClickOutside.js +30 -0
- package/dist/es/canvastable/hooks/useColumnResize.js +130 -0
- package/dist/es/canvastable/hooks/useContainerSize.js +40 -0
- package/dist/es/canvastable/hooks/useCopyToClipboard.js +150 -0
- package/dist/es/canvastable/hooks/useHeaderHeight.js +103 -0
- package/dist/es/canvastable/hooks/useMergeCells.js +111 -0
- package/dist/es/canvastable/hooks/useOverlays.js +364 -0
- package/dist/es/canvastable/hooks/usePopovers.js +93 -0
- package/dist/es/canvastable/hooks/useProcessedColumns.js +94 -0
- package/dist/es/canvastable/hooks/useScroll.js +251 -0
- package/dist/es/canvastable/hooks/useSummaryRow.js +81 -0
- package/dist/es/canvastable/hooks/useTableInteraction.js +804 -0
- package/dist/es/canvastable/hooks/useTableRender.js +1289 -0
- package/dist/es/canvastable/hooks/useTableSelection.js +57 -0
- package/dist/es/canvastable/hooks/useTableState.js +218 -0
- package/dist/es/canvastable/index.js +5 -0
- package/dist/es/canvastable/utils/canvasDrawHelpers.js +156 -0
- package/dist/es/canvastable/utils/cellHelpers.js +121 -0
- package/dist/es/canvastable/utils/columnHelpers.js +67 -0
- package/dist/es/canvastable/utils/constants.js +42 -0
- package/dist/es/canvastable/utils/formatHelpers.js +60 -0
- package/dist/es/canvastable/utils/interactionHelpers.js +176 -0
- package/dist/es/canvastable/utils/multiHeaderHelpers.js +82 -0
- package/dist/es/canvastable/utils/tableCalculations.js +100 -0
- package/dist/es/form/form.js +1 -0
- package/dist/index.dark.css +1 -1
- package/dist/index.default.css +1 -1
- package/dist/index.es.css +1 -1
- package/dist/less/components/CanvasTable/style/index.less +106 -0
- package/dist/less/components/Form/style/index.less +6 -1
- package/package.json +1 -1
- package/dist/es/cascader/index.css +0 -1
- package/dist/es/collapse/index.css +0 -1
- package/dist/es/container/index.css +0 -1
- package/dist/es/datepicker/index.css +0 -1
- package/dist/es/descriptions/index.css +0 -1
- package/dist/es/detaillist/index.css +0 -1
- package/dist/es/differences/index.css +0 -1
- package/dist/es/dynamicsetting/index.css +0 -1
- package/dist/es/electronsignatures/index.css +0 -1
- package/dist/es/footer/index.css +0 -1
- package/dist/es/form/index.css +0 -1
- package/dist/es/formitem/index.css +0 -1
- package/dist/es/input/index.css +0 -1
- package/dist/es/inputnumber/index.css +0 -1
- package/dist/es/leftcontent/index.css +0 -1
- package/dist/es/message/index.css +0 -1
- package/dist/es/microloading/index.css +0 -1
- package/dist/es/modal/index.css +0 -1
- package/dist/es/notauthpage/index.css +0 -0
- package/dist/es/notroutepage/index.css +0 -0
- package/dist/es/pagination/index.css +0 -1
- package/dist/es/placeholder/index.css +0 -1
- package/dist/es/print/index.css +0 -1
- package/dist/es/select/index.css +0 -1
- package/dist/es/table/index.css +0 -1
- package/dist/es/tabs/index.css +0 -1
- package/dist/es/tag/index.css +0 -1
- package/dist/es/title/index.css +0 -1
- package/dist/es/tree/index.css +0 -1
- package/dist/es/treeselect/index.css +0 -1
- package/dist/es/uploadlist/index.css +0 -1
- package/dist/es/watermark/index.css +0 -1
- package/dist/es/zttransfer/index.css +0 -1
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import { useMemo, isValidElement } from 'react';
|
|
2
|
+
import { IS_SUMMARY } from '../../table/constant.js';
|
|
3
|
+
import '../../_virtual/_tslib.js';
|
|
4
|
+
import 'lodash/isEqual';
|
|
5
|
+
import 'ahooks';
|
|
6
|
+
import '../../node_modules/immutability-helper/index.js';
|
|
7
|
+
import 'react/jsx-runtime';
|
|
8
|
+
import 'zmdms-utils';
|
|
9
|
+
import '../../node_modules/exceljs/dist/exceljs.min.js';
|
|
10
|
+
import 'dayjs';
|
|
11
|
+
|
|
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中直接绘制)
|
|
30
|
+
*/
|
|
31
|
+
var useTableCellOverlay = function (params) {
|
|
32
|
+
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.fixedSummaryRow, fixedSummaryRow = _b === void 0 ? false : _b;
|
|
33
|
+
// 计算可见的单元格覆盖层信息
|
|
34
|
+
var cellOverlays = useMemo(function () {
|
|
35
|
+
var overlays = [];
|
|
36
|
+
// 计算固定行数量
|
|
37
|
+
var fixedTopRowsCount = fixedRowsCount || (fixedRowsConfig === null || fixedRowsConfig === void 0 ? void 0 : fixedRowsConfig.topCount) || 0;
|
|
38
|
+
var fixedBottomRowsCount = (fixedRowsConfig === null || fixedRowsConfig === void 0 ? void 0 : fixedRowsConfig.bottomCount) || 0;
|
|
39
|
+
// 计算fixed列的右边界,用于裁剪非fixed列的覆盖层
|
|
40
|
+
var fixedColumnsRightEdge = columnRenderInfos.reduce(function (maxEdge, info) {
|
|
41
|
+
if (info.fixed) {
|
|
42
|
+
var rightEdge = info.fixedLeft + info.width;
|
|
43
|
+
return Math.max(maxEdge, rightEdge);
|
|
44
|
+
}
|
|
45
|
+
return maxEdge;
|
|
46
|
+
}, 0);
|
|
47
|
+
// 计算有效容器尺寸
|
|
48
|
+
var effectiveWidth = needVerticalScrollbar
|
|
49
|
+
? containerWidth - scrollbarSize
|
|
50
|
+
: containerWidth;
|
|
51
|
+
// 计算可用高度,需要为固定合计行预留空间
|
|
52
|
+
var fixedSummaryHeight = fixedSummaryRow && hasSummaryRow ? rowHeight : 0;
|
|
53
|
+
var effectiveHeight = (needHorizontalScrollbar
|
|
54
|
+
? containerHeight - scrollbarSize
|
|
55
|
+
: containerHeight) - fixedSummaryHeight;
|
|
56
|
+
/**
|
|
57
|
+
* 通用的单元格覆盖层处理函数
|
|
58
|
+
*/
|
|
59
|
+
var processCell = function (rowIndex, y, isFixedRow) {
|
|
60
|
+
if (isFixedRow === void 0) { isFixedRow = false; }
|
|
61
|
+
var record = processedDataSource[rowIndex];
|
|
62
|
+
if (!record)
|
|
63
|
+
return;
|
|
64
|
+
columnRenderInfos.forEach(function (info, colIndex) {
|
|
65
|
+
var column = info.column, x = info.x, width = info.width, fixed = info.fixed, fixedLeft = info.fixedLeft;
|
|
66
|
+
// 跳过选择框列
|
|
67
|
+
if (column.key === "__selection__") {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
// 检查该列是否有 render 函数
|
|
71
|
+
if (!column.render) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
// 跳过合计行的 render 函数处理
|
|
75
|
+
if (record[IS_SUMMARY]) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
var drawX = fixed ? fixedLeft : x - scrollState.scrollLeft;
|
|
79
|
+
// 跳过不在可视区域的列
|
|
80
|
+
if (!fixed && (drawX + width < 0 || drawX > effectiveWidth)) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
// 对于非fixed列,检查是否被fixed列完全遮挡
|
|
84
|
+
if (!fixed &&
|
|
85
|
+
fixedColumnsRightEdge > 0 &&
|
|
86
|
+
drawX < fixedColumnsRightEdge) {
|
|
87
|
+
// 如果完全被遮挡,跳过
|
|
88
|
+
if (drawX + width <= fixedColumnsRightEdge) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// 需要处理左右边界的裁剪
|
|
93
|
+
var effectiveCellWidth = width;
|
|
94
|
+
var effectiveDrawX = drawX;
|
|
95
|
+
var offsetLeft = 0; // 记录左侧被裁剪的宽度
|
|
96
|
+
if (!fixed) {
|
|
97
|
+
// 处理左边界:如果单元格部分在左边界外
|
|
98
|
+
if (drawX < 0) {
|
|
99
|
+
offsetLeft = -drawX; // 左侧被裁剪的宽度
|
|
100
|
+
effectiveCellWidth = width + drawX; // 减少宽度
|
|
101
|
+
effectiveDrawX = 0; // 从容器左边界开始绘制
|
|
102
|
+
if (effectiveCellWidth <= 0)
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
// 处理被fixed列遮挡的情况
|
|
106
|
+
if (fixedColumnsRightEdge > 0 &&
|
|
107
|
+
effectiveDrawX < fixedColumnsRightEdge) {
|
|
108
|
+
var overlap = fixedColumnsRightEdge - effectiveDrawX;
|
|
109
|
+
if (overlap < effectiveCellWidth) {
|
|
110
|
+
offsetLeft += overlap; // 增加左侧裁剪量
|
|
111
|
+
effectiveCellWidth -= overlap; // 减少宽度
|
|
112
|
+
effectiveDrawX = fixedColumnsRightEdge; // 从fixed列右边界开始绘制
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// 处理右边界:如果单元格部分在右边界外(fixed 和非 fixed 列都需要处理)
|
|
117
|
+
if (effectiveDrawX + effectiveCellWidth > effectiveWidth) {
|
|
118
|
+
effectiveCellWidth = effectiveWidth - effectiveDrawX;
|
|
119
|
+
if (effectiveCellWidth <= 0)
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
// 获取单元格值
|
|
123
|
+
var dataIndex = column.dataIndex || column.key;
|
|
124
|
+
var cellValue = record[dataIndex];
|
|
125
|
+
// 调用 render 函数获取内容
|
|
126
|
+
var renderedContent = column.render(cellValue, record, rowIndex);
|
|
127
|
+
// 只有返回的不是字符串或数字时,才需要渲染到覆盖层
|
|
128
|
+
// 字符串和数字会在 Canvas 中直接绘制
|
|
129
|
+
if (typeof renderedContent !== "string" &&
|
|
130
|
+
typeof renderedContent !== "number" &&
|
|
131
|
+
renderedContent !== null &&
|
|
132
|
+
renderedContent !== undefined) {
|
|
133
|
+
// 处理 y 轴的边界裁剪,类似于 x 轴的处理
|
|
134
|
+
var effectiveCellHeight = rowHeight;
|
|
135
|
+
var effectiveDrawY = y;
|
|
136
|
+
var offsetTop = 0; // 记录上方被裁剪的高度
|
|
137
|
+
// 处理上边界:根据行类型进行不同的边界检查
|
|
138
|
+
var minTopY = headerHeight; // 默认最小Y为表头高度
|
|
139
|
+
if (!isFixedRow) {
|
|
140
|
+
// 非固定行还需要避开固定顶部行区域
|
|
141
|
+
minTopY = headerHeight + fixedTopRowsHeight;
|
|
142
|
+
}
|
|
143
|
+
if (y < minTopY) {
|
|
144
|
+
offsetTop = minTopY - y; // 上方被裁剪的高度
|
|
145
|
+
effectiveCellHeight = rowHeight - offsetTop; // 减少高度
|
|
146
|
+
effectiveDrawY = minTopY; // 从允许的最小Y开始绘制
|
|
147
|
+
if (effectiveCellHeight <= 0)
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// 处理下边界:根据行类型进行不同的边界检查
|
|
151
|
+
var maxBottomY = void 0;
|
|
152
|
+
if (isFixedRow) {
|
|
153
|
+
// 固定行使用完整的容器高度(减去滚动条)
|
|
154
|
+
maxBottomY = needHorizontalScrollbar
|
|
155
|
+
? containerHeight - scrollbarSize
|
|
156
|
+
: containerHeight;
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
// 非固定行需要严格避开所有固定行区域
|
|
160
|
+
var currentFixedBottomHeight = fixedBottomRowsCount * rowHeight;
|
|
161
|
+
var currentFixedSummaryHeight = fixedSummaryRow && hasSummaryRow ? rowHeight : 0;
|
|
162
|
+
// 计算可滚动区域的严格边界
|
|
163
|
+
var scrollableAreaBottom = containerHeight -
|
|
164
|
+
(needHorizontalScrollbar ? scrollbarSize : 0) -
|
|
165
|
+
currentFixedBottomHeight -
|
|
166
|
+
currentFixedSummaryHeight;
|
|
167
|
+
maxBottomY = Math.min(effectiveHeight, scrollableAreaBottom);
|
|
168
|
+
}
|
|
169
|
+
// 如果单元格部分在底部边界外
|
|
170
|
+
if (effectiveDrawY + effectiveCellHeight > maxBottomY) {
|
|
171
|
+
effectiveCellHeight = maxBottomY - effectiveDrawY;
|
|
172
|
+
if (effectiveCellHeight <= 0)
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
overlays.push({
|
|
176
|
+
rowIndex: rowIndex,
|
|
177
|
+
colIndex: colIndex,
|
|
178
|
+
x: effectiveDrawX,
|
|
179
|
+
y: effectiveDrawY,
|
|
180
|
+
width: effectiveCellWidth,
|
|
181
|
+
height: effectiveCellHeight,
|
|
182
|
+
content: renderedContent,
|
|
183
|
+
record: record,
|
|
184
|
+
columnKey: column.key,
|
|
185
|
+
isFixed: fixed || false,
|
|
186
|
+
isFixedRow: isFixedRow,
|
|
187
|
+
offsetTop: offsetTop,
|
|
188
|
+
offsetLeft: offsetLeft,
|
|
189
|
+
originalHeight: rowHeight,
|
|
190
|
+
originalWidth: width,
|
|
191
|
+
align: column.align,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
};
|
|
196
|
+
// 1. 处理固定顶部行
|
|
197
|
+
if (fixedTopRowsCount > 0) {
|
|
198
|
+
for (var i = 0; i < fixedTopRowsCount; i++) {
|
|
199
|
+
var y = headerHeight + i * rowHeight;
|
|
200
|
+
processCell(i, y, true);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// 2. 处理可滚动区域的行
|
|
204
|
+
var fixedTopRowsHeight = fixedTopRowsCount * rowHeight;
|
|
205
|
+
var fixedBottomRowsHeight = fixedBottomRowsCount * rowHeight;
|
|
206
|
+
// 计算可滚动数据区域的高度
|
|
207
|
+
var scrollableAreaHeight = containerHeight -
|
|
208
|
+
headerHeight -
|
|
209
|
+
fixedTopRowsHeight -
|
|
210
|
+
fixedBottomRowsHeight -
|
|
211
|
+
fixedSummaryHeight -
|
|
212
|
+
(needHorizontalScrollbar ? scrollbarSize : 0);
|
|
213
|
+
// 计算可见的滚动行范围
|
|
214
|
+
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
|
+
// 调整行索引,从固定顶部行之后开始
|
|
219
|
+
var adjustedStartRow = fixedTopRowsCount + scrollStartRow;
|
|
220
|
+
var adjustedEndRow = fixedTopRowsCount + scrollEndRow;
|
|
221
|
+
for (var rowIndex = adjustedStartRow; rowIndex < adjustedEndRow; rowIndex++) {
|
|
222
|
+
if (rowIndex < 0 || rowIndex >= processedDataSource.length)
|
|
223
|
+
continue;
|
|
224
|
+
// 计算相对于滚动区域的位置
|
|
225
|
+
var relativeRowIndex = rowIndex - fixedTopRowsCount;
|
|
226
|
+
var y = headerHeight +
|
|
227
|
+
fixedTopRowsHeight +
|
|
228
|
+
relativeRowIndex * rowHeight -
|
|
229
|
+
scrollState.scrollTop;
|
|
230
|
+
// 检查是否在可见区域内,并确保不会与固定行重叠
|
|
231
|
+
var minVisibleY = headerHeight + fixedTopRowsHeight;
|
|
232
|
+
var maxVisibleY = minVisibleY + scrollableAreaHeight;
|
|
233
|
+
// 额外检查:确保不会延伸到固定底部行或固定合计行区域
|
|
234
|
+
var maxAllowedY = containerHeight -
|
|
235
|
+
(needHorizontalScrollbar ? scrollbarSize : 0) -
|
|
236
|
+
fixedBottomRowsHeight -
|
|
237
|
+
fixedSummaryHeight;
|
|
238
|
+
// 可见性检查:允许部分可见的行(被固定行遮挡的情况)
|
|
239
|
+
if (y + rowHeight <= minVisibleY ||
|
|
240
|
+
y >= maxVisibleY ||
|
|
241
|
+
y >= maxAllowedY // 只检查行顶部是否超出边界,允许底部被遮挡
|
|
242
|
+
) {
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
processCell(rowIndex, y, false);
|
|
246
|
+
}
|
|
247
|
+
// 3. 处理固定底部行
|
|
248
|
+
if (fixedBottomRowsCount > 0) {
|
|
249
|
+
var bottomRowsStartIndex = processedDataSource.length -
|
|
250
|
+
fixedBottomRowsCount -
|
|
251
|
+
(fixedSummaryRow && hasSummaryRow ? 1 : 0);
|
|
252
|
+
for (var i = 0; i < fixedBottomRowsCount; i++) {
|
|
253
|
+
var rowIndex = bottomRowsStartIndex + i;
|
|
254
|
+
var y = containerHeight -
|
|
255
|
+
(needHorizontalScrollbar ? scrollbarSize : 0) -
|
|
256
|
+
fixedSummaryHeight -
|
|
257
|
+
fixedBottomRowsCount * rowHeight +
|
|
258
|
+
i * rowHeight;
|
|
259
|
+
processCell(rowIndex, y, true);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// 4. 处理固定合计行
|
|
263
|
+
if (fixedSummaryRow && hasSummaryRow) {
|
|
264
|
+
var summaryRowIndex = processedDataSource.length - 1;
|
|
265
|
+
var summaryY = containerHeight -
|
|
266
|
+
(needHorizontalScrollbar ? scrollbarSize : 0) -
|
|
267
|
+
rowHeight;
|
|
268
|
+
processCell(summaryRowIndex, summaryY, true);
|
|
269
|
+
}
|
|
270
|
+
// 排序覆盖层:优先级顺序 - 确保固定合计行有最高优先级
|
|
271
|
+
return overlays.sort(function (a, b) {
|
|
272
|
+
// 计算优先级(数值越大优先级越高)
|
|
273
|
+
var getPriority = function (overlay) {
|
|
274
|
+
// 检查是否是固定合计行(最后一行且固定合计行开启)
|
|
275
|
+
var isSummaryRow = fixedSummaryRow &&
|
|
276
|
+
hasSummaryRow &&
|
|
277
|
+
overlay.rowIndex === processedDataSource.length - 1;
|
|
278
|
+
if (isSummaryRow && overlay.isFixed)
|
|
279
|
+
return 6; // 固定合计行固定列(最高优先级)
|
|
280
|
+
if (isSummaryRow && !overlay.isFixed)
|
|
281
|
+
return 5; // 固定合计行非固定列
|
|
282
|
+
if (overlay.isFixedRow && overlay.isFixed)
|
|
283
|
+
return 4; // 其他固定行固定列
|
|
284
|
+
if (overlay.isFixedRow && !overlay.isFixed)
|
|
285
|
+
return 3; // 其他固定行非固定列
|
|
286
|
+
if (!overlay.isFixedRow && overlay.isFixed)
|
|
287
|
+
return 2; // 非固定行固定列
|
|
288
|
+
return 1; // 非固定行非固定列(最低优先级)
|
|
289
|
+
};
|
|
290
|
+
return getPriority(a) - getPriority(b);
|
|
291
|
+
});
|
|
292
|
+
}, [
|
|
293
|
+
processedDataSource,
|
|
294
|
+
columnRenderInfos,
|
|
295
|
+
scrollState.scrollTop,
|
|
296
|
+
scrollState.scrollLeft,
|
|
297
|
+
containerWidth,
|
|
298
|
+
containerHeight,
|
|
299
|
+
headerHeight,
|
|
300
|
+
rowHeight,
|
|
301
|
+
needHorizontalScrollbar,
|
|
302
|
+
needVerticalScrollbar,
|
|
303
|
+
scrollbarSize,
|
|
304
|
+
fixedRowsCount,
|
|
305
|
+
fixedRowsConfig,
|
|
306
|
+
hasSummaryRow,
|
|
307
|
+
fixedSummaryRow,
|
|
308
|
+
]);
|
|
309
|
+
return {
|
|
310
|
+
cellOverlays: cellOverlays,
|
|
311
|
+
};
|
|
312
|
+
};
|
|
313
|
+
// ==================== Hook 2: 表头覆盖层管理 ====================
|
|
314
|
+
/**
|
|
315
|
+
* 表头覆盖层管理 Hook
|
|
316
|
+
*
|
|
317
|
+
* 功能:
|
|
318
|
+
* - 计算需要渲染为 React 组件的表头位置信息
|
|
319
|
+
* - 只处理 title 为 React 元素的列
|
|
320
|
+
* - 支持列宽调整时的临时宽度
|
|
321
|
+
*/
|
|
322
|
+
var useHeaderOverlay = function (params) {
|
|
323
|
+
var columnRenderInfos = params.columnRenderInfos, scrollLeft = params.scrollLeft, headerHeight = params.headerHeight, containerWidth = params.containerWidth, needVerticalScrollbar = params.needVerticalScrollbar, scrollbarSize = params.scrollbarSize, getColumnWidth = params.getColumnWidth;
|
|
324
|
+
var headerOverlays = useMemo(function () {
|
|
325
|
+
var overlays = [];
|
|
326
|
+
var displayWidth = needVerticalScrollbar
|
|
327
|
+
? containerWidth - scrollbarSize
|
|
328
|
+
: containerWidth;
|
|
329
|
+
columnRenderInfos.forEach(function (info, index) {
|
|
330
|
+
var column = info.column, x = info.x, fixed = info.fixed, fixedLeft = info.fixedLeft;
|
|
331
|
+
// 只处理 title 为 React 元素的列
|
|
332
|
+
if (!isValidElement(column.title)) {
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
// 使用 getColumnWidth 获取列宽(考虑拖拽时的临时宽度)
|
|
336
|
+
var width = getColumnWidth ? getColumnWidth(index) : info.width;
|
|
337
|
+
var drawX = fixed ? fixedLeft : x - scrollLeft;
|
|
338
|
+
// 跳过不在可视区域的列
|
|
339
|
+
if (!fixed && (drawX + width < 0 || drawX > displayWidth)) {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
overlays.push({
|
|
343
|
+
columnKey: column.key,
|
|
344
|
+
x: drawX,
|
|
345
|
+
y: 0,
|
|
346
|
+
width: width,
|
|
347
|
+
height: headerHeight,
|
|
348
|
+
content: column.title,
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
return overlays;
|
|
352
|
+
}, [
|
|
353
|
+
columnRenderInfos,
|
|
354
|
+
scrollLeft,
|
|
355
|
+
headerHeight,
|
|
356
|
+
containerWidth,
|
|
357
|
+
needVerticalScrollbar,
|
|
358
|
+
scrollbarSize,
|
|
359
|
+
getColumnWidth,
|
|
360
|
+
]);
|
|
361
|
+
return { headerOverlays: headerOverlays };
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
export { useHeaderOverlay, useTableCellOverlay };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { __assign } from '../../_virtual/_tslib.js';
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { useCallback, useEffect, useMemo } from 'react';
|
|
4
|
+
import 'dayjs';
|
|
5
|
+
import { findColumnByKey } from '../utils/columnHelpers.js';
|
|
6
|
+
import FilterPopover from '../components/FilterPopover.js';
|
|
7
|
+
import '../../node_modules/react-contexify/dist/index.js';
|
|
8
|
+
import '../../node_modules/screenfull/index.js';
|
|
9
|
+
import 'ahooks';
|
|
10
|
+
import '../components/ColumnDynamic.js';
|
|
11
|
+
|
|
12
|
+
// ==================== Hook 1: Badge弹窗管理 ====================
|
|
13
|
+
/**
|
|
14
|
+
* Badge弹窗管理 Hook
|
|
15
|
+
*
|
|
16
|
+
* 功能:
|
|
17
|
+
* - 提供关闭Badge弹窗的方法
|
|
18
|
+
* - 滚动时自动关闭Badge弹窗和Tooltip
|
|
19
|
+
*/
|
|
20
|
+
var useBadgePopover = function (params) {
|
|
21
|
+
var badgePopover = params.badgePopover, tooltip = params.tooltip, scrollTop = params.scrollTop, scrollLeft = params.scrollLeft, setState = params.setState;
|
|
22
|
+
// 关闭badge弹窗
|
|
23
|
+
var handleCloseBadgePopover = useCallback(function () {
|
|
24
|
+
setState(function (prev) { return (__assign(__assign({}, prev), { badgePopover: {
|
|
25
|
+
visible: false,
|
|
26
|
+
content: "",
|
|
27
|
+
position: { x: 0, y: 0 },
|
|
28
|
+
} })); });
|
|
29
|
+
}, [setState]);
|
|
30
|
+
// 滚动时关闭badge弹窗和tooltip
|
|
31
|
+
useEffect(function () {
|
|
32
|
+
if (badgePopover.visible || tooltip.visible) {
|
|
33
|
+
setState(function (prev) { return (__assign(__assign({}, prev), { badgePopover: {
|
|
34
|
+
visible: false,
|
|
35
|
+
content: "",
|
|
36
|
+
position: { x: 0, y: 0 },
|
|
37
|
+
}, tooltip: {
|
|
38
|
+
visible: false,
|
|
39
|
+
content: "",
|
|
40
|
+
position: { x: 0, y: 0 },
|
|
41
|
+
cellInfo: null,
|
|
42
|
+
} })); });
|
|
43
|
+
}
|
|
44
|
+
}, [scrollTop, scrollLeft, setState, badgePopover.visible, tooltip.visible]);
|
|
45
|
+
return {
|
|
46
|
+
handleCloseBadgePopover: handleCloseBadgePopover,
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
// ==================== Hook 2: 筛选弹窗管理 ====================
|
|
50
|
+
/**
|
|
51
|
+
* 筛选弹窗管理 Hook
|
|
52
|
+
*
|
|
53
|
+
* 功能:
|
|
54
|
+
* - 在多级表头中递归查找列配置
|
|
55
|
+
* - 处理筛选选项的优先级(用户配置 > 自动生成)
|
|
56
|
+
* - 渲染筛选弹窗组件
|
|
57
|
+
*/
|
|
58
|
+
var useFilterPopover = function (params) {
|
|
59
|
+
var filterPopover = params.filterPopover, filters = params.filters, columns = params.columns, autoGeneratedFilters = params.autoGeneratedFilters, onFilterChange = params.onFilterChange, onClose = params.onClose, popoverRef = params.popoverRef;
|
|
60
|
+
var filterPopoverElement = useMemo(function () {
|
|
61
|
+
var visible = filterPopover.visible, columnKey = filterPopover.columnKey, position = filterPopover.position;
|
|
62
|
+
if (!visible || !columnKey) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
// 在多级表头中递归查找列
|
|
66
|
+
var column = findColumnByKey(columns, columnKey);
|
|
67
|
+
if (!column) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
// 优先使用列配置的filters,如果为空则使用自动生成的
|
|
71
|
+
var filterOptions = column.filters && column.filters.length > 0
|
|
72
|
+
? column.filters
|
|
73
|
+
: autoGeneratedFilters[columnKey];
|
|
74
|
+
if (!filterOptions || filterOptions.length === 0) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
var selectedValues = filters[columnKey] || [];
|
|
78
|
+
return (jsx(FilterPopover, { visible: visible, columnKey: columnKey, columnTitle: column.title, dataType: column.dataType, precision: column.precision, thousand: column.thousand, position: position, filterOptions: filterOptions, selectedValues: selectedValues, onConfirm: function (values) { return onFilterChange(columnKey, values); }, onReset: function () { return onFilterChange(columnKey, []); }, onClose: onClose, popoverRef: popoverRef }));
|
|
79
|
+
}, [
|
|
80
|
+
filterPopover,
|
|
81
|
+
filters,
|
|
82
|
+
columns,
|
|
83
|
+
autoGeneratedFilters,
|
|
84
|
+
onFilterChange,
|
|
85
|
+
onClose,
|
|
86
|
+
popoverRef,
|
|
87
|
+
]);
|
|
88
|
+
return {
|
|
89
|
+
filterPopoverElement: filterPopoverElement,
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export { useBadgePopover, useFilterPopover };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { __spreadArray } from '../../_virtual/_tslib.js';
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { DEFAULT_SELECTION_COLUMN_WIDTH } from '../utils/constants.js';
|
|
5
|
+
import 'dayjs';
|
|
6
|
+
import { processColumnRender } from '../utils/columnHelpers.js';
|
|
7
|
+
import { MERGE_INDEX } from '../../table/constant.js';
|
|
8
|
+
import 'lodash/isEqual';
|
|
9
|
+
import 'ahooks';
|
|
10
|
+
import '../../node_modules/immutability-helper/index.js';
|
|
11
|
+
import 'zmdms-utils';
|
|
12
|
+
import '../../node_modules/exceljs/dist/exceljs.min.js';
|
|
13
|
+
|
|
14
|
+
var useProcessedColumns = function (params) {
|
|
15
|
+
var columns = params.columns, dynamicColumns = params.dynamicColumns, mode = params.mode, rowSelection = params.rowSelection, internalColumnWidths = params.internalColumnWidths, dynamicKey = params.dynamicKey, _a = params.renderMode, renderMode = _a === void 0 ? "object" : _a, dynamicSettingRef = params.dynamicSettingRef;
|
|
16
|
+
return useMemo(function () {
|
|
17
|
+
var cols = __spreadArray([], (dynamicColumns || columns), true);
|
|
18
|
+
// 添加序号列
|
|
19
|
+
if (mode === "index") {
|
|
20
|
+
var title = "序号";
|
|
21
|
+
if (dynamicKey && dynamicSettingRef) {
|
|
22
|
+
// 动态引入ColumnDynamic组件,避免循环依赖
|
|
23
|
+
var ColumnDynamic = require("../components/ColumnDynamic").default;
|
|
24
|
+
title = jsx(ColumnDynamic, { dynamicSettingRef: dynamicSettingRef });
|
|
25
|
+
}
|
|
26
|
+
cols.unshift({
|
|
27
|
+
key: "__index__",
|
|
28
|
+
title: title,
|
|
29
|
+
dynamicTitle: "序号",
|
|
30
|
+
width: 60,
|
|
31
|
+
fixed: "left",
|
|
32
|
+
align: "center",
|
|
33
|
+
isOrder: false,
|
|
34
|
+
isFilter: false,
|
|
35
|
+
render: renderMode === "object"
|
|
36
|
+
? function (_a) {
|
|
37
|
+
var index = _a.index, record = _a.record;
|
|
38
|
+
var v = record[MERGE_INDEX] !== undefined
|
|
39
|
+
? record[MERGE_INDEX]
|
|
40
|
+
: index;
|
|
41
|
+
return "".concat(v + 1);
|
|
42
|
+
}
|
|
43
|
+
: function (_text, record, index) {
|
|
44
|
+
var v = record[MERGE_INDEX] !== undefined
|
|
45
|
+
? record[MERGE_INDEX]
|
|
46
|
+
: index;
|
|
47
|
+
return "".concat(v + 1);
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
// 添加选择框列
|
|
52
|
+
if (rowSelection) {
|
|
53
|
+
cols.unshift({
|
|
54
|
+
key: "__selection__",
|
|
55
|
+
title: "",
|
|
56
|
+
width: rowSelection.columnWidth || DEFAULT_SELECTION_COLUMN_WIDTH,
|
|
57
|
+
fixed: rowSelection.fixed ? rowSelection.fixed : "left",
|
|
58
|
+
align: "center",
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
// 应用内部列宽状态(未开启动态配置时)
|
|
62
|
+
if (!dynamicKey && Object.keys(internalColumnWidths).length > 0) {
|
|
63
|
+
cols.forEach(function (col) {
|
|
64
|
+
if (col.key && internalColumnWidths[col.key]) {
|
|
65
|
+
col.width = internalColumnWidths[col.key];
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
// 验证动态列配置
|
|
70
|
+
if (dynamicKey) {
|
|
71
|
+
cols.forEach(function (col) {
|
|
72
|
+
var title = col.title, dynamicTitle = col.dynamicTitle, key = col.key, dataIndex = col.dataIndex;
|
|
73
|
+
if (title && !dynamicTitle && typeof title !== "string") {
|
|
74
|
+
console.error("\u4F60\u4F20\u5165\u7684title\u4E0D\u662F\u4E00\u4E2A\u5B57\u7B26\u4E32,\u5E76\u4E14\u4F60\u6CA1\u6709\u4F20\u5165dynamicTitle\u7684\u914D\u7F6E\u3002\n\u95EE\u9898\u53EF\u80FD\u51FA\u73B0\u5728: ".concat(key || dataIndex, " \u5217\u3002\u8BF7\u4F20\u5165\u4E00\u4E2AdynamicTitle \u4F5C\u4E3A\u52A8\u6001\u5217\u914D\u7F6E\u7684title\u503C"));
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
// 处理render函数
|
|
79
|
+
return cols.map(function (col) {
|
|
80
|
+
return processColumnRender(col, renderMode);
|
|
81
|
+
});
|
|
82
|
+
}, [
|
|
83
|
+
dynamicColumns,
|
|
84
|
+
columns,
|
|
85
|
+
rowSelection,
|
|
86
|
+
mode,
|
|
87
|
+
dynamicKey,
|
|
88
|
+
internalColumnWidths,
|
|
89
|
+
renderMode,
|
|
90
|
+
dynamicSettingRef,
|
|
91
|
+
]);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export { useProcessedColumns };
|