zmdms-webui 2.3.6 → 2.3.7
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 +109 -24
- package/dist/es/canvastable/components/CanvasTableMenu.js +1 -2
- package/dist/es/canvastable/hooks/useHeaderHeight.js +4 -9
- package/dist/es/canvastable/hooks/useProcessedColumns.js +17 -7
- package/dist/es/canvastable/hooks/useSummaryRow.js +4 -11
- package/dist/es/canvastable/hooks/useTableRender.js +152 -48
- package/dist/es/canvastable/interface.d.ts +89 -1
- package/dist/es/canvastable/utils/columnHelpers.js +6 -2
- package/dist/es/canvastable/utils/constants.js +9 -2
- package/dist/es/canvastable/utils/multiHeaderHelpers.js +5 -9
- package/dist/es/canvastable/utils/tableCalculations.js +13 -4
- package/dist/index.build.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __assign } from '../_virtual/_tslib.js';
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
-
import { useRef, useState, useCallback, useMemo } from 'react';
|
|
3
|
+
import { useRef, useState, useCallback, useMemo, useImperativeHandle } from 'react';
|
|
4
4
|
import { Spin } from 'antd';
|
|
5
5
|
import './components/FilterPopover.js';
|
|
6
6
|
import CellOverlay from './components/CellOverlay.js';
|
|
@@ -39,7 +39,7 @@ 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;
|
|
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;
|
|
43
43
|
var canvasRef = useRef(null);
|
|
44
44
|
var containerRef = useRef(null);
|
|
45
45
|
var filterPopoverRef = useRef(null);
|
|
@@ -61,15 +61,17 @@ function CanvasTable(props) {
|
|
|
61
61
|
return String((_a = record[rowKey]) !== null && _a !== void 0 ? _a : index);
|
|
62
62
|
}, [rowKey]);
|
|
63
63
|
// 动态列配置
|
|
64
|
-
var
|
|
64
|
+
var _v = useDynamicListByColumns(columns, {
|
|
65
65
|
dynamicKey: dynamicKey,
|
|
66
66
|
dynamicVersion: dynamicVersion,
|
|
67
67
|
customDynamicListHandle: customDynamicListHandle,
|
|
68
|
-
}), defaultDynamicList =
|
|
68
|
+
}), defaultDynamicList = _v.defaultDynamicList, currentDynamicList = _v.currentDynamicList, onCurrentListChange = _v.onCurrentListChange, dynamicSettingRef = _v.dynamicSettingRef;
|
|
69
69
|
// 根据动态列配置处理columns
|
|
70
70
|
var dynamicColumns = useMemo(function () { return getTableColumns(columns, currentDynamicList); }, [columns, currentDynamicList]).columns;
|
|
71
71
|
// 内部列宽状态(未开启动态配置时使用)
|
|
72
|
-
var
|
|
72
|
+
var _w = useState({}), internalColumnWidths = _w[0], setInternalColumnWidths = _w[1];
|
|
73
|
+
// 跟踪用户手动调整过宽度的列(用于排除自动宽度分配)
|
|
74
|
+
var _x = useState(new Set()), manuallyResizedColumnKeys = _x[0], setManuallyResizedColumnKeys = _x[1];
|
|
73
75
|
// 处理选中框列、序号列等
|
|
74
76
|
var processedColumnsOld = useProcessedColumns({
|
|
75
77
|
columns: columns,
|
|
@@ -81,30 +83,31 @@ function CanvasTable(props) {
|
|
|
81
83
|
renderMode: renderMode,
|
|
82
84
|
dynamicSettingRef: dynamicSettingRef,
|
|
83
85
|
headerWrap: headerWrap,
|
|
86
|
+
headerAlign: headerAlign,
|
|
84
87
|
});
|
|
85
88
|
// 表格状态管理
|
|
86
|
-
var
|
|
89
|
+
var _y = useTableState({
|
|
87
90
|
dataSource: dataSource,
|
|
88
91
|
columns: processedColumnsOld,
|
|
89
92
|
rowSelection: rowSelection,
|
|
90
93
|
onFilterChange: onFilterChange,
|
|
91
|
-
}), state =
|
|
94
|
+
}), state = _y.state, setState = _y.setState, processedDataSource = _y.processedDataSource, handleFilterChange = _y.handleFilterChange, closeFilterPopover = _y.closeFilterPopover, autoGeneratedFilters = _y.autoGeneratedFilters;
|
|
92
95
|
var order = useMemo(function () {
|
|
93
96
|
return state.sortOrder && state.sortField
|
|
94
97
|
? { field: state.sortField, order: state.sortOrder }
|
|
95
98
|
: undefined;
|
|
96
99
|
}, [state.sortOrder, state.sortField]);
|
|
97
|
-
var
|
|
100
|
+
var _z = useAutoMerge(processedDataSource, processedColumnsOld, {
|
|
98
101
|
isAutoMerge: isAutoMerge,
|
|
99
102
|
isDimensionDynamic: isDimensionDynamic,
|
|
100
103
|
order: order,
|
|
101
104
|
dimensionCustomSumKeys: dimensionCustomSumKeys,
|
|
102
|
-
}), newDataSource =
|
|
105
|
+
}), newDataSource = _z[0], processedColumns = _z[1];
|
|
103
106
|
// 生成合计行和最终数据源
|
|
104
|
-
var
|
|
107
|
+
var _0 = useSummaryRow({
|
|
105
108
|
columns: processedColumns,
|
|
106
109
|
dataSource: newDataSource,
|
|
107
|
-
}), finalDataSource =
|
|
110
|
+
}), finalDataSource = _0.finalDataSource, hasSummaryRow = _0.hasSummaryRow;
|
|
108
111
|
// 自动高度计算(需要在容器尺寸计算之前)
|
|
109
112
|
var autoHeight = useCanvasTableAutoHeight(isAutoScrollY, autoScrollYMarginBottom, canvasTableId);
|
|
110
113
|
// 监听容器尺寸变化(提前计算,用于列宽自适应)
|
|
@@ -116,7 +119,10 @@ function CanvasTable(props) {
|
|
|
116
119
|
var containerWidth = containerSize.width;
|
|
117
120
|
var containerHeight = containerSize.height;
|
|
118
121
|
// 计算列的渲染信息(使用容器宽度进行自适应填充)
|
|
119
|
-
|
|
122
|
+
// 手动调整过宽度的列不参与自动宽度分配
|
|
123
|
+
var columnRenderInfos = useMemo(function () {
|
|
124
|
+
return calculateColumnRenderInfos(processedColumns, containerWidth, manuallyResizedColumnKeys);
|
|
125
|
+
}, [processedColumns, containerWidth, manuallyResizedColumnKeys]);
|
|
120
126
|
// 计算表头动态高度(支持wrap换行)
|
|
121
127
|
// 注意:必须在 columnRenderInfos 计算之后,以便使用实际的列宽
|
|
122
128
|
var calculatedHeaderHeight = useHeaderHeight({
|
|
@@ -137,7 +143,7 @@ function CanvasTable(props) {
|
|
|
137
143
|
return calculateTotalHeight(calculatedHeaderHeight, finalDataSource.length, rowHeight);
|
|
138
144
|
}, [calculatedHeaderHeight, finalDataSource.length, rowHeight]);
|
|
139
145
|
// 计算滚动条指标
|
|
140
|
-
var
|
|
146
|
+
var _1 = useScrollbarMetrics({
|
|
141
147
|
containerWidth: containerWidth,
|
|
142
148
|
containerHeight: containerHeight,
|
|
143
149
|
totalWidth: totalWidth,
|
|
@@ -145,15 +151,15 @@ function CanvasTable(props) {
|
|
|
145
151
|
headerHeight: calculatedHeaderHeight,
|
|
146
152
|
scrollTop: 0,
|
|
147
153
|
scrollLeft: 0,
|
|
148
|
-
}), maxScrollTop =
|
|
154
|
+
}), maxScrollTop = _1.maxScrollTop, maxScrollLeft = _1.maxScrollLeft;
|
|
149
155
|
// 滚动管理(使用预先计算的maxScrollTop和maxScrollLeft)
|
|
150
|
-
var
|
|
156
|
+
var _2 = useTableScroll({
|
|
151
157
|
canvasRef: canvasRef,
|
|
152
158
|
containerRef: containerRef,
|
|
153
159
|
maxScrollTop: maxScrollTop,
|
|
154
160
|
maxScrollLeft: maxScrollLeft,
|
|
155
161
|
onScroll: onScroll,
|
|
156
|
-
}), scrollState =
|
|
162
|
+
}), scrollState = _2.scrollState, setScrollState = _2.setScrollState;
|
|
157
163
|
// 数据变化时重置滚动位置(筛选、排序、数据源更新等操作后)
|
|
158
164
|
useScrollReset({
|
|
159
165
|
dataSourceLength: dataSource.length,
|
|
@@ -174,17 +180,23 @@ function CanvasTable(props) {
|
|
|
174
180
|
scrollLeft: scrollState.scrollLeft,
|
|
175
181
|
}).actualMetrics;
|
|
176
182
|
// 单元格框选
|
|
177
|
-
var
|
|
183
|
+
var _3 = useTableSelection({
|
|
178
184
|
state: state,
|
|
179
185
|
setState: setState,
|
|
180
186
|
}),
|
|
181
187
|
// selectionStartRef,
|
|
182
|
-
startSelection =
|
|
188
|
+
startSelection = _3.startSelection, updateSelection = _3.updateSelection, extendSelection = _3.extendSelection;
|
|
183
189
|
// 处理列宽调整
|
|
184
190
|
var handleColumnResize = useCallback(function (columnKey, newWidth) {
|
|
185
191
|
var _a;
|
|
186
192
|
// 先调用外部回调(用户可以监听列宽变化)
|
|
187
193
|
onColumnResize === null || onColumnResize === void 0 ? void 0 : onColumnResize(columnKey, newWidth);
|
|
194
|
+
// 记录用户手动调整过的列
|
|
195
|
+
setManuallyResizedColumnKeys(function (prev) {
|
|
196
|
+
var newSet = new Set(prev);
|
|
197
|
+
newSet.add(columnKey);
|
|
198
|
+
return newSet;
|
|
199
|
+
});
|
|
188
200
|
if (dynamicKey && currentDynamicList) {
|
|
189
201
|
// 开启了动态配置:更新到动态配置中
|
|
190
202
|
var newList = currentDynamicList.map(function (item) { return (__assign({}, item)); });
|
|
@@ -228,13 +240,13 @@ function CanvasTable(props) {
|
|
|
228
240
|
onCurrentListChange,
|
|
229
241
|
]);
|
|
230
242
|
// 列宽调整
|
|
231
|
-
var
|
|
243
|
+
var _4 = useColumnResize({
|
|
232
244
|
columnRenderInfos: columnRenderInfos,
|
|
233
245
|
containerWidth: containerWidth,
|
|
234
246
|
headerHeight: calculatedHeaderHeight,
|
|
235
247
|
scrollLeft: scrollState.scrollLeft,
|
|
236
248
|
onColumnResize: handleColumnResize,
|
|
237
|
-
}), resizeState =
|
|
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;
|
|
238
250
|
// 复制到剪贴板
|
|
239
251
|
var getSelectedCellsText = useCopyToClipboard({
|
|
240
252
|
cellSelection: state.cellSelection,
|
|
@@ -251,13 +263,17 @@ function CanvasTable(props) {
|
|
|
251
263
|
});
|
|
252
264
|
}
|
|
253
265
|
}, [getSelectedCellsText]);
|
|
266
|
+
// 过滤勾选框和index行给导出用
|
|
267
|
+
var exportColumns = useMemo(function () {
|
|
268
|
+
return processedColumns.filter(function (item) { return !item.key.includes("__"); });
|
|
269
|
+
}, [processedColumns]);
|
|
254
270
|
// Excel导出功能
|
|
255
271
|
var exportExcel = useExcelExport(processedDataSource, {
|
|
256
|
-
columns:
|
|
272
|
+
columns: exportColumns,
|
|
257
273
|
isAutoMerge: isAutoMerge,
|
|
258
274
|
});
|
|
259
275
|
// 交互事件处理(使用baseScrollbarMetrics的maxScrollTop/maxScrollLeft以保持稳定)
|
|
260
|
-
var
|
|
276
|
+
var _5 = useTableInteraction({
|
|
261
277
|
state: state,
|
|
262
278
|
setState: setState,
|
|
263
279
|
scrollState: scrollState,
|
|
@@ -303,7 +319,7 @@ function CanvasTable(props) {
|
|
|
303
319
|
fixedRowsCount: fixedRowsCount,
|
|
304
320
|
fixedRowsConfig: fixedRowsConfig,
|
|
305
321
|
summaryFixed: summaryFixed,
|
|
306
|
-
}), handleCanvasMouseDown =
|
|
322
|
+
}), handleCanvasMouseDown = _5.handleCanvasMouseDown, handleCanvasMouseMove = _5.handleCanvasMouseMove, handleCanvasMouseUp = _5.handleCanvasMouseUp, handleCanvasMouseLeave = _5.handleCanvasMouseLeave, handleCanvasContextMenu = _5.handleCanvasContextMenu;
|
|
307
323
|
// 渲染表格
|
|
308
324
|
useTableRender(__assign(__assign({ canvasRef: canvasRef, processedDataSource: finalDataSource, columnRenderInfos: columnRenderInfos, columns: processedColumns, // 传递原始columns用于渲染多级表头
|
|
309
325
|
state: state, scrollState: scrollState, rowSelection: rowSelection, containerWidth: containerWidth, containerHeight: containerHeight, headerHeight: calculatedHeaderHeight, baseHeaderHeight: headerHeight, // 传入原始基础高度用于计算每层高度
|
|
@@ -365,6 +381,73 @@ function CanvasTable(props) {
|
|
|
365
381
|
isVisible: state.badgePopover.visible,
|
|
366
382
|
onClose: handleCloseBadgePopover,
|
|
367
383
|
});
|
|
384
|
+
// 暴露给外部的方法
|
|
385
|
+
useImperativeHandle(tableRefHandle, function () { return ({
|
|
386
|
+
/** 获取当前表格的配置信息(动态列配置) */
|
|
387
|
+
getDynamicList: function () {
|
|
388
|
+
return currentDynamicList || [];
|
|
389
|
+
},
|
|
390
|
+
/** 动态列配置重置 */
|
|
391
|
+
onResetDynamicList: function () {
|
|
392
|
+
var _a, _b;
|
|
393
|
+
(_b = (_a = dynamicSettingRef.current) === null || _a === void 0 ? void 0 : _a.resetList) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
394
|
+
},
|
|
395
|
+
/** 动态列配置设置 */
|
|
396
|
+
onSetDynamicList: function (list) {
|
|
397
|
+
var _a, _b;
|
|
398
|
+
(_b = (_a = dynamicSettingRef.current) === null || _a === void 0 ? void 0 : _a.updateList) === null || _b === void 0 ? void 0 : _b.call(_a, list);
|
|
399
|
+
},
|
|
400
|
+
/** 导出Excel */
|
|
401
|
+
exportExcel: exportExcel,
|
|
402
|
+
/** 获取表格容器 */
|
|
403
|
+
getContainer: function () { return containerRef.current; },
|
|
404
|
+
/** 全屏展示表格 */
|
|
405
|
+
toggleFullScreen: function () {
|
|
406
|
+
var _a;
|
|
407
|
+
(_a = tableMenuRef.current) === null || _a === void 0 ? void 0 : _a.toggleFullscreen();
|
|
408
|
+
},
|
|
409
|
+
/** 获取选中的行keys */
|
|
410
|
+
getSelectedRowKeys: function () {
|
|
411
|
+
return state.selectedRowKeys;
|
|
412
|
+
},
|
|
413
|
+
/** 设置选中的行keys */
|
|
414
|
+
setSelectedRowKeys: function (keys) {
|
|
415
|
+
setState(function (prev) { return (__assign(__assign({}, prev), { selectedRowKeys: keys })); });
|
|
416
|
+
},
|
|
417
|
+
/** 滚动到指定位置 */
|
|
418
|
+
scrollTo: function (params) {
|
|
419
|
+
setScrollState(function (prev) { return (__assign(__assign({}, prev), { scrollLeft: params.x !== undefined ? params.x : prev.scrollLeft, scrollTop: params.y !== undefined ? params.y : prev.scrollTop })); });
|
|
420
|
+
},
|
|
421
|
+
/** 获取当前排序状态 */
|
|
422
|
+
getSortState: function () {
|
|
423
|
+
return {
|
|
424
|
+
field: state.sortField,
|
|
425
|
+
order: state.sortOrder,
|
|
426
|
+
};
|
|
427
|
+
},
|
|
428
|
+
/** 获取当前过滤状态 */
|
|
429
|
+
getFilterState: function () {
|
|
430
|
+
return state.filters;
|
|
431
|
+
},
|
|
432
|
+
/** 清除排序 */
|
|
433
|
+
clearSort: function () {
|
|
434
|
+
setState(function (prev) { return (__assign(__assign({}, prev), { sortField: null, sortOrder: null })); });
|
|
435
|
+
},
|
|
436
|
+
/** 清除过滤 */
|
|
437
|
+
clearFilter: function () {
|
|
438
|
+
setState(function (prev) { return (__assign(__assign({}, prev), { filters: {} })); });
|
|
439
|
+
},
|
|
440
|
+
}); }, [
|
|
441
|
+
currentDynamicList,
|
|
442
|
+
dynamicSettingRef,
|
|
443
|
+
exportExcel,
|
|
444
|
+
state.selectedRowKeys,
|
|
445
|
+
state.sortField,
|
|
446
|
+
state.sortOrder,
|
|
447
|
+
state.filters,
|
|
448
|
+
setState,
|
|
449
|
+
setScrollState,
|
|
450
|
+
]);
|
|
368
451
|
return (jsx(Spin, __assign({ spinning: loading }, { children: jsxs("div", __assign({ ref: containerRef, id: canvasTableId, className: "canvas-table-container ".concat(className || ""), tabIndex: 0, style: __assign(__assign({}, style), { position: "relative", width: width || "100%", height: containerHeight, overflow: "hidden", touchAction: "none", outline: "none" }) }, { children: [jsx("canvas", { ref: canvasRef, onMouseDown: handleCanvasMouseDown, onMouseMove: handleCanvasMouseMove, onMouseUp: handleCanvasMouseUp, onMouseLeave: handleCanvasMouseLeave, onContextMenu: handleCanvasContextMenu, style: {
|
|
369
452
|
display: "block",
|
|
370
453
|
// cursor 由 useTableInteraction 动态管理
|
|
@@ -374,7 +457,9 @@ function CanvasTable(props) {
|
|
|
374
457
|
WebkitFontSmoothing: "antialiased",
|
|
375
458
|
MozOsxFontSmoothing: "grayscale",
|
|
376
459
|
textRendering: "optimizeLegibility",
|
|
377
|
-
} }), dynamicKey ? (jsx(DynamicSetting, { parentDynamicKey: TABLE_DYNAMIC_KEY, dynamicKey: dynamicKey, defaultList: defaultDynamicList, onCurrentListChange: onCurrentListChange, ref: dynamicSettingRef, hiddenOperationIcon: true, isMore: true, isFixed: true, isDimensionDynamic: isDimensionDynamic })) : null, jsx(EmptyPlaceholder, { visible: finalDataSource.length === 0, text: emptyText, headerHeight: calculatedHeaderHeight }), jsx(HeaderOverlay, { overlays: headerOverlays }), jsx(CellOverlay, { overlays: cellOverlays }), filterPopoverElement, jsx(Tooltip, { visible: state.tooltip.visible, content: state.tooltip.content, position: state.tooltip.position }), jsx(BadgePopover, { visible: state.badgePopover.visible, content: state.badgePopover.content, position: state.badgePopover.position, popoverRef: badgePopoverRef }), menuId ? (jsx(CanvasTableMenu, { menuId: menuId, containerRef: containerRef, isFullscreenHandle: isFullscreenHandle, tableMenuRef: tableMenuRef, onCopy: handleCopy, onExport:
|
|
460
|
+
} }), dynamicKey ? (jsx(DynamicSetting, { parentDynamicKey: TABLE_DYNAMIC_KEY, dynamicKey: dynamicKey, defaultList: defaultDynamicList, onCurrentListChange: onCurrentListChange, ref: dynamicSettingRef, hiddenOperationIcon: true, isMore: true, isFixed: true, isDimensionDynamic: isDimensionDynamic })) : null, jsx(EmptyPlaceholder, { visible: finalDataSource.length === 0, text: emptyText, headerHeight: calculatedHeaderHeight }), jsx(HeaderOverlay, { overlays: headerOverlays }), jsx(CellOverlay, { overlays: cellOverlays }), filterPopoverElement, jsx(Tooltip, { visible: state.tooltip.visible, content: state.tooltip.content, position: state.tooltip.position }), jsx(BadgePopover, { visible: state.badgePopover.visible, content: state.badgePopover.content, position: state.badgePopover.position, popoverRef: badgePopoverRef }), menuId ? (jsx(CanvasTableMenu, { menuId: menuId, containerRef: containerRef, isFullscreenHandle: isFullscreenHandle, tableMenuRef: tableMenuRef, onCopy: handleCopy, onExport: function () {
|
|
461
|
+
return exportExcel((exportExcelConfig === null || exportExcelConfig === void 0 ? void 0 : exportExcelConfig.fileName) || "表格数据.xlsx", __assign({}, exportExcelConfig));
|
|
462
|
+
} })) : null] })) })));
|
|
378
463
|
}
|
|
379
464
|
|
|
380
465
|
export { CanvasTable as default };
|
|
@@ -32,8 +32,7 @@ var CanvasTableMenu = function (_a) {
|
|
|
32
32
|
break;
|
|
33
33
|
}
|
|
34
34
|
case "export": {
|
|
35
|
-
|
|
36
|
-
onExport === null || onExport === void 0 ? void 0 : onExport(fileName);
|
|
35
|
+
onExport === null || onExport === void 0 ? void 0 : onExport();
|
|
37
36
|
break;
|
|
38
37
|
}
|
|
39
38
|
}
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import { __spreadArray } from '../../_virtual/_tslib.js';
|
|
2
2
|
import { useState, useEffect } from 'react';
|
|
3
3
|
import { getMaxDepth, calculateLayerHeights } from '../utils/multiHeaderHelpers.js';
|
|
4
|
+
import { FONT_SIZE, FONT_FAMILY, LINE_HEIGHT, TEXT_PADDING, FILTER_ICON_WIDTH, SORT_ICON_WIDTH, ICON_SPACING } from '../utils/constants.js';
|
|
4
5
|
|
|
5
|
-
var FONT_SIZE = 13;
|
|
6
|
-
var FONT_FAMILY = '"Microsoft YaHei", 微软雅黑, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
7
|
-
var LINE_HEIGHT = 20;
|
|
8
|
-
var FILTER_ICON_WIDTH = 15;
|
|
9
|
-
var SORT_ICON_WIDTH = 15;
|
|
10
|
-
var ICON_SPACING = 4;
|
|
11
|
-
var TEXT_PADDING = 5;
|
|
12
6
|
/**
|
|
13
7
|
* 计算文本在给定宽度下需要的行数
|
|
14
8
|
*/
|
|
@@ -94,9 +88,10 @@ var useHeaderHeight = function (params) {
|
|
|
94
88
|
var columnWidth = ((_a = columnRenderInfos === null || columnRenderInfos === void 0 ? void 0 : columnRenderInfos[index]) === null || _a === void 0 ? void 0 : _a.width) || column.width || 100;
|
|
95
89
|
return calculateColumnLines(ctx, column, columnWidth);
|
|
96
90
|
}), false));
|
|
97
|
-
//
|
|
91
|
+
// 当有换行时:上边距(5px) + 行数 * 行高 + 下边距(5px)
|
|
92
|
+
// 当没有换行时:使用原始的 headerHeight
|
|
98
93
|
return maxLines > 1
|
|
99
|
-
?
|
|
94
|
+
? 10 + maxLines * LINE_HEIGHT // 上下边距各5px,共10px
|
|
100
95
|
: headerHeight;
|
|
101
96
|
};
|
|
102
97
|
setCalculatedHeight(calculateHeight());
|
|
@@ -16,7 +16,7 @@ import '../../node_modules/screenfull/index.js';
|
|
|
16
16
|
import ColumnDynamic from '../components/ColumnDynamic.js';
|
|
17
17
|
|
|
18
18
|
var useProcessedColumns = function (params) {
|
|
19
|
-
var columns = params.columns, dynamicColumns = params.dynamicColumns, mode = params.mode, rowSelection = params.rowSelection, internalColumnWidths = params.internalColumnWidths, dynamicKey = params.dynamicKey, _a = params.renderMode, renderMode = _a === void 0 ? "object" : _a, dynamicSettingRef = params.dynamicSettingRef, headerWrap = params.headerWrap;
|
|
19
|
+
var columns = params.columns, dynamicColumns = params.dynamicColumns, mode = params.mode, rowSelection = params.rowSelection, internalColumnWidths = params.internalColumnWidths, dynamicKey = params.dynamicKey, _a = params.renderMode, renderMode = _a === void 0 ? "object" : _a, dynamicSettingRef = params.dynamicSettingRef, headerWrap = params.headerWrap, _b = params.headerAlign, headerAlign = _b === void 0 ? "center" : _b;
|
|
20
20
|
return useMemo(function () {
|
|
21
21
|
var cols = __spreadArray([], (dynamicColumns || columns), true);
|
|
22
22
|
// 添加序号列
|
|
@@ -62,11 +62,19 @@ var useProcessedColumns = function (params) {
|
|
|
62
62
|
}
|
|
63
63
|
// 应用内部列宽状态(未开启动态配置时)
|
|
64
64
|
if (!dynamicKey && Object.keys(internalColumnWidths).length > 0) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
// 递归应用列宽
|
|
66
|
+
var applyColumnWidths_1 = function (columns) {
|
|
67
|
+
columns.forEach(function (col) {
|
|
68
|
+
if (col.key && internalColumnWidths[col.key]) {
|
|
69
|
+
col.width = internalColumnWidths[col.key];
|
|
70
|
+
}
|
|
71
|
+
// 递归处理子列(多级表头)
|
|
72
|
+
if (col.children && col.children.length > 0) {
|
|
73
|
+
applyColumnWidths_1(col.children);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
applyColumnWidths_1(cols);
|
|
70
78
|
}
|
|
71
79
|
// 验证动态列配置
|
|
72
80
|
if (dynamicKey) {
|
|
@@ -79,7 +87,7 @@ var useProcessedColumns = function (params) {
|
|
|
79
87
|
}
|
|
80
88
|
// 处理render函数
|
|
81
89
|
return cols.map(function (col) {
|
|
82
|
-
return processColumnRender(col, renderMode, headerWrap);
|
|
90
|
+
return processColumnRender(col, renderMode, headerWrap, headerAlign);
|
|
83
91
|
});
|
|
84
92
|
}, [
|
|
85
93
|
dynamicColumns,
|
|
@@ -90,6 +98,8 @@ var useProcessedColumns = function (params) {
|
|
|
90
98
|
internalColumnWidths,
|
|
91
99
|
renderMode,
|
|
92
100
|
dynamicSettingRef,
|
|
101
|
+
headerWrap,
|
|
102
|
+
headerAlign,
|
|
93
103
|
]);
|
|
94
104
|
};
|
|
95
105
|
|
|
@@ -22,15 +22,8 @@ var useSummaryRow = function (params) {
|
|
|
22
22
|
if (!hasSummary)
|
|
23
23
|
return null;
|
|
24
24
|
var summaryRecord = {};
|
|
25
|
-
//
|
|
26
|
-
var
|
|
27
|
-
for (var i = 0; i < leafColumns.length; i++) {
|
|
28
|
-
var col = leafColumns[i];
|
|
29
|
-
if (col.key !== "__index__" && col.key !== "__selection__") {
|
|
30
|
-
firstDataColIndex = i;
|
|
31
|
-
break;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
25
|
+
// 找到第一个列(包括序号列、选择框列)
|
|
26
|
+
var firstColIndex = leafColumns.length > 0 ? 0 : -1;
|
|
34
27
|
leafColumns.forEach(function (column, colIndex) {
|
|
35
28
|
var dataIndex = column.dataIndex || column.key;
|
|
36
29
|
if (column.isSummary) {
|
|
@@ -60,8 +53,8 @@ var useSummaryRow = function (params) {
|
|
|
60
53
|
}
|
|
61
54
|
summaryRecord[dataIndex] = formattedSum;
|
|
62
55
|
}
|
|
63
|
-
else if (colIndex ===
|
|
64
|
-
//
|
|
56
|
+
else if (colIndex === firstColIndex) {
|
|
57
|
+
// 第一列显示"合计"(可以是序号列、选择框列或数据列)
|
|
65
58
|
summaryRecord[dataIndex] = "合计";
|
|
66
59
|
}
|
|
67
60
|
else {
|
|
@@ -129,7 +129,6 @@ var useTableRender = function (params) {
|
|
|
129
129
|
ctx.fillStyle = COLORS.text;
|
|
130
130
|
ctx.font = "".concat(FONT_WEIGHT, " ").concat(FONT_SIZE, "px ").concat(FONT_FAMILY);
|
|
131
131
|
ctx.textBaseline = "middle";
|
|
132
|
-
var textX = drawX + 5;
|
|
133
132
|
var textY = headerHeight / 2;
|
|
134
133
|
// 绘制选择框
|
|
135
134
|
if (column.key === "__selection__") {
|
|
@@ -142,26 +141,65 @@ var useTableRender = function (params) {
|
|
|
142
141
|
else {
|
|
143
142
|
// 计算图标占用的宽度
|
|
144
143
|
var iconArea = calculateIconArea(column, width);
|
|
145
|
-
//
|
|
146
|
-
var
|
|
144
|
+
// 确定表头对齐方式,优先使用列的 headerAlign,其次是 align,最后是默认值
|
|
145
|
+
var headerAlign = column.headerAlign || column.align || "center";
|
|
147
146
|
// 绘制文本(如果 title 是 React 元素,跳过Canvas渲染,在覆盖层中渲染)
|
|
148
147
|
if (!isValidElement(column.title)) {
|
|
149
148
|
var titleText = String(column.title || "");
|
|
149
|
+
// 根据对齐方式和图标情况设置文本位置
|
|
150
|
+
var textX_1;
|
|
151
|
+
var textMaxWidth = void 0;
|
|
152
|
+
if (iconArea.iconsWidth > 0) {
|
|
153
|
+
// 有图标时,根据headerAlign调整文本位置和最大宽度
|
|
154
|
+
if (headerAlign === "right") {
|
|
155
|
+
ctx.textAlign = "right";
|
|
156
|
+
textX_1 = drawX + width - 5 - iconArea.iconsWidth;
|
|
157
|
+
textMaxWidth = width - 10 - iconArea.iconsWidth;
|
|
158
|
+
}
|
|
159
|
+
else if (headerAlign === "center") {
|
|
160
|
+
ctx.textAlign = "center";
|
|
161
|
+
textX_1 = drawX + (width - iconArea.iconsWidth) / 2;
|
|
162
|
+
textMaxWidth = width - 10 - iconArea.iconsWidth;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
ctx.textAlign = "left";
|
|
166
|
+
textX_1 = drawX + 5;
|
|
167
|
+
textMaxWidth = width - 5 - iconArea.iconsWidth;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
// 没有图标时,根据headerAlign设置对齐方式
|
|
172
|
+
if (headerAlign === "left") {
|
|
173
|
+
ctx.textAlign = "left";
|
|
174
|
+
textX_1 = drawX + 5;
|
|
175
|
+
textMaxWidth = width - 10;
|
|
176
|
+
}
|
|
177
|
+
else if (headerAlign === "right") {
|
|
178
|
+
ctx.textAlign = "right";
|
|
179
|
+
textX_1 = drawX + width - 5;
|
|
180
|
+
textMaxWidth = width - 10;
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
ctx.textAlign = "center";
|
|
184
|
+
textX_1 = drawX + width / 2;
|
|
185
|
+
textMaxWidth = width - 10;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
150
188
|
// 根据 ellipsis 和 wrap 属性处理文本
|
|
151
189
|
if (column.wrap) {
|
|
152
190
|
// 换行显示(支持\n和自动换行)
|
|
153
191
|
var lines = wrapText(ctx, titleText, textMaxWidth);
|
|
154
|
-
var lineHeight_1 =
|
|
192
|
+
var lineHeight_1 = FONT_SIZE + 5; // 字体大小 + 行间距5px
|
|
155
193
|
var startY_1 = textY - ((lines.length - 1) * lineHeight_1) / 2;
|
|
156
194
|
lines.forEach(function (line, index) {
|
|
157
195
|
var lineY = startY_1 + index * lineHeight_1;
|
|
158
|
-
ctx.fillText(line,
|
|
196
|
+
ctx.fillText(line, textX_1, lineY);
|
|
159
197
|
});
|
|
160
198
|
}
|
|
161
199
|
else {
|
|
162
200
|
// 默认截断显示
|
|
163
201
|
var truncatedText = truncateText(ctx, titleText, textMaxWidth);
|
|
164
|
-
ctx.fillText(truncatedText,
|
|
202
|
+
ctx.fillText(truncatedText, textX_1, textY);
|
|
165
203
|
}
|
|
166
204
|
}
|
|
167
205
|
// 绘制筛选图标(最右侧,距离右边5px)
|
|
@@ -178,6 +216,7 @@ var useTableRender = function (params) {
|
|
|
178
216
|
drawSortIcon(ctx, iconX, textY, column.key === state.sortField ? state.sortOrder : null);
|
|
179
217
|
}
|
|
180
218
|
}
|
|
219
|
+
ctx.textAlign = "left"; // 重置对齐方式
|
|
181
220
|
ctx.restore();
|
|
182
221
|
// 绘制表头列之间的边框
|
|
183
222
|
if (bordered) {
|
|
@@ -286,44 +325,73 @@ var useTableRender = function (params) {
|
|
|
286
325
|
var iconArea = shouldShowIcons
|
|
287
326
|
? calculateIconArea(column, width)
|
|
288
327
|
: { hasOrder: false, hasFilter: false, iconsWidth: 0 };
|
|
289
|
-
//
|
|
328
|
+
// 确定表头对齐方式,优先使用列的 headerAlign,其次是 align,最后是默认值
|
|
329
|
+
var headerAlign = column.headerAlign || column.align || "center";
|
|
330
|
+
// 如果是最末级且有图标,需要调整对齐方式
|
|
290
331
|
if (isLastLevel && iconArea.iconsWidth > 0) {
|
|
291
|
-
|
|
292
|
-
var
|
|
293
|
-
var textMaxWidth =
|
|
332
|
+
// 有图标时,根据headerAlign调整文本位置和最大宽度
|
|
333
|
+
var textX_2;
|
|
334
|
+
var textMaxWidth = void 0;
|
|
335
|
+
if (headerAlign === "right") {
|
|
336
|
+
ctx.textAlign = "right";
|
|
337
|
+
textX_2 = drawX + width - 5 - iconArea.iconsWidth;
|
|
338
|
+
textMaxWidth = width - 10 - iconArea.iconsWidth;
|
|
339
|
+
}
|
|
340
|
+
else if (headerAlign === "center") {
|
|
341
|
+
ctx.textAlign = "center";
|
|
342
|
+
textX_2 = drawX + (width - iconArea.iconsWidth) / 2;
|
|
343
|
+
textMaxWidth = width - 10 - iconArea.iconsWidth;
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
ctx.textAlign = "left";
|
|
347
|
+
textX_2 = drawX + 5;
|
|
348
|
+
textMaxWidth = width - 5 - iconArea.iconsWidth;
|
|
349
|
+
}
|
|
294
350
|
// 根据 wrap 属性处理文本
|
|
295
351
|
if (column.wrap) {
|
|
296
352
|
// 换行显示(支持\n和自动换行)
|
|
297
353
|
var lines = wrapText(ctx, titleText, textMaxWidth);
|
|
298
|
-
var lineHeight_2 =
|
|
354
|
+
var lineHeight_2 = FONT_SIZE + 5; // 字体大小 + 行间距5px
|
|
299
355
|
var startY_2 = textY - ((lines.length - 1) * lineHeight_2) / 2;
|
|
300
356
|
lines.forEach(function (line, index) {
|
|
301
357
|
var lineY = startY_2 + index * lineHeight_2;
|
|
302
|
-
ctx.fillText(line,
|
|
358
|
+
ctx.fillText(line, textX_2, lineY);
|
|
303
359
|
});
|
|
304
360
|
}
|
|
305
361
|
else {
|
|
306
362
|
var truncated = truncateText(ctx, titleText, textMaxWidth);
|
|
307
|
-
ctx.fillText(truncated,
|
|
363
|
+
ctx.fillText(truncated, textX_2, textY);
|
|
308
364
|
}
|
|
309
365
|
}
|
|
310
366
|
else {
|
|
311
|
-
|
|
312
|
-
var
|
|
367
|
+
// 没有图标时,根据headerAlign设置对齐方式
|
|
368
|
+
var textX_3;
|
|
369
|
+
if (headerAlign === "left") {
|
|
370
|
+
ctx.textAlign = "left";
|
|
371
|
+
textX_3 = drawX + 5;
|
|
372
|
+
}
|
|
373
|
+
else if (headerAlign === "right") {
|
|
374
|
+
ctx.textAlign = "right";
|
|
375
|
+
textX_3 = drawX + width - 5;
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
ctx.textAlign = "center";
|
|
379
|
+
textX_3 = drawX + width / 2;
|
|
380
|
+
}
|
|
313
381
|
// 根据 wrap 属性处理文本
|
|
314
382
|
if (column.wrap) {
|
|
315
383
|
// 换行显示(支持\n和自动换行)
|
|
316
384
|
var lines = wrapText(ctx, titleText, width - 10); // 左右各5px
|
|
317
|
-
var lineHeight_3 =
|
|
385
|
+
var lineHeight_3 = FONT_SIZE + 5; // 字体大小 + 行间距5px
|
|
318
386
|
var startY_3 = textY - ((lines.length - 1) * lineHeight_3) / 2;
|
|
319
387
|
lines.forEach(function (line, index) {
|
|
320
388
|
var lineY = startY_3 + index * lineHeight_3;
|
|
321
|
-
ctx.fillText(line,
|
|
389
|
+
ctx.fillText(line, textX_3, lineY);
|
|
322
390
|
});
|
|
323
391
|
}
|
|
324
392
|
else {
|
|
325
393
|
var truncated = truncateText(ctx, titleText, width - 10); // 左右各5px
|
|
326
|
-
ctx.fillText(truncated,
|
|
394
|
+
ctx.fillText(truncated, textX_3, textY);
|
|
327
395
|
}
|
|
328
396
|
}
|
|
329
397
|
// 绘制筛选图标(仅在最末级表头显示)
|
|
@@ -533,10 +601,30 @@ var useTableRender = function (params) {
|
|
|
533
601
|
}
|
|
534
602
|
// 单元格内容
|
|
535
603
|
if (column.key === "__selection__") {
|
|
536
|
-
|
|
537
|
-
var
|
|
538
|
-
|
|
539
|
-
|
|
604
|
+
// 检查是否是合计行
|
|
605
|
+
var isSummaryRow = record[IS_SUMMARY];
|
|
606
|
+
if (!isSummaryRow) {
|
|
607
|
+
// 非合计行显示选择框
|
|
608
|
+
var checkboxProps = ((_a = rowSelection === null || rowSelection === void 0 ? void 0 : rowSelection.getCheckboxProps) === null || _a === void 0 ? void 0 : _a.call(rowSelection, record)) || {};
|
|
609
|
+
var disabled = checkboxProps.disabled || false;
|
|
610
|
+
// 对于合并单元格,使用合并后的单元格高度进行垂直居中
|
|
611
|
+
drawCheckbox(ctx, drawX + width / 2, y + cellHeight / 2, isSelected, disabled, false);
|
|
612
|
+
}
|
|
613
|
+
else {
|
|
614
|
+
// 合计行选择框列显示文本(比如"合计")
|
|
615
|
+
var dataIndex = column.dataIndex || column.key;
|
|
616
|
+
var cellValue = record[dataIndex];
|
|
617
|
+
var cellText = formatCellValue(cellValue, column);
|
|
618
|
+
if (cellText) {
|
|
619
|
+
ctx.fillStyle = COLORS.text;
|
|
620
|
+
ctx.font = "bold ".concat(FONT_SIZE, "px ").concat(FONT_FAMILY);
|
|
621
|
+
ctx.textBaseline = "middle";
|
|
622
|
+
ctx.textAlign = "center";
|
|
623
|
+
var textX = drawX + width / 2;
|
|
624
|
+
var textY = y + cellHeight / 2;
|
|
625
|
+
ctx.fillText(cellText, textX, textY);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
540
628
|
}
|
|
541
629
|
else {
|
|
542
630
|
var dataIndex = column.dataIndex || column.key;
|
|
@@ -584,14 +672,14 @@ var useTableRender = function (params) {
|
|
|
584
672
|
: "".concat(FONT_WEIGHT, " ").concat(FONT_SIZE, "px ").concat(FONT_FAMILY);
|
|
585
673
|
ctx.textBaseline = "middle";
|
|
586
674
|
var align = column.align || "left";
|
|
587
|
-
var
|
|
675
|
+
var textX_4 = drawX + 5;
|
|
588
676
|
if (align === "center") {
|
|
589
677
|
ctx.textAlign = "center";
|
|
590
|
-
|
|
678
|
+
textX_4 = drawX + width / 2;
|
|
591
679
|
}
|
|
592
680
|
else if (align === "right") {
|
|
593
681
|
ctx.textAlign = "right";
|
|
594
|
-
|
|
682
|
+
textX_4 = drawX + width - 5;
|
|
595
683
|
}
|
|
596
684
|
else {
|
|
597
685
|
ctx.textAlign = "left";
|
|
@@ -601,9 +689,23 @@ var useTableRender = function (params) {
|
|
|
601
689
|
var ellipsis = column.ellipsis !== false; // 默认为true
|
|
602
690
|
var wrap = column.wrap === true; // 默认为false
|
|
603
691
|
if (wrap) {
|
|
604
|
-
//
|
|
605
|
-
var
|
|
606
|
-
var
|
|
692
|
+
// 换行显示,最多显示2行
|
|
693
|
+
var allLines = wrapText(ctx, cellText, maxWidth);
|
|
694
|
+
var maxLines = 2; // 限制最多显示2行
|
|
695
|
+
var lines = allLines.slice(0, maxLines);
|
|
696
|
+
// 如果超过2行,在第2行末尾强制添加省略号
|
|
697
|
+
if (allLines.length > maxLines && lines.length === maxLines) {
|
|
698
|
+
// 确保第2行有足够空间显示省略号
|
|
699
|
+
var lastLine = lines[maxLines - 1];
|
|
700
|
+
var ellipsisText = "...";
|
|
701
|
+
// 如果最后一行加上省略号会超出宽度,需要截断
|
|
702
|
+
while (lastLine.length > 0 &&
|
|
703
|
+
ctx.measureText(lastLine + ellipsisText).width > maxWidth) {
|
|
704
|
+
lastLine = lastLine.slice(0, -1);
|
|
705
|
+
}
|
|
706
|
+
lines[maxLines - 1] = lastLine + ellipsisText;
|
|
707
|
+
}
|
|
708
|
+
var lineHeight_4 = FONT_SIZE + 5; // 字体大小 + 行间距5px
|
|
607
709
|
var totalHeight = lines.length * lineHeight_4;
|
|
608
710
|
// 使用合并后的单元格高度计算垂直居中位置
|
|
609
711
|
var startY_4 = y + (cellHeight - totalHeight) / 2 + lineHeight_4 / 2;
|
|
@@ -611,7 +713,7 @@ var useTableRender = function (params) {
|
|
|
611
713
|
var lineY = startY_4 + lineIndex * lineHeight_4;
|
|
612
714
|
// 只绘制在单元格可见区域内的文本
|
|
613
715
|
if (lineY >= y && lineY <= y + cellHeight) {
|
|
614
|
-
ctx.fillText(line,
|
|
716
|
+
ctx.fillText(line, textX_4, lineY);
|
|
615
717
|
}
|
|
616
718
|
});
|
|
617
719
|
}
|
|
@@ -619,12 +721,12 @@ var useTableRender = function (params) {
|
|
|
619
721
|
// 省略显示 - 使用合并后的单元格高度
|
|
620
722
|
var textY = y + cellHeight / 2;
|
|
621
723
|
var truncatedText = truncateText(ctx, cellText, maxWidth);
|
|
622
|
-
ctx.fillText(truncatedText,
|
|
724
|
+
ctx.fillText(truncatedText, textX_4, textY);
|
|
623
725
|
}
|
|
624
726
|
else {
|
|
625
727
|
// 不处理,直接显示 - 使用合并后的单元格高度
|
|
626
728
|
var textY = y + cellHeight / 2;
|
|
627
|
-
ctx.fillText(cellText,
|
|
729
|
+
ctx.fillText(cellText, textX_4, textY);
|
|
628
730
|
}
|
|
629
731
|
if (column.badge && !isSummaryRow) {
|
|
630
732
|
var badgeProps = typeof column.badge === "function"
|
|
@@ -833,28 +935,30 @@ var useTableRender = function (params) {
|
|
|
833
935
|
ctx.fillRect(drawX, fixedY, actualWidth, rowHeight);
|
|
834
936
|
// 处理序号列
|
|
835
937
|
if (column.key === "__index__") {
|
|
836
|
-
//
|
|
837
|
-
if (rowType
|
|
938
|
+
// 非合计行显示序号
|
|
939
|
+
if (rowType !== "summary") {
|
|
940
|
+
var indexText = String(rowIndex + 1);
|
|
941
|
+
ctx.fillStyle = COLORS.text;
|
|
942
|
+
ctx.font = "".concat(FONT_WEIGHT, " ").concat(FONT_SIZE, "px ").concat(FONT_FAMILY);
|
|
943
|
+
ctx.textBaseline = "middle";
|
|
944
|
+
setTextAlign(ctx, "center");
|
|
945
|
+
var textX = drawX + actualWidth / 2;
|
|
946
|
+
var textY = fixedY + rowHeight / 2;
|
|
947
|
+
ctx.fillText(indexText, textX, textY);
|
|
838
948
|
return;
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
ctx.font = "".concat(FONT_WEIGHT, " ").concat(FONT_SIZE, "px ").concat(FONT_FAMILY);
|
|
842
|
-
ctx.textBaseline = "middle";
|
|
843
|
-
setTextAlign(ctx, "center");
|
|
844
|
-
var textX = drawX + actualWidth / 2;
|
|
845
|
-
var textY = fixedY + rowHeight / 2;
|
|
846
|
-
ctx.fillText(indexText, textX, textY);
|
|
847
|
-
return;
|
|
949
|
+
}
|
|
950
|
+
// 合计行序号列继续执行后面的逻辑,可能显示"合计"文字
|
|
848
951
|
}
|
|
849
952
|
// 处理选择框列
|
|
850
953
|
if (column.key === "__selection__") {
|
|
851
|
-
//
|
|
852
|
-
if (rowType
|
|
954
|
+
// 非合计行显示选择框
|
|
955
|
+
if (rowType !== "summary") {
|
|
956
|
+
var checkboxX = drawX + actualWidth / 2;
|
|
957
|
+
var textY = fixedY + rowHeight / 2;
|
|
958
|
+
drawCheckbox(ctx, checkboxX, textY, isSelected, false, false);
|
|
853
959
|
return;
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
drawCheckbox(ctx, checkboxX, textY, isSelected, false, false);
|
|
857
|
-
return;
|
|
960
|
+
}
|
|
961
|
+
// 合计行选择框列继续执行后面的逻辑,可能显示"合计"文字
|
|
858
962
|
}
|
|
859
963
|
// 获取单元格值
|
|
860
964
|
var dataIndex = column.dataIndex || column.key;
|
|
@@ -36,6 +36,10 @@ interface ICanvasColumnType<RecordType = any> {
|
|
|
36
36
|
* 对齐方式
|
|
37
37
|
*/
|
|
38
38
|
align?: "left" | "center" | "right";
|
|
39
|
+
/**
|
|
40
|
+
* 表头对齐方式(如果不设置,使用全局 headerAlign 或 align)
|
|
41
|
+
*/
|
|
42
|
+
headerAlign?: "left" | "center" | "right";
|
|
39
43
|
/**
|
|
40
44
|
* 是否固定列
|
|
41
45
|
*/
|
|
@@ -249,6 +253,10 @@ interface ICanvasTableProps<RecordType = any> {
|
|
|
249
253
|
* 表头换行
|
|
250
254
|
*/
|
|
251
255
|
headerWrap?: boolean;
|
|
256
|
+
/**
|
|
257
|
+
* 表头对齐方式(默认居中)
|
|
258
|
+
*/
|
|
259
|
+
headerAlign?: "left" | "center" | "right";
|
|
252
260
|
/**
|
|
253
261
|
* 勾选配置
|
|
254
262
|
*/
|
|
@@ -394,6 +402,86 @@ interface ICanvasTableProps<RecordType = any> {
|
|
|
394
402
|
* 表格id(用于自动高度计算时定位元素)
|
|
395
403
|
*/
|
|
396
404
|
canvasTableId?: string;
|
|
405
|
+
/**
|
|
406
|
+
* 表格ref句柄,用于暴露表格的一些方法
|
|
407
|
+
*/
|
|
408
|
+
tableRefHandle?: React__default.Ref<ICanvasTableRefHandle>;
|
|
409
|
+
/**
|
|
410
|
+
* 导出excel的一些配置
|
|
411
|
+
*/
|
|
412
|
+
exportExcelConfig?: {
|
|
413
|
+
topDescription?: string;
|
|
414
|
+
time?: string;
|
|
415
|
+
topDescriptionRowHeight?: number;
|
|
416
|
+
fileName: string;
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* CanvasTable 暴露的方法
|
|
421
|
+
*/
|
|
422
|
+
interface ICanvasTableRefHandle {
|
|
423
|
+
/**
|
|
424
|
+
* 获取当前表格的配置信息(动态列配置)
|
|
425
|
+
*/
|
|
426
|
+
getDynamicList: () => any[];
|
|
427
|
+
/**
|
|
428
|
+
* 动态列配置重置
|
|
429
|
+
*/
|
|
430
|
+
onResetDynamicList: () => void;
|
|
431
|
+
/**
|
|
432
|
+
* 动态列配置设置
|
|
433
|
+
*/
|
|
434
|
+
onSetDynamicList: (list: any[]) => void;
|
|
435
|
+
/**
|
|
436
|
+
* 导出Excel
|
|
437
|
+
*/
|
|
438
|
+
exportExcel?: (fileName: string, config?: {
|
|
439
|
+
topDescription?: string;
|
|
440
|
+
time?: string;
|
|
441
|
+
topDescriptionRowHeight?: number;
|
|
442
|
+
}) => void;
|
|
443
|
+
/**
|
|
444
|
+
* 获取表格容器
|
|
445
|
+
*/
|
|
446
|
+
getContainer: () => HTMLDivElement | null;
|
|
447
|
+
/**
|
|
448
|
+
* 全屏展示表格
|
|
449
|
+
*/
|
|
450
|
+
toggleFullScreen: () => void;
|
|
451
|
+
/**
|
|
452
|
+
* 获取选中的行keys
|
|
453
|
+
*/
|
|
454
|
+
getSelectedRowKeys: () => React__default.Key[];
|
|
455
|
+
/**
|
|
456
|
+
* 设置选中的行keys
|
|
457
|
+
*/
|
|
458
|
+
setSelectedRowKeys: (keys: React__default.Key[]) => void;
|
|
459
|
+
/**
|
|
460
|
+
* 滚动到指定位置
|
|
461
|
+
*/
|
|
462
|
+
scrollTo: (params: {
|
|
463
|
+
x?: number;
|
|
464
|
+
y?: number;
|
|
465
|
+
}) => void;
|
|
466
|
+
/**
|
|
467
|
+
* 获取当前排序状态
|
|
468
|
+
*/
|
|
469
|
+
getSortState: () => {
|
|
470
|
+
field: string | null;
|
|
471
|
+
order: SortOrder;
|
|
472
|
+
};
|
|
473
|
+
/**
|
|
474
|
+
* 获取当前过滤状态
|
|
475
|
+
*/
|
|
476
|
+
getFilterState: () => Record<string, any[]>;
|
|
477
|
+
/**
|
|
478
|
+
* 清除排序
|
|
479
|
+
*/
|
|
480
|
+
clearSort: () => void;
|
|
481
|
+
/**
|
|
482
|
+
* 清除过滤
|
|
483
|
+
*/
|
|
484
|
+
clearFilter: () => void;
|
|
397
485
|
}
|
|
398
486
|
|
|
399
|
-
export { ColumnDataType, FilterConfig, IBadgeProps, ICanvasColumnType, ICanvasColumnsType, ICanvasRowSelection, ICanvasTableProps, SortOrder };
|
|
487
|
+
export { ColumnDataType, FilterConfig, IBadgeProps, ICanvasColumnType, ICanvasColumnsType, ICanvasRowSelection, ICanvasTableProps, ICanvasTableRefHandle, SortOrder };
|
|
@@ -24,13 +24,17 @@ var findColumnByKey = function (columns, key) {
|
|
|
24
24
|
/**
|
|
25
25
|
* 递归处理列的render函数(转换为统一的调用格式)
|
|
26
26
|
*/
|
|
27
|
-
var processColumnRender = function (column, renderMode, headerWrap) {
|
|
27
|
+
var processColumnRender = function (column, renderMode, headerWrap, headerAlign) {
|
|
28
28
|
if (renderMode === void 0) { renderMode = "object"; }
|
|
29
29
|
var processedColumn = __assign({}, column);
|
|
30
30
|
if (headerWrap) {
|
|
31
31
|
processedColumn.wrap =
|
|
32
32
|
processedColumn.wrap === undefined ? headerWrap : processedColumn.wrap;
|
|
33
33
|
}
|
|
34
|
+
// 应用表头对齐方式(仅当列没有设置 headerAlign 或 align 时)
|
|
35
|
+
if (headerAlign && !processedColumn.headerAlign && !processedColumn.align) {
|
|
36
|
+
processedColumn.headerAlign = headerAlign;
|
|
37
|
+
}
|
|
34
38
|
// 处理当前列的render函数
|
|
35
39
|
if (column.render) {
|
|
36
40
|
var render_1 = column.render;
|
|
@@ -44,7 +48,7 @@ var processColumnRender = function (column, renderMode, headerWrap) {
|
|
|
44
48
|
// 递归处理children
|
|
45
49
|
if (column.children && Array.isArray(column.children)) {
|
|
46
50
|
processedColumn.children = column.children.map(function (child) {
|
|
47
|
-
return processColumnRender(child, renderMode, headerWrap);
|
|
51
|
+
return processColumnRender(child, renderMode, headerWrap, headerAlign);
|
|
48
52
|
});
|
|
49
53
|
}
|
|
50
54
|
return processedColumn;
|
|
@@ -38,6 +38,13 @@ var FONT_SIZE = 13;
|
|
|
38
38
|
var FONT_WEIGHT = "400"; // 正常字重,避免过细导致不清晰
|
|
39
39
|
// 图标尺寸
|
|
40
40
|
var CHECKBOX_SIZE = 16;
|
|
41
|
-
var SORT_ICON_SIZE = 6;
|
|
41
|
+
var SORT_ICON_SIZE = 6;
|
|
42
|
+
var SORT_ICON_WIDTH = 15; // 排序图标宽度(用于表头宽度计算)
|
|
43
|
+
var FILTER_ICON_WIDTH = 15; // 筛选图标宽度(用于表头宽度计算)
|
|
44
|
+
// 间距和内边距
|
|
45
|
+
var ICON_SPACING = 4; // 图标之间的间距
|
|
46
|
+
var TEXT_PADDING = 5; // 文本内边距
|
|
47
|
+
// 行高计算
|
|
48
|
+
var LINE_HEIGHT = FONT_SIZE + 5; // 字体大小 + 行间距5px
|
|
42
49
|
|
|
43
|
-
export { CHECKBOX_SIZE, COLORS, DEFAULT_COLUMN_WIDTH, DEFAULT_SELECTION_COLUMN_WIDTH, FONT_FAMILY, FONT_SIZE, FONT_WEIGHT, MIN_SCROLLBAR_SIZE, SCROLLBAR_PADDING, SCROLLBAR_SIZE, SORT_ICON_SIZE };
|
|
50
|
+
export { CHECKBOX_SIZE, COLORS, DEFAULT_COLUMN_WIDTH, DEFAULT_SELECTION_COLUMN_WIDTH, FILTER_ICON_WIDTH, FONT_FAMILY, FONT_SIZE, FONT_WEIGHT, ICON_SPACING, LINE_HEIGHT, MIN_SCROLLBAR_SIZE, SCROLLBAR_PADDING, SCROLLBAR_SIZE, SORT_ICON_SIZE, SORT_ICON_WIDTH, TEXT_PADDING };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { FONT_SIZE, FONT_FAMILY, TEXT_PADDING, LINE_HEIGHT, FILTER_ICON_WIDTH, SORT_ICON_WIDTH, ICON_SPACING } from './constants.js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* 多级表头工具函数
|
|
3
5
|
*/
|
|
@@ -96,13 +98,6 @@ function calculateLayerHeights(columns, baseHeaderHeight, columnRenderInfos) {
|
|
|
96
98
|
}
|
|
97
99
|
var flattenedHeaderRows = flattenHeaders(columns);
|
|
98
100
|
var leafColumns = getLeafColumns(columns);
|
|
99
|
-
var FONT_SIZE = 13;
|
|
100
|
-
var FONT_FAMILY = '"Microsoft YaHei", 微软雅黑, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
101
|
-
var LINE_HEIGHT = 20;
|
|
102
|
-
var FILTER_ICON_WIDTH = 15;
|
|
103
|
-
var SORT_ICON_WIDTH = 15;
|
|
104
|
-
var ICON_SPACING = 4;
|
|
105
|
-
var TEXT_PADDING = 5;
|
|
106
101
|
// 创建临时canvas用于测量文本
|
|
107
102
|
var tempCanvas = document.createElement("canvas");
|
|
108
103
|
var ctx = tempCanvas.getContext("2d");
|
|
@@ -187,9 +182,10 @@ function calculateLayerHeights(columns, baseHeaderHeight, columnRenderInfos) {
|
|
|
187
182
|
}
|
|
188
183
|
maxLines = Math.max(maxLines, totalLines);
|
|
189
184
|
});
|
|
190
|
-
//
|
|
185
|
+
// 当有换行时:上边距(5px) + 行数 * 行高 + 下边距(5px)
|
|
186
|
+
// 当没有换行时:使用原始的 baseHeaderHeight
|
|
191
187
|
var layerHeight = maxLines > 1
|
|
192
|
-
?
|
|
188
|
+
? 10 + maxLines * LINE_HEIGHT // 上下边距各5px,共10px
|
|
193
189
|
: baseHeaderHeight;
|
|
194
190
|
layerHeights.push(layerHeight);
|
|
195
191
|
});
|
|
@@ -9,8 +9,9 @@ import { getLeafColumns } from './multiHeaderHelpers.js';
|
|
|
9
9
|
* 注意:多级表头时,只处理叶子列(用于渲染数据)
|
|
10
10
|
* @param columns 列配置
|
|
11
11
|
* @param containerWidth 容器宽度(可选),如果提供且总宽度小于容器宽度,会自动填充
|
|
12
|
+
* @param manuallyResizedColumns 用户手动调整过宽度的列的key集合(可选),这些列不参与自动宽度分配
|
|
12
13
|
*/
|
|
13
|
-
var calculateColumnRenderInfos = function (columns, containerWidth) {
|
|
14
|
+
var calculateColumnRenderInfos = function (columns, containerWidth, manuallyResizedColumns) {
|
|
14
15
|
// 获取叶子列(多级表头时只有叶子列才渲染数据)
|
|
15
16
|
var leafColumns = getLeafColumns(columns);
|
|
16
17
|
// 第一次计算:使用原始宽度
|
|
@@ -27,13 +28,21 @@ var calculateColumnRenderInfos = function (columns, containerWidth) {
|
|
|
27
28
|
totalWidth += columnWidth;
|
|
28
29
|
});
|
|
29
30
|
// 如果提供了容器宽度且总宽度小于容器宽度,将剩余宽度平分到各列
|
|
30
|
-
//
|
|
31
|
+
// 注意:序号列、勾选框列、手动调整过的列除外,保持原宽度
|
|
31
32
|
if (containerWidth && totalWidth < containerWidth) {
|
|
32
33
|
var remainingWidth = containerWidth - totalWidth;
|
|
33
|
-
//
|
|
34
|
+
// 统计需要平分宽度的列(排除序号列、勾选框列和手动调整过的列)
|
|
34
35
|
var columnsToExpand = tempInfos.filter(function (info) {
|
|
35
36
|
var key = info.column.key;
|
|
36
|
-
|
|
37
|
+
// 排除序号列和勾选框列
|
|
38
|
+
if (key === "__index__" || key === "__selection__") {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
// 排除用户手动调整过宽度的列
|
|
42
|
+
if (manuallyResizedColumns && manuallyResizedColumns.has(key)) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
37
46
|
});
|
|
38
47
|
if (columnsToExpand.length > 0) {
|
|
39
48
|
var additionalWidthPerColumn_1 = remainingWidth / columnsToExpand.length;
|
package/dist/index.build.d.ts
CHANGED
|
@@ -49,7 +49,7 @@ export { default as Sortable } from './es/sortable/sortable.js';
|
|
|
49
49
|
export { default as ElectronSignatures } from './es/electronsignatures/index.js';
|
|
50
50
|
export { default as message } from './es/message/index.js';
|
|
51
51
|
export { default as CanvasTable } from './es/canvastable/canvasTable.js';
|
|
52
|
-
export { ICanvasColumnType, ICanvasColumnsType, ICanvasTableProps } from './es/canvastable/interface.js';
|
|
52
|
+
export { ICanvasColumnType, ICanvasColumnsType, ICanvasTableProps, ICanvasTableRefHandle } from './es/canvastable/interface.js';
|
|
53
53
|
export { Affix, Anchor, AutoComplete, Avatar, BackTop, Badge, Breadcrumb, Card, Carousel, Cascader, Checkbox, Col, Comment, ConfigProvider, Divider, Drawer, Dropdown, Empty, Grid, Image, Layout, List, Mentions, Menu, PageHeader, Popconfirm, Popover, Progress, Radio, Rate, Result, Row, Segmented, Skeleton, Slider, Space, Spin, Statistic, Steps, Switch, Timeline, Tooltip, Transfer, Typography, Upload, notification } from 'antd';
|
|
54
54
|
export { IButtonProps } from './es/button/interface.js';
|
|
55
55
|
export { IButtonDownloadProps } from './es/button/buttonDownload.js';
|