Files
smart-fin-chart/docs/方案设计.md
T

203 lines
12 KiB
Markdown
Raw 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.
# 智能财报分析平台 · 方案设计
> 版本:v0.3(P0 已落地)
>
> 状态:与当前代码同步
> 范围:本仓库负责「规范化 CSV → ECharts 图表展示」。原始财报的抽取、整理与复核在仓库外完成。
---
## 1. 当前目标
这是一个以“够用、易维护”为优先级的多公司财报图表工具,而不是一个预先建设完整数据平台的项目。
1. **多公司浏览**:左侧选择公司,中间按分析主题查看图表,右侧可跳转当前栏目的图表。
2. **概览优先**:概览只展示最值得先看的跨主题图表;它是精选入口,不是新的数据或图表副本。
3. **确定性渲染**:CSV 相同,图表结果相同;AI 只协助将原始财报整理成 CSV,或一次性生成经 review 后固化的新增图表代码。
4. **低维护成本**:更新已有图表时只替换 CSV;新增专属图时才增加图表构建文件与注册项。
第一阶段不建设自动累计转单季、通用指标平台、完整财务勾稽或运行期聊天机器人。这些只在第二家公司接入后,确实出现重复劳动时再考虑。
---
## 2. 当前架构
```
原始财报 / PDF / XLSX(仓库外保存)
│ 人工、AI 或脚本:抽取、归一化、口径确认
▼
data/{company}/*.csv ← 运行时数据
▼
manifest.json ← 展示编排与图表配置的唯一事实来源
├─ chartCatalog ← 每张图只定义一次
└─ tabs[].chartRefs ← 各栏目仅引用图表并决定顺序
▼
js/charts/index.js ← chart key → ECharts option 构建函数
js/main.js + js/ui.js ← 解析引用、渲染三栏、导出和刷新
```
### 2.1 图表定义与页面编排分离
每家公司拥有一份 `chartCatalog`。一张图的 `key`、CSV、标题、高度与导出名只在这里维护一次;Tab 只使用 `chartRefs` 引用它。
```json
{
"id": "ppmt",
"chartCatalog": {
"ppmt-growth": {
"key": "ppmt-growth",
"title": "营收到利润的增速对比",
"csv": "data/ppmt/ppmt_growth.csv",
"height": 700,
"filename": "泡泡玛特营收到利润增速对比"
}
},
"tabs": [
{ "id": "overview", "name": "概览", "chartRefs": ["ppmt-growth"] },
{ "id": "profitability", "name": "盈利能力", "chartRefs": ["ppmt-growth"] }
]
}
```
这保证概览与原分类使用**同一数据源、同一图表构建函数、同一份展示配置**。修改图表只需改 `chartCatalog` 一处。
页面在每次展示时生成 `公司 + Tab + 图表 ID` 的实例 ID,供 DOM 和 ECharts 使用。因此,同一图既能出现在概览,也能出现在原分类,不会发生画布或导出实例冲突。URL 中仍使用稳定的图表 ID,例如:`#/ppmt/profitability/ppmt-growth`。
### 2.2 图表代码职责
- `manifest.json`:图表定义在哪里展示、读哪个 CSV、卡片尺寸和导出名。
- `js/charts/index.js`:注册 `key → build 函数`。
- `js/charts/*.js`:只处理该图的业务字段与 ECharts 表达。
- `js/theme.js`:字体、配色、图例、坐标轴、脚注和水印等统一视觉规范。
- `data/{company}/`:图表需要的规范化 CSV。
---
## 3. 页面与交互
```
┌──────────┬────────────────────────────────────┬──────────┐
│ 公司列表 │ [概览][盈利能力][费用率][资产负债]… │ 当前图表 │
│ 泡泡玛特 │ ┌────────────────────────────────┐ │ · 图表 A │
│ 示例 │ │ 图表卡片:标题、数据路径、导出 │ │ · 图表 B │
│ │ └────────────────────────────────┘ │ │
└──────────┴────────────────────────────────────┴──────────┘
```
- 左栏切换公司;顶部 Tab 切换该公司的分析栏目;仅渲染当前栏目,切走后释放 ECharts 实例。
- 右栏显示当前栏目锚点,点击后平滑定位到相应图表。
- 右上角固定刷新按钮重新读取 manifest 与 CSV;导出按钮按当前卡片导出 PNG。
- 宽度 **≤1040px** 时隐藏右侧锚点;宽度 **≤880px** 时公司栏改为页面顶部横向菜单,图表卡片允许横向滚动以保持可读性。
- Vite 开发环境中,JS/CSS 修改热更新;`manifest.json` 或 CSV 修改会自动整页刷新。
---
## 4. 泡泡玛特当前栏目设计
### 4.1 概览:精选入口
概览用四张图快速回答“公司是否仍在增长、增长是否转化为利润、增长来自哪里、海外/渠道结构如何”。它们同时保留在原分析栏目中。
1. **营收到利润的增速对比**:经营增长和利润兑现。
2. **盈利能力**:主要利润率趋势。
3. **主要 IP 收入占比**:IP 集中度与核心 IP 贡献。
4. **区域渠道分布**:区域、渠道的收入结构。
### 4.2 详细栏目
| Tab | 当前内容 | 设计意图 |
|---|---|---|
| 概览 | 上述 4 张精选图 | 进入公司后的快速判断 |
| 盈利能力 | 营收到利润的增速对比、核心利润及同比、核心利润率、净利率同比拆解、利润流向、经营现金流与净利润(年度)、三大现金流与现金净增加(年度) | 将“增长是否兑现为利润”与利润质量放在同一叙事中 |
| 费用率 | 利润率与费用率拆解、费用结构与费用率(年度) | 从费率和金额两个角度拆解利润率变化 |
| 资产负债 | 资产结构演变、现金、负债与净营运资本、营运资本效率 | 观察资本与资产结构、流动性、资金占用和现金转换周期 |
| IP 与品类 | IP 收入趋势/占比、非 THE MONSTERS IP、品类结构 | 观察 IP 集中度与品类演变 |
| 区域渠道 | 区域渠道分布、同比增速、同比增速趋势、渠道收入结构与增速 | 观察全球化与渠道驱动 |
**成长性不是泡泡玛特的独立 Tab。** 目前它只有“营收到利润的增速对比”一张图,且目标是解释利润增长,因此归入“盈利能力”。未来若有多张独立增长主题图(如收入、门店、海外、分部增速),再恢复单独的“成长性”Tab。
“利润流向”是单期的利润结构细节,放在“盈利能力”而非概览。
---
## 5. 数据与时间维度
### 5.1 CSV 约定
- 每图一份 CSV;同一图的年度、半年、季度视图使用各自 CSV。
- 一份 CSV 只表达一种期间口径,禁止混合累计和单期含义。
- CSV 保留四位年份;显示层可简写。`H2` 的含义必须以数据口径为准:若为下半年单期,不得显示成全年累计。
- 同比、环比、核心利润等需要计算的指标,应在 CSV 整理阶段明确生成;前端不自动从累计值推导单季或下半年。
- CSV 至少包含 `period` 和该图需要的指标列;单位、口径与重要计算方式通过图表脚注说明。
### 5.2 可选周期切换
需要切换年度、半年、季度的图,可在 `chartCatalog` 中使用 `views` 替代单个 `csv`:
```json
{
"key": "some-chart",
"title": "净利润与同比",
"defaultView": "annual",
"views": {
"annual": "data/company/net_profit_annual.csv",
"halfyear": "data/company/net_profit_halfyear.csv",
"quarter": "data/company/net_profit_quarter.csv"
}
}
```
页面仅在声明多个视图时显示切换按钮,并将选择写入 URL query;尚未启用多视图的图表维持单一 CSV,不显示控制器。
泡泡玛特已在 15 张连续图启用该能力:盈利能力、营收到利润的增速对比、核心利润及同比增速、核心利润率、利润率与费用率拆解、资产结构演变、主要 IP 收入趋势、各 IP 收入占比、除 THE MONSTERS 外 IP 收入及同比、品类收入结构、经营现金流与净利润、现金/负债/净营运资本、三大现金流与现金净增加、费用结构与费用率、渠道收入结构与增速。默认显示“全部”,并提供“年度 / 半年”;其原始披露没有可靠 Q1/Q3 数据,故不展示“季度”。其中 `FY` 为全年、`H1/H2` 为单独半年,流量类指标的 H2 在数据归一化阶段由 `FY − H1` 生成,比率与同比也在数据层重算;资产负债表类则为期末余额,H2 对应年末时点而非累计金额。
---
## 6. 视觉一致性与新增图表
新增图表必须复用 `theme.js` 的 `FONT`、`PALETTE`、`LAYOUT`、`periodAxis()`、`standardLegend()`、`lineSeries()`、`barSeries()`、`footnote()` 与 `watermarks()`,而不是在单个图表中重复手写基础样式。
- 财务含义相同的系列应使用固定语义色;IP、区域、品类等多分类数据使用统一分类色板。
- 柱线组合图采用已确认的“轻快消费”色板:柱状系列用不同色相承载分类,折线只保留一条高辨识度强调色。现金流、利润与同比使用 `FINANCIAL_COLORS`,渠道使用 `CHANNEL_COLORS`;瀑布图使用 `BRIDGE_COLORS`(蓝色基准、青绿色正向、珊瑚红负向)。新图不得在图表文件内散落同等语义的十六进制颜色。
- 一张图只保留一个视觉主角。辅助柱使用中等饱和度,避免多个红、橙、紫同时争夺注意力;分类图的相邻系列须同时拉开色相与明度。
- 颜色不是唯一编码:折线还须依靠线宽、实虚线、空心圆点和标签优先级;柱线混合图的折线标签使用 `lineDataWithSafeLabels()` 等通用避让规则,避免文字压在柱端。
- 新图的业务差异由 chart 文件表达;统一视觉由主题文件表达;展示位置与 CSV 由 manifest 表达。
- 新增或调整图表后,必须检查标签、图例、脚注和控制器是否重叠,以及颜色与文字是否有足够对比度。
通用图表模板仍然后置。只有至少两家公司需要相同图型、字段映射与口径已稳定时,才抽取 `template(rows, meta, { width, height }) => option`;在此之前,保留一图一文件更低风险。
---
## 7. 校验、发布与维护
### 7.1 当前校验
`pnpm test` 会遍历每家公司的 `chartCatalog`,以 ECharts SSR 渲染所有图表并检查:
- 图表 key 已在 registry 注册;
- CSV 可读取;
- Tab 的 `chartRefs` 都存在,且同一 Tab 不重复;
- 图例、网格、折线圆点等共享视觉规范;
- SVG 导出没有字体引号导致的非法属性。
截至当前,仓库登记 **27 张**图表(泡泡玛特 22 张、示例 5 张)。概览中的重复展示不增加图表定义或测试数量。
### 7.2 日常工作流
1. 更新已有数据:替换对应 CSV,检查口径与脚注,运行 `pnpm test`。
2. 新增图表:新增 CSV → 新增图表构建文件 → 在 registry 注册 key → 在公司的 `chartCatalog` 登记一次 → 在需要的 Tab 增加 `chartRefs`。
3. 调整首页:只调整 `overview.chartRefs` 的选择与顺序,不复制任何图表配置。
4. 发布静态文件:运行 `pnpm build`;产物只包含运行需要的 manifest 和 CSV,不包含 `data/*/raw/` 中的原始文件。
---
## 8. 明确后置的能力
- 原始 PDF 自动抽取与全自动财务勾稽;
- 自动将累计半年/季度数据拆分为单期;
- 全公司统一指标库与 schema 强校验;
- 现金流、人效、偿债等通用模板;
- 截图像素级视觉回归。
这些能力并非不需要,而是在当前“先把现有公司稳定用起来”的阶段不应抢占开发成本。出现第二家公司、稳定重复的数据与图型后,再按实际痛点逐项引入。