zmdms-webui 2.4.0 → 2.4.2

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.
@@ -39,7 +39,8 @@ import { getTableColumns } from '../table/utils.js';
39
39
  import DynamicSetting from '../dynamicsetting/dynamicSetting.js';
40
40
 
41
41
  function CanvasTable(props) {
42
- var _a = props.dataSource, dataSource = _a === void 0 ? [] : _a, _b = props.columns, columns = _b === void 0 ? [] : _b, _c = props.rowKey, rowKey = _c === void 0 ? "id" : _c, _d = props.height, height = _d === void 0 ? 600 : _d, width = props.width, _e = props.rowHeight, rowHeight = _e === void 0 ? 36 : _e, _f = props.headerHeight, headerHeight = _f === void 0 ? 36 : _f, rowSelection = props.rowSelection, onSortChange = props.onSortChange, onFilterChange = props.onFilterChange, onScroll = props.onScroll, onRowClick = props.onRowClick, onColumnResize = props.onColumnResize, _g = props.bordered, bordered = _g === void 0 ? true : _g, _h = props.striped, striped = _h === void 0 ? false : _h, _j = props.emptyText, emptyText = _j === void 0 ? "暂无数据" : _j, style = props.style, className = props.className, _k = props.loading, loading = _k === void 0 ? false : _k, _l = props.isContextMenu, isContextMenu = _l === void 0 ? true : _l, isFullscreenHandle = props.isFullscreenHandle, _m = props.mode, mode = _m === void 0 ? "index" : _m, dynamicKey = props.dynamicKey, dynamicVersion = props.dynamicVersion, customDynamicListHandle = props.customDynamicListHandle, isDimensionDynamic = props.isDimensionDynamic, dimensionCustomSumKeys = props.dimensionCustomSumKeys, isAutoMerge = props.isAutoMerge, _o = props.isIndexMerge, isIndexMerge = _o === void 0 ? true : _o, _p = props.isSelectionMerge, isSelectionMerge = _p === void 0 ? false : _p, _q = props.renderMode, renderMode = _q === void 0 ? "object" : _q, fixedRowsCount = props.fixedRowsCount, fixedRowsConfig = props.fixedRowsConfig, _r = props.summaryFixed, summaryFixed = _r === void 0 ? false : _r, _s = props.isAutoScrollY, isAutoScrollY = _s === void 0 ? false : _s, _t = props.autoScrollYMarginBottom, autoScrollYMarginBottom = _t === void 0 ? 65 : _t, canvasTableId = props.canvasTableId, headerWrap = props.headerWrap, _u = props.headerAlign, headerAlign = _u === void 0 ? "center" : _u, tableRefHandle = props.tableRefHandle, exportExcelConfig = props.exportExcelConfig;
42
+ var _a = props.dataSource, dataSource = _a === void 0 ? [] : _a, _b = props.columns, columns = _b === void 0 ? [] : _b, _c = props.rowKey, rowKey = _c === void 0 ? "id" : _c, _d = props.height, height = _d === void 0 ? 600 : _d, width = props.width, _e = props.rowHeight, rowHeight = _e === void 0 ? 36 : _e, _f = props.headerHeight, headerHeight = _f === void 0 ? 36 : _f, rowSelection = props.rowSelection, onSortChange = props.onSortChange, onFilterChange = props.onFilterChange, onScroll = props.onScroll, onRowClick = props.onRowClick, onColumnResize = props.onColumnResize, _g = props.bordered, bordered = _g === void 0 ? true : _g, _h = props.striped, striped = _h === void 0 ? false : _h, _j = props.emptyText, emptyText = _j === void 0 ? "暂无数据" : _j, style = props.style, className = props.className, _k = props.loading, loading = _k === void 0 ? false : _k, _l = props.isContextMenu, isContextMenu = _l === void 0 ? true : _l, isFullscreenHandle = props.isFullscreenHandle, mode = props.mode, dynamicKey = props.dynamicKey, dynamicVersion = props.dynamicVersion, customDynamicListHandle = props.customDynamicListHandle, isDimensionDynamic = props.isDimensionDynamic, dimensionCustomSumKeys = props.dimensionCustomSumKeys, isAutoMerge = props.isAutoMerge, _m = props.isIndexMerge, isIndexMerge = _m === void 0 ? true : _m, _o = props.isSelectionMerge, isSelectionMerge = _o === void 0 ? false : _o, _p = props.renderMode, renderMode = _p === void 0 ? "object" : _p, fixedRowsCount = props.fixedRowsCount, fixedRowsConfig = props.fixedRowsConfig, _q = props.summaryFixed, summaryFixed = _q === void 0 ? false : _q, _r = props.isAutoScrollY, isAutoScrollY = _r === void 0 ? false : _r, _s = props.autoScrollYMarginBottom, autoScrollYMarginBottom = _s === void 0 ? 65 : _s, canvasTableId = props.canvasTableId, headerWrap = props.headerWrap, _t = props.headerAlign, headerAlign = _t === void 0 ? "center" : _t, tableRefHandle = props.tableRefHandle, exportExcelConfig = props.exportExcelConfig;
43
+ var actualMode = "mode" in props ? mode : "index";
43
44
  var canvasRef = useRef(null);
44
45
  var containerRef = useRef(null);
45
46
  var filterPopoverRef = useRef(null);
@@ -61,22 +62,22 @@ function CanvasTable(props) {
61
62
  return String((_a = record[rowKey]) !== null && _a !== void 0 ? _a : index);
62
63
  }, [rowKey]);
