100 lines
4.8 KiB
JavaScript
100 lines
4.8 KiB
JavaScript
import { loadCSV } from './csv.js';
|
|
import { inventoryChart } from './charts/inventory.js';
|
|
import { marginChart } from './charts/margin.js';
|
|
import { twoLineChart } from './charts/twoline.js';
|
|
import { growthChart } from './charts/growth.js';
|
|
import { fxChart } from './charts/fx.js';
|
|
import { assetsChart } from './charts/ppmt_assets.js';
|
|
import { profitChart } from './charts/ppmt_profit.js';
|
|
import { ipChart } from './charts/ppmt_ip.js';
|
|
import { categoryChart } from './charts/ppmt_category.js';
|
|
import { sankeyChart } from './charts/ppmt_sankey.js';
|
|
import { regionChannelYoyChart } from './charts/ppmt_region_yoy.js';
|
|
import { ppmtGrowthChart } from './charts/ppmt_growth.js';
|
|
import { ppmtMarginsChart } from './charts/ppmt_margins.js';
|
|
import { ppmtBridgeChart } from './charts/ppmt_bridge.js';
|
|
import { ppmtCoreProfitChart } from './charts/ppmt_core_profit.js';
|
|
import { ppmtCoreMarginChart } from './charts/ppmt_core_margin.js';
|
|
import { ppmtIpShareChart } from './charts/ppmt_ip_share.js';
|
|
import { ppmtIpShareHistoryChart } from './charts/ppmt_ip_share_history.js';
|
|
import { ppmtIpExMonstersChart } from './charts/ppmt_ip_ex_monsters.js';
|
|
|
|
/** 图表清单:加新图只需在这里加一行 */
|
|
const CHARTS = [
|
|
// 示例图表
|
|
{ id: 'chart-inventory', csv: 'data/inventory.csv', build: inventoryChart, height: 620 },
|
|
{ id: 'chart-margin', csv: 'data/margin.csv', build: marginChart, height: 620 },
|
|
{ id: 'chart-twoline', csv: 'data/margin.csv', build: twoLineChart, height: 620 },
|
|
{ id: 'chart-growth', csv: 'data/growth.csv', build: growthChart, height: 700 },
|
|
{ id: 'chart-fx', csv: 'data/fx.csv', build: fxChart, height: 780 },
|
|
// 泡泡玛特图表
|
|
{ id: 'chart-ppmt-assets', csv: 'data/ppmt_assets.csv', build: assetsChart, height: 680 },
|
|
{ id: 'chart-ppmt-profit', csv: 'data/ppmt_profit.csv', build: profitChart, height: 680 },
|
|
{ id: 'chart-ppmt-ip', csv: 'data/ppmt_ip.csv', build: ipChart, height: 720 },
|
|
{ id: 'chart-ppmt-category', csv: 'data/ppmt_category.csv', build: categoryChart, height: 680 },
|
|
{ id: 'chart-ppmt-sankey', csv: 'data/ppmt_sankey_2026h1.csv', build: sankeyChart, height: 800 },
|
|
{ id: 'chart-ppmt-region-yoy', csv: 'data/ppmt_region_channel_yoy.csv', build: regionChannelYoyChart, height: 620 },
|
|
{ id: 'chart-ppmt-growth', csv: 'data/ppmt_growth.csv', build: ppmtGrowthChart, height: 700 },
|
|
{ id: 'chart-ppmt-margins', csv: 'data/ppmt_margins.csv', build: ppmtMarginsChart, height: 680 },
|
|
{ id: 'chart-ppmt-bridge', csv: 'data/ppmt_margin_bridge.csv', build: ppmtBridgeChart, height: 700 },
|
|
{ id: 'chart-ppmt-core', csv: 'data/ppmt_core_profit.csv', build: ppmtCoreProfitChart, height: 720 },
|
|
{ id: 'chart-ppmt-core-margin', csv: 'data/ppmt_core_margin.csv', build: ppmtCoreMarginChart, height: 680 },
|
|
{ id: 'chart-ppmt-ip-share', csv: 'data/ppmt_ip_share_2026h1.csv', build: ppmtIpShareChart, height: 720 },
|
|
{ id: 'chart-ppmt-ip-share-history', csv: 'data/ppmt_ip_share_history.csv', build: ppmtIpShareHistoryChart, height: 700 },
|
|
{ id: 'chart-ppmt-ip-ex-monsters', csv: 'data/ppmt_ip_ex_monsters.csv', build: ppmtIpExMonstersChart, height: 700 },
|
|
];
|
|
|
|
const instances = new Map();
|
|
|
|
async function render(spec) {
|
|
const el = document.getElementById(spec.id);
|
|
if (!el) return;
|
|
|
|
try {
|
|
// 加时间戳绕过缓存,改完 CSV 刷新就能看到
|
|
const rows = await loadCSV(`${spec.csv}?t=${Date.now()}`);
|
|
const chart = instances.get(spec.id) || echarts.init(el, null, { renderer: 'canvas' });
|
|
instances.set(spec.id, chart);
|
|
|
|
const { width, height } = el.getBoundingClientRect();
|
|
chart.setOption(spec.build(rows, { width, height }), true);
|
|
} catch (err) {
|
|
el.innerHTML = `<div class="chart-error">${err.message}</div>`;
|
|
console.error(spec.id, err);
|
|
}
|
|
}
|
|
|
|
async function renderAll() {
|
|
await Promise.all(CHARTS.map(render));
|
|
}
|
|
|
|
/** 导出当前图为 PNG,2 倍图,微信公众号里够清晰 */
|
|
function exportPNG(id, filename) {
|
|
const chart = instances.get(id);
|
|
if (!chart) return;
|
|
const url = chart.getDataURL({ type: 'png', pixelRatio: 2, backgroundColor: '#fff' });
|
|
const a = document.createElement('a');
|
|
a.href = url;
|
|
a.download = `${filename}.png`;
|
|
a.click();
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
renderAll();
|
|
|
|
document.getElementById('btn-reload').addEventListener('click', renderAll);
|
|
|
|
document.querySelectorAll('[data-export]').forEach((btn) => {
|
|
btn.addEventListener('click', () => {
|
|
exportPNG(btn.dataset.export, btn.dataset.filename || btn.dataset.export);
|
|
});
|
|
});
|
|
|
|
let timer;
|
|
window.addEventListener('resize', () => {
|
|
clearTimeout(timer);
|
|
// resize 后水印数量要跟着画布变,所以整体重绘而不是 chart.resize()
|
|
timer = setTimeout(renderAll, 200);
|
|
});
|
|
});
|