diff --git a/common/changes/@visactor/vtable/fix-issue-5137-regression_2026-06-11-07-35.json b/common/changes/@visactor/vtable/fix-issue-5137-regression_2026-06-11-07-35.json new file mode 100644 index 000000000..a250ad7b9 --- /dev/null +++ b/common/changes/@visactor/vtable/fix-issue-5137-regression_2026-06-11-07-35.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: resolve regression from #5137 fix which broke nested header drag and exposed internal state\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file diff --git a/packages/vtable-plugins/__tests__/add-row-column-plugin.test.ts b/packages/vtable-plugins/__tests__/add-row-column-plugin.test.ts index 68dbcc748..9d9b2731b 100644 --- a/packages/vtable-plugins/__tests__/add-row-column-plugin.test.ts +++ b/packages/vtable-plugins/__tests__/add-row-column-plugin.test.ts @@ -1,6 +1,6 @@ // @ts-nocheck import { ListTable } from '@visactor/vtable'; -import { AddRowColumnPlugin } from '../src'; +import { AddRowColumnPlugin } from '../src/add-row-column'; import { createDiv } from '../../vtable/__tests__/dom'; global.__VERSION__ = 'none'; diff --git a/packages/vtable-plugins/jest.config.js b/packages/vtable-plugins/jest.config.js index 40c71a2d4..e3fb8ebf8 100644 --- a/packages/vtable-plugins/jest.config.js +++ b/packages/vtable-plugins/jest.config.js @@ -1,9 +1,14 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires +const path = require('path'); + const isCI = process.env.CI === 'true' || process.env.CI === '1'; module.exports = { preset: 'ts-jest', - testEnvironment: 'jsdom', - testMatch: ['/__tests__/**/*.test.(ts|js)'], + runner: 'jest-electron/runner', + testEnvironment: 'jest-electron/environment', + testRegex: '/__tests__(/.*)+\\.test\\.(js|ts)$', + testPathIgnorePatterns: ['/node_modules/', '/cjs/', '/es/', '/\\.rollup\\.cache/'], silent: false, verbose: true, globals: { @@ -13,16 +18,18 @@ module.exports = { }, tsconfig: { resolveJsonModule: true, - esModuleInterop: true + esModuleInterop: true, + paths: { + '@src/vrender': ['../vtable/src/vrender.ts'], + '@src/*': ['../vtable/src/*'] + } } }, __DEV__: true }, collectCoverage: true, coverageReporters: ['json-summary', 'lcov', 'text'], - collectCoverageFrom: [ - '/src/history/**/*.ts' - ], + collectCoverageFrom: ['/src/history/**/*.ts'], coverageThreshold: isCI ? { global: { @@ -33,6 +40,30 @@ module.exports = { } } : undefined, - moduleNameMapper: {}, + moduleNameMapper: { + 'd3-array': path.resolve( + __dirname, + '../../common/temp/node_modules/.pnpm/d3-array@3.2.3/node_modules/d3-array/dist/d3-array.min.js' + ), + 'd3-geo': path.resolve( + __dirname, + '../../common/temp/node_modules/.pnpm/d3-geo@1.12.1/node_modules/d3-geo/dist/d3-geo.min.js' + ), + 'd3-dsv': path.resolve( + __dirname, + '../../common/temp/node_modules/.pnpm/d3-dsv@3.0.1/node_modules/d3-dsv/dist/d3-dsv.min.js' + ), + 'd3-hexbin': path.resolve( + __dirname, + '../../common/temp/node_modules/.pnpm/d3-hexbin@0.2.2/node_modules/d3-hexbin/build/d3-hexbin.min.js' + ), + 'd3-hierarchy': path.resolve( + __dirname, + '../../common/temp/node_modules/.pnpm/d3-hierarchy@3.1.2/node_modules/d3-hierarchy/dist/d3-hierarchy.min.js' + ), + '^@visactor/vtable/es/(.*)$': '/../vtable/src/$1', + '@visactor/vtable': path.resolve(__dirname, '../vtable/src/index.ts'), + '@src/vrender': path.resolve(__dirname, '../vtable/src/vrender.ts') + }, setupFiles: ['./setup-mock.js'] }; diff --git a/packages/vtable-plugins/src/global.d.ts b/packages/vtable-plugins/src/global.d.ts new file mode 100644 index 000000000..fd30a9e5c --- /dev/null +++ b/packages/vtable-plugins/src/global.d.ts @@ -0,0 +1,2 @@ +declare const __DEV__: boolean; +declare const __VERSION__: string; diff --git a/packages/vtable/__tests__/options/listTable-api-with-frozen.test.ts b/packages/vtable/__tests__/options/listTable-api-with-frozen.test.ts index 7d6d6073a..eb9077cf5 100644 --- a/packages/vtable/__tests__/options/listTable-api-with-frozen.test.ts +++ b/packages/vtable/__tests__/options/listTable-api-with-frozen.test.ts @@ -135,11 +135,11 @@ describe('listTable init test', () => { expect(frozenTable.getBodyVisibleRowRange()).toEqual({ rowStart: 10, - rowEnd: 28 + rowEnd: 29 }); expect(frozenTable.getBodyVisibleCellRange()).toMatchObject({ rowStart: 10, - rowEnd: 28 + rowEnd: 29 }); }); }); diff --git a/packages/vtable/src/ListTable.ts b/packages/vtable/src/ListTable.ts index 47e7c0d69..070c74ee6 100644 --- a/packages/vtable/src/ListTable.ts +++ b/packages/vtable/src/ListTable.ts @@ -1062,17 +1062,21 @@ export class ListTable extends BaseTable implements ListTableAPI { return null; } private syncColumnsStateFromLayoutMap() { - const visibleColumns = this.internalProps.layoutMap.columnObjects.map(column => column.define); - let visibleIndex = 0; - const nextColumns = this.internalProps.columns.map(column => { - if (column.hide === true) { - return column; - } - const nextVisibleColumn = visibleColumns[visibleIndex]; - visibleIndex += 1; - return nextVisibleColumn ?? column; - }); - this.internalProps.columns = cloneDeepSpec(nextColumns, ['children']); + const nextColumns = cloneDeepSpec(this.internalProps.columns, ['children']); + const cleanColumns = (columns: any[]) => { + columns.forEach(col => { + delete col.level; + delete col.size; + delete col.startInTotal; + delete col.startIndex; + delete col.id; + delete col.hierarchyState; + if (col.columns) { + cleanColumns(col.columns); + } + }); + }; + cleanColumns(nextColumns); this.options.columns = nextColumns; if (this.options.header) { this.options.header = nextColumns; diff --git a/packages/vtable/src/layout/simple-header-layout.ts b/packages/vtable/src/layout/simple-header-layout.ts index a175d9b5e..6fc891809 100644 --- a/packages/vtable/src/layout/simple-header-layout.ts +++ b/packages/vtable/src/layout/simple-header-layout.ts @@ -1311,10 +1311,16 @@ export class SimpleHeaderLayoutMap implements LayoutMapAPI { } //#endregion // #region 将_columns的列定义调整位置 同调整_headerCellIds逻辑 - const sourceColumns = this._columns.splice( - sourceCellRange.start.col - this.leftRowSeriesNumberColumnCount, - sourceSize - ); + const sourceColIndex = sourceCellRange.start.col - this.leftRowSeriesNumberColumnCount; + const targetColIndex = + target.col >= source.col + ? targetCellRange.end.col - this.leftRowSeriesNumberColumnCount + : targetCellRange.start.col - this.leftRowSeriesNumberColumnCount; + + const sourceTotalIndex = (this._columns[sourceColIndex]?.define as any)?.startInTotal ?? sourceColIndex; + const targetTotalIndex = (this._columns[targetColIndex]?.define as any)?.startInTotal ?? targetColIndex; + + const sourceColumns = this._columns.splice(sourceColIndex, sourceSize); sourceColumns.unshift((targetIndex - this.leftRowSeriesNumberColumnCount) as any, 0 as any); Array.prototype.splice.apply(this._columns, sourceColumns); //#region 设置了maintainArrayDataOrder 需要调整columnTree中的field值 @@ -1327,11 +1333,7 @@ export class SimpleHeaderLayoutMap implements LayoutMapAPI { //#endregion //#endregion // #region 对表头columnTree调整节点位置 - this.columnTree.movePosition( - sourceCellRange.start.row, - sourceCellRange.start.col - this.leftRowSeriesNumberColumnCount, - targetIndex - this.leftRowSeriesNumberColumnCount - ); + this.columnTree.movePosition(sourceCellRange.start.row, sourceTotalIndex, targetTotalIndex); //#region 设置了maintainArrayDataOrder 需要调整columnTree中的field值 if (this._table.options.dragOrder?.maintainArrayDataOrder) { //重新整理column中的field值 @@ -1381,15 +1383,21 @@ export class SimpleHeaderLayoutMap implements LayoutMapAPI { Array.prototype.splice.apply(this._headerCellIds[row], sourceIds); } //将_columns的列定义调整位置 同调整_headerCellIds逻辑 - const sourceColumns = this._columns.splice(sourceCellRange.start.row, sourceSize); + const sourceRowIndex = sourceCellRange.start.row; + const targetRowIndex = target.row >= source.row ? targetCellRange.end.row : targetCellRange.start.row; + + const sourceTotalIndex = (this._columns[sourceRowIndex]?.define as any)?.startInTotal ?? sourceRowIndex; + const targetTotalIndex = (this._columns[targetRowIndex]?.define as any)?.startInTotal ?? targetRowIndex; + + const sourceColumns = this._columns.splice(sourceRowIndex, sourceSize); sourceColumns.unshift(targetIndex as any, 0 as any); Array.prototype.splice.apply(this._columns, sourceColumns); // 对表头columnTree调整节点位置 this.columnTree.movePosition( sourceCellRange.start.col - this.leftRowSeriesNumberColumnCount, - sourceCellRange.start.row, - targetIndex + (target.row > source.row ? sourceCellRange.end.row - sourceCellRange.start.row : 0) + sourceTotalIndex, + targetTotalIndex ); this.columnTree.reset(this.columnTree.tree.children); this._cellRangeMap = new Map();