import { col } from '../csv.js'; import { PALETTE, FONT, axisCommon, periodAxis, titleStyle, legendStyle, footnote, watermarks, LAYOUT, } from '../theme.js'; /** * 核心利润及同比增速(2020H1-2026H1) * 核心利润 = 毛利 - 销售费用 - 管理费用,反映主业盈利能力去除营销和管理成本后的净额。 * 柱状图展示绝对值(亿元),折线图展示同比增速(%)。 */ export function ppmtCoreProfitChart(rows, { width, height }) { const periods = col(rows, 'period'); const core = col(rows, 'core_profit'); const yoy = col(rows, 'yoy'); return { backgroundColor: '#fff', title: { ...titleStyle, text: '泡泡玛特核心利润及同比增速(20H1-26H1)', subtext: '核心利润 = 毛利 - 销售费用 - 管理费用,单位:亿元', }, legend: { top: LAYOUT.legendTop, itemGap: 32, textStyle: { color: PALETTE.ink, fontSize: 14, fontFamily: FONT, }, data: ['核心利润', '同比增速'], }, grid: { left: 78, right: 128, top: LAYOUT.gridTop, bottom: 100 }, tooltip: { trigger: 'axis', axisPointer: { type: 'cross' }, textStyle: { fontFamily: FONT }, formatter: (params) => { let result = `${params[0].axisValue}
`; params.forEach((p) => { if (p.seriesName === '核心利润') { result += `${p.marker}${p.seriesName}: ${p.value.toFixed(1)}亿
`; } else if (p.seriesName === '同比增速' && p.value !== null) { result += `${p.marker}${p.seriesName}: ${p.value > 0 ? '+' : ''}${p.value.toFixed(1)}%
`; } }); return result; }, }, xAxis: { ...periodAxis, data: periods }, yAxis: [ { // 左轴:核心利润(亿元) ...axisCommon, type: 'value', name: '核心利润(亿元)', nameLocation: 'middle', nameGap: 48, nameTextStyle: { color: PALETTE.grey, fontSize: 13, fontFamily: FONT }, min: 0, axisLabel: { ...axisCommon.axisLabel, formatter: '{value}' }, }, { // 右轴:同比增速(%) type: 'value', name: '同比增速(%)', nameLocation: 'middle', nameGap: 58, nameTextStyle: { color: PALETTE.grey, fontSize: 13, fontFamily: FONT }, min: -100, max: 500, interval: 100, axisLine: { show: false }, axisTick: { show: false }, splitLine: { show: false }, axisLabel: { color: PALETTE.grey, fontSize: 12, fontFamily: FONT, formatter: '{value}%', }, }, ], series: [ { name: '核心利润', type: 'bar', yAxisIndex: 0, data: core, barWidth: 32, itemStyle: { color: PALETTE.navy }, label: { show: true, position: 'top', fontFamily: FONT, fontSize: 11, color: PALETTE.ink, formatter: (p) => p.value.toFixed(1), // 强制显示所有标签,即使柱子很矮 overflow: 'none', }, }, { name: '同比增速', type: 'line', yAxisIndex: 1, data: yoy, lineStyle: { color: PALETTE.coral, width: 3.08 }, // 与拆解图毛利率线一致 // 空心圆点:白心 + 彩色描边。图例会自动继承这个样式, // 渲染成「短线 + 空心圆」 itemStyle: { color: '#fff', borderColor: PALETTE.coral, borderWidth: 2.5, // 与 theme.js lineSeries 一致 }, symbol: 'circle', symbolSize: 9, // 与 theme.js lineSeries 一致 showSymbol: true, label: { show: true, position: 'top', fontFamily: FONT, fontSize: 11, color: PALETTE.coral, fontWeight: '600', formatter: (p) => { if (p.value === null || p.value === '') return ''; return `${p.value > 0 ? '+' : ''}${p.value.toFixed(1)}%`; }, }, }, ], graphic: [ ...watermarks(width, height), footnote( '核心利润反映主业盈利能力(扣除营销与管理成本);' + '2025H1/H2同比增速受益于费用率优化和规模效应 | @思考的Joey' ), ], }; }