63
64
  // 动态列配置
64
- var _v = useDynamicListByColumns(columns, {
65
+ var _u = useDynamicListByColumns(columns, {
65
66
  dynamicKey: dynamicKey,
66
67
  dynamicVersion: dynamicVersion,
67
68
  customDynamicListHandle: customDynamicListHandle,
68
- }), defaultDynamicList = _v.defaultDynamicList, currentDynamicList = _v.currentDynamicList, onCurrentListChange = _v.onCurrentListChange, dynamicSettingRef = _v.dynamicSettingRef;
69
+ }), defaultDynamicList = _u.defaultDynamicList, currentDynamicList = _u.currentDynamicList, onCurrentListChange = _u.onCurrentListChange, dynamicSettingRef = _u.dynamicSettingRef;
69
70
  // 根据动态列配置处理columns
70
71
  var dynamicColumns = useMemo(function () { return getTableColumns(columns, currentDynamicList); }, [columns, currentDynamicList]).columns;
71
72
  // 内部列宽状态(未开启动态配置时使用)
72
- var _w = useState({}), internalColumnWidths = _w[0], setInternalColumnWidths = _w[1];
73
+ var _v = useState({}), internalColumnWidths = _v[0], setInternalColumnWidths = _v[1];
73
74
  // 跟踪用户手动调整过宽度的列(用于排除自动宽度分配)
74
- var _x = useState(new Set()), manuallyResizedColumnKeys = _x[0], setManuallyResizedColumnKeys = _x[1];
75
+ var _w = useState(new Set()), manuallyResizedColumnKeys = _w[0], setManuallyResizedColumnKeys = _w[1];
75
76
  // 处理选中框列、序号列等
76
77
  var processedColumnsOld = useProcessedColumns({
77
78
  columns: columns,
78
79
  dynamicColumns: dynamicColumns,
79
- mode: mode,
80
+ mode: actualMode,
80
81
  rowSelection: rowSelection,
81
82
  internalColumnWidths: internalColumnWidths,
82
83
  dynamicKey: dynamicKey,
@@ -86,29 +87,29 @@ function CanvasTable(props) {
86
87
  headerAlign: headerAlign,
87
88
  });
88
89
  // 表格状态管理
89
- var _y = useTableState({
90
+ var _x = useTableState({
90
91
  dataSource: dataSource,
91
92
  columns: processedColumnsOld,
92
93
  rowSelection: rowSelection,
93
94
  onFilterChange: onFilterChange,
94
95
  isAutoMerge: isAutoMerge,
95
- }), state = _y.state, setState = _y.setState, processedDataSource = _y.processedDataSource, handleFilterChange = _y.handleFilterChange, closeFilterPopover = _y.closeFilterPopover, autoGeneratedFilters = _y.autoGeneratedFilters;
96
+ }), state = _x.state, setState = _x.setState, processedDataSource = _x.processedDataSource, handleFilterChange = _x.handleFilterChange, closeFilterPopover = _x.closeFilterPopover, autoGeneratedFilters = _x.autoGeneratedFilters;
96
97
  var order = useMemo(function () {
97
98
  return state.sortOrder && state.sortField
98
99
  ? { field: state.sortField, order: state.sortOrder }
99
100
  : undefined;
100
101
  }, [state.sortOrder, state.sortField]);
101
- var _z = useAutoMerge(processedDataSource, processedColumnsOld, {
102
+ var _y = useAutoMerge(processedDataSource, processedColumnsOld, {
102
103
  isAutoMerge: isAutoMerge,
103
104
  isDimensionDynamic: isDimensionDynamic,
104
105
  order: order,
105
106
  dimensionCustomSumKeys: dimensionCustomSumKeys,
106
- }), newDataSource = _z[0], processedColumns = _z[1];
107
+ }), newDataSource = _y[0], processedColumns = _y[1];
107
108
  // 生成合计行和最终数据源
108
- var _0 = useSummaryRow({
109
+ var _z = useSummaryRow({
109
110
  columns: processedColumns,
110
111
  dataSource: newDataSource,
111
- }), finalDataSource = _0.finalDataSource, hasSummaryRow = _0.hasSummaryRow;
112
+ }), finalDataSource = _z.finalDataSource, hasSummaryRow = _z.hasSummaryRow;
112
113
  // 自动高度计算(需要在容器尺寸计算之前)
113
114
  var autoHeight = useCanvasTableAutoHeight(isAutoScrollY, autoScrollYMarginBottom, canvasTableId);
114
115
  // 监听容器尺寸变化(提前计算,用于列宽自适应)
@@ -144,7 +145,7 @@ function CanvasTable(props) {
144
145
  return calculateTotalHeight(calculatedHeaderHeight, finalDataSource.length, rowHeight);
145
146
  }, [calculatedHeaderHeight, finalDataSource.length, rowHeight]);
