Files
smart-fin-chart/js/charts/ppmt_stores_retail.js
2026-09-09 15:31:05 +08:00

135 lines
4.5 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { col } from '../csv.js';
import {
PALETTE, FONT, axisCommon, standalonePeriodAxis, titleStyle, standardLegend,
financialViewLabel, lineSeries, footnote, watermarks, LAYOUT,
} from '../theme.js';
/**
* 泡泡玛特分地区零售门店数量与同比增速。
* 堆叠柱为各期末门店数,折线为全球合计数量的同比。
* 口径:2023年及以前"海外合计"含港澳台;2024年起港澳台单列并计入中国,
* 海外合计 = 亚太 + 美洲 + 欧洲。两段口径不可直接跨 2023/2024 对比海外。
*/
// 门店数是计数而非金额,保留整数(CLAUDE.md 一位小数规则针对金额/比率)。
const SEGMENT_COLORS = {
mainland: '#3F7FBE',
hkmtw: '#AECBE8',
apac: '#36A28F',
americas: '#E4A349',
europe: PALETTE.brown,
overseas: '#C2726B',
};
// 段内标签文字色:浅色底(港澳台、美洲)用深字,深色底用白字
const INSIDE_LABEL_COLORS = {
mainland: '#fff',
hkmtw: PALETTE.ink,
apac: '#fff',
americas: PALETTE.ink,
europe: '#fff',
overseas: '#fff',
};
const regions = [
{ key: 'mainland', name: '中国内地' },
{ key: 'hkmtw', name: '港澳台' },
{ key: 'apac', name: '亚太' },
{ key: 'americas', name: '美洲' },
{ key: 'europe', name: '欧洲' },
{ key: 'overseas', name: '海外合计(含港澳台)' },
];
const num = (value) => (Number.isFinite(value) ? value : null);
// 2024 起披露口径变为港澳台单列 + 亚太/美洲/欧洲分列;此前只有含港澳台的海外合计。
// 同一根柱内两种披露结构互斥出现,堆叠总和始终等于全球合计。
function stackValue(row, key) {
const split = Number.isFinite(row.apac);
if (key === 'overseas') return split ? null : num(row.overseas);
if (!split && key !== 'mainland') return null;
return num(row[key]);
}
export function storesRetailChart(rows, { width, height, view = 'all' }) {
return {
backgroundColor: '#fff',
title: {
...titleStyle,
text: `泡泡玛特分地区零售门店数量与同比增速(${financialViewLabel(view)})`,
subtext: '柱状为各期末零售门店数(堆叠);折线为全球合计门店数量同比',
},
legend: standardLegend([...regions.map((item) => item.name), '全球合计同比']),
grid: { left: 78, right: 82, top: LAYOUT.gridTop, bottom: 100 },
tooltip: {
trigger: 'axis',
axisPointer: { type: 'shadow' },
textStyle: { fontFamily: FONT },
},
xAxis: { ...standalonePeriodAxis, data: col(rows, 'period') },
yAxis: [
{
...axisCommon,
type: 'value',
name: '零售门店数量(家)',
nameLocation: 'middle',
nameGap: 52,
nameTextStyle: { color: PALETTE.grey, fontSize: 13, fontFamily: FONT },
min: 0,
max: 700,
interval: 100,
},
{
...axisCommon,
type: 'value',
name: '全球合计同比(%)',
nameLocation: 'middle',
nameGap: 60,
nameRotate: -90,
nameTextStyle: { color: PALETTE.grey, fontSize: 13, fontFamily: FONT },
min: 0,
max: 100,
interval: 20,
axisLabel: { ...axisCommon.axisLabel, formatter: '{value}%' },
splitLine: { show: false },
},
],
series: [
...regions.map((item) => ({
name: item.name,
type: 'bar',
stack: 'stores-retail',
data: rows.map((row) => stackValue(row, item.key)),
itemStyle: { color: SEGMENT_COLORS[item.key] },
// 每段标注门店数:浅色段用深字、深色段用白字,保证段内可读
label: {
show: true,
position: 'inside',
fontSize: 10,
fontWeight: 500,
fontFamily: FONT,
color: INSIDE_LABEL_COLORS[item.key],
overflow: 'none',
},
// 相邻矮段(如 2024H1 美洲/欧洲)标签贴得近时沿 y 向微移避让
labelLayout: { moveOverlap: 'shiftY' },
emphasis: { focus: 'series' },
})),
{
...lineSeries({
name: '全球合计同比',
data: col(rows, 'global_yoy'),
color: '#8256B2',
formatter: (p) => `${p.value.toFixed(1)}%`,
}),
yAxisIndex: 1,
z: 10,
},
],
graphic: [
...watermarks(width, height),
footnote('数据来源:泡泡玛特历年公告;门店数为各期末时点数\n2023年及以前海外合计含港澳台;2024年起港澳台单列,海外=亚太+美洲+欧洲 | @Joey知行记'),
],
};
}