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.
Files changed (73) hide show
  1. package/dist/es/canvastable/canvasTable.js +367 -0
  2. package/dist/es/canvastable/components/BadgePopover.js +27 -0
  3. package/dist/es/canvastable/components/CanvasTableMenu.js +74 -0
  4. package/dist/es/canvastable/components/CellOverlay.js +49 -0
  5. package/dist/es/canvastable/components/ColumnDynamic.js +12 -0
  6. package/dist/es/canvastable/components/EmptyPlaceholder.js +20 -0
  7. package/dist/es/canvastable/components/FilterPopover.js +274 -0
  8. package/dist/es/canvastable/components/HeaderOverlay.js +22 -0
  9. package/dist/es/canvastable/components/Tooltip.js +27 -0
  10. package/dist/es/canvastable/hooks/useClickOutside.js +30 -0
  11. package/dist/es/canvastable/hooks/useColumnResize.js +130 -0
  12. package/dist/es/canvastable/hooks/useContainerSize.js +40 -0
  13. package/dist/es/canvastable/hooks/useCopyToClipboard.js +150 -0
  14. package/dist/es/canvastable/hooks/useHeaderHeight.js +103 -0
  15. package/dist/es/canvastable/hooks/useMergeCells.js +111 -0
  16. package/dist/es/canvastable/hooks/useOverlays.js +364 -0
  17. package/dist/es/canvastable/hooks/usePopovers.js +93 -0
  18. package/dist/es/canvastable/hooks/useProcessedColumns.js +94 -0
  19. package/dist/es/canvastable/hooks/useScroll.js +251 -0
  20. package/dist/es/canvastable/hooks/useSummaryRow.js +81 -0
  21. package/dist/es/canvastable/hooks/useTableInteraction.js +804 -0
  22. package/dist/es/canvastable/hooks/useTableRender.js +1289 -0
  23. package/dist/es/canvastable/hooks/useTableSelection.js +57 -0
  24. package/dist/es/canvastable/hooks/useTableState.js +218 -0
  25. package/dist/es/canvastable/index.js +5 -0
  26. package/dist/es/canvastable/utils/canvasDrawHelpers.js +156 -0
  27. package/dist/es/canvastable/utils/cellHelpers.js +121 -0
  28. package/dist/es/canvastable/utils/columnHelpers.js +67 -0
  29. package/dist/es/canvastable/utils/constants.js +42 -0
  30. package/dist/es/canvastable/utils/formatHelpers.js +60 -0
  31. package/dist/es/canvastable/utils/interactionHelpers.js +176 -0
  32. package/dist/es/canvastable/utils/multiHeaderHelpers.js +82 -0
  33. package/dist/es/canvastable/utils/tableCalculations.js +100 -0
  34. package/dist/es/form/form.js +1 -0
  35. package/dist/index.dark.css +1 -1
  36. package/dist/index.default.css +1 -1
  37. package/dist/index.es.css +1 -1
  38. package/dist/less/components/CanvasTable/style/index.less +106 -0
  39. package/dist/less/components/Form/style/index.less +6 -1
  40. package/package.json +1 -1
  41. package/dist/es/cascader/index.css +0 -1
  42. package/dist/es/collapse/index.css +0 -1
  43. package/dist/es/container/index.css +0 -1
  44. package/dist/es/datepicker/index.css +0 -1
  45. package/dist/es/descriptions/index.css +0 -1
  46. package/dist/es/detaillist/index.css +0 -1
  47. package/dist/es/differences/index.css +0 -1
  48. package/dist/es/dynamicsetting/index.css +0 -1
  49. package/dist/es/electronsignatures/index.css +0 -1
  50. package/dist/es/footer/index.css +0 -1
  51. package/dist/es/form/index.css +0 -1
  52. package/dist/es/formitem/index.css +0 -1
  53. package/dist/es/input/index.css +0 -1
  54. package/dist/es/inputnumber/index.css +0 -1
  55. package/dist/es/leftcontent/index.css +0 -1
  56. package/dist/es/message/index.css +0 -1
  57. package/dist/es/microloading/index.css +0 -1
  58. package/dist/es/modal/index.css +0 -1
  59. package/dist/es/notauthpage/index.css +0 -0
  60. package/dist/es/notroutepage/index.css +0 -0
  61. package/dist/es/pagination/index.css +0 -1
  62. package/dist/es/placeholder/index.css +0 -1
  63. package/dist/es/print/index.css +0 -1
  64. package/dist/es/select/index.css +0 -1
  65. package/dist/es/table/index.css +0 -1
  66. package/dist/es/tabs/index.css +0 -1
  67. package/dist/es/tag/index.css +0 -1
  68. package/dist/es/title/index.css +0 -1
  69. package/dist/es/tree/index.css +0 -1
  70. package/dist/es/treeselect/index.css +0 -1
  71. package/dist/es/uploadlist/index.css +0 -1
  72. package/dist/es/watermark/index.css +0 -1
  73. package/dist/es/zttransfer/index.css +0 -1
@@ -0,0 +1,251 @@
1
+ import { __assign } from '../../_virtual/_tslib.js';
2
+ import { useMemo, useState, useRef, useEffect } from 'react';
3
+ import { SCROLLBAR_SIZE, MIN_SCROLLBAR_SIZE } from '../utils/constants.js';
4
+ import { calculateScrollbarMetrics } from '../utils/tableCalculations.js';
5
+ import 'dayjs';
6
+
7
+ /**
8
+ * 滚动管理 Hook - 统一管理所有滚动相关逻辑
9
+ *
10
+ * 包含功能:
11
+ * 1. 滚动条指标计算(useScrollbarMetrics)
12
+ * 2. 滚动事件处理(useTableScroll)
13
+ * 3. 滚动位置重置(useScrollReset)
14
+ */
15
+ // ==================== 工具函数 ====================
16
+ /**
17
+ * 检查两个对象是否相等(深度比较)
18
+ */
19
+ var isEqual = function (obj1, obj2) {
20
+ return JSON.stringify(obj1) === JSON.stringify(obj2);
21
+ };
22
+ // ==================== Hook 1: 滚动条指标计算 ====================
23
+ /**
24
+ * 滚动条指标计算 Hook
25
+ *
26
+ * 计算滚动条的各项指标,包括:
27
+ * - 基础指标(不依赖滚动位置)
28
+ * - 实际指标(包含当前滚动位置)
29
+ * - 最大滚动值
30
+ */
31
+ var useScrollbarMetrics = function (params) {
32
+ var containerWidth = params.containerWidth, containerHeight = params.containerHeight, totalWidth = params.totalWidth, totalHeight = params.totalHeight, headerHeight = params.headerHeight, scrollTop = params.scrollTop, scrollLeft = params.scrollLeft;
33
+ // 基础滚动条指标(不依赖滚动位置,用于计算最大滚动值)
34
+ var baseMetrics = useMemo(function () {
35
+ return calculateScrollbarMetrics({
36
+ containerWidth: containerWidth,
37
+ containerHeight: containerHeight,
38
+ totalWidth: totalWidth,
39
+ totalHeight: totalHeight,
40
+ headerHeight: headerHeight,
41
+ scrollbarSize: SCROLLBAR_SIZE,
42
+ minScrollbarSize: MIN_SCROLLBAR_SIZE,
43
+ scrollTop: 0,
44
+ scrollLeft: 0,
45
+ });
46
+ }, [containerWidth, containerHeight, totalWidth, totalHeight, headerHeight]);
47
+ // 实际滚动条指标(包含当前滚动位置,用于渲染)
48
+ var actualMetrics = useMemo(function () {
49
+ return calculateScrollbarMetrics({
50
+ containerWidth: containerWidth,
51
+ containerHeight: containerHeight,
52
+ totalWidth: totalWidth,
53
+ totalHeight: totalHeight,
54
+ headerHeight: headerHeight,
55
+ scrollbarSize: SCROLLBAR_SIZE,
56
+ minScrollbarSize: MIN_SCROLLBAR_SIZE,
57
+ scrollTop: scrollTop,
58
+ scrollLeft: scrollLeft,
59
+ });
60
+ }, [
61
+ containerWidth,
62
+ containerHeight,
63
+ totalWidth,
64
+ totalHeight,
65
+ headerHeight,
66
+ scrollTop,
67
+ scrollLeft,
68
+ ]);
69
+ return {
70
+ baseMetrics: baseMetrics,
71
+ actualMetrics: actualMetrics,
72
+ maxScrollTop: baseMetrics.maxScrollTop,
73
+ maxScrollLeft: baseMetrics.maxScrollLeft,
74
+ };
75
+ };
76
+ // ==================== Hook 2: 滚动事件处理 ====================
77
+ /**
78
+ * 表格滚动管理 Hook
79
+ *
80
+ * 处理滚动相关的所有事件:
81
+ * - Canvas 滚轮事件(使用 RAF 节流)
82
+ * - Container 滚轮事件(阻止默认行为)
83
+ * - 全局鼠标事件(拖拽滚动条)
84
+ */
85
+ var useTableScroll = function (params) {
86
+ var canvasRef = params.canvasRef, containerRef = params.containerRef, maxScrollTop = params.maxScrollTop, maxScrollLeft = params.maxScrollLeft, onScroll = params.onScroll;
87
+ var _a = useState({
88
+ scrollLeft: 0,
89
+ scrollTop: 0,
90
+ isDraggingVertical: false,
91
+ isDraggingHorizontal: false,
92
+ dragStartY: 0,
93
+ dragStartX: 0,
94
+ dragStartScrollTop: 0,
95
+ dragStartScrollLeft: 0,
96
+ }), scrollState = _a[0], setScrollState = _a[1];
97
+ // 用于节流滚轮事件的refs
98
+ var rafIdRef = useRef(null);
99
+ var pendingDeltaRef = useRef({ deltaX: 0, deltaY: 0 });
100
+ // 滚轮事件处理(Canvas)- 使用 requestAnimationFrame 节流
101
+ useEffect(function () {
102
+ var canvas = canvasRef.current;
103
+ if (!canvas)
104
+ return;
105
+ var handleNativeWheel = function (e) {
106
+ e.preventDefault();
107
+ e.stopPropagation();
108
+ // 累积滚动增量
109
+ pendingDeltaRef.current.deltaX += e.deltaX;
110
+ pendingDeltaRef.current.deltaY += e.deltaY;
111
+ // 如果已经有pending的动画帧,不需要再次请求
112
+ if (rafIdRef.current !== null) {
113
+ return;
114
+ }
115
+ // 使用 requestAnimationFrame 节流更新
116
+ rafIdRef.current = requestAnimationFrame(function () {
117
+ var deltaX = pendingDeltaRef.current.deltaX;
118
+ var deltaY = pendingDeltaRef.current.deltaY;
119
+ // 重置累积的增量
120
+ pendingDeltaRef.current.deltaX = 0;
121
+ pendingDeltaRef.current.deltaY = 0;
122
+ rafIdRef.current = null;
123
+ // 批量更新状态
124
+ setScrollState(function (prev) {
125
+ var newScrollTop = Math.max(0, Math.min(maxScrollTop, prev.scrollTop + deltaY));
126
+ var newScrollLeft = Math.max(0, Math.min(maxScrollLeft, prev.scrollLeft + deltaX));
127
+ if (newScrollTop !== prev.scrollTop ||
128
+ newScrollLeft !== prev.scrollLeft) {
129
+ onScroll === null || onScroll === void 0 ? void 0 : onScroll(newScrollLeft, newScrollTop);
130
+ return __assign(__assign({}, prev), { scrollTop: newScrollTop, scrollLeft: newScrollLeft });
131
+ }
132
+ return prev;
133
+ });
134
+ });
135
+ };
136
+ canvas.addEventListener("wheel", handleNativeWheel, { passive: false });
137
+ return function () {
138
+ canvas.removeEventListener("wheel", handleNativeWheel);
139
+ // 清理pending的动画帧
140
+ if (rafIdRef.current !== null) {
141
+ cancelAnimationFrame(rafIdRef.current);
142
+ rafIdRef.current = null;
143
+ }
144
+ };
145
+ }, [maxScrollTop, maxScrollLeft, onScroll, canvasRef, setScrollState]);
146
+ // 滚轮事件处理(Container)
147
+ useEffect(function () {
148
+ var container = containerRef.current;
149
+ if (!container)
150
+ return;
151
+ var handleNativeContainerWheel = function (e) {
152
+ // 检查事件是否来自过滤弹框,如果是,允许滚动
153
+ var target = e.target;
154
+ var isInFilterPopover = target.closest(".canvas-table-filter-popover");
155
+ if (isInFilterPopover) {
156
+ // 允许过滤弹框内部滚动
157
+ return;
158
+ }
159
+ e.preventDefault();
160
+ e.stopPropagation();
161
+ };
162
+ container.addEventListener("wheel", handleNativeContainerWheel, {
163
+ passive: false,
164
+ });
165
+ return function () {
166
+ container.removeEventListener("wheel", handleNativeContainerWheel);
167
+ };
168
+ }, [containerRef]);
169
+ // 全局鼠标事件处理(拖拽滚动条)
170
+ useEffect(function () {
171
+ var handleGlobalMouseUp = function () {
172
+ setScrollState(function (prev) { return (__assign(__assign({}, prev), { isDraggingVertical: false, isDraggingHorizontal: false })); });
173
+ };
174
+ var handleGlobalMouseMove = function (e) {
175
+ if (scrollState.isDraggingVertical || scrollState.isDraggingHorizontal) {
176
+ e.preventDefault();
177
+ }
178
+ };
179
+ if (scrollState.isDraggingVertical || scrollState.isDraggingHorizontal) {
180
+ document.addEventListener("mouseup", handleGlobalMouseUp);
181
+ document.addEventListener("mousemove", handleGlobalMouseMove);
182
+ return function () {
183
+ document.removeEventListener("mouseup", handleGlobalMouseUp);
184
+ document.removeEventListener("mousemove", handleGlobalMouseMove);
185
+ };
186
+ }
187
+ }, [scrollState.isDraggingVertical, scrollState.isDraggingHorizontal]);
188
+ return {
189
+ scrollState: scrollState,
190
+ setScrollState: setScrollState,
191
+ };
192
+ };
193
+ // ==================== Hook 3: 滚动位置重置 ====================
194
+ /**
195
+ * 滚动位置重置 Hook
196
+ *
197
+ * 当数据变化时自动重置滚动位置:
198
+ * - 数据长度变小时重置 Y 轴滚动
199
+ * - 筛选条件变化时重置 Y 轴滚动
200
+ * - 排序条件变化时重置 Y 轴滚动
201
+ *
202
+ * 注意:
203
+ * - X 轴滚动(scrollLeft)始终保持不变
204
+ * - 数据长度变大时不重置滚动位置
205
+ */
206
+ var useScrollReset = function (params) {
207
+ var dataSourceLength = params.dataSourceLength, processedDataLength = params.processedDataLength, filters = params.filters, sortField = params.sortField, sortOrder = params.sortOrder, setScrollState = params.setScrollState;
208
+ // 使用 ref 跟踪上一次的状态
209
+ var prevDataSourceLengthRef = useRef(dataSourceLength);
210
+ var prevProcessedLengthRef = useRef(processedDataLength);
211
+ var prevFiltersRef = useRef(filters);
212
+ var prevSortRef = useRef({ field: sortField, order: sortOrder });
213
+ useEffect(function () {
214
+ // 判断数据长度是否变小了
215
+ var dataLengthDecreased = prevDataSourceLengthRef.current > dataSourceLength ||
216
+ prevProcessedLengthRef.current > processedDataLength;
217
+ // 判断筛选或排序是否变化
218
+ var filtersChanged = !isEqual(prevFiltersRef.current, filters);
219
+ var sortChanged = prevSortRef.current.field !== sortField ||
220
+ prevSortRef.current.order !== sortOrder;
221
+ // 只在数据变小或筛选/排序变化时重置Y轴滚动
222
+ var shouldResetScrollTop = dataLengthDecreased || filtersChanged || sortChanged;
223
+ if (shouldResetScrollTop) {
224
+ // 更新 ref 保存的值
225
+ prevDataSourceLengthRef.current = dataSourceLength;
226
+ prevProcessedLengthRef.current = processedDataLength;
227
+ prevFiltersRef.current = filters;
228
+ prevSortRef.current = { field: sortField, order: sortOrder };
229
+ // 只重置垂直滚动位置到顶部,保持水平滚动位置不变
230
+ setScrollState(function (prev) { return (__assign(__assign({}, prev), { scrollTop: 0 })); });
231
+ }
232
+ else {
233
+ // 只是数据长度变大,不重置滚动,但更新 ref
234
+ var dataChanged = prevDataSourceLengthRef.current !== dataSourceLength ||
235
+ prevProcessedLengthRef.current !== processedDataLength;
236
+ if (dataChanged) {
237
+ prevDataSourceLengthRef.current = dataSourceLength;
238
+ prevProcessedLengthRef.current = processedDataLength;
239
+ }
240
+ }
241
+ }, [
242
+ dataSourceLength,
243
+ processedDataLength,
244
+ filters,
245
+ sortField,
246
+ sortOrder,
247
+ setScrollState,
248
+ ]);
249
+ };
250
+
251
+ export { useScrollReset, useScrollbarMetrics, useTableScroll };
@@ -0,0 +1,81 @@
1
+ import { __spreadArray } from '../../_virtual/_tslib.js';
2
+ import { useMemo } from 'react';
3
+ import { IS_SUMMARY } from '../../table/constant.js';
4
+ import 'lodash/isEqual';
5
+ import 'ahooks';
6
+ import '../../node_modules/immutability-helper/index.js';
7
+ import 'react/jsx-runtime';
8
+ import { plus } from 'zmdms-utils';
9
+ import '../../node_modules/exceljs/dist/exceljs.min.js';
10
+ import 'dayjs';
11
+
12
+ /**
13
+ * 合计行计算 Hook
14
+ */
15
+ var useSummaryRow = function (params) {
16
+ var columns = params.columns, dataSource = params.dataSource;
17
+ var summaryRow = useMemo(function () {
18
+ var hasSummary = columns.some(function (col) { return col.isSummary; });
19
+ if (!hasSummary)
20
+ return null;
21
+ var summaryRecord = {};
22
+ // 找到第一个数据列(非序号列、非选择框列)
23
+ var firstDataColIndex = -1;
24
+ for (var i = 0; i < columns.length; i++) {
25
+ var col = columns[i];
26
+ if (col.key !== "__index__" && col.key !== "__selection__") {
27
+ firstDataColIndex = i;
28
+ break;
29
+ }
30
+ }
31
+ columns.forEach(function (column, colIndex) {
32
+ var dataIndex = column.dataIndex || column.key;
33
+ if (column.isSummary) {
34
+ // 计算合计值
35
+ var sum_1 = 0;
36
+ dataSource.forEach(function (record) {
37
+ var value = record[dataIndex];
38
+ var num = typeof value === "string" ? parseFloat(value) : value;
39
+ if (!isNaN(num) &&
40
+ num !== null &&
41
+ num !== undefined &&
42
+ !record[IS_SUMMARY]) {
43
+ sum_1 = plus(sum_1, num);
44
+ }
45
+ });
46
+ // 应用格式化
47
+ var formattedSum = sum_1;
48
+ if (column.precision !== undefined) {
49
+ formattedSum = sum_1.toFixed(column.precision);
50
+ }
51
+ if (column.thousand) {
52
+ formattedSum = Number(formattedSum).toLocaleString("en-US");
53
+ }
54
+ summaryRecord[dataIndex] = formattedSum;
55
+ }
56
+ else if (colIndex === firstDataColIndex) {
57
+ // 第一个数据列显示"合计"
58
+ summaryRecord[dataIndex] = "合计";
59
+ }
60
+ else {
61
+ summaryRecord[dataIndex] = "";
62
+ }
63
+ });
64
+ summaryRecord[IS_SUMMARY] = true;
65
+ return summaryRecord;
66
+ }, [columns, dataSource]);
67
+ // 包含合计行的数据源
68
+ var finalDataSource = useMemo(function () {
69
+ if (summaryRow) {
70
+ return __spreadArray(__spreadArray([], dataSource, true), [summaryRow], false);
71
+ }
72
+ return dataSource;
73
+ }, [dataSource, summaryRow]);
74
+ return {
75
+ summaryRow: summaryRow,
76
+ finalDataSource: finalDataSource,
77
+ hasSummaryRow: !!summaryRow,
78
+ };
79
+ };
80
+
81
+ export { useSummaryRow };