fix(图表): 修复面积图以及柱条图可能出现提示中缺少指标的问题

This commit is contained in:
jianneng-fit2cloud
2026-06-02 17:03:23 +08:00
parent bf5587fb35
commit 255338be8a
3 changed files with 121 additions and 25 deletions

View File

@@ -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<ViewSpec, G2Column> {
if (!tooltipAttr.show) {
return options
}
const formatterMap = tooltipAttr.seriesTooltipFormatter
?.filter(i => i.show)
.reduce((pre, next) => {
pre[next.id] = next
return pre
}, {}) as Record<string, SeriesFormatter>
const formatterMap = getSeriesTooltipFormatterMap(tooltipAttr)
const tooltipOptions: ViewSpec = {
tooltip: d => d,
interaction: {
@@ -268,24 +268,34 @@ export class Bar extends G2ChartView<ViewSpec, G2Column> {
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
? ''

View File

@@ -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<ChartTooltipAttr>) {
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<string, SeriesFormatter>)
}
export function getTooltipItemFieldId(item?: any) {
return item?.quotaList?.[0]?.id ?? item?.data?.quotaList?.[0]?.id ?? item?.fieldId
}
// 旧图表样式可能带着过期 formatter当前字段缺少配置时按默认展示处理。
export function isSeriesTooltipFormatterShown(
formatterMap: Record<string, SeriesFormatter>,
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<string, SeriesFormatter>,
item?: any,
axisType?: AxisType
) {
return isSeriesTooltipFormatterShown(formatterMap, getTooltipItemFieldId(item), axisType)
}
// 带槽位的 formatter 缺项时回退到当前轴字段,避免旧 id 级配置污染新指标。
export function getSeriesTooltipFormatter(
formatterMap: Record<string, SeriesFormatter>,
fieldId?: string,
fields: Partial<Axis>[] = [],
axisType?: AxisType
) {
const field = fields.find(field => field?.id === fieldId)
const seriesId = (field as Partial<SeriesFormatter>)?.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<string, SeriesFormatter>,
item: any,
fields: Partial<Axis>[] = [],
axisType?: AxisType
) {
return getSeriesTooltipFormatter(formatterMap, getTooltipItemFieldId(item), fields, axisType)
}
// 将字段显示名降级到原始字段名,避免 tooltip 分组标题为空
export function getFieldDisplayName(field?: Partial<ChartViewField>) {
return field?.chartShowName || field?.name || ''

View File

@@ -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<string, SeriesFormatter>
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