diff --git a/common/changes/@visactor/vtable/fix-custom-merge-select_2024-05-21-12-09.json b/common/changes/@visactor/vtable/fix-custom-merge-select_2024-05-21-12-09.json new file mode 100644 index 000000000..2f311ac2a --- /dev/null +++ b/common/changes/@visactor/vtable/fix-custom-merge-select_2024-05-21-12-09.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vtable", + "comment": "fix: fix custom merge cell display problem when select header", + "type": "none" + } + ], + "packageName": "@visactor/vtable" +} \ No newline at end of file diff --git a/packages/vtable/src/scenegraph/layout/frozen.ts b/packages/vtable/src/scenegraph/layout/frozen.ts index e6124c84a..62dd6b7e1 100644 --- a/packages/vtable/src/scenegraph/layout/frozen.ts +++ b/packages/vtable/src/scenegraph/layout/frozen.ts @@ -66,7 +66,7 @@ export function resetFrozen(scene: Scenegraph) { scene.deleteAllSelectBorder(); scene.table.stateManager.select.ranges.forEach(range => { - scene.updateCellSelectBorder(range.start.col, range.start.row, range.end.col, range.end.row); + scene.updateCellSelectBorder(range); }); // scene.frozenColCount = scene.rowHeaderGroup.childrenCount; diff --git a/packages/vtable/src/scenegraph/scenegraph.ts b/packages/vtable/src/scenegraph/scenegraph.ts index c3dbd6624..7fec67657 100644 --- a/packages/vtable/src/scenegraph/scenegraph.ts +++ b/packages/vtable/src/scenegraph/scenegraph.ts @@ -689,14 +689,8 @@ export class Scenegraph { deleteAllSelectBorder(this); } - updateCellSelectBorder( - newStartCol: number, - newStartRow: number, - newEndCol: number, - newEndRow: number, - extendSelectRange: boolean = true - ) { - updateCellSelectBorder(this, newStartCol, newStartRow, newEndCol, newEndRow, extendSelectRange); + updateCellSelectBorder(selectRange: CellRange & { skipBodyMerge?: boolean }, extendSelectRange: boolean = true) { + updateCellSelectBorder(this, selectRange, extendSelectRange); } removeFillHandleFromSelectComponents() { @@ -706,7 +700,7 @@ export class Scenegraph { recreateAllSelectRangeComponents() { deleteAllSelectBorder(this); this.table.stateManager.select.ranges.forEach((cellRange: CellRange) => { - updateCellSelectBorder(this, cellRange.start.col, cellRange.start.row, cellRange.end.col, cellRange.end.row); + updateCellSelectBorder(this, cellRange); }); moveSelectingRangeComponentsToSelectedRangeComponents(this); } diff --git a/packages/vtable/src/scenegraph/select/update-select-border.ts b/packages/vtable/src/scenegraph/select/update-select-border.ts index c5a54fb9b..e27992e3b 100644 --- a/packages/vtable/src/scenegraph/select/update-select-border.ts +++ b/packages/vtable/src/scenegraph/select/update-select-border.ts @@ -1,6 +1,6 @@ import type { IRect } from '@src/vrender'; import type { Scenegraph } from '../scenegraph'; -import type { CellSubLocation } from '../../ts-types'; +import type { CellRange, CellSubLocation } from '../../ts-types'; import { getCellMergeInfo } from '../utils/get-cell-merge'; export function updateAllSelectComponent(scene: Scenegraph) { @@ -318,12 +318,15 @@ function updateComponent( export function updateCellSelectBorder( scene: Scenegraph, - newStartCol: number, - newStartRow: number, - newEndCol: number, - newEndRow: number, + selectRange: CellRange & { skipBodyMerge?: boolean }, ifExtendSelectRange: boolean = true ) { + const newStartCol = selectRange.start.col; + const newStartRow = selectRange.start.row; + const newEndCol = selectRange.end.col; + const newEndRow = selectRange.end.row; + const skipBodyMerge = selectRange.skipBodyMerge; + let startCol = Math.max(Math.min(newEndCol, newStartCol), 0); let startRow = Math.max(Math.min(newEndRow, newStartRow), 0); let endCol = Math.min(Math.max(newEndCol, newStartCol), scene.table.colCount - 1); @@ -334,6 +337,9 @@ export function updateCellSelectBorder( for (let col = startCol; col <= endCol; col++) { if (col === startCol) { for (let row = startRow; row <= endRow; row++) { + if (!scene.table.isHeader(col, row) && skipBodyMerge) { + continue; + } const mergeInfo = getCellMergeInfo(scene.table, col, row); if (mergeInfo && mergeInfo.start.col < startCol) { startCol = mergeInfo.start.col; @@ -344,6 +350,9 @@ export function updateCellSelectBorder( } if (!isExtend && col === endCol) { for (let row = startRow; row <= endRow; row++) { + if (!scene.table.isHeader(col, row) && skipBodyMerge) { + continue; + } const mergeInfo = getCellMergeInfo(scene.table, col, row); if (mergeInfo && Math.min(mergeInfo.end.col, scene.table.colCount - 1) > endCol) { endCol = mergeInfo.end.col; @@ -361,6 +370,9 @@ export function updateCellSelectBorder( for (let row = startRow; row <= endRow; row++) { if (row === startRow) { for (let col = startCol; col <= endCol; col++) { + if (!scene.table.isHeader(col, row) && skipBodyMerge) { + continue; + } const mergeInfo = getCellMergeInfo(scene.table, col, row); if (mergeInfo && mergeInfo.start.row < startRow) { startRow = mergeInfo.start.row; @@ -371,6 +383,9 @@ export function updateCellSelectBorder( } if (!isExtend && row === endRow) { for (let col = startCol; col <= endCol; col++) { + if (!scene.table.isHeader(col, row) && skipBodyMerge) { + continue; + } const mergeInfo = getCellMergeInfo(scene.table, col, row); if (mergeInfo && Math.min(mergeInfo.end.row, scene.table.rowCount - 1) > endRow) { endRow = mergeInfo.end.row; diff --git a/packages/vtable/src/state/select/update-position.ts b/packages/vtable/src/state/select/update-position.ts index afd54a5d2..33117bdcc 100644 --- a/packages/vtable/src/state/select/update-position.ts +++ b/packages/vtable/src/state/select/update-position.ts @@ -21,6 +21,7 @@ export function updateSelectPosition( const { table, interactionState } = state; const { scenegraph } = table; const { highlightScope, disableHeader, cellPos } = state.select; + if ((disableHeader && table.isHeader(col, row)) || highlightScope === 'none') { col = -1; row = -1; @@ -61,13 +62,7 @@ export function updateSelectPosition( end: { col: table.colCount - 1, row: table.rowCount - 1 } }); const currentRange = state.select.ranges[state.select.ranges.length - 1]; - scenegraph.updateCellSelectBorder( - currentRange.start.col, - currentRange.start.row, - currentRange.end.col, - currentRange.end.row, - false - ); + scenegraph.updateCellSelectBorder(currentRange, false); } else if (cellPos.col !== -1 && cellPos.row !== -1 && (col === -1 || row === -1)) { // 输入-1清空选中状态 // clearMultiSelect(scenegraph, ranges, highlightScope, singleStyle); @@ -102,12 +97,7 @@ export function updateSelectPosition( currentRange.end = { col, row }; } scenegraph.deleteLastSelectedRangeComponents(); - scenegraph.updateCellSelectBorder( - currentRange.start.col, - currentRange.start.row, - currentRange.end.col, - currentRange.end.row - ); + scenegraph.updateCellSelectBorder(currentRange); // } else if (isCtrl) { // cellPos.col = col; // cellPos.row = row; @@ -121,7 +111,7 @@ export function updateSelectPosition( // // 更新select border // // calculateAndUpdateMultiSelectBorder(scenegraph, col, row, col, row, state.select.ranges); // // 更新select border - // scenegraph.updateCellSelectBorder(cellPos.col, cellPos.row, cellPos.col, cellPos.row); + // scenegraph.updateCellSelectBorder(cellPos); } else { let extendSelectRange = true; // 单选或多选开始 @@ -130,30 +120,39 @@ export function updateSelectPosition( scenegraph.deleteAllSelectBorder(); } if (state.select.headerSelectMode !== 'cell' && table.isColumnHeader(col, row)) { + // 选中行表头 const cellRange = table.getCellRange(col, row); state.select.ranges.push({ start: { col: cellRange.start.col, row }, - end: { col: cellRange.end.col, row: table.rowCount - 1 } + end: { col: cellRange.end.col, row: table.rowCount - 1 }, + skipBodyMerge: true }); } else if (state.select.headerSelectMode !== 'cell' && table.isRowHeader(col, row)) { + // 选中列表头 const cellRange = table.getCellRange(col, row); state.select.ranges.push({ start: { col, row: cellRange.start.row }, - end: { col: table.colCount - 1, row: cellRange.end.row } + end: { col: table.colCount - 1, row: cellRange.end.row }, + skipBodyMerge: true }); } else if ((table.internalProps.layoutMap as SimpleHeaderLayoutMap).isSeriesNumberInHeader(col, row)) { + // 选中表头行号单元格 extendSelectRange = false; state.select.ranges.push({ start: { col: 0, row: 0 }, - end: { col: table.colCount - 1, row: table.rowCount - 1 } + end: { col: table.colCount - 1, row: table.rowCount - 1 }, + skipBodyMerge: true }); } else if ((table.internalProps.layoutMap as SimpleHeaderLayoutMap).isSeriesNumberInBody(col, row)) { + // 选中内容行号单元格 extendSelectRange = false; state.select.ranges.push({ start: { col, row: row }, - end: { col: table.colCount - 1, row: row } + end: { col: table.colCount - 1, row: row }, + skipBodyMerge: true }); } else if (col >= 0 && row >= 0) { + // 选中普通单元格 const cellRange = table.getCellRange(col, row); state.select.ranges.push({ start: { col: cellRange.start.col, row: cellRange.start.row }, @@ -164,14 +163,7 @@ export function updateSelectPosition( cellPos.row = row; // scenegraph.setCellNormalStyle(col, row); const currentRange = state.select.ranges?.[state.select.ranges.length - 1]; - currentRange && - scenegraph.updateCellSelectBorder( - currentRange.start.col, - currentRange.start.row, - currentRange.end.col, - currentRange.end.row, - extendSelectRange - ); + currentRange && scenegraph.updateCellSelectBorder(currentRange, extendSelectRange); } } else if ( (interactionState === InteractionState.grabing || table.eventManager.isDraging) && @@ -264,13 +256,7 @@ export function updateSelectPosition( }; } } - scenegraph.updateCellSelectBorder( - currentRange.start.col, - currentRange.start.row, - currentRange.end.col, - currentRange.end.row, - extendSelectRange - ); + scenegraph.updateCellSelectBorder(currentRange, extendSelectRange); } } scenegraph.updateNextFrame(); diff --git a/packages/vtable/src/state/state.ts b/packages/vtable/src/state/state.ts index 2495efdc6..234f28fd7 100644 --- a/packages/vtable/src/state/state.ts +++ b/packages/vtable/src/state/state.ts @@ -63,7 +63,7 @@ export class StateManager { interactionState: InteractionState; // select记录两个位置,第二个位置只在range模式生效 select: { - ranges: CellRange[]; + ranges: (CellRange & { skipBodyMerge?: boolean })[]; highlightScope: HighlightScope; cellPos: CellPosition; // cellPosStart: CellPosition;