140 lines
3.6 KiB
JavaScript
140 lines
3.6 KiB
JavaScript
import {
|
||
PALETTE, FONT, titleStyle, footnote, watermarks,
|
||
} from '../theme.js';
|
||
|
||
/**
|
||
* 泡泡玛特利润流向桑基图(2026H1)
|
||
* 从营业收入到非GAAP归母净利润的完整流程
|
||
*/
|
||
export function sankeyChart(rows, { width, height }) {
|
||
// 从 CSV 构建桑基图的 links 数据
|
||
const links = rows.map(row => ({
|
||
source: row.source,
|
||
target: row.target,
|
||
value: row.value,
|
||
}));
|
||
|
||
// 定义节点颜色
|
||
const nodeColors = {
|
||
'营业收入': PALETTE.navy,
|
||
'营业成本': PALETTE.grey,
|
||
'毛利': PALETTE.sage,
|
||
'销售费用': PALETTE.orange,
|
||
'管理费用': PALETTE.purple,
|
||
'财务费用': PALETTE.brown,
|
||
'营业利润': PALETTE.green,
|
||
'投资收益': PALETTE.blue,
|
||
'公允价值变动': PALETTE.blue,
|
||
'其他收入': PALETTE.blue,
|
||
'利润总额': PALETTE.sage,
|
||
'所得税费用': PALETTE.grey,
|
||
'净利润': PALETTE.green,
|
||
'少数股东损益': PALETTE.grey,
|
||
'归母净利润': PALETTE.coral,
|
||
'非GAAP调整项': PALETTE.blue,
|
||
'非GAAP归母净利润': PALETTE.red,
|
||
};
|
||
|
||
return {
|
||
backgroundColor: '#fff',
|
||
title: {
|
||
...titleStyle,
|
||
text: '泡泡玛特利润流向分析(2026H1)',
|
||
subtext: '从营业收入到非GAAP归母净利润的完整流程,单位:亿元',
|
||
top: 18,
|
||
},
|
||
tooltip: {
|
||
trigger: 'item',
|
||
triggerOn: 'mousemove',
|
||
textStyle: { fontFamily: FONT, fontSize: 13 },
|
||
formatter: (params) => {
|
||
if (params.dataType === 'edge') {
|
||
return `${params.data.source} → ${params.data.target}<br/><b>${params.data.value.toFixed(2)} 亿元</b>`;
|
||
} else {
|
||
return `<b>${params.name}</b><br/>总额: ${params.value.toFixed(2)} 亿元`;
|
||
}
|
||
},
|
||
},
|
||
series: [
|
||
{
|
||
type: 'sankey',
|
||
layout: 'none',
|
||
emphasis: {
|
||
focus: 'adjacency',
|
||
},
|
||
nodeAlign: 'left',
|
||
layoutIterations: 0,
|
||
nodeWidth: 26,
|
||
nodeGap: 14,
|
||
left: 120,
|
||
right: 180,
|
||
top: 110,
|
||
bottom: 90,
|
||
data: Object.keys(nodeColors).map(name => ({
|
||
name,
|
||
itemStyle: { color: nodeColors[name] },
|
||
})),
|
||
links,
|
||
label: {
|
||
color: PALETTE.ink,
|
||
fontFamily: FONT,
|
||
fontSize: 12,
|
||
fontWeight: 'normal',
|
||
formatter: (params) => {
|
||
// 给每个节点标注名称和数值
|
||
return `{name|${params.name}}\n{value|${params.value.toFixed(2)}亿}`;
|
||
},
|
||
rich: {
|
||
name: {
|
||
fontSize: 12,
|
||
fontFamily: FONT,
|
||
color: PALETTE.ink,
|
||
},
|
||
value: {
|
||
fontSize: 11,
|
||
fontFamily: FONT,
|
||
color: PALETTE.grey,
|
||
fontWeight: 'bold',
|
||
},
|
||
},
|
||
},
|
||
lineStyle: {
|
||
color: 'gradient',
|
||
curveness: 0.5,
|
||
opacity: 0.3,
|
||
},
|
||
levels: [
|
||
{
|
||
depth: 0,
|
||
label: { position: 'left' },
|
||
},
|
||
{
|
||
depth: 1,
|
||
label: { position: 'right' },
|
||
},
|
||
{
|
||
depth: 2,
|
||
label: { position: 'right' },
|
||
},
|
||
{
|
||
depth: 3,
|
||
label: { position: 'right' },
|
||
},
|
||
{
|
||
depth: 4,
|
||
label: { position: 'right' },
|
||
},
|
||
{
|
||
depth: 5,
|
||
label: { position: 'right' },
|
||
},
|
||
],
|
||
},
|
||
],
|
||
graphic: [
|
||
...watermarks(width, height),
|
||
footnote('数据来源:泡泡玛特财报 | @思考的Joey'),
|
||
],
|
||
};
|
||
}
|