From 255338be8afff3babcc27b568812864ddca7b96e Mon Sep 17 00:00:00 2001 From: jianneng-fit2cloud Date: Tue, 2 Jun 2026 17:03:23 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E5=9B=BE=E8=A1=A8):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E9=9D=A2=E7=A7=AF=E5=9B=BE=E4=BB=A5=E5=8F=8A=E6=9F=B1=E6=9D=A1?= =?UTF-8?q?=E5=9B=BE=E5=8F=AF=E8=83=BD=E5=87=BA=E7=8E=B0=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E4=B8=AD=E7=BC=BA=E5=B0=91=E6=8C=87=E6=A0=87=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/js/panel/charts/g2/bar/bar.ts | 36 +++++---- .../js/panel/charts/g2/bar/barUtil.ts | 76 +++++++++++++++++++ .../js/panel/charts/g2/line/area.ts | 34 ++++++--- 3 files changed, 121 insertions(+), 25 deletions(-) diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/bar.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/bar.ts index 03db9738f8..5c4d1ef45a 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/bar.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/bar.ts @@ -32,8 +32,13 @@ import { } from '@/views/chart/components/editor/util/chart' import { createTooltipWrapper, + getSeriesTooltipFormatter, + getSeriesTooltipFormatterMap, getStackTooltipGroupName, + getTooltipItemFormatter, handleEmptyDataStrategy, + isSeriesTooltipFormatterShown, + isTooltipItemShown, renderGroupedTooltipItems, tooltipCss, tooltipMaxHeight, @@ -248,12 +253,7 @@ export class Bar extends G2ChartView { if (!tooltipAttr.show) { return options } - const formatterMap = tooltipAttr.seriesTooltipFormatter - ?.filter(i => i.show) - .reduce((pre, next) => { - pre[next.id] = next - return pre - }, {}) as Record + const formatterMap = getSeriesTooltipFormatterMap(tooltipAttr) const tooltipOptions: ViewSpec = { tooltip: d => d, interaction: { @@ -268,24 +268,34 @@ export class Bar extends G2ChartView { const titleHtml = TOOLTIP_TITLE_TPL.replace('{title}', title) let tooltipItems = originalItems if (tooltipAttr.seriesTooltipFormatter?.length) { - tooltipItems = originalItems.filter(item => formatterMap[item.quotaList[0].id]) + // 只隐藏明确配置为不展示的字段,避免过期 formatter 漏掉新指标。 + tooltipItems = originalItems.filter(item => + isTooltipItemShown(formatterMap, item, 'yAxis') + ) } const result = [] const head = originalItems[0] tooltipItems.forEach(item => { - const formatter = formatterMap[item.quotaList[0].id] ?? yAxis[0] + const formatter = getTooltipItemFormatter(formatterMap, item, yAxis, 'yAxis') const value = item.value === null || item.value === undefined ? '' - : valueFormatter(item.value, formatter.formatterCfg) - const name = isEmpty(formatter.chartShowName) - ? formatter.name + : valueFormatter( + item.value, + formatter?.formatterCfg ?? tooltipAttr.tooltipFormatter + ) + const name = isEmpty(formatter?.chartShowName) + ? formatter?.name ?? item.name : formatter.chartShowName result.push({ ...item, name, value }) }) head.dynamicTooltipValue?.forEach(item => { - const formatter = formatterMap[item.fieldId] - if (formatter) { + const formatter = getSeriesTooltipFormatter( + formatterMap, + item.fieldId, + chart.extTooltip + ) + if (formatter && isSeriesTooltipFormatterShown(formatterMap, item.fieldId)) { const value = item.value === null || item.value === undefined ? '' diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/barUtil.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/barUtil.ts index 3d5a945b8c..55e147c744 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/barUtil.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/barUtil.ts @@ -283,6 +283,82 @@ export function tooltipMaxHeight(chart: Chart) { return `max-height: ${maxHeight}px;max-width: ${chartRect.width / 2}px;` } +export function getSeriesTooltipFormatterMap(tooltipAttr?: DeepPartial) { + return (tooltipAttr?.seriesTooltipFormatter || []).reduce((pre, next) => { + if (!next?.id) { + return pre + } + const formatter = next as SeriesFormatter + // 同一字段可出现在不同指标槽位,优先用 seriesId 区分具体槽位。 + if (formatter.seriesId) { + pre[formatter.seriesId] = formatter + } + if (!formatter.seriesId || formatter.seriesId === formatter.id) { + pre[formatter.id] = formatter + } + return pre + }, {} as Record) +} + +export function getTooltipItemFieldId(item?: any) { + return item?.quotaList?.[0]?.id ?? item?.data?.quotaList?.[0]?.id ?? item?.fieldId +} + +// 旧图表样式可能带着过期 formatter;当前字段缺少配置时按默认展示处理。 +export function isSeriesTooltipFormatterShown( + formatterMap: Record, + fieldId?: string, + axisType?: AxisType +) { + if (!fieldId) { + return true + } + if (axisType) { + // 带槽位的主指标不能被旧的 id 级 show:false 误隐藏。 + const seriesKey = `${fieldId}-${axisType}` + return Object.prototype.hasOwnProperty.call(formatterMap, seriesKey) + ? formatterMap[seriesKey]?.show !== false + : true + } + if (Object.prototype.hasOwnProperty.call(formatterMap, fieldId)) { + return formatterMap[fieldId]?.show !== false + } + return true +} + +export function isTooltipItemShown( + formatterMap: Record, + item?: any, + axisType?: AxisType +) { + return isSeriesTooltipFormatterShown(formatterMap, getTooltipItemFieldId(item), axisType) +} + +// 带槽位的 formatter 缺项时回退到当前轴字段,避免旧 id 级配置污染新指标。 +export function getSeriesTooltipFormatter( + formatterMap: Record, + fieldId?: string, + fields: Partial[] = [], + axisType?: AxisType +) { + const field = fields.find(field => field?.id === fieldId) + const seriesId = (field as Partial)?.seriesId + if (axisType && fieldId) { + const seriesKey = `${fieldId}-${axisType}` + return formatterMap[seriesKey] || (seriesId && formatterMap[seriesId]) || field + } + return (fieldId && formatterMap[fieldId]) || (seriesId && formatterMap[seriesId]) || field +} + +export function getTooltipItemFormatter( + formatterMap: Record, + item: any, + fields: Partial[] = [], + axisType?: AxisType +) { + return getSeriesTooltipFormatter(formatterMap, getTooltipItemFieldId(item), fields, axisType) +} + // 将字段显示名降级到原始字段名,避免 tooltip 分组标题为空 export function getFieldDisplayName(field?: Partial) { return field?.chartShowName || field?.name || '' diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/area.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/area.ts index d30552c21f..66056d5069 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/area.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/area.ts @@ -38,8 +38,13 @@ import { registerSymbol, Symbols } from '@antv/g2/esm/utils/marker' import G2TooltipCarousel from '@/views/chart/components/js/G2TooltipCarousel' import { createTooltipWrapper, + getSeriesTooltipFormatter, + getSeriesTooltipFormatterMap, getStackTooltipGroupName, + getTooltipItemFormatter, renderGroupedTooltipItems, + isSeriesTooltipFormatterShown, + isTooltipItemShown, tooltipCss, tooltipMaxHeight } from '../bar/barUtil' @@ -608,12 +613,7 @@ export class Area extends G2ChartView { defaultsDeep(lineMark, { tooltip: false }) return options } - const formatterMap = tooltipAttr.seriesTooltipFormatter - ?.filter(i => i.show) - .reduce((pre, next) => { - pre[next.id] = next - return pre - }, {}) as Record + const formatterMap = getSeriesTooltipFormatterMap(tooltipAttr) const yAxis = chart.yAxis const tooltipOptions: G2Spec = { tooltip: d => d, @@ -623,11 +623,14 @@ export class Area extends G2ChartView { mount: createTooltipWrapper(chart), css: tooltipCss(tooltipAttr), enterable: true, - render: (e, { title, items: originalItems }) => { + render: (_e, { title, items: originalItems }) => { const titleHtml = TOOLTIP_TITLE_TPL.replace('{title}', title) let tooltipItems = originalItems if (tooltipAttr.seriesTooltipFormatter?.length) { - tooltipItems = originalItems.filter(item => formatterMap[item.quotaList[0].id]) + // 只隐藏明确配置为不展示的字段,避免过期 formatter 漏掉新指标。 + tooltipItems = originalItems.filter(item => + isTooltipItemShown(formatterMap, item, 'yAxis') + ) } const result = [] const head = originalItems[0] @@ -635,13 +638,20 @@ export class Area extends G2ChartView { if (item.value === null || item.value === undefined) { return } - const formatter = formatterMap[item.quotaList[0].id] ?? yAxis[0] - const value = valueFormatter(item.value, formatter.formatterCfg) + const formatter = getTooltipItemFormatter(formatterMap, item, yAxis, 'yAxis') + const value = valueFormatter( + item.value, + formatter?.formatterCfg ?? tooltipAttr.tooltipFormatter + ) result.push({ ...item, name: item.category, value }) }) head.dynamicTooltipValue?.forEach(item => { - const formatter = formatterMap[item.fieldId] - if (formatter) { + const formatter = getSeriesTooltipFormatter( + formatterMap, + item.fieldId, + chart.extTooltip + ) + if (formatter && isSeriesTooltipFormatterShown(formatterMap, item.fieldId)) { const value = valueFormatter(parseFloat(item.value), formatter.formatterCfg) const name = isEmpty(formatter.chartShowName) ? formatter.name