zmdms-webui 2.6.2 → 2.6.4

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.
@@ -0,0 +1,181 @@
1
+ import { COLORS, SCROLLBAR_SIZE } from '../../utils/constants.js';
2
+ import 'zmdms-utils';
3
+ import 'dayjs';
4
+ import '../../../_virtual/_tslib.js';
5
+
6
+ /**
7
+ * 选择区域渲染�?
8
+ * 负责渲染单元格框选区�?
9
+ */
10
+ var SelectionRenderer = /** @class */ (function () {
11
+ function SelectionRenderer() {
12
+ this.context = null;
13
+ }
14
+ SelectionRenderer.prototype.setContext = function (context) {
15
+ this.context = context;
16
+ };
17
+ /**
18
+ * 渲染单元格选择区域
19
+ */
20
+ SelectionRenderer.prototype.render = function () {
21
+ if (!this.context || !this.context.state.cellSelection)
22
+ return;
23
+ var _a = this.context, ctx = _a.ctx, state = _a.state, columnRenderInfos = _a.columnRenderInfos, processedDataSource = _a.processedDataSource, headerHeight = _a.headerHeight, rowHeight = _a.rowHeight, scrollState = _a.scrollState, displayWidth = _a.displayWidth, displayHeight = _a.displayHeight, needHorizontalScrollbar = _a.needHorizontalScrollbar, fixedRowsConfig = _a.fixedRowsConfig, fixedRowsCount = _a.fixedRowsCount, summaryFixed = _a.summaryFixed, hasSummaryRow = _a.hasSummaryRow, mergeCellMap = _a.mergeCellMap;
24
+ var _b = state.cellSelection, startRow = _b.startRow, endRow = _b.endRow, startCol = _b.startCol, endCol = _b.endCol;
25
+ // 计算选择区域的边�?
26
+ var minRow = Math.min(startRow, endRow);
27
+ var maxRow = Math.max(startRow, endRow);
28
+ var minCol = Math.min(startCol, endCol);
29
+ var maxCol = Math.max(startCol, endCol);
30
+ // 计算fixed列的右边�?
31
+ var fixedColumnsRightEdge = 0;
32
+ columnRenderInfos.forEach(function (info) {
33
+ if (info.fixed) {
34
+ var rightEdge = info.fixedLeft + info.width;
35
+ fixedColumnsRightEdge = Math.max(fixedColumnsRightEdge, rightEdge);
36
+ }
37
+ });
38
+ // 记录已绘制的合并单元�?
39
+ var drawnMergeCells = new Set();
40
+ // 记录选区的边界坐�?
41
+ var selectionTop = Infinity;
42
+ var selectionBottom = -Infinity;
43
+ var selectionLeft = Infinity;
44
+ var selectionRight = -Infinity;
45
+ // 计算固定行的范围
46
+ var fixedTopRowsCount = (fixedRowsConfig === null || fixedRowsConfig === void 0 ? void 0 : fixedRowsConfig.topCount) || fixedRowsCount || 0;
47
+ var fixedBottomRowsCount = (fixedRowsConfig === null || fixedRowsConfig === void 0 ? void 0 : fixedRowsConfig.bottomCount) || 0;
48
+ var bottomRowsStartIndex = processedDataSource.length -
49
+ fixedBottomRowsCount -
50
+ (summaryFixed && hasSummaryRow ? 1 : 0);
51
+ var summaryRowIndex = hasSummaryRow
52
+ ? processedDataSource.length - 1
53
+ : -1;
54
+ // 绘制选中的单元格背景
55
+ for (var row = minRow; row <= maxRow; row++) {
56
+ var y = void 0;
57
+ var cellHeight = void 0;
58
+ var isFixedRow = false;
59
+ if (row === -1) {
60
+ // 表头�?
61
+ y = 0;
62
+ cellHeight = headerHeight;
63
+ }
64
+ else if (row < fixedTopRowsCount) {
65
+ // 固定顶部�?
66
+ y = headerHeight + row * rowHeight;
67
+ cellHeight = rowHeight;
68
+ isFixedRow = true;
69
+ }
70
+ else if (fixedBottomRowsCount > 0 &&
71
+ row >= bottomRowsStartIndex &&
72
+ row < bottomRowsStartIndex + fixedBottomRowsCount) {
73
+ // 固定底部�?
74
+ var relativeIndex = row - bottomRowsStartIndex;
75
+ var fixedSummaryHeight = summaryFixed && hasSummaryRow ? rowHeight : 0;
76
+ y =
77
+ displayHeight -
78
+ (needHorizontalScrollbar ? SCROLLBAR_SIZE : 0) -
79
+ fixedSummaryHeight -
80
+ fixedBottomRowsCount * rowHeight +
81
+ relativeIndex * rowHeight;
82
+ cellHeight = rowHeight;
83
+ isFixedRow = true;
84
+ }
85
+ else if (summaryFixed && row === summaryRowIndex) {
86
+ // 固定合计�?
87
+ var summaryRowY = displayHeight -
88
+ (needHorizontalScrollbar ? SCROLLBAR_SIZE : 0) -
89
+ rowHeight;
90
+ y = summaryRowY;
91
+ cellHeight = rowHeight;
92
+ isFixedRow = true;
93
+ }
94
+ else {
95
+ // 普通数据行
96
+ var adjustedRow = row - fixedTopRowsCount;
97
+ y =
98
+ headerHeight +
99
+ fixedTopRowsCount * rowHeight +
100
+ adjustedRow * rowHeight -
101
+ scrollState.scrollTop;
102
+ cellHeight = rowHeight;
103
+ // 数据行的可见性检�?
104
+ if (y + cellHeight < headerHeight + fixedTopRowsCount * rowHeight ||
105
+ y > displayHeight)
106
+ continue;
107
+ }
108
+ for (var col = minCol; col <= maxCol; col++) {
109
+ var columnInfo = columnRenderInfos[col];
110
+ if (!columnInfo)
111
+ continue;
112
+ // 表头行不处理合并单元�?
113
+ if (row !== -1) {
114
+ var mergeCellKey = "".concat(row, "-").concat(col);
115
+ var mergeInfo = mergeCellMap === null || mergeCellMap === void 0 ? void 0 : mergeCellMap.get(mergeCellKey);
116
+ // 如果是被合并的单元格,跳�?
117
+ if (mergeInfo && mergeInfo.skip) {
118
+ continue;
119
+ }
120
+ // 如果是合并单元格的主单元格,检查是否已绘制
121
+ if (mergeInfo && !mergeInfo.skip) {
122
+ var mergeKey = "".concat(mergeInfo.rowIndex, "-").concat(mergeInfo.colIndex);
123
+ if (drawnMergeCells.has(mergeKey)) {
124
+ continue;
125
+ }
126
+ drawnMergeCells.add(mergeKey);
127
+ }
128
+ // 计算单元格高度(考虑合并�?
129
+ if (mergeInfo && mergeInfo.rowSpan > 1) {
130
+ cellHeight = rowHeight * mergeInfo.rowSpan;
131
+ }
132
+ }
133
+ var x = columnInfo.x, width = columnInfo.width, fixed = columnInfo.fixed, fixedLeft = columnInfo.fixedLeft;
134
+ var drawX = fixed ? fixedLeft : x - scrollState.scrollLeft;
135
+ var drawWidth = width;
136
+ if (!fixed && (drawX + width < 0 || drawX > displayWidth))
137
+ continue;
138
+ // 对于非fixed列,需要裁剪掉被fixed列遮挡的部分
139
+ if (!fixed && drawX < fixedColumnsRightEdge) {
140
+ var overlap = fixedColumnsRightEdge - drawX;
141
+ if (overlap >= width) {
142
+ continue;
143
+ }
144
+ drawX = fixedColumnsRightEdge;
145
+ drawWidth = width - overlap;
146
+ }
147
+ // 绘制选中背景
148
+ ctx.fillStyle = COLORS.selectionBg;
149
+ var clipY = void 0;
150
+ var clipHeight = void 0;
151
+ if (row === -1 || isFixedRow) {
152
+ clipY = y;
153
+ clipHeight = cellHeight;
154
+ }
155
+ else {
156
+ var minVisibleY = headerHeight + fixedTopRowsCount * rowHeight;
157
+ clipY = Math.max(y, minVisibleY);
158
+ var actualBottom = y + cellHeight;
159
+ clipHeight = Math.max(0, Math.min(actualBottom - clipY, displayHeight - clipY));
160
+ }
161
+ if (clipHeight > 0) {
162
+ ctx.fillRect(drawX, clipY, drawWidth, clipHeight);
163
+ // 更新选区边界
164
+ selectionTop = Math.min(selectionTop, clipY);
165
+ selectionBottom = Math.max(selectionBottom, clipY + clipHeight);
166
+ selectionLeft = Math.min(selectionLeft, drawX);
167
+ selectionRight = Math.max(selectionRight, drawX + drawWidth);
168
+ }
169
+ }
170
+ }
171
+ // 绘制整个选区的外边框
172
+ if (selectionLeft !== Infinity && selectionTop !== Infinity) {
173
+ ctx.strokeStyle = COLORS.primary;
174
+ ctx.lineWidth = 2;
175
+ ctx.strokeRect(selectionLeft, selectionTop, selectionRight - selectionLeft, selectionBottom - selectionTop);
176
+ }
177
+ };
178
+ return SelectionRenderer;
179
+ }());
180
+
181
+ export { SelectionRenderer };
@@ -0,0 +1,185 @@
1
+ import { useState, useCallback, useMemo, useEffect } from 'react';
2
+ import { useMemoizedFn } from 'ahooks';
3
+
4
+ /**
5
+ * 树形展开 Hook
6
+ */
7
+ var useExpandable = function (params) {
8
+ var dataSource = params.dataSource, expandable = params.expandable, rowKey = params.rowKey;
9
+ // 展开状态管理
10
+ var _a = useState(function () {
11
+ if (!expandable)
12
+ return new Set();
13
+ // 优先级:expandedRowKeys > defaultExpandedRowKeys > defaultExpandAllRows
14
+ if (expandable.expandedRowKeys && expandable.expandedRowKeys.length > 0) {
15
+ return new Set(expandable.expandedRowKeys);
16
+ }
17
+ if (expandable.defaultExpandedRowKeys) {
18
+ return new Set(expandable.defaultExpandedRowKeys);
19
+ }
20
+ if (expandable.defaultExpandAllRows) {
21
+ // 延迟到数据加载后执行
22
+ return new Set();
23
+ }
24
+ return new Set();
25
+ }), expandedKeys = _a[0], setExpandedKeys = _a[1];
26
+ // 获取行的key
27
+ var getRowKey = useCallback(function (record, index) {
28
+ var _a;
29
+ if (typeof rowKey === "function") {
30
+ return String(rowKey(record));
31
+ }
32
+ return String((_a = record[rowKey]) !== null && _a !== void 0 ? _a : index);
33
+ }, [rowKey]);
34
+ // 子节点字段名
35
+ var childrenColumnName = useMemo(function () {
36
+ return (expandable === null || expandable === void 0 ? void 0 : expandable.childrenColumnName) || "children";
37
+ }, [expandable]);
38
+ // 默认展开所有行的处理
39
+ useEffect(function () {
40
+ if ((expandable === null || expandable === void 0 ? void 0 : expandable.defaultExpandAllRows) &&
41
+ expandedKeys.size === 0 &&
42
+ dataSource.length > 0) {
43
+ // 递归获取所有有子节点的key
44
+ var collectExpandableKeys_1 = function (records, level) {
45
+ if (level === void 0) { level = 0; }
46
+ var keys = [];
47
+ records.forEach(function (record, index) {
48
+ var key = getRowKey(record, index);
49
+ var children = record[childrenColumnName];
50
+ if (children && children.length > 0) {
51
+ keys.push(key);
52
+ // 递归展开子节点
53
+ keys.push.apply(keys, collectExpandableKeys_1(children, level + 1));
54
+ }
55
+ });
56
+ return keys;
57
+ };
58
+ var allKeys = collectExpandableKeys_1(dataSource);
59
+ setExpandedKeys(new Set(allKeys));
60
+ }
61
+ }, [
62
+ expandable === null || expandable === void 0 ? void 0 : expandable.defaultExpandAllRows,
63
+ dataSource,
64
+ expandedKeys.size,
65
+ getRowKey,
66
+ childrenColumnName,
67
+ ]);
68
+ // 同步外部传入的 expandedRowKeys
69
+ useEffect(function () {
70
+ if (expandable === null || expandable === void 0 ? void 0 : expandable.expandedRowKeys) {
71
+ setExpandedKeys(new Set(expandable.expandedRowKeys));
72
+ }
73
+ }, [expandable === null || expandable === void 0 ? void 0 : expandable.expandedRowKeys]);
74
+ /**
75
+ * 展平树形数据
76
+ */
77
+ var flattenedData = useMemo(function () {
78
+ if (!expandable) {
79
+ // 如果没有展开配置,直接返回原数据
80
+ return dataSource.map(function (record, index) { return ({
81
+ record: record,
82
+ level: 0,
83
+ hasChildren: false,
84
+ isExpanded: false,
85
+ key: getRowKey(record, index),
86
+ indexInParent: index + 1,
87
+ }); });
88
+ }
89
+ var result = [];
90
+ var flatten = function (records, level, parentKey) {
91
+ records.forEach(function (record, index) {
92
+ var key = getRowKey(record, index);
93
+ var children = record[childrenColumnName];
94
+ result.push({
95
+ record: record,
96
+ level: level,
97
+ hasChildren: !!(children && children.length > 0),
98
+ isExpanded: expandedKeys.has(key),
99
+ parentKey: parentKey,
100
+ key: key,
101
+ indexInParent: index + 1, // 在当前层级的序号(从1开始)
102
+ });
103
+ // 如果该节点已展开,且有子节点,则递归展开子节点
104
+ var node = result[result.length - 1];
105
+ if (node.hasChildren && node.isExpanded && children) {
106
+ flatten(children, level + 1, key);
107
+ }
108
+ });
109
+ };
110
+ flatten(dataSource, 0);
111
+ return result;
112
+ }, [dataSource, expandable, expandedKeys, getRowKey, childrenColumnName]);
113
+ /**
114
+ * 切换指定行的展开状态
115
+ */
116
+ var toggleExpand = useMemoizedFn(function (key) {
117
+ var newExpandedKeys = new Set(expandedKeys);
118
+ if (newExpandedKeys.has(key)) {
119
+ newExpandedKeys.delete(key);
120
+ }
121
+ else {
122
+ newExpandedKeys.add(key);
123
+ }
124
+ setExpandedKeys(newExpandedKeys);
125
+ // 调用外部回调
126
+ if (expandable === null || expandable === void 0 ? void 0 : expandable.onExpandedRowsChange) {
127
+ // 找到对应的record
128
+ var findRecordByKey_1 = function (records, targetKey) {
129
+ for (var _i = 0, records_1 = records; _i < records_1.length; _i++) {
130
+ var record_1 = records_1[_i];
131
+ var k = getRowKey(record_1, 0);
132
+ if (k === targetKey) {
133
+ return record_1;
134
+ }
135
+ var children = record_1[childrenColumnName];
136
+ if (children) {
137
+ var found = findRecordByKey_1(children, targetKey);
138
+ if (found)
139
+ return found;
140
+ }
141
+ }
142
+ return null;
143
+ };
144
+ var record = findRecordByKey_1(dataSource, key);
145
+ if (record) {
146
+ var isExpanded = !expandedKeys.has(key);
147
+ expandable.onExpandedRowsChange(Array.from(newExpandedKeys), record, isExpanded ? "expand" : "collapse");
148
+ }
149
+ }
150
+ });
151
+ /**
152
+ * 展开指定行
153
+ */
154
+ var expandRow = useMemoizedFn(function (key) {
155
+ var newExpandedKeys = new Set(expandedKeys);
156
+ newExpandedKeys.add(key);
157
+ setExpandedKeys(newExpandedKeys);
158
+ });
159
+ /**
160
+ * 收起指定行
161
+ */
162
+ var collapseRow = useMemoizedFn(function (key) {
163
+ var newExpandedKeys = new Set(expandedKeys);
164
+ newExpandedKeys.delete(key);
165
+ setExpandedKeys(newExpandedKeys);
166
+ });
167
+ /**
168
+ * 设置展开状态
169
+ */
170
+ var setExpandedRowKeys = useMemoizedFn(function (keys) {
171
+ setExpandedKeys(new Set(keys));
172
+ });
173
+ return {
174
+ expandedKeys: expandedKeys,
175
+ flattenedData: flattenedData,
176
+ toggleExpand: toggleExpand,
177
+ expandRow: expandRow,
178
+ collapseRow: collapseRow,
179
+ setExpandedRowKeys: setExpandedRowKeys,
180
+ // 是否开启了展开功能
181
+ hasExpandable: !!expandable,
182
+ };
183
+ };
184
+
185
+ export { useExpandable };
@@ -14,7 +14,7 @@ import { calculateSelectionState, toggleSelectAll, handleSortClick, calculateIco
14
14
  * 表格交互事件处理 Hook
15
15
  */
16
16
  var useTableInteraction = function (params) {
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
+ 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, flattenedData = params.flattenedData, expandable = params.expandable, 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, onExpand = params.onExpand, 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;
18
18
  // 获取鼠标位置对应的单元格
19
19
  var getCellFromPosition = useMemoizedFn(function (x, y) {
20
20
  var fixedTopRowsCount = (fixedRowsConfig === null || fixedRowsConfig === void 0 ? void 0 : fixedRowsConfig.topCount) || fixedRowsCount || 0;
@@ -398,6 +398,42 @@ var useTableInteraction = function (params) {
398
398
  return;
399
399
  }
400
400
  }
401
+ // 检查是否点击了展开图标(树形展开功能)
402
+ if (expandable &&
403
+ flattenedData &&
404
+ cell &&
405
+ cell.col === (expandable.expandIconColumnIndex || 0)) {
406
+ var flattenedRow = flattenedData[cell.row];
407
+ if (flattenedRow && flattenedRow.hasChildren) {
408
+ var level = flattenedRow.level;
409
+ // 计算展开图标的位置
410
+ var columnInfo = columnRenderInfos[cell.col];
411
+ if (columnInfo) {
412
+ var drawX = columnInfo.fixed
413
+ ? columnInfo.fixedLeft
414
+ : columnInfo.x - scrollState.scrollLeft;
415
+ var iconX = drawX + 8 + level * 20; // TEXT_PADDING + level * 缩进
416
+ var iconY = headerHeight +
417
+ (fixedRowsCount || (fixedRowsConfig === null || fixedRowsConfig === void 0 ? void 0 : fixedRowsConfig.topCount) || 0) * rowHeight +
418
+ (cell.row -
419
+ (fixedRowsCount || (fixedRowsConfig === null || fixedRowsConfig === void 0 ? void 0 : fixedRowsConfig.topCount) || 0)) *
420
+ rowHeight -
421
+ scrollState.scrollTop +
422
+ rowHeight / 2;
423
+ // 检查点击位置是否在展开图标范围内
424
+ var iconRadius = 8;
425
+ var distance = Math.sqrt(Math.pow(x - iconX, 2) + Math.pow(y - iconY, 2));
426
+ if (distance <= iconRadius + 3) {
427
+ // 点击了展开图标,切换展开状态
428
+ var rowKey = getRowKey(processedDataSource[cell.row], cell.row);
429
+ if (onExpand) {
430
+ onExpand(rowKey);
431
+ }
432
+ return; // 点击了展开图标,不继续其他逻辑
433
+ }
434
+ }
435
+ }
436
+ }
401
437
  // 检查是否点击了选择框列,如果是,则不启用框选
402
438
  var isSelectionColumn = cell && ((_b = columnRenderInfos[cell.col]) === null || _b === void 0 ? void 0 : _b.column.key) === "__selection__";
403
439
  if (cell && !e.shiftKey && !isSelectionColumn) {