146
147
  // 计算滚动条指标
147
- var _1 = useScrollbarMetrics({
148
+ var _0 = useScrollbarMetrics({
148
149
  containerWidth: containerWidth,
149
150
  containerHeight: containerHeight,
150
151
  totalWidth: totalWidth,
@@ -152,14 +153,14 @@ function CanvasTable(props) {
152
153
  headerHeight: calculatedHeaderHeight,
153
154
  scrollTop: 0,
154
155
  scrollLeft: 0,
155
- }), maxScrollTop = _1.maxScrollTop, maxScrollLeft = _1.maxScrollLeft;
156
+ }), maxScrollTop = _0.maxScrollTop, maxScrollLeft = _0.maxScrollLeft;
156
157
  // 滚动管理(使用预先计算的maxScrollTop和maxScrollLeft)
157
- var _2 = useTableScroll({
158
+ var _1 = useTableScroll({
158
159
  containerRef: containerRef,
159
160
  maxScrollTop: maxScrollTop,
160
161
  maxScrollLeft: maxScrollLeft,
161
162
  onScroll: onScroll,
162
- }), scrollState = _2.scrollState, setScrollState = _2.setScrollState;
163
+ }), scrollState = _1.scrollState, setScrollState = _1.setScrollState;
163
164
  // 数据变化时重置滚动位置(筛选、排序、数据源更新等操作后)
164
165
  useScrollReset({
165
166
  dataSourceLength: dataSource.length,
@@ -180,12 +181,12 @@ function CanvasTable(props) {
180
181
  scrollLeft: scrollState.scrollLeft,
181
182
  }).actualMetrics;
182
183
  // 单元格框选
183
- var _3 = useTableSelection({
184
+ var _2 = useTableSelection({
184
185
  state: state,
185
186
  setState: setState,
186
187
  }),
187
188
  // selectionStartRef,
188
- startSelection = _3.startSelection, updateSelection = _3.updateSelection, extendSelection = _3.extendSelection;
189
+ startSelection = _2.startSelection, updateSelection = _2.updateSelection, extendSelection = _2.extendSelection;
189
190
  // 处理列宽调整
190
191
  var handleColumnResize = useCallback(function (columnKey, newWidth) {
191
192
  var _a;
@@ -240,13 +241,13 @@ function CanvasTable(props) {
240
241
  onCurrentListChange,
241
242
  ]);
242
243
  // 列宽调整
243
- var _4 = useColumnResize({
244
+ var _3 = useColumnResize({
244
245
  columnRenderInfos: columnRenderInfos,
245
246
  containerWidth: containerWidth,
246
247
  headerHeight: calculatedHeaderHeight,
247
248
  scrollLeft: scrollState.scrollLeft,
248
249
  onColumnResize: handleColumnResize,
249
- }), resizeState = _4.resizeState, checkResizeHandle = _4.checkResizeHandle, startResize = _4.startResize, updateResize = _4.updateResize, endResize = _4.endResize, setHoverResizeColumn = _4.setHoverResizeColumn, getColumnWidth = _4.getColumnWidth, RESIZE_HANDLE_WIDTH = _4.RESIZE_HANDLE_WIDTH;
250
+ }), resizeState = _3.resizeState, checkResizeHandle = _3.checkResizeHandle, startResize = _3.startResize, updateResize = _3.updateResize, endResize = _3.endResize, setHoverResizeColumn = _3.setHoverResizeColumn, getColumnWidth = _3.getColumnWidth, RESIZE_HANDLE_WIDTH = _3.RESIZE_HANDLE_WIDTH;
250
251
  // 复制到剪贴板
251
252
  var getSelectedCellsText = useCopyToClipboard({
252
253
  cellSelection: state.cellSelection,
@@ -274,7 +275,7 @@ function CanvasTable(props) {
274
275
  summaryConfig: [],
275
276
  });
276
277
  // 交互事件处理(使用baseScrollbarMetrics的maxScrollTop/maxScrollLeft以保持稳定)
277
- var _5 = useTableInteraction({
278
+ var _4 = useTableInteraction({
278
279
  state: state,
279
280
  setState: setState,
280
281
  scrollState: scrollState,
@@ -289,6 +290,7 @@ function CanvasTable(props) {
289
290
  containerHeight: containerHeight,
290
291
  scrollbarSize: SCROLLBAR_SIZE,
291
292
  canvasRef: canvasRef,
293
+ containerRef: containerRef,
292
294
  totalHeight: totalHeight,
293
295
  totalWidth: totalWidth,
294
296
  // 使用scrollbarMetrics的显示相关属性(需要随滚动更新)
@@ -320,7 +322,7 @@ function CanvasTable(props) {
320
322
  fixedRowsCount: fixedRowsCount,
321
323
  fixedRowsConfig: fixedRowsConfig,
322
324
  summaryFixed: summaryFixed,
323
- }), handleCanvasMouseDown = _5.handleCanvasMouseDown, handleCanvasMouseMove = _5.handleCanvasMouseMove, handleCanvasMouseUp = _5.handleCanvasMouseUp, handleCanvasMouseLeave = _5.handleCanvasMouseLeave, handleCanvasContextMenu = _5.handleCanvasContextMenu;
325
+ }), handleCanvasMouseDown = _4.handleCanvasMouseDown, handleCanvasMouseMove = _4.handleCanvasMouseMove, handleCanvasMouseUp = _4.handleCanvasMouseUp, handleCanvasMouseLeave = _4.handleCanvasMouseLeave, handleCanvasContextMenu = _4.handleCanvasContextMenu;
324
326
  // 渲染表格
325
327
  useTableRender(__assign(__assign({ canvasRef: canvasRef, processedDataSource: finalDataSource, columnRenderInfos: columnRenderInfos, columns: processedColumns, // 传递原始columns用于渲染多级表头
326
328
  state: state, scrollState: scrollState, rowSelection: rowSelection, containerWidth: containerWidth, containerHeight: containerHeight, headerHeight: calculatedHeaderHeight, baseHeaderHeight: headerHeight, // 传入原始基础高度用于计算每层高度
@@ -1,5 +1,5 @@
1
1
  import { __assign } from '../../_virtual/_tslib.js';
2
- import { useMemo, useState, useRef, useEffect } from 'react';
2
+ import { useMemo, useState, useRef, useEffect, useCallback } from 'react';
3
3
  import { SCROLLBAR_SIZE, MIN_SCROLLBAR_SIZE } from '../utils/constants.js';
4
4
  import { calculateScrollbarMetrics } from '../utils/tableCalculations.js';
5
5
  import 'zmdms-utils';
@@ -115,8 +115,17 @@ var useTableScroll = function (params) {
115
115
  e.stopPropagation();
116
116
  // 当鼠标在容器内任何位置(包括CellOverlay)时都能滚动
117
117
  // 累积滚动增量
118
- pendingDeltaRef.current.deltaX += e.deltaX;
119
- pendingDeltaRef.current.deltaY += e.deltaY;
118
+ // 支持 Shift + 鼠标滚轮进行水平滚动
119
+ if (e.shiftKey) {
120
+ // 按住 Shift 键时,将垂直滚动转换为水平滚动
121
+ pendingDeltaRef.current.deltaX += e.deltaY;
122
+ pendingDeltaRef.current.deltaY += 0;
123
+ }
124
+ else {
125
+ // 正常滚动逻辑
126
+ pendingDeltaRef.current.deltaX += e.deltaX;
127
+ pendingDeltaRef.current.deltaY += e.deltaY;
128
+ }
120
129
  // 如果已经有pending的动画帧,不需要再次请求
121
130
  if (rafIdRef.current !== null) {
122
131
  return;
@@ -178,7 +187,239 @@ var useTableScroll = function (params) {
178
187
  setScrollState: setScrollState,
179
188
  };
180
189
  };
181
- // ==================== Hook 3: 滚动位置重置 ====================
190
+ var useSelectionBoundaryScroll = function (params) {
191
+ var containerRef = params.containerRef, isSelecting = params.isSelecting,
192
+ // scrollState,
193
+ setScrollState = params.setScrollState, maxScrollTop = params.maxScrollTop, maxScrollLeft = params.maxScrollLeft, onScroll = params.onScroll, getCellFromPosition = params.getCellFromPosition, updateSelection = params.updateSelection, columnRenderInfos = params.columnRenderInfos;
194
+ var scrollRafRef = useRef(null);
195
+ var currentMousePosRef = useRef(null);
196
+ var lastCellRef = useRef(null);
197
+ var scrollVelocityRef = useRef({
198
+ deltaX: 0,
199
+ deltaY: 0,
200
+ });
201
+ // 状态更新去抖:避免频繁的状态更新
202
+ var stateUpdateRafRef = useRef(null);
203
+ var pendingStateUpdateRef = useRef(null);
204
+ // 缓存当前的滚动状态,避免频繁读取
205
+ var currentScrollStateRef = useRef({ scrollLeft: 0, scrollTop: 0 });
206
+ // 使用 ref 保存最新的函数引用,避免闭包问题
207
+ var setScrollStateRef = useRef(setScrollState);
208
+ var onScrollRef = useRef(onScroll);
209
+ var getCellFromPositionRef = useRef(getCellFromPosition);
210
+ var updateSelectionRef = useRef(updateSelection);
211
+ var columnRenderInfosRef = useRef(columnRenderInfos);
212
+ // 更新 ref 中的函数引用
213
+ useEffect(function () {
214
+ setScrollStateRef.current = setScrollState;
215
+ onScrollRef.current = onScroll;
216
+ getCellFromPositionRef.current = getCellFromPosition;
217
+ updateSelectionRef.current = updateSelection;
218
+ columnRenderInfosRef.current = columnRenderInfos;
219
+ });
220
+ // 同步当前滚动状态到 ref
221
+ useEffect(function () {
222
+ // 通过 setScrollState 的返回值来获取当前状态(不触发状态更新)
223
+ var currentState;
224
+ setScrollStateRef.current(function (prev) {
225
+ currentState = prev;
226
+ return prev; // 不修改状态,只读取
227
+ });
228
+ if (currentState) {
229
+ currentScrollStateRef.current = {
230
+ scrollLeft: currentState.scrollLeft,
231
+ scrollTop: currentState.scrollTop,
232
+ };
233
+ }
234
+ });
235
+ var SCROLL_BOUNDARY_SIZE = 50; // 触发滚动的边界距离
236
+ var SCROLL_SPEED = 6; // 每次滚动的距离(进一步降低以减少频率)
237
+ // 防抖:避免鼠标移动时过度频繁地触发边界检测
238
+ var boundaryCheckThrottleRef = useRef(0);
239
+ // 批量状态更新函数:减少重新渲染次数
240
+ var batchUpdateScrollState = useCallback(function (newScrollLeft, newScrollTop) {
241
+ // 立即更新缓存状态
242
+ currentScrollStateRef.current = {
243
+ scrollLeft: newScrollLeft,
244
+ scrollTop: newScrollTop,
245
+ };
246
+ // 保存待更新的状态
247
+ pendingStateUpdateRef.current = {
248
+ scrollLeft: newScrollLeft,
249
+ scrollTop: newScrollTop,
250
+ };
251
+ // 如果已经有待处理的更新,直接返回
252
+ if (stateUpdateRafRef.current !== null) {
253
+ return;
254
+ }
255
+ // 延迟到下一个渲染周期批量更新
256
+ stateUpdateRafRef.current = requestAnimationFrame(function () {
257
+ var pendingUpdate = pendingStateUpdateRef.current;
258
+ if (pendingUpdate) {
259
+ setScrollStateRef.current(function (prev) {
260
+ if (prev.scrollLeft !== pendingUpdate.scrollLeft ||
261
+ prev.scrollTop !== pendingUpdate.scrollTop) {
262
+ // 延迟调用 onScroll 回调,避免阻塞滚动
263
+ setTimeout(function () {
264
+ var _a;
265
+ (_a = onScrollRef.current) === null || _a === void 0 ? void 0 : _a.call(onScrollRef, pendingUpdate.scrollLeft, pendingUpdate.scrollTop);
266
+ }, 0);
267
+ return __assign(__assign({}, prev), { scrollLeft: pendingUpdate.scrollLeft, scrollTop: pendingUpdate.scrollTop });
268
+ }
269
+ return prev;
270
+ });
271
+ }
272
+ // 清理状态
273
+ stateUpdateRafRef.current = null;
274
+ pendingStateUpdateRef.current = null;
275
+ });
276
+ }, []);
277
+ // 检查边界滚动
278
+ var checkBoundaryScroll = useCallback(function (mouseX, mouseY) {
279
+ if (!containerRef.current || !isSelecting)
280
+ return;
281
+ // 节流:限制边界检测频率(每16ms最多执行一次,约60fps)
282
+ var now = performance.now();
283
+ if (now - boundaryCheckThrottleRef.current < 16) {
284
+ return;
285
+ }
286
+ boundaryCheckThrottleRef.current = now;
287
+ var rect = containerRef.current.getBoundingClientRect();
288
+ var containerWidth = rect.width;
289
+ var containerHeight = rect.height;
290
+ var scrollDeltaX = 0;
291
+ var scrollDeltaY = 0;
292
+ // 检查水平边界
293
+ if (mouseX < SCROLL_BOUNDARY_SIZE) {
294
+ // 接近左边界,向左滚动
295
+ scrollDeltaX = -SCROLL_SPEED;
296
+ }
297
+ else if (mouseX > containerWidth - SCROLL_BOUNDARY_SIZE) {
298
+ // 接近右边界,向右滚动
299
+ scrollDeltaX = SCROLL_SPEED;
300
+ }
301
+ // 检查垂直边界
302
+ if (mouseY < SCROLL_BOUNDARY_SIZE) {
303
+ // 接近顶部边界,向上滚动
304
+ scrollDeltaY = -SCROLL_SPEED;
305
+ }
306
+ else if (mouseY > containerHeight - SCROLL_BOUNDARY_SIZE) {
307
+ // 接近底部边界,向下滚动
308
+ scrollDeltaY = SCROLL_SPEED;
309
+ }
310
+ // 保存当前鼠标位置和滚动速度
311
+ currentMousePosRef.current = { x: mouseX, y: mouseY };
312
+ scrollVelocityRef.current = {
313
+ deltaX: scrollDeltaX,
314
+ deltaY: scrollDeltaY,
315
+ };
316
+ // 如果需要滚动
317
+ if (scrollDeltaX !== 0 || scrollDeltaY !== 0) {
318
+ // 清除之前的动画帧
319
+ if (scrollRafRef.current) {
320
+ cancelAnimationFrame(scrollRafRef.current);
321
+ }
322
+ // 开始持续滚动(优化版本)
323
+ var performScroll_1 = function () {
324
+ var _a;
325
+ var velocity = scrollVelocityRef.current;
326
+ if (velocity.deltaX === 0 && velocity.deltaY === 0) {
327
+ return; // 停止滚动
328
+ }
329
+ // 获取当前滚动状态(从缓存中读取,避免触发状态更新)
330
+ var currentState = currentScrollStateRef.current;
331
+ var newScrollLeft = Math.max(0, Math.min(maxScrollLeft, currentState.scrollLeft + velocity.deltaX));
332
+ var newScrollTop = Math.max(0, Math.min(maxScrollTop, currentState.scrollTop + velocity.deltaY));
333
+ // 只有在位置真正发生变化时才更新
334
+ if (newScrollLeft !== currentState.scrollLeft ||
335
+ newScrollTop !== currentState.scrollTop) {
336
+ // 使用批量更新机制
337
+ batchUpdateScrollState(newScrollLeft, newScrollTop);
338
+ // 优化的框选更新:减少不必要的计算
339
+ if (getCellFromPositionRef.current &&
340
+ updateSelectionRef.current &&
341
+ columnRenderInfosRef.current &&
342
+ currentMousePosRef.current) {
343
+ var _b = currentMousePosRef.current, x = _b.x, y = _b.y;
344
+ // 添加位置计算的缓存,避免重复计算
345
+ try {
346
+ var cell = getCellFromPositionRef.current(x, y);
347
+ // 只有当单元格位置发生变化时才更新框选
348
+ if (cell &&
349
+ (!lastCellRef.current ||
350
+ lastCellRef.current.row !== cell.row ||
351
+ lastCellRef.current.col !== cell.col)) {
352
+ var isSelectionColumn = ((_a = columnRenderInfosRef.current[cell.col]) === null || _a === void 0 ? void 0 : _a.column.key) ===
353
+ "__selection__";
354
+ if (!isSelectionColumn) {
355
+ updateSelectionRef.current(cell);
356
+ lastCellRef.current = cell;
357
+ }
358
+ }
359
+ }
360
+ catch (error) {
361
+ // 如果计算单元格位置出错,静默处理,不影响滚动
362
+ console.warn("Cell position calculation error during boundary scroll:", error);
363
+ }
364
+ }
365
+ }
366
+ // 继续滚动
367
+ scrollRafRef.current = requestAnimationFrame(performScroll_1);
368
+ };
369
+ scrollRafRef.current = requestAnimationFrame(performScroll_1);
370
+ }
371
+ else {
372
+ // 停止滚动
373
+ if (scrollRafRef.current) {
374
+ cancelAnimationFrame(scrollRafRef.current);
375
+ scrollRafRef.current = null;
376
+ }
377
+ scrollVelocityRef.current = { deltaX: 0, deltaY: 0 };
378
+ }
379
+ }, [
380
+ containerRef,
381
+ isSelecting,
382
+ maxScrollTop,
383
+ maxScrollLeft,
384
+ batchUpdateScrollState,
385
+ ]);
386
+ // 停止边界滚动
387
+ var stopBoundaryScroll = useCallback(function () {
388
+ if (scrollRafRef.current) {
389
+ cancelAnimationFrame(scrollRafRef.current);
390
+ scrollRafRef.current = null;
391
+ }
392
+ if (stateUpdateRafRef.current) {
393
+ cancelAnimationFrame(stateUpdateRafRef.current);
394
+ stateUpdateRafRef.current = null;
395
+ }
396
+ scrollVelocityRef.current = { deltaX: 0, deltaY: 0 };
397
+ pendingStateUpdateRef.current = null;
398
+ lastCellRef.current = null; // 重置缓存的单元格位置
399
+ }, []);
400
+ // 当框选结束时停止滚动
401
+ useEffect(function () {
402
+ if (!isSelecting) {
403
+ stopBoundaryScroll();
404
+ }
405
+ }, [isSelecting, stopBoundaryScroll]);
406
+ // 组件卸载时清理动画帧
407
+ useEffect(function () {
408
+ return function () {
409
+ if (scrollRafRef.current) {
410
+ cancelAnimationFrame(scrollRafRef.current);
411
+ }
412
+ if (stateUpdateRafRef.current) {
413
+ cancelAnimationFrame(stateUpdateRafRef.current);
414
+ }
415
+ };
416
+ }, []);
417
+ return {
418
+ checkBoundaryScroll: checkBoundaryScroll,
419
+ stopBoundaryScroll: stopBoundaryScroll,
420
+ };
421
+ };
422
+ // ==================== Hook 4: 滚动位置重置 ====================
182
423
  /**
183
424
  * 滚动位置重置 Hook
184
425
  *
@@ -236,4 +477,4 @@ var useScrollReset = function (params) {
236
477
  ]);
237
478
  };
238
479
 
239
- export { useScrollReset, useScrollbarMetrics, useTableScroll };
480
+ export { useScrollReset, useScrollbarMetrics, useSelectionBoundaryScroll, useTableScroll };
@@ -22,6 +22,8 @@ var useSummaryRow = function (params) {
22
22
  if (!hasSummary)
23
23
  return null;
24
24
  var summaryRecord = {};
25
+ // 原始值,为转为千分符的
26
+ var summaryOriginalValues = {};
25
27
  // 找到第一个列(包括序号列、选择框列)
26
28
  var firstColIndex = leafColumns.length > 0 ? 0 : -1;
27
29
  leafColumns.forEach(function (column, colIndex) {
@@ -43,9 +45,11 @@ var useSummaryRow = function (params) {
43
45
  calculatedSum = sum_1;
44
46
  // 应用格式化(仅在没有自定义回调或回调返回数值时)
45
47
  var formattedSum = calculatedSum;
48
+ summaryOriginalValues[dataIndex] = calculatedSum;
46
49
  if (typeof calculatedSum === "number") {
47
50
  if (column.precision !== undefined) {
48
51
  formattedSum = exactRound(calculatedSum, column.precision);
52
+ summaryOriginalValues[dataIndex] = calculatedSum;
49
53
  }
50
54
  if (column.thousand) {
51
55
  formattedSum = addThousedSeparator(formattedSum);
@@ -64,7 +68,7 @@ var useSummaryRow = function (params) {
64
68
  leafColumns.forEach(function (column) {
65
69
  if (column.totalCalcCallback) {
66
70
  var dataIndex = column.dataIndex || column.key;
67
- summaryRecord[dataIndex] = column.totalCalcCallback(summaryRecord[dataIndex], summaryRecord);
71
+ summaryRecord[dataIndex] = column.totalCalcCallback(summaryOriginalValues[dataIndex], summaryOriginalValues);
68
72
  }
69
73
  });
70
74
  summaryRecord[IS_SUMMARY] = true;
@@ -1,6 +1,7 @@
1
1
  import { __assign, __spreadArray } from '../../_virtual/_tslib.js';
2
2
  import { useRef, useEffect } from 'react';
3
3
  import { useMemoizedFn } from 'ahooks';
4
+ import { useSelectionBoundaryScroll } from './useScroll.js';
4
5
  import { FONT_SIZE, FONT_FAMILY } from '../utils/constants.js';
5
6
  import { isTextTruncated } from '../utils/canvasDrawHelpers.js';
6
7
  import { getMaxDepth, flattenHeaders, getLeafColumns } from '../utils/multiHeaderHelpers.js';
@@ -13,7 +14,7 @@ import { calculateSelectionState, toggleSelectAll, handleSortClick, calculateIco
13
14
  * 表格交互事件处理 Hook
14
15
  */
15
16
  var useTableInteraction = function (params) {
16
- 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, summaryFixed = params.summaryFixed;
17
+ 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, containerRef = params.containerRef, 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, summaryFixed = params.summaryFixed;
17
18
  // 获取鼠标位置对应的单元格
18
19
  var getCellFromPosition = useMemoizedFn(function (x, y) {
19
20
  var fixedTopRowsCount = (fixedRowsConfig === null || fixedRowsConfig === void 0 ? void 0 : fixedRowsConfig.topCount) || fixedRowsCount || 0;
@@ -464,6 +465,8 @@ var useTableInteraction = function (params) {
464
465
  updateSelection(cell);
465
466
  }
466
467
  }
468
+ // 检查边界滚动 - 当鼠标接近容器边界时自动滚动
469
+ checkBoundaryScroll(x, y);
467
470
  return;
468
471
  }
469
472
  // 检测列宽调整手柄hover状态
@@ -612,6 +615,8 @@ var useTableInteraction = function (params) {
612
615
  // 结束框选
613
616
  if (state.isSelecting) {
614
617
  setState(function (prev) { return (__assign(__assign({}, prev), { isSelecting: false })); });
618
+ // 停止边界滚动
619
+ stopBoundaryScroll();
615
620
  }
616
621
  });
617
622
  // 检查目标元素是否是Canvas内部渲染的元素
@@ -808,6 +813,8 @@ var useTableInteraction = function (params) {
808
813
  // 结束框选
809
814
  if (currentState.isSelecting) {
810
815
  setState(function (prev) { return (__assign(__assign({}, prev), { isSelecting: false })); });
816
+ // 停止边界滚动
817
+ stopBoundaryScroll();
811
818
  }
812
819
  setScrollState(function (prev) { return (__assign(__assign({}, prev), { isDraggingVertical: false, isDraggingHorizontal: false })); });
813
820
  };
@@ -828,6 +835,21 @@ var useTableInteraction = function (params) {
828
835
  // updateResize, endResize, handleVerticalScrollDrag, handleHorizontalScrollDrag,
829
836
  // updateSelection, setState, getCellFromPosition, columnRenderInfos,
830
837
  ]);
838
+ // 边界滚动Hook - 用于框选时的自动滚动
839
+ var _c = useSelectionBoundaryScroll({
840
+ containerRef: containerRef,
841
+ isSelecting: state.isSelecting,
842
+ scrollState: scrollState,
843
+ setScrollState: setScrollState,
844
+ maxScrollTop: maxScrollTop,
845
+ maxScrollLeft: maxScrollLeft,
846
+ onScroll: function (scrollLeft, scrollTop) {
847
+ // 边界滚动时的回调,可以在这里添加额外的逻辑
848
+ },
849
+ getCellFromPosition: getCellFromPosition,
850
+ updateSelection: updateSelection,
851
+ columnRenderInfos: columnRenderInfos,
852
+ }), checkBoundaryScroll = _c.checkBoundaryScroll, stopBoundaryScroll = _c.stopBoundaryScroll;
831
853
  return {
832
854
  handleCanvasMouseDown: handleCanvasMouseDown,
833
855
  handleCanvasMouseMove: handleCanvasMouseMove,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zmdms-webui",
3
- "version": "2.4.0",
3
+ "version": "2.4.2",
4
4
  "private": false,
5
5
  "main": "dist/index.es.js",
6
6
  "module": "dist/index.es.js",