zmdms-webui 2.4.0 → 2.4.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.
@@ -289,6 +289,7 @@ function CanvasTable(props) {
289
289
  containerHeight: containerHeight,
290
290
  scrollbarSize: SCROLLBAR_SIZE,
291
291
  canvasRef: canvasRef,
292
+ containerRef: containerRef,
292
293
  totalHeight: totalHeight,
293
294
  totalWidth: totalWidth,
294
295
  // 使用scrollbarMetrics的显示相关属性(需要随滚动更新)
@@ -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,128 @@ 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 scrollIntervalRef = useRef(null);
195
+ var currentMousePosRef = useRef(null);
196
+ var SCROLL_BOUNDARY_SIZE = 50; // 触发滚动的边界距离
197
+ var SCROLL_SPEED = 10; // 每次滚动的距离
198
+ // 检查边界滚动
199
+ var checkBoundaryScroll = useMemo(function () {
200
+ return function (mouseX, mouseY) {
201
+ if (!containerRef.current || !isSelecting)
202
+ return;
203
+ var rect = containerRef.current.getBoundingClientRect();
204
+ var containerWidth = rect.width;
205
+ var containerHeight = rect.height;
206
+ var scrollDeltaX = 0;
207
+ var scrollDeltaY = 0;
208
+ // 检查水平边界
209
+ if (mouseX < SCROLL_BOUNDARY_SIZE) {
210
+ // 接近左边界,向左滚动
211
+ scrollDeltaX = -SCROLL_SPEED;
212
+ }
213
+ else if (mouseX > containerWidth - SCROLL_BOUNDARY_SIZE) {
214
+ // 接近右边界,向右滚动
215
+ scrollDeltaX = SCROLL_SPEED;
216
+ }
217
+ // 检查垂直边界
218
+ if (mouseY < SCROLL_BOUNDARY_SIZE) {
219
+ // 接近顶部边界,向上滚动
220
+ scrollDeltaY = -SCROLL_SPEED;
221
+ }
222
+ else if (mouseY > containerHeight - SCROLL_BOUNDARY_SIZE) {
223
+ // 接近底部边界,向下滚动
224
+ scrollDeltaY = SCROLL_SPEED;
225
+ }
226
+ // 保存当前鼠标位置(用于滚动时更新框选)
227
+ currentMousePosRef.current = { x: mouseX, y: mouseY };
228
+ // 如果需要滚动
229
+ if (scrollDeltaX !== 0 || scrollDeltaY !== 0) {
230
+ // 清除之前的定时器
231
+ if (scrollIntervalRef.current) {
232
+ clearInterval(scrollIntervalRef.current);
233
+ }
234
+ // 开始持续滚动
235
+ scrollIntervalRef.current = setInterval(function () {
236
+ setScrollState(function (prev) {
237
+ var _a;
238
+ var newScrollLeft = Math.max(0, Math.min(maxScrollLeft, prev.scrollLeft + scrollDeltaX));
239
+ var newScrollTop = Math.max(0, Math.min(maxScrollTop, prev.scrollTop + scrollDeltaY));
240
+ if (newScrollLeft !== prev.scrollLeft ||
241
+ newScrollTop !== prev.scrollTop) {
242
+ onScroll === null || onScroll === void 0 ? void 0 : onScroll(newScrollLeft, newScrollTop);
243
+ // 滚动后检查鼠标位置的单元格并更新框选
244
+ if (getCellFromPosition &&
245
+ updateSelection &&
246
+ columnRenderInfos &&
247
+ currentMousePosRef.current) {
248
+ var _b = currentMousePosRef.current, x = _b.x, y = _b.y;
249
+ var cell = getCellFromPosition(x, y);
250
+ if (cell) {
251
+ // 检查是否在选择框列,如果是,则不更新框选
252
+ var isSelectionColumn = ((_a = columnRenderInfos[cell.col]) === null || _a === void 0 ? void 0 : _a.column.key) === "__selection__";
253
+ if (!isSelectionColumn) {
254
+ updateSelection(cell);
255
+ }
256
+ }
257
+ }
258
+ return __assign(__assign({}, prev), { scrollLeft: newScrollLeft, scrollTop: newScrollTop });
259
+ }
260
+ return prev;
261
+ });
262
+ }, 50); // 每50毫秒滚动一次
263
+ }
264
+ else {
265
+ // 停止滚动
266
+ if (scrollIntervalRef.current) {
267
+ clearInterval(scrollIntervalRef.current);
268
+ scrollIntervalRef.current = null;
269
+ }
270
+ }
271
+ };
272
+ }, [
273
+ containerRef,
274
+ isSelecting,
275
+ setScrollState,
276
+ maxScrollTop,
277
+ maxScrollLeft,
278
+ onScroll,
279
+ getCellFromPosition,
280
+ updateSelection,
281
+ columnRenderInfos,
282
+ ]);
283
+ // 停止边界滚动
284
+ var stopBoundaryScroll = useMemo(function () {
285
+ return function () {
286
+ if (scrollIntervalRef.current) {
287
+ clearInterval(scrollIntervalRef.current);
288
+ scrollIntervalRef.current = null;
289
+ }
290
+ };
291
+ }, []);
292
+ // 当框选结束时停止滚动
293
+ useEffect(function () {
294
+ if (!isSelecting) {
295
+ stopBoundaryScroll();
296
+ }
297
+ }, [isSelecting, stopBoundaryScroll]);
298
+ // 组件卸载时清理定时器
299
+ useEffect(function () {
300
+ return function () {
301
+ if (scrollIntervalRef.current) {
302
+ clearInterval(scrollIntervalRef.current);
303
+ }
304
+ };
305
+ }, []);
306
+ return {
307
+ checkBoundaryScroll: checkBoundaryScroll,
308
+ stopBoundaryScroll: stopBoundaryScroll,
309
+ };
310
+ };
311
+ // ==================== Hook 4: 滚动位置重置 ====================
182
312
  /**
183
313
  * 滚动位置重置 Hook
184
314
  *
@@ -236,4 +366,4 @@ var useScrollReset = function (params) {
236
366
  ]);
237
367
  };
238
368
 
239
- export { useScrollReset, useScrollbarMetrics, useTableScroll };
369
+ 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.1",
4
4
  "private": false,
5
5
  "main": "dist/index.es.js",
6
6
  "module": "dist/index.es.js",