From 893450421297a9c2f10b6aafae45b35842a352df Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Fri, 19 Dec 2025 14:35:55 +0800 Subject: [PATCH 1/5] fix: pivot chart no left axis case --- .../pivot-chart/axis-hover.ts | 2 +- .../layout/chart-helper/get-axis-config.ts | 13 +- .../vtable/src/layout/pivot-header-layout.ts | 169 ++++++++++-------- 3 files changed, 103 insertions(+), 81 deletions(-) diff --git a/packages/vtable/src/event/self-event-listener/pivot-chart/axis-hover.ts b/packages/vtable/src/event/self-event-listener/pivot-chart/axis-hover.ts index a98d4c525f..bba2af70ba 100644 --- a/packages/vtable/src/event/self-event-listener/pivot-chart/axis-hover.ts +++ b/packages/vtable/src/event/self-event-listener/pivot-chart/axis-hover.ts @@ -33,7 +33,7 @@ export function bindAxisHoverEvent(table: BaseTableAPI) { function getAxisPosition(col: number, row: number, layout: PivotHeaderLayoutMap) { if (layout.indicatorsAsCol) { if ( - layout.hasTwoIndicatorAxes && + layout.hasTopIndicatorAxis && row === layout.columnHeaderLevelCount - 1 && col >= layout.rowHeaderLevelCount && col < layout.colCount - layout.rightFrozenColCount diff --git a/packages/vtable/src/layout/chart-helper/get-axis-config.ts b/packages/vtable/src/layout/chart-helper/get-axis-config.ts index 773ead32cd..b774f236a2 100644 --- a/packages/vtable/src/layout/chart-helper/get-axis-config.ts +++ b/packages/vtable/src/layout/chart-helper/get-axis-config.ts @@ -24,14 +24,14 @@ export function getAxisConfigInPivotChart(col: number, row: number, layout: Pivo // 是否是指标 if (layout.indicatorsAsCol) { if ( - layout.hasTwoIndicatorAxes && + layout.hasTopIndicatorAxis && row === layout.columnHeaderLevelCount - 1 && col >= layout.rowHeaderLevelCount && col < layout.colCount - layout.rightFrozenColCount ) { const indicatorKey = layout.getIndicatorKey(col, row); const indicatorInfo = layout.getIndicatorInfo(indicatorKey); - if (!(indicatorInfo as any)?.hasTwoIndicatorAxes) { + if (!(indicatorInfo as any)?.hasTopIndicatorAxis) { return; } const axisRange = getRange('top', col, row + 1, col, layout.columnHeaderLevelCount - 1, col, row, 1, layout); @@ -348,7 +348,7 @@ export function getAxisConfigInPivotChart(col: number, row: number, layout: Pivo ) { const indicatorKey = layout.getIndicatorKey(col, row); const indicatorInfo = layout.getIndicatorInfo(indicatorKey); - if (!(indicatorInfo as any)?.hasTwoIndicatorAxes) { + if (!(indicatorInfo as any)?.hasRightIndicatorAxis) { return; } @@ -663,7 +663,7 @@ export function isTopOrBottomAxis(col: number, row: number, layout: PivotHeaderL if (layout.indicatorsAsCol) { if ( - layout.hasTwoIndicatorAxes && + layout.hasTopIndicatorAxis && row === layout.columnHeaderLevelCount - 1 && col >= layout.rowHeaderLevelCount && col < layout.colCount - layout.rightFrozenColCount @@ -858,7 +858,10 @@ function getRange( defaultSeriesIndice: number, layout: PivotHeaderLayoutMap ) { - const indicatorKeys = layout.getIndicatorKeyInChartSpec(colForIndicatorKey, rowForIndicatorKey); + const indicatorKeys = layout.getIndicatorKeyInChartSpec( + colForIndicatorKey >= 0 ? colForIndicatorKey : col, + rowForIndicatorKey >= 0 ? rowForIndicatorKey : row + ); let path; if (position === 'top' || position === 'bottom') { path = layout.getColKeysPath(col, row); diff --git a/packages/vtable/src/layout/pivot-header-layout.ts b/packages/vtable/src/layout/pivot-header-layout.ts index d2d34c54b5..d3f2dc645f 100644 --- a/packages/vtable/src/layout/pivot-header-layout.ts +++ b/packages/vtable/src/layout/pivot-header-layout.ts @@ -153,7 +153,11 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { currentPageEndIndex: number; // _extensionRowHeaderCellIds //#region pivotChart专有 - hasTwoIndicatorAxes: boolean; + /** 指标轴是否存在(按方位区分,用于更精确布局) */ + hasLeftIndicatorAxis: boolean = false; + hasRightIndicatorAxis: boolean = false; + hasTopIndicatorAxis: boolean = false; + hasBottomIndicatorAxis: boolean = false; /** 图表spec中barWidth的收集 */ _chartItemSpanSize: number; _chartPaddingInner: number; @@ -242,85 +246,100 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this.rowDimensionKeys = this.rowDimensionTree.dimensionKeysIncludeVirtual.valueArr(); this.fullRowDimensionKeys = this.fullRowDimensionKeys.concat(this.rowDimensionKeys); - this.resetRowHeaderLevelCount(); - if (this._table.isPivotChart()) { - this.hasTwoIndicatorAxes = false; - this.indicatorsDefine.forEach((indicatorObject: any) => { - if ( - indicatorObject.chartSpec && - indicatorObject.chartSpec.series && - indicatorObject.chartSpec.series.length > 1 - ) { - const axes = indicatorObject.chartSpec.axes ?? (this._table as PivotChart).pivotChartAxes ?? []; - if ( - !axes.length || - axes.every((axis: any) => { - if (axis.orient === (this.indicatorsAsCol ? 'top' : 'right') && axis.visible === false) { - return false; - } - return true; - }) - ) { - indicatorObject.hasTwoIndicatorAxes = true; - this.hasTwoIndicatorAxes = true; - return true; - } - } - indicatorObject.hasTwoIndicatorAxes = false; - return false; - }); - //上面的series多系列判断逻辑基础上,在判断是否主动配置了两个指标轴(不是series的话应该是两个一模一样的轴) - // if (this.hasTwoIndicatorAxes === false) { + this.hasLeftIndicatorAxis = false; + this.hasRightIndicatorAxis = false; + this.hasTopIndicatorAxis = false; + this.hasBottomIndicatorAxis = false; + + // 根据 chartSpec.axes / pivotChartAxes 推断“指标轴”的分布(按方位),并写回到 indicator define 上供后续轴配置/布局使用 this.indicatorsDefine.forEach((indicatorObject: any) => { - if ((indicatorObject as any).hasTwoIndicatorAxes) { - return false; + // 默认全部置为 false,避免复用旧对象时残留脏数据 + indicatorObject.hasLeftIndicatorAxis = false; + indicatorObject.hasRightIndicatorAxis = false; + indicatorObject.hasTopIndicatorAxis = false; + indicatorObject.hasBottomIndicatorAxis = false; + + if (!indicatorObject?.chartSpec) { + return; } - if (indicatorObject.chartSpec) { - const axes = indicatorObject.chartSpec.axes ?? (this._table as PivotChart).pivotChartAxes ?? []; - if (this.indicatorsAsCol) { - const topAxis = axes.find((axis: any) => { - if (axis.orient === 'top' && axis.visible !== false) { - return true; - } - return false; - }); - const bottomAxis = axes.find((axis: any) => { - if (axis.orient === 'bottom' && axis.visible !== false) { - return true; + + const axes = indicatorObject.chartSpec.axes ?? (this._table as PivotChart).pivotChartAxes ?? []; + const visibleOrients = new Set(); + (axes ?? []).forEach((axis: any) => { + if (axis?.orient && axis.visible !== false) { + visibleOrients.add(axis.orient); + } + }); + + const isMultiSeries = indicatorObject.chartSpec?.series?.length > 1; + + if (this.indicatorsAsCol) { + // 指标在列:指标轴位于 top/bottom + let hasTop = visibleOrients.has('top'); + let hasBottom = visibleOrients.has('bottom'); + + // 未配置 axes 时,默认存在 bottom 指标轴(与现有 bottomFrozenRowCount 逻辑保持一致) + if (!axes.length) { + hasBottom = true; + } + + // 多系列场景:若未显式隐藏 top 轴,则认为存在 top 副指标轴(并同时认为 bottom 主指标轴存在) + if (isMultiSeries) { + const topHiddenExplicitly = axes.some((axis: any) => axis?.orient === 'top' && axis.visible === false); + if (!axes.length || !topHiddenExplicitly) { + hasTop = true; + const bottomHiddenExplicitly = axes.some( + (axis: any) => axis?.orient === 'bottom' && axis.visible === false + ); + if (!bottomHiddenExplicitly) { + hasBottom = true; } - return false; - }); - if (topAxis && bottomAxis) { - indicatorObject.hasTwoIndicatorAxes = true; - this.hasTwoIndicatorAxes = true; - return true; } - } else { - const leftAxis = axes.find((axis: any) => { - if (axis.orient === 'left' && axis.visible !== false) { - return true; - } - return false; - }); - const rightAxis = axes.find((axis: any) => { - if (axis.orient === 'right' && axis.visible !== false) { - return true; + } + + indicatorObject.hasTopIndicatorAxis = hasTop; + indicatorObject.hasBottomIndicatorAxis = hasBottom; + // 指标在列时 left/right 不是“指标轴” + indicatorObject.hasLeftIndicatorAxis = false; + indicatorObject.hasRightIndicatorAxis = false; + } else { + // 指标在行:指标轴位于 left/right + let hasLeft = visibleOrients.has('left'); + let hasRight = visibleOrients.has('right'); + + // 未配置 axes 时,默认存在 left 指标轴(与现有 leftAxesCount/布局逻辑保持一致) + if (!axes.length) { + hasLeft = true; + } + + // 多系列场景:若未显式隐藏 right 轴,则认为存在 right 副指标轴(并同时认为 left 主指标轴存在) + if (isMultiSeries) { + const rightHiddenExplicitly = axes.some((axis: any) => axis?.orient === 'right' && axis.visible === false); + if (!axes.length || !rightHiddenExplicitly) { + hasRight = true; + const leftHiddenExplicitly = axes.some((axis: any) => axis?.orient === 'left' && axis.visible === false); + if (!leftHiddenExplicitly) { + hasLeft = true; } - return false; - }); - if (leftAxis && rightAxis) { - indicatorObject.hasTwoIndicatorAxes = true; - this.hasTwoIndicatorAxes = true; - return true; } } + + indicatorObject.hasLeftIndicatorAxis = hasLeft; + indicatorObject.hasRightIndicatorAxis = hasRight; + // 指标在行时 top/bottom 不是“指标轴” + indicatorObject.hasTopIndicatorAxis = false; + indicatorObject.hasBottomIndicatorAxis = false; } - indicatorObject.hasTwoIndicatorAxes = false; - return false; + + // 汇总到 layout 级别(任意指标存在对应方位轴,则 layout 认为存在) + this.hasLeftIndicatorAxis ||= !!indicatorObject.hasLeftIndicatorAxis; + this.hasRightIndicatorAxis ||= !!indicatorObject.hasRightIndicatorAxis; + this.hasTopIndicatorAxis ||= !!indicatorObject.hasTopIndicatorAxis; + this.hasBottomIndicatorAxis ||= !!indicatorObject.hasBottomIndicatorAxis; }); - // } } + this.resetRowHeaderLevelCount(); this.resetColumnHeaderLevelCount(); // this.indicatorsAsCol = !isValid(this.rowDimensionKeys.find(key => key === this.indicatorDimensionKey)); @@ -1613,7 +1632,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this.indicatorsAsCol && !this.dataset?.colKeys?.length && this.columnDimensionTree?.tree?.level === 0 && - !this.hasTwoIndicatorAxes + !this.hasTopIndicatorAxis ) { this.columnHeaderLevelCount = 0; return; @@ -1675,7 +1694,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { if ( this._table.isPivotChart() && this.indicatorsAsCol && - !this.hasTwoIndicatorAxes && + !this.hasTopIndicatorAxis && checkHasCartesianChart(this.indicatorsDefine) ) { count -= 1; @@ -1750,7 +1769,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { //#endregion if ( !this.indicatorsAsCol && - this.hideIndicatorName && + (this.hideIndicatorName || !this.hasLeftIndicatorAxis) && this.rowDimensionKeys[this.rowDimensionKeys.length - 1] === this.indicatorDimensionKey ) { count = rowLevelCount - 1; @@ -1859,7 +1878,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { if (this.indicatorsAsCol) { return 0; // 指标在列上,没有图表需要显示右轴 - } else if (this.hasTwoIndicatorAxes) { + } else if (this.hasRightIndicatorAxis) { // 查找指标,判断是否有双轴情况,如果有,则右侧冻结列数为1 return 1; } @@ -3777,7 +3796,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { return true; } if ( - this.hasTwoIndicatorAxes && + this.hasTopIndicatorAxis && this.indicatorsAsCol && row === this.columnHeaderLevelCount - 1 && isHasCartesianChartInline(col, row, 'col', this) @@ -4248,7 +4267,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { if (axisOption?.visible === false) { return 0; } - if (this.indicatorsAsCol && this.hasTwoIndicatorAxes) { + if (this.indicatorsAsCol && this.hasTopIndicatorAxis) { return 1; // 顶部副指标 } return 0; // 顶部无轴 From f5c40a4dc48ae90ff1d8ff65540ffed51de798d7 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Fri, 19 Dec 2025 14:36:28 +0800 Subject: [PATCH 2/5] docs: update changlog of rush --- .../fix-noLeftAxes-pivotChart_2025-12-19-06-36.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vtable/fix-noLeftAxes-pivotChart_2025-12-19-06-36.json diff --git a/common/changes/@visactor/vtable/fix-noLeftAxes-pivotChart_2025-12-19-06-36.json b/common/changes/@visactor/vtable/fix-noLeftAxes-pivotChart_2025-12-19-06-36.json new file mode 100644 index 0000000000..57b9593f43 --- /dev/null +++ b/common/changes/@visactor/vtable/fix-noLeftAxes-pivotChart_2025-12-19-06-36.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: pivot chart no left axis case\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file From 80e9a9c56fa2bdb2e863186a040f5ac9b5d91b78 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Fri, 19 Dec 2025 14:59:49 +0800 Subject: [PATCH 3/5] fix: hasLeftIndicatorAxis judgement logic --- packages/vtable/src/layout/pivot-header-layout.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vtable/src/layout/pivot-header-layout.ts b/packages/vtable/src/layout/pivot-header-layout.ts index d3f2dc645f..605ddca5a0 100644 --- a/packages/vtable/src/layout/pivot-header-layout.ts +++ b/packages/vtable/src/layout/pivot-header-layout.ts @@ -1769,7 +1769,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { //#endregion if ( !this.indicatorsAsCol && - (this.hideIndicatorName || !this.hasLeftIndicatorAxis) && + (this.hideIndicatorName || (!this.hasLeftIndicatorAxis && this._table.isPivotChart())) && this.rowDimensionKeys[this.rowDimensionKeys.length - 1] === this.indicatorDimensionKey ) { count = rowLevelCount - 1; From a0ee5e15aa312f3951f110ff74dc3cb4c0ce866f Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Mon, 22 Dec 2025 15:09:20 +0800 Subject: [PATCH 4/5] fix: show dimension tooltip delay logic error --- packages/vtable/src/scenegraph/graphic/chart.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vtable/src/scenegraph/graphic/chart.ts b/packages/vtable/src/scenegraph/graphic/chart.ts index 08d2eddf9f..fda2fcab39 100644 --- a/packages/vtable/src/scenegraph/graphic/chart.ts +++ b/packages/vtable/src/scenegraph/graphic/chart.ts @@ -287,7 +287,7 @@ export class Chart extends Rect { } this.justShowMarkTooltip = justShowMarkTooltip; let delayRunDimensionHover: boolean = false; - if (prev_justShowMarkTooltip === true && justShowMarkTooltip === false) { + if (prev_justShowMarkTooltip !== false && justShowMarkTooltip === false) { this.justShowMarkTooltipTimer = Date.now(); delayRunDimensionHover = true; } else if (prev_justShowMarkTooltip === false && justShowMarkTooltip === false) { From 76b37ecb51c9effb919983a2ed9792149fd7d341 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Mon, 22 Dec 2025 15:09:37 +0800 Subject: [PATCH 5/5] docs: update changlog of rush --- .../fix-noLeftAxes-pivotChart_2025-12-22-07-09.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vtable/fix-noLeftAxes-pivotChart_2025-12-22-07-09.json diff --git a/common/changes/@visactor/vtable/fix-noLeftAxes-pivotChart_2025-12-22-07-09.json b/common/changes/@visactor/vtable/fix-noLeftAxes-pivotChart_2025-12-22-07-09.json new file mode 100644 index 0000000000..4b954ba463 --- /dev/null +++ b/common/changes/@visactor/vtable/fix-noLeftAxes-pivotChart_2025-12-22-07-09.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: show dimension tooltip delay logic error\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file