zmdms-webui 2.3.0 → 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/index.es.css +1 -1
- package/dist/less/components/CanvasTable/style/index.less +106 -0
- 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,804 @@
|
|
|
1
|
+
import { __assign, __spreadArray } from '../../_virtual/_tslib.js';
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import { useMemoizedFn } from 'ahooks';
|
|
4
|
+
import { FONT_SIZE, FONT_FAMILY } from '../utils/constants.js';
|
|
5
|
+
import { isTextTruncated } from '../utils/canvasDrawHelpers.js';
|
|
6
|
+
import { getMaxDepth, flattenHeaders, getLeafColumns } from '../utils/multiHeaderHelpers.js';
|
|
7
|
+
import { getCellFromMousePosition, extractCellText } from '../utils/cellHelpers.js';
|
|
8
|
+
import 'dayjs';
|
|
9
|
+
import { calculateSelectionState, toggleSelectAll, handleSortClick, calculateIconArea, isClickInIconArea, calculateScrollPosition, calculatePopoverPosition, isPointInTriangle } from '../utils/interactionHelpers.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 表格交互事件处理 Hook
|
|
13
|
+
*/
|
|
14
|
+
var useTableInteraction = function (params) {
|
|
15
|
+
var state = params.state, setState = params.setState, scrollState = params.scrollState, setScrollState = params.setScrollState, processedDataSource = params.processedDataSource, columnRenderInfos = params.columnRenderInfos, _a = params.columns, columns = _a === void 0 ? [] : _a, rowSelection = params.rowSelection, rowHeight = params.rowHeight, headerHeight = params.headerHeight, containerWidth = params.containerWidth, containerHeight = params.containerHeight, scrollbarSize = params.scrollbarSize, canvasRef = params.canvasRef, needVerticalScrollbar = params.needVerticalScrollbar, needHorizontalScrollbar = params.needHorizontalScrollbar, verticalScrollbarTop = params.verticalScrollbarTop, verticalScrollbarHeight = params.verticalScrollbarHeight, horizontalScrollbarLeft = params.horizontalScrollbarLeft, horizontalScrollbarWidth = params.horizontalScrollbarWidth, maxScrollTop = params.maxScrollTop, maxScrollLeft = params.maxScrollLeft, totalHeight = params.totalHeight, totalWidth = params.totalWidth, dataAreaHeight = params.dataAreaHeight, onSortChange = params.onSortChange, onRowClick = params.onRowClick, getRowKey = params.getRowKey, startSelection = params.startSelection, updateSelection = params.updateSelection, extendSelection = params.extendSelection, checkResizeHandle = params.checkResizeHandle, startResize = params.startResize, updateResize = params.updateResize, endResize = params.endResize, setHoverResizeColumn = params.setHoverResizeColumn, resizeState = params.resizeState, _b = params.hasSummaryRow, hasSummaryRow = _b === void 0 ? false : _b, mergeCellMap = params.mergeCellMap, menuShow = params.menuShow, fixedRowsCount = params.fixedRowsCount, fixedRowsConfig = params.fixedRowsConfig, fixedSummaryRow = params.fixedSummaryRow;
|
|
16
|
+
// 获取鼠标位置对应的单元格
|
|
17
|
+
var getCellFromPosition = useMemoizedFn(function (x, y) {
|
|
18
|
+
var fixedTopRowsCount = (fixedRowsConfig === null || fixedRowsConfig === void 0 ? void 0 : fixedRowsConfig.topCount) || fixedRowsCount || 0;
|
|
19
|
+
var fixedBottomRowsCount = (fixedRowsConfig === null || fixedRowsConfig === void 0 ? void 0 : fixedRowsConfig.bottomCount) || 0;
|
|
20
|
+
return getCellFromMousePosition({
|
|
21
|
+
x: x,
|
|
22
|
+
y: y,
|
|
23
|
+
headerHeight: headerHeight,
|
|
24
|
+
rowHeight: rowHeight,
|
|
25
|
+
scrollTop: scrollState.scrollTop,
|
|
26
|
+
scrollLeft: scrollState.scrollLeft,
|
|
27
|
+
columnRenderInfos: columnRenderInfos,
|
|
28
|
+
dataLength: processedDataSource.length,
|
|
29
|
+
fixedTopRowsCount: fixedTopRowsCount,
|
|
30
|
+
fixedBottomRowsCount: fixedBottomRowsCount,
|
|
31
|
+
hasSummaryRow: hasSummaryRow,
|
|
32
|
+
fixedSummaryRow: fixedSummaryRow,
|
|
33
|
+
displayHeight: containerHeight,
|
|
34
|
+
needHorizontalScrollbar: needHorizontalScrollbar,
|
|
35
|
+
scrollbarSize: scrollbarSize,
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
// 处理选择框列的全选点击
|
|
39
|
+
var handleSelectAllClick = useMemoizedFn(function () {
|
|
40
|
+
var _a;
|
|
41
|
+
var selectionState = calculateSelectionState(processedDataSource, state.selectedRowKeys, getRowKey, rowSelection === null || rowSelection === void 0 ? void 0 : rowSelection.getCheckboxProps);
|
|
42
|
+
var newSelectedKeys = toggleSelectAll(processedDataSource, selectionState.isAllSelected, getRowKey, rowSelection === null || rowSelection === void 0 ? void 0 : rowSelection.getCheckboxProps);
|
|
43
|
+
setState(function (prev) { return (__assign(__assign({}, prev), { selectedRowKeys: newSelectedKeys })); });
|
|
44
|
+
var newSelectedRows = selectionState.isAllSelected
|
|
45
|
+
? []
|
|
46
|
+
: processedDataSource.filter(function (record) {
|
|
47
|
+
var _a;
|
|
48
|
+
var checkboxProps = ((_a = rowSelection === null || rowSelection === void 0 ? void 0 : rowSelection.getCheckboxProps) === null || _a === void 0 ? void 0 : _a.call(rowSelection, record)) || {};
|
|
49
|
+
return !checkboxProps.disabled;
|
|
50
|
+
});
|
|
51
|
+
(_a = rowSelection === null || rowSelection === void 0 ? void 0 : rowSelection.onChange) === null || _a === void 0 ? void 0 : _a.call(rowSelection, newSelectedKeys, newSelectedRows);
|
|
52
|
+
});
|
|
53
|
+
// 处理筛选图标点击
|
|
54
|
+
var handleFilterIconClick = useMemoizedFn(function (columnKey, drawX, width) {
|
|
55
|
+
var popoverPosition = calculatePopoverPosition(drawX, width, containerWidth, headerHeight);
|
|
56
|
+
setState(function (prev) { return (__assign(__assign({}, prev), { filterPopover: {
|
|
57
|
+
visible: true,
|
|
58
|
+
columnKey: columnKey,
|
|
59
|
+
position: popoverPosition,
|
|
60
|
+
} })); });
|
|
61
|
+
});
|
|
62
|
+
// 处理排序图标点击
|
|
63
|
+
var handleSortIconClick = useMemoizedFn(function (columnKey, clickedUpper) {
|
|
64
|
+
var sortResult = handleSortClick(clickedUpper, state.sortField, state.sortOrder, columnKey);
|
|
65
|
+
setState(function (prev) { return (__assign(__assign({}, prev), { sortField: sortResult.sortField, sortOrder: sortResult.sortOrder })); });
|
|
66
|
+
onSortChange === null || onSortChange === void 0 ? void 0 : onSortChange(columnKey, sortResult.sortOrder);
|
|
67
|
+
});
|
|
68
|
+
// 处理单个表头单元格的点击事件
|
|
69
|
+
var handleHeaderCellClick = useMemoizedFn(function (column, x, y, drawX, width, cellHeight, cellY) {
|
|
70
|
+
if (cellY === void 0) { cellY = 0; }
|
|
71
|
+
// 点击选择框列
|
|
72
|
+
if (column.key === "__selection__") {
|
|
73
|
+
handleSelectAllClick();
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
// 计算图标区域
|
|
77
|
+
var iconArea = calculateIconArea(column, width);
|
|
78
|
+
var relativeX = x - drawX;
|
|
79
|
+
// 点击筛选图标
|
|
80
|
+
if (isClickInIconArea(relativeX, iconArea, "filter")) {
|
|
81
|
+
handleFilterIconClick(column.key, drawX, width);
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
// 点击排序图标
|
|
85
|
+
if (isClickInIconArea(relativeX, iconArea, "sort")) {
|
|
86
|
+
var relativeY = y - cellY;
|
|
87
|
+
var clickedUpper = relativeY < cellHeight / 2;
|
|
88
|
+
handleSortIconClick(column.key, clickedUpper);
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
return false;
|
|
92
|
+
});
|
|
93
|
+
// 处理表头点击
|
|
94
|
+
var handleHeaderClick = useMemoizedFn(function (x, y) {
|
|
95
|
+
// 判断是否是多级表头
|
|
96
|
+
var maxDepth = getMaxDepth(columns);
|
|
97
|
+
var isMultiHeader = maxDepth > 1;
|
|
98
|
+
if (isMultiHeader) {
|
|
99
|
+
// 多级表头处理
|
|
100
|
+
var flattenedHeaderRows = flattenHeaders(columns);
|
|
101
|
+
var rowHeight_1 = headerHeight / maxDepth;
|
|
102
|
+
var clickedRowIndex = Math.floor(y / rowHeight_1);
|
|
103
|
+
if (clickedRowIndex < 0 ||
|
|
104
|
+
clickedRowIndex >= flattenedHeaderRows.length) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
var leafColumns = getLeafColumns(columns);
|
|
108
|
+
// 找到被点击的表头单元格
|
|
109
|
+
var foundCell = false;
|
|
110
|
+
for (var rowIdx = 0; rowIdx <= clickedRowIndex && !foundCell; rowIdx++) {
|
|
111
|
+
var headerRow = flattenedHeaderRows[rowIdx];
|
|
112
|
+
for (var _i = 0, headerRow_1 = headerRow; _i < headerRow_1.length; _i++) {
|
|
113
|
+
var headerCell = headerRow_1[_i];
|
|
114
|
+
var column = headerCell.column, colSpan = headerCell.colSpan, rowSpan = headerCell.rowSpan, colIndex = headerCell.colIndex;
|
|
115
|
+
// 计算该表头单元格的位置和宽度
|
|
116
|
+
var cellX = 0;
|
|
117
|
+
var cellWidth = 0;
|
|
118
|
+
var isFixed = false;
|
|
119
|
+
var fixedLeft = 0;
|
|
120
|
+
for (var i = 0; i < leafColumns.length; i++) {
|
|
121
|
+
var leafInfo = columnRenderInfos[i];
|
|
122
|
+
if (i < colIndex) {
|
|
123
|
+
cellX += leafInfo.width;
|
|
124
|
+
}
|
|
125
|
+
else if (i < colIndex + colSpan) {
|
|
126
|
+
cellWidth += leafInfo.width;
|
|
127
|
+
if (leafInfo.fixed) {
|
|
128
|
+
isFixed = true;
|
|
129
|
+
if (i === colIndex) {
|
|
130
|
+
fixedLeft = leafInfo.fixedLeft;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
var drawX = isFixed ? fixedLeft : cellX - scrollState.scrollLeft;
|
|
136
|
+
var cellY = rowIdx * rowHeight_1;
|
|
137
|
+
var cellHeight = rowSpan * rowHeight_1;
|
|
138
|
+
// 检查点击是否在该单元格内
|
|
139
|
+
var inYRange = y >= cellY && y < cellY + cellHeight;
|
|
140
|
+
if (inYRange && x >= drawX && x < drawX + cellWidth) {
|
|
141
|
+
foundCell = true;
|
|
142
|
+
// 判断是否是最末级表头且非特殊列
|
|
143
|
+
var isLastLevel = rowIdx + rowSpan === maxDepth;
|
|
144
|
+
var isSpecialColumn = column.key === "__selection__" || column.key === "__index__";
|
|
145
|
+
// 只有最末级且非特殊列才能排序和筛选
|
|
146
|
+
if (column.key === "__selection__" ||
|
|
147
|
+
(isLastLevel && !isSpecialColumn)) {
|
|
148
|
+
handleHeaderCellClick(column, x, y, drawX, cellWidth, cellHeight, cellY);
|
|
149
|
+
}
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
// 单层表头处理
|
|
157
|
+
for (var _a = 0, columnRenderInfos_1 = columnRenderInfos; _a < columnRenderInfos_1.length; _a++) {
|
|
158
|
+
var info = columnRenderInfos_1[_a];
|
|
159
|
+
var column = info.column, fixed = info.fixed, fixedLeft = info.fixedLeft, width = info.width;
|
|
160
|
+
var drawX = fixed ? fixedLeft : info.x - scrollState.scrollLeft;
|
|
161
|
+
if (x >= drawX && x < drawX + width) {
|
|
162
|
+
handleHeaderCellClick(column, x, y, drawX, width, headerHeight);
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
// 检查是否点击了badge
|
|
169
|
+
var checkBadgeClick = useMemoizedFn(function (x, y, cell, clientX, clientY) {
|
|
170
|
+
var row = cell.row, col = cell.col;
|
|
171
|
+
var record = processedDataSource[row];
|
|
172
|
+
if (!record)
|
|
173
|
+
return false;
|
|
174
|
+
// 跳过合计行的badge点击
|
|
175
|
+
var isSummaryRow = hasSummaryRow && row === processedDataSource.length - 1;
|
|
176
|
+
if (isSummaryRow)
|
|
177
|
+
return false;
|
|
178
|
+
var columnInfo = columnRenderInfos[col];
|
|
179
|
+
if (!columnInfo)
|
|
180
|
+
return false;
|
|
181
|
+
var column = columnInfo.column, width = columnInfo.width, fixed = columnInfo.fixed, fixedLeft = columnInfo.fixedLeft, colX = columnInfo.x;
|
|
182
|
+
// 检查该列是否有badge配置
|
|
183
|
+
if (!column.badge)
|
|
184
|
+
return false;
|
|
185
|
+
// 获取badge配置
|
|
186
|
+
var badgeProps = typeof column.badge === "function"
|
|
187
|
+
? column.badge(record)
|
|
188
|
+
: column.badge;
|
|
189
|
+
if (!badgeProps || !badgeProps.text)
|
|
190
|
+
return false;
|
|
191
|
+
// 计算单元格的位置和大小
|
|
192
|
+
var cellX = fixed ? fixedLeft : colX - scrollState.scrollLeft;
|
|
193
|
+
var cellY = headerHeight + row * rowHeight - scrollState.scrollTop;
|
|
194
|
+
var cellWidth = width;
|
|
195
|
+
var cellHeight = rowHeight;
|
|
196
|
+
var position = badgeProps.position || "top-right";
|
|
197
|
+
// 使用工具函数判断点击位置是否在三角形区域内
|
|
198
|
+
var isInTriangle = isPointInTriangle(x, y, cellX, cellY, cellWidth, cellHeight, position);
|
|
199
|
+
if (isInTriangle) {
|
|
200
|
+
// 如果已经显示相同内容的弹框,则关闭;否则显示新弹框
|
|
201
|
+
setState(function (prev) {
|
|
202
|
+
if (prev.badgePopover.visible &&
|
|
203
|
+
prev.badgePopover.content === badgeProps.text) {
|
|
204
|
+
return __assign(__assign({}, prev), { badgePopover: {
|
|
205
|
+
visible: false,
|
|
206
|
+
content: "",
|
|
207
|
+
position: { x: 0, y: 0 },
|
|
208
|
+
} });
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
return __assign(__assign({}, prev), { badgePopover: {
|
|
212
|
+
visible: true,
|
|
213
|
+
content: badgeProps.text,
|
|
214
|
+
position: { x: clientX + 10, y: clientY + 10 },
|
|
215
|
+
} });
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
return false;
|
|
221
|
+
});
|
|
222
|
+
// 处理行点击
|
|
223
|
+
var handleRowClick = useMemoizedFn(function (x, y) {
|
|
224
|
+
var _a, _b;
|
|
225
|
+
var adjustedY = y + scrollState.scrollTop - headerHeight;
|
|
226
|
+
var rowIndex = Math.floor(adjustedY / rowHeight);
|
|
227
|
+
if (rowIndex < 0 || rowIndex >= processedDataSource.length)
|
|
228
|
+
return;
|
|
229
|
+
// 检查是否点击选择框列
|
|
230
|
+
var selectionColumn = columnRenderInfos.find(function (info) { return info.column.key === "__selection__"; });
|
|
231
|
+
if (selectionColumn) {
|
|
232
|
+
var drawX = selectionColumn.fixed
|
|
233
|
+
? selectionColumn.fixedLeft
|
|
234
|
+
: selectionColumn.x - scrollState.scrollLeft;
|
|
235
|
+
if (x >= drawX && x < drawX + selectionColumn.width) {
|
|
236
|
+
// 处理合并单元格的情况:如果点击的是被合并的单元格,需要找到主单元格
|
|
237
|
+
var selectionColIndex = columnRenderInfos.indexOf(selectionColumn);
|
|
238
|
+
var mergeCellKey = "".concat(rowIndex, "-").concat(selectionColIndex);
|
|
239
|
+
var mergeInfo = mergeCellMap === null || mergeCellMap === void 0 ? void 0 : mergeCellMap.get(mergeCellKey);
|
|
240
|
+
// 如果是被合并的单元格,找到对应的主单元格
|
|
241
|
+
if (mergeInfo && mergeInfo.skip) {
|
|
242
|
+
// 向上查找主单元格
|
|
243
|
+
for (var i = rowIndex - 1; i >= 0; i--) {
|
|
244
|
+
var mainCellKey = "".concat(i, "-").concat(selectionColIndex);
|
|
245
|
+
var mainMergeInfo = mergeCellMap === null || mergeCellMap === void 0 ? void 0 : mergeCellMap.get(mainCellKey);
|
|
246
|
+
if (mainMergeInfo && !mainMergeInfo.skip) {
|
|
247
|
+
// 检查这个主单元格是否覆盖了当前点击的位置
|
|
248
|
+
var mainCellEndRow = i + mainMergeInfo.rowSpan - 1;
|
|
249
|
+
if (rowIndex <= mainCellEndRow) {
|
|
250
|
+
rowIndex = i; // 使用主单元格的行索引
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
var record_1 = processedDataSource[rowIndex];
|
|
257
|
+
var recordKey_1 = getRowKey(record_1, rowIndex);
|
|
258
|
+
var checkboxProps = ((_a = rowSelection === null || rowSelection === void 0 ? void 0 : rowSelection.getCheckboxProps) === null || _a === void 0 ? void 0 : _a.call(rowSelection, record_1)) || {};
|
|
259
|
+
if (!checkboxProps.disabled) {
|
|
260
|
+
var isSelected = state.selectedRowKeys.includes(recordKey_1);
|
|
261
|
+
var newSelectedKeys_1 = isSelected
|
|
262
|
+
? state.selectedRowKeys.filter(function (key) { return key !== recordKey_1; })
|
|
263
|
+
: __spreadArray(__spreadArray([], state.selectedRowKeys, true), [recordKey_1], false);
|
|
264
|
+
setState(function (prev) { return (__assign(__assign({}, prev), { selectedRowKeys: newSelectedKeys_1 })); });
|
|
265
|
+
var newSelectedRows = processedDataSource.filter(function (r, i) {
|
|
266
|
+
return newSelectedKeys_1.includes(getRowKey(r, i));
|
|
267
|
+
});
|
|
268
|
+
(_b = rowSelection === null || rowSelection === void 0 ? void 0 : rowSelection.onChange) === null || _b === void 0 ? void 0 : _b.call(rowSelection, newSelectedKeys_1, newSelectedRows);
|
|
269
|
+
}
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
var record = processedDataSource[rowIndex];
|
|
274
|
+
onRowClick === null || onRowClick === void 0 ? void 0 : onRowClick(record, rowIndex);
|
|
275
|
+
});
|
|
276
|
+
// Canvas 鼠标按下事件
|
|
277
|
+
var handleCanvasMouseDown = useMemoizedFn(function (e) {
|
|
278
|
+
var _a, _b;
|
|
279
|
+
// 忽略右键点击,避免影响框选
|
|
280
|
+
if (e.button === 2)
|
|
281
|
+
return;
|
|
282
|
+
var canvas = e.currentTarget;
|
|
283
|
+
var rect = canvas.getBoundingClientRect();
|
|
284
|
+
var x = e.clientX - rect.left;
|
|
285
|
+
var y = e.clientY - rect.top;
|
|
286
|
+
// 检查是否点击了垂直滚动条
|
|
287
|
+
if (needVerticalScrollbar &&
|
|
288
|
+
x >= containerWidth - scrollbarSize &&
|
|
289
|
+
y >= headerHeight &&
|
|
290
|
+
y <
|
|
291
|
+
(needHorizontalScrollbar
|
|
292
|
+
? containerHeight - scrollbarSize
|
|
293
|
+
: containerHeight)) {
|
|
294
|
+
var scrollbarRelativeY = y - headerHeight;
|
|
295
|
+
var scrollbarTop = verticalScrollbarTop;
|
|
296
|
+
// 点击滚动条滑块
|
|
297
|
+
if (scrollbarRelativeY >= scrollbarTop &&
|
|
298
|
+
scrollbarRelativeY <= scrollbarTop + verticalScrollbarHeight) {
|
|
299
|
+
setScrollState(function (prev) { return (__assign(__assign({}, prev), { isDraggingVertical: true, dragStartY: y, dragStartScrollTop: prev.scrollTop })); });
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
// 点击滚动条轨道
|
|
303
|
+
var clickRatio = scrollbarRelativeY / dataAreaHeight;
|
|
304
|
+
var newScrollTop_1 = Math.max(0, Math.min(maxScrollTop, clickRatio * (totalHeight - headerHeight)));
|
|
305
|
+
setScrollState(function (prev) { return (__assign(__assign({}, prev), { scrollTop: newScrollTop_1 })); });
|
|
306
|
+
}
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
// 检查是否点击了水平滚动条
|
|
310
|
+
if (needHorizontalScrollbar &&
|
|
311
|
+
y >= containerHeight - scrollbarSize &&
|
|
312
|
+
x <
|
|
313
|
+
(needVerticalScrollbar
|
|
314
|
+
? containerWidth - scrollbarSize
|
|
315
|
+
: containerWidth)) {
|
|
316
|
+
// 点击滚动条滑块
|
|
317
|
+
if (x >= horizontalScrollbarLeft &&
|
|
318
|
+
x <= horizontalScrollbarLeft + horizontalScrollbarWidth) {
|
|
319
|
+
setScrollState(function (prev) { return (__assign(__assign({}, prev), { isDraggingHorizontal: true, dragStartX: x, dragStartScrollLeft: prev.scrollLeft })); });
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
// 点击滚动条轨道
|
|
323
|
+
var clickRatio = x /
|
|
324
|
+
(needVerticalScrollbar
|
|
325
|
+
? containerWidth - scrollbarSize
|
|
326
|
+
: containerWidth);
|
|
327
|
+
var newScrollLeft_1 = Math.max(0, Math.min(maxScrollLeft, clickRatio * totalWidth - containerWidth / 2));
|
|
328
|
+
setScrollState(function (prev) { return (__assign(__assign({}, prev), { scrollLeft: newScrollLeft_1 })); });
|
|
329
|
+
}
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
// 检查是否点击了列宽调整手柄
|
|
333
|
+
if (checkResizeHandle) {
|
|
334
|
+
var resizeColumnIndex = checkResizeHandle(x, y);
|
|
335
|
+
if (resizeColumnIndex !== null && startResize) {
|
|
336
|
+
startResize(resizeColumnIndex, x);
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
// 点击表头
|
|
341
|
+
if (y < headerHeight) {
|
|
342
|
+
// 先检查是否点击了功能区域(排序、筛选、选择框)
|
|
343
|
+
var isClickOnHeaderFunction = false;
|
|
344
|
+
for (var _i = 0, columnRenderInfos_2 = columnRenderInfos; _i < columnRenderInfos_2.length; _i++) {
|
|
345
|
+
var info = columnRenderInfos_2[_i];
|
|
346
|
+
var column = info.column, fixed = info.fixed, fixedLeft = info.fixedLeft, width = info.width;
|
|
347
|
+
var drawX = fixed ? fixedLeft : info.x - scrollState.scrollLeft;
|
|
348
|
+
if (x >= drawX && x < drawX + width) {
|
|
349
|
+
// 点击选择框列
|
|
350
|
+
if (column.key === "__selection__") {
|
|
351
|
+
isClickOnHeaderFunction = true;
|
|
352
|
+
break;
|
|
353
|
+
}
|
|
354
|
+
// 检查是否点击图标区域
|
|
355
|
+
var iconArea = calculateIconArea(column, width);
|
|
356
|
+
var relativeX = x - drawX;
|
|
357
|
+
if (isClickInIconArea(relativeX, iconArea, "filter") ||
|
|
358
|
+
isClickInIconArea(relativeX, iconArea, "sort")) {
|
|
359
|
+
isClickOnHeaderFunction = true;
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
if (isClickOnHeaderFunction) {
|
|
366
|
+
// 点击了功能区域,执行原有的表头点击逻辑
|
|
367
|
+
handleHeaderClick(x, y);
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
// 点击了表头的非功能区域,启动框选
|
|
371
|
+
var cell = getCellFromPosition(x, y);
|
|
372
|
+
if (cell) {
|
|
373
|
+
// 检查是否点击了选择框列,如果是则不启用框选
|
|
374
|
+
var isSelectionColumn = ((_a = columnRenderInfos[cell.col]) === null || _a === void 0 ? void 0 : _a.column.key) === "__selection__";
|
|
375
|
+
if (!isSelectionColumn) {
|
|
376
|
+
if (!e.shiftKey) {
|
|
377
|
+
startSelection(cell);
|
|
378
|
+
}
|
|
379
|
+
else if (state.cellSelection) {
|
|
380
|
+
extendSelection(cell);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
// 检查是否点击了badge
|
|
388
|
+
var cell = getCellFromPosition(x, y);
|
|
389
|
+
if (cell) {
|
|
390
|
+
var badgeClicked = checkBadgeClick(x, y, cell, e.clientX, e.clientY);
|
|
391
|
+
if (badgeClicked) {
|
|
392
|
+
// badge被点击,已处理,不继续其他逻辑
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
// 检查是否点击了选择框列,如果是,则不启用框选
|
|
397
|
+
var isSelectionColumn = cell && ((_b = columnRenderInfos[cell.col]) === null || _b === void 0 ? void 0 : _b.column.key) === "__selection__";
|
|
398
|
+
if (cell && !e.shiftKey && !isSelectionColumn) {
|
|
399
|
+
startSelection(cell);
|
|
400
|
+
}
|
|
401
|
+
else if (cell &&
|
|
402
|
+
e.shiftKey &&
|
|
403
|
+
state.cellSelection &&
|
|
404
|
+
!isSelectionColumn) {
|
|
405
|
+
extendSelection(cell);
|
|
406
|
+
}
|
|
407
|
+
else if (!isSelectionColumn) {
|
|
408
|
+
handleRowClick(x, y);
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
// 如果点击的是选择框列,直接处理行点击(勾选逻辑)
|
|
412
|
+
handleRowClick(x, y);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
// 处理垂直滚动条拖拽
|
|
417
|
+
var handleVerticalScrollDrag = useMemoizedFn(function (deltaY) {
|
|
418
|
+
var newScrollTop = calculateScrollPosition(deltaY, scrollState.dragStartScrollTop, maxScrollTop, totalHeight - headerHeight, scrollState.dragStartY, dataAreaHeight - verticalScrollbarHeight);
|
|
419
|
+
setScrollState(function (prev) { return (__assign(__assign({}, prev), { scrollTop: newScrollTop })); });
|
|
420
|
+
});
|
|
421
|
+
// 处理水平滚动条拖拽
|
|
422
|
+
var handleHorizontalScrollDrag = useMemoizedFn(function (deltaX) {
|
|
423
|
+
var scrollableWidth = needVerticalScrollbar
|
|
424
|
+
? containerWidth - scrollbarSize - horizontalScrollbarWidth
|
|
425
|
+
: containerWidth - horizontalScrollbarWidth;
|
|
426
|
+
var newScrollLeft = calculateScrollPosition(deltaX, scrollState.dragStartScrollLeft, maxScrollLeft, totalWidth, scrollState.dragStartX, scrollableWidth);
|
|
427
|
+
setScrollState(function (prev) { return (__assign(__assign({}, prev), { scrollLeft: newScrollLeft })); });
|
|
428
|
+
});
|
|
429
|
+
// Canvas 鼠标移动事件
|
|
430
|
+
var handleCanvasMouseMove = useMemoizedFn(function (e) {
|
|
431
|
+
var _a;
|
|
432
|
+
var canvas = e.currentTarget;
|
|
433
|
+
var rect = canvas.getBoundingClientRect();
|
|
434
|
+
var x = e.clientX - rect.left;
|
|
435
|
+
var y = e.clientY - rect.top;
|
|
436
|
+
// 处理列宽调整拖拽
|
|
437
|
+
if ((resizeState === null || resizeState === void 0 ? void 0 : resizeState.isResizing) && updateResize) {
|
|
438
|
+
canvas.style.cursor = "col-resize";
|
|
439
|
+
updateResize(x);
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
// 处理垂直滚动条拖拽
|
|
443
|
+
if (scrollState.isDraggingVertical) {
|
|
444
|
+
canvas.style.cursor = "grabbing";
|
|
445
|
+
handleVerticalScrollDrag(y - scrollState.dragStartY);
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
// 处理水平滚动条拖拽
|
|
449
|
+
if (scrollState.isDraggingHorizontal) {
|
|
450
|
+
canvas.style.cursor = "grabbing";
|
|
451
|
+
handleHorizontalScrollDrag(x - scrollState.dragStartX);
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
// 处理框选
|
|
455
|
+
if (state.isSelecting) {
|
|
456
|
+
var cell = getCellFromPosition(x, y);
|
|
457
|
+
if (cell) {
|
|
458
|
+
// 检查是否在选择框列,如果是,则不更新框选
|
|
459
|
+
var isSelectionColumn = ((_a = columnRenderInfos[cell.col]) === null || _a === void 0 ? void 0 : _a.column.key) === "__selection__";
|
|
460
|
+
if (!isSelectionColumn) {
|
|
461
|
+
updateSelection(cell);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
// 检测列宽调整手柄hover状态
|
|
467
|
+
if (checkResizeHandle && setHoverResizeColumn) {
|
|
468
|
+
var resizeColumnIndex = checkResizeHandle(x, y);
|
|
469
|
+
setHoverResizeColumn(resizeColumnIndex);
|
|
470
|
+
// 如果鼠标在调整手柄上,改变鼠标样式
|
|
471
|
+
if (resizeColumnIndex !== null) {
|
|
472
|
+
canvas.style.cursor = "col-resize";
|
|
473
|
+
return; // 优先处理列宽调整
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
// 检测鼠标是否悬浮在排序/过滤图标上
|
|
477
|
+
var isHoveringHeaderIcon = false;
|
|
478
|
+
if (y < headerHeight) {
|
|
479
|
+
for (var _i = 0, columnRenderInfos_3 = columnRenderInfos; _i < columnRenderInfos_3.length; _i++) {
|
|
480
|
+
var info = columnRenderInfos_3[_i];
|
|
481
|
+
var column = info.column, fixed = info.fixed, fixedLeft = info.fixedLeft, width = info.width;
|
|
482
|
+
var drawX = fixed ? fixedLeft : info.x - scrollState.scrollLeft;
|
|
483
|
+
if (x >= drawX && x < drawX + width) {
|
|
484
|
+
var iconArea = calculateIconArea(column, width);
|
|
485
|
+
var relativeX = x - drawX;
|
|
486
|
+
// 检查是否在图标区域内
|
|
487
|
+
if (isClickInIconArea(relativeX, iconArea, "filter") ||
|
|
488
|
+
isClickInIconArea(relativeX, iconArea, "sort")) {
|
|
489
|
+
isHoveringHeaderIcon = true;
|
|
490
|
+
break;
|
|
491
|
+
}
|
|
492
|
+
break;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
// 根据检测结果设置鼠标样式
|
|
497
|
+
canvas.style.cursor = isHoveringHeaderIcon ? "pointer" : "default";
|
|
498
|
+
// Hover 行高亮 & Tooltip
|
|
499
|
+
if (y > headerHeight &&
|
|
500
|
+
y <
|
|
501
|
+
(needHorizontalScrollbar
|
|
502
|
+
? containerHeight - scrollbarSize
|
|
503
|
+
: containerHeight)) {
|
|
504
|
+
var adjustedY = y + scrollState.scrollTop - headerHeight;
|
|
505
|
+
var rowIndex_1 = Math.floor(adjustedY / rowHeight);
|
|
506
|
+
if (rowIndex_1 >= 0 && rowIndex_1 < processedDataSource.length) {
|
|
507
|
+
setState(function (prev) {
|
|
508
|
+
if (prev.hoverRowIndex !== rowIndex_1) {
|
|
509
|
+
return __assign(__assign({}, prev), { hoverRowIndex: rowIndex_1 });
|
|
510
|
+
}
|
|
511
|
+
return prev;
|
|
512
|
+
});
|
|
513
|
+
// 检测tooltip
|
|
514
|
+
var cell_1 = getCellFromPosition(x, y);
|
|
515
|
+
if (cell_1 && cell_1.row >= 0 && cell_1.col >= 0) {
|
|
516
|
+
var columnInfo = columnRenderInfos[cell_1.col];
|
|
517
|
+
if (columnInfo && columnInfo.column.key !== "__selection__") {
|
|
518
|
+
var record = processedDataSource[cell_1.row];
|
|
519
|
+
var column = columnInfo.column;
|
|
520
|
+
// 检查是否有render函数返回自定义组件(这种情况不显示tooltip)
|
|
521
|
+
var shouldShowTooltip = true;
|
|
522
|
+
if (column.render) {
|
|
523
|
+
var dataIndex = column.dataIndex || column.key;
|
|
524
|
+
var cellValue = record[dataIndex];
|
|
525
|
+
var rendered = column.render(cellValue, record, cell_1.row);
|
|
526
|
+
if (typeof rendered !== "string" &&
|
|
527
|
+
typeof rendered !== "number" &&
|
|
528
|
+
rendered !== null &&
|
|
529
|
+
rendered !== undefined) {
|
|
530
|
+
shouldShowTooltip = false;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
if (shouldShowTooltip) {
|
|
534
|
+
var dataIndex = column.dataIndex || column.key;
|
|
535
|
+
var cellValue = record[dataIndex];
|
|
536
|
+
var cellText_1 = extractCellText({
|
|
537
|
+
cellValue: cellValue,
|
|
538
|
+
record: record,
|
|
539
|
+
rowIndex: cell_1.row,
|
|
540
|
+
renderFn: column.render,
|
|
541
|
+
});
|
|
542
|
+
// 检查是否启用了ellipsis(默认为true)且文本被截断
|
|
543
|
+
var ellipsis = column.ellipsis !== false;
|
|
544
|
+
if (ellipsis && cellText_1) {
|
|
545
|
+
// 创建临时canvas来测量文本
|
|
546
|
+
var tempCanvas = document.createElement("canvas");
|
|
547
|
+
var tempCtx = tempCanvas.getContext("2d");
|
|
548
|
+
if (tempCtx) {
|
|
549
|
+
tempCtx.font = "".concat(FONT_SIZE, "px ").concat(FONT_FAMILY);
|
|
550
|
+
var maxWidth = columnInfo.width - 32;
|
|
551
|
+
var isTruncated = isTextTruncated(tempCtx, cellText_1, maxWidth);
|
|
552
|
+
if (isTruncated) {
|
|
553
|
+
// 显示tooltip
|
|
554
|
+
setState(function (prev) { return (__assign(__assign({}, prev), { tooltip: {
|
|
555
|
+
visible: true,
|
|
556
|
+
content: cellText_1,
|
|
557
|
+
position: { x: e.clientX + 10, y: e.clientY + 10 },
|
|
558
|
+
cellInfo: { rowIndex: cell_1.row, colIndex: cell_1.col },
|
|
559
|
+
} })); });
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
// 如果到这里,说明不需要显示tooltip,隐藏它
|
|
568
|
+
setState(function (prev) {
|
|
569
|
+
if (prev.tooltip.visible) {
|
|
570
|
+
return __assign(__assign({}, prev), { tooltip: {
|
|
571
|
+
visible: false,
|
|
572
|
+
content: "",
|
|
573
|
+
position: { x: 0, y: 0 },
|
|
574
|
+
cellInfo: null,
|
|
575
|
+
} });
|
|
576
|
+
}
|
|
577
|
+
return prev;
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
else {
|
|
582
|
+
setState(function (prev) {
|
|
583
|
+
var updates = {};
|
|
584
|
+
if (prev.hoverRowIndex !== null) {
|
|
585
|
+
updates.hoverRowIndex = null;
|
|
586
|
+
}
|
|
587
|
+
if (prev.tooltip.visible) {
|
|
588
|
+
updates.tooltip = {
|
|
589
|
+
visible: false,
|
|
590
|
+
content: "",
|
|
591
|
+
position: { x: 0, y: 0 },
|
|
592
|
+
cellInfo: null,
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
if (Object.keys(updates).length > 0) {
|
|
596
|
+
return __assign(__assign({}, prev), updates);
|
|
597
|
+
}
|
|
598
|
+
return prev;
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
// Canvas 鼠标抬起事件
|
|
603
|
+
var handleCanvasMouseUp = useMemoizedFn(function () {
|
|
604
|
+
// 结束列宽调整
|
|
605
|
+
if ((resizeState === null || resizeState === void 0 ? void 0 : resizeState.isResizing) && endResize) {
|
|
606
|
+
endResize();
|
|
607
|
+
}
|
|
608
|
+
setScrollState(function (prev) { return (__assign(__assign({}, prev), { isDraggingVertical: false, isDraggingHorizontal: false })); });
|
|
609
|
+
// 结束框选
|
|
610
|
+
if (state.isSelecting) {
|
|
611
|
+
setState(function (prev) { return (__assign(__assign({}, prev), { isSelecting: false })); });
|
|
612
|
+
}
|
|
613
|
+
});
|
|
614
|
+
// 检查目标元素是否是Canvas内部渲染的元素
|
|
615
|
+
var isCanvasInternalElement = useMemoizedFn(function (element) {
|
|
616
|
+
var _a;
|
|
617
|
+
// 严格类型检查
|
|
618
|
+
if (!element || !(element instanceof Node)) {
|
|
619
|
+
return false;
|
|
620
|
+
}
|
|
621
|
+
// 获取Canvas容器
|
|
622
|
+
var canvasContainer = (_a = canvasRef.current) === null || _a === void 0 ? void 0 : _a.parentElement;
|
|
623
|
+
if (!canvasContainer)
|
|
624
|
+
return false;
|
|
625
|
+
// Canvas内部渲染的覆盖层元素选择器
|
|
626
|
+
var canvasInternalSelectors = [
|
|
627
|
+
".canvas-table-header-overlay",
|
|
628
|
+
".canvas-table-cell-overlay",
|
|
629
|
+
".canvas-table-cell-content",
|
|
630
|
+
".canvas-table-filter-popover",
|
|
631
|
+
".canvas-table-tooltip",
|
|
632
|
+
".canvas-table-badge-popover",
|
|
633
|
+
".canvas-table-menu",
|
|
634
|
+
".canvas-table--exit-fullscreen",
|
|
635
|
+
".canvas-table-empty",
|
|
636
|
+
".react-contexify",
|
|
637
|
+
".react-contexify__item", // 菜单项
|
|
638
|
+
];
|
|
639
|
+
// Antd组件选择器(这些可能渲染到body中)
|
|
640
|
+
var antdSelectors = [
|
|
641
|
+
".ant-select-dropdown",
|
|
642
|
+
".ant-checkbox",
|
|
643
|
+
".ant-input",
|
|
644
|
+
".ant-btn",
|
|
645
|
+
".ant-tabs",
|
|
646
|
+
".ant-tab-pane",
|
|
647
|
+
".ant-checkbox-wrapper", // 复选框容器
|
|
648
|
+
];
|
|
649
|
+
try {
|
|
650
|
+
// 检查是否在Canvas容器内
|
|
651
|
+
if (!canvasContainer.contains(element)) {
|
|
652
|
+
return false;
|
|
653
|
+
}
|
|
654
|
+
// 合并所有选择器进行检查
|
|
655
|
+
var allSelectors = __spreadArray(__spreadArray([], canvasInternalSelectors, true), antdSelectors, true);
|
|
656
|
+
// 检查元素本身或其父元素是否匹配选择器
|
|
657
|
+
var currentElement = element;
|
|
658
|
+
while (currentElement &&
|
|
659
|
+
currentElement instanceof Node &&
|
|
660
|
+
canvasContainer.contains(currentElement)) {
|
|
661
|
+
// 确保 currentElement 是 Element 类型才调用 matches
|
|
662
|
+
if (currentElement instanceof Element) {
|
|
663
|
+
for (var _i = 0, allSelectors_1 = allSelectors; _i < allSelectors_1.length; _i++) {
|
|
664
|
+
var selector = allSelectors_1[_i];
|
|
665
|
+
try {
|
|
666
|
+
if (currentElement.matches(selector)) {
|
|
667
|
+
return true;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
catch (e) {
|
|
671
|
+
// 忽略无效选择器错误
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
currentElement = currentElement.parentElement;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
catch (e) {
|
|
679
|
+
// 如果出现任何错误,返回false以确保稳定性
|
|
680
|
+
console.warn("Error in isCanvasInternalElement:", e);
|
|
681
|
+
return false;
|
|
682
|
+
}
|
|
683
|
+
return false;
|
|
684
|
+
});
|
|
685
|
+
// Canvas 鼠标离开事件
|
|
686
|
+
var handleCanvasMouseLeave = useMemoizedFn(function (e) {
|
|
687
|
+
var canvas = e.currentTarget;
|
|
688
|
+
// 如果正在拖拽滚动条或调整列宽,不做任何处理
|
|
689
|
+
// 让document级别的监听器继续处理,直到mouseup
|
|
690
|
+
if (scrollState.isDraggingVertical ||
|
|
691
|
+
scrollState.isDraggingHorizontal ||
|
|
692
|
+
(resizeState === null || resizeState === void 0 ? void 0 : resizeState.isResizing)) {
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
// 检查鼠标移动的目标元素
|
|
696
|
+
var relatedTarget = e.relatedTarget;
|
|
697
|
+
// 如果鼠标移动到Canvas内部渲染的元素,不停止框选
|
|
698
|
+
if (isCanvasInternalElement(relatedTarget)) {
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
// 重置光标样式
|
|
702
|
+
canvas.style.cursor = "default";
|
|
703
|
+
// 清理状态
|
|
704
|
+
setState(function (prev) {
|
|
705
|
+
var updates = {};
|
|
706
|
+
// 结束框选
|
|
707
|
+
if (prev.isSelecting) {
|
|
708
|
+
updates.isSelecting = false;
|
|
709
|
+
}
|
|
710
|
+
// 清理 hover
|
|
711
|
+
if (prev.hoverRowIndex !== null) {
|
|
712
|
+
updates.hoverRowIndex = null;
|
|
713
|
+
}
|
|
714
|
+
// 清理 tooltip
|
|
715
|
+
if (prev.tooltip.visible) {
|
|
716
|
+
updates.tooltip = {
|
|
717
|
+
visible: false,
|
|
718
|
+
content: "",
|
|
719
|
+
position: { x: 0, y: 0 },
|
|
720
|
+
cellInfo: null,
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
if (Object.keys(updates).length > 0) {
|
|
724
|
+
return __assign(__assign({}, prev), updates);
|
|
725
|
+
}
|
|
726
|
+
return prev;
|
|
727
|
+
});
|
|
728
|
+
});
|
|
729
|
+
// Canvas 右键菜单事件
|
|
730
|
+
var handleCanvasContextMenu = useMemoizedFn(function (e) {
|
|
731
|
+
if (!menuShow)
|
|
732
|
+
return;
|
|
733
|
+
e.preventDefault();
|
|
734
|
+
e.stopPropagation();
|
|
735
|
+
// 显示右键菜单
|
|
736
|
+
menuShow({ event: e });
|
|
737
|
+
});
|
|
738
|
+
// 在document上监听拖拽事件,以支持鼠标移出canvas后继续拖拽
|
|
739
|
+
useEffect(function () {
|
|
740
|
+
var isDragging = scrollState.isDraggingVertical ||
|
|
741
|
+
scrollState.isDraggingHorizontal ||
|
|
742
|
+
(resizeState === null || resizeState === void 0 ? void 0 : resizeState.isResizing);
|
|
743
|
+
if (!isDragging)
|
|
744
|
+
return;
|
|
745
|
+
var handleDocumentMouseMove = function (e) {
|
|
746
|
+
// 获取当前实例的canvas
|
|
747
|
+
var canvas = canvasRef.current;
|
|
748
|
+
if (!canvas)
|
|
749
|
+
return;
|
|
750
|
+
var rect = canvas.getBoundingClientRect();
|
|
751
|
+
var x = e.clientX - rect.left;
|
|
752
|
+
var y = e.clientY - rect.top;
|
|
753
|
+
// 处理列宽调整拖拽
|
|
754
|
+
if ((resizeState === null || resizeState === void 0 ? void 0 : resizeState.isResizing) && updateResize) {
|
|
755
|
+
updateResize(x);
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
// 处理垂直滚动条拖拽
|
|
759
|
+
if (scrollState.isDraggingVertical) {
|
|
760
|
+
handleVerticalScrollDrag(y - scrollState.dragStartY);
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
// 处理水平滚动条拖拽
|
|
764
|
+
if (scrollState.isDraggingHorizontal) {
|
|
765
|
+
handleHorizontalScrollDrag(x - scrollState.dragStartX);
|
|
766
|
+
}
|
|
767
|
+
};
|
|
768
|
+
var handleDocumentMouseUp = function () {
|
|
769
|
+
// 结束列宽调整
|
|
770
|
+
if ((resizeState === null || resizeState === void 0 ? void 0 : resizeState.isResizing) && endResize) {
|
|
771
|
+
endResize();
|
|
772
|
+
}
|
|
773
|
+
setScrollState(function (prev) { return (__assign(__assign({}, prev), { isDraggingVertical: false, isDraggingHorizontal: false })); });
|
|
774
|
+
};
|
|
775
|
+
document.addEventListener("mousemove", handleDocumentMouseMove);
|
|
776
|
+
document.addEventListener("mouseup", handleDocumentMouseUp);
|
|
777
|
+
return function () {
|
|
778
|
+
document.removeEventListener("mousemove", handleDocumentMouseMove);
|
|
779
|
+
document.removeEventListener("mouseup", handleDocumentMouseUp);
|
|
780
|
+
};
|
|
781
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
782
|
+
}, [
|
|
783
|
+
scrollState.isDraggingVertical,
|
|
784
|
+
scrollState.isDraggingHorizontal,
|
|
785
|
+
resizeState === null || resizeState === void 0 ? void 0 : resizeState.isResizing,
|
|
786
|
+
updateResize,
|
|
787
|
+
endResize,
|
|
788
|
+
handleVerticalScrollDrag,
|
|
789
|
+
handleHorizontalScrollDrag,
|
|
790
|
+
canvasRef,
|
|
791
|
+
]);
|
|
792
|
+
return {
|
|
793
|
+
handleCanvasMouseDown: handleCanvasMouseDown,
|
|
794
|
+
handleCanvasMouseMove: handleCanvasMouseMove,
|
|
795
|
+
handleCanvasMouseUp: handleCanvasMouseUp,
|
|
796
|
+
handleCanvasMouseLeave: handleCanvasMouseLeave,
|
|
797
|
+
handleCanvasContextMenu: handleCanvasContextMenu,
|
|
798
|
+
handleHeaderClick: handleHeaderClick,
|
|
799
|
+
handleRowClick: handleRowClick,
|
|
800
|
+
getCellFromPosition: getCellFromPosition,
|
|
801
|
+
};
|
|
802
|
+
};
|
|
803
|
+
|
|
804
|
+
export { useTableInteraction };
|