AI-video-lifeplan-demo/.qoder/repowiki/zh/content/核心功能/财务数据建模与图表构建.md

16 KiB
Raw Blame History

财务数据建模与图表构建

**本文引用的文件** - [backend/data_builder.py](file://backend/data_builder.py) - [frontend/src/render-props-types.ts](file://frontend/src/render-props-types.ts) - [src/types.ts](file://src/types.ts) - [src/CashFlowChart.tsx](file://src/CashFlowChart.tsx) - [src/LifePlanChart.tsx](file://src/LifePlanChart.tsx) - [src/DualChartView.tsx](file://src/DualChartView.tsx) - [src/mock-cashflow.json](file://src/mock-cashflow.json) - [src/mock-data.json](file://src/mock-data.json) - [PROJECT_README.md](file://PROJECT_README.md)

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考量
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本文件面向开发者,系统性阐述财务数据建模与图表构建模块,重点解析后端 data_builder.py 如何将原始财务输入转化为可用于 Remotion 动画渲染的结构化时序数据;详解现金流模拟算法、资产耗尽预测模型与年度快照(YearlySnapshot)生成逻辑;说明 CashFlowDataSchema 与 YearlySnapshotSchema 的设计原则及与前端 Recharts 组件的映射关系;结合代码展示数据插值、单位转换与异常值处理的关键步骤;解释 render_props.json 中 charts 字段的构造流程,并提供自定义财务假设(通胀率、投资回报率、赤字利率)的配置方法;最后给出大数据量下的分段处理与性能优化建议。

项目结构

该模块位于 Python 后端与前端 Remotion 之间,通过 render_props.json 建立强类型契约,确保前后端数据一致。后端负责财务模拟与数据转换,前端负责动画渲染与交互。

graph TB
A["后端 data_builder.py<br/>金融模拟与数据转换"] --> B["render_props.json<br/>数据契约"]
B --> C["前端 Remotion 组件<br/>CashFlowChart.tsx / LifePlanChart.tsx / DualChartView.tsx"]
C --> D["Recharts 图表<br/>动态可视化"]

图示来源

章节来源

核心组件

  • FinancialSimulator:负责按年推进财务模拟,应用通胀、退休收入停止、事件成本、正负资产余额的不同收益/利息规则,生成 YearlySnapshot 列表。
  • build_chart_data:从 PDF 提取参数,调用 FinancialSimulator,产出 assetDepletion 与 cashFlow 两套图表数据。
  • YearlySnapshot 与 CashFlowData:前后端共同约定的数据结构,分别用于资产耗尽趋势与收支明细可视化。
  • Recharts 组件:CashFlowChart 与 LifePlanChart 将上述数据结构映射到图表,支持动画与 HUD 信息同步。

章节来源

架构总览

后端 data_builder.py 以 FinancialSimulator 为核心,将 PDF 输入转换为两条时间线:

  • 年度快照(YearlySnapshot):资产余额、收入/支出、事件标记、是否临界。
  • 现金流明细(CashFlowData):按类别拆分的支出、净现金流、资产余额。

前端通过 render_props.json 接收两条时间线,CashFlowChart 与 LifePlanChart 分别消费这些数据,实现双视图联动与统一动画进度。

sequenceDiagram
participant PDF as "PDF 输入"
participant Builder as "data_builder.py"
participant Sim as "FinancialSimulator"
participant JSON as "render_props.json"
participant CF as "CashFlowChart"
participant LP as "LifePlanChart"
PDF->>Builder : 提取年龄/退休/寿命/资产/收入/支出/事件
Builder->>Sim : 传入财务参数与生命周期
Sim-->>Builder : 返回 YearlySnapshot 列表
Builder->>Builder : 构造 CashFlowData 列表
Builder->>JSON : 写入 charts.assetDepletion 与 charts.cashFlow
JSON->>CF : 传入 CashFlowData
JSON->>LP : 传入 YearlySnapshot
CF-->>CF : 动画与 HUD 更新
LP-->>LP : 动画与 HUD 更新

图示来源

详细组件分析

1) FinancialSimulator 与现金流模拟算法

  • 财务参数默认值:通胀率、投资回报率、赤字利率,均可通过配置注入。
  • 生命周期推进:从当前年龄到预期寿命,每年计算:
    • 收入:退休前为年收入,退休后为 0。
    • 通胀:支出按年通胀指数增长。
    • 事件:匹配当年事件成本累加到支出。
    • 净现金流:收入减去总支出。
    • 资产更新:若资产余额非负,按投资回报率复利;否则按赤字利率复利(债务复合)。
  • 输出:YearlySnapshot 列表,包含年份、年龄、收入/支出/资产余额、事件标签、是否临界。
flowchart TD
Start(["开始模拟"]) --> Init["初始化资产余额与年份"]
Init --> Loop{"年龄未达寿命?"}
Loop --> |是| YearCalc["计算当年收入/通胀支出/事件成本"]
YearCalc --> Net["计算净现金流"]
Net --> Balance{"资产余额>=0?"}
Balance --> |是| Invest["按投资回报率复利"]
Balance --> |否| Deficit["按赤字利率复利"]
Invest --> Snapshot["生成 YearlySnapshot"]
Deficit --> Snapshot
Snapshot --> Loop
Loop --> |否| End(["结束"])

图示来源

章节来源

2) YearlySnapshot 与 CashFlowData 的生成与映射

  • YearlySnapshot:用于资产耗尽趋势图,包含年份、代表者与配偶年龄、收入/支出/资产余额、事件与临界标记。
  • CashFlowData:用于收支明细图,包含年份、年龄、收入(合计)、各类支出(生活/住房/教育/税费/事件)、总支出、净现金流、资产余额。
  • 数据映射:DualChartView 将 CashFlowData 转换为 YearlySnapshot 供 LifePlanChart 使用,保持统一动画进度与 HUD。
classDiagram
class YearlySnapshot {
+number year
+object ages
+object financials
+string[] events
+boolean isCritical
}
class CashFlowData {
+number year
+number age
+object income
+object expenses
+number totalExpense
+number netCashFlow
+number assetBalance
}
class FinancialSimulator {
+simulate_timeline(...)
+build_cashflow_data(timeline)
}
class DualChartView {
+convert CashFlowData -> YearlySnapshot
}
FinancialSimulator --> YearlySnapshot : "生成"
FinancialSimulator --> CashFlowData : "生成"
DualChartView --> YearlySnapshot : "转换"

图示来源

章节来源

3) Recharts 组件与数据契约映射

  • YearlySnapshotSchema:约束资产耗尽图的时间线结构,含货币单位与起始年份元数据。
  • CashFlowDataSchema:约束收支明细图的时间线结构,含货币单位元数据。
  • 组件职责:
    • CashFlowChart:堆叠柱状图展示各类支出,折线展示收入,支持年进度插值与 HUD。
    • LifePlanChart:面积图展示资产余额,支持年进度插值与渐变色(正负区间)。
    • DualChartView:统一动画进度,将 CashFlowData 转 YearlySnapshot 供 LifePlanChart 使用。
sequenceDiagram
participant TS as "render-props-types.ts"
participant CF as "CashFlowChart"
participant LP as "LifePlanChart"
participant DCV as "DualChartView"
TS->>CF : YearlySnapshotSchema/CashFlowDataSchema
TS->>LP : YearlySnapshotSchema
DCV->>LP : 转换后的 YearlySnapshot[]
DCV->>CF : CashFlowData[]
CF-->>CF : 动画与 HUD
LP-->>LP : 动画与 HUD

图示来源

章节来源

4) 数据插值、单位转换与异常值处理

  • 插值:
    • LifePlanChart:在年与年之间进行线性插值,生成“当前年进度”的中间点,保证面积图平滑过渡。
    • CashFlowChart:对当前年份内的支出条目按阶段顺序增长,同时生成一个“延伸点”以平滑收入线的视觉过渡。
  • 单位转换:
    • 元数据 currencyUnit 统一为“万円”,前端 Y 轴与 HUD 显示使用该单位。
    • LifePlanChart 对大数值采用“亿”格式化显示。
  • 异常值处理:
    • 事件成本按年聚合,避免重复或遗漏。
    • 资产余额为负时标记 isCritical,用于图表颜色与 HUD 提示。
    • 当可视窗口小于固定长度时,填充空年份占位,避免坐标轴偏移。

章节来源

5) render_props.json 中 charts 字段的构造过程

  • 构造函数 build_chart_data 读取 PDF 参数,调用 FinancialSimulator 生成两条时间线:
    • assetDepletion:timeline 为 YearlySnapshot[],meta 包含 currencyUnit 与 startYear。
    • cashFlow:timeline 为 CashFlowData[],meta 包含 currencyUnit。
  • 前端通过 render-props-types.ts 的 Schema 校验,确保数据一致性。

章节来源

6) 自定义财务假设配置方法

  • 配置入口:FinancialSimulator 的构造函数接收 config 字典,支持以下键:
    • inflation_rate:通胀率,默认 2%
    • investment_return:投资回报率,默认 3%
    • deficit_interest_rate:赤字利率(负资产时的复合成本),默认 15%
  • 使用方式:在调用 build_chart_data 前,将上述键值放入 config 传入 FinancialSimulator。

章节来源

依赖关系分析

  • 后端依赖:typing、math(用于幂运算与圆整)。
  • 前端依赖:Remotion hooks(useCurrentFrame/useVideoConfig/interpolate)、Recharts(ComposedChart/AreaChart 等)、Zod(Schema 校验)。
  • 类型契约:render-props-types.ts 定义 YearlySnapshotSchema 与 CashFlowDataSchema,确保前后端一致。
graph LR
DB["data_builder.py"] --> FS["FinancialSimulator"]
FS --> YS["YearlySnapshot"]
FS --> CFData["CashFlowData"]
RP["render-props-types.ts"] --> YSS["YearlySnapshotSchema"]
RP --> CFS["CashFlowDataSchema"]
CF["CashFlowChart.tsx"] --> YS
LP["LifePlanChart.tsx"] --> YS
DCV["DualChartView.tsx"] --> YS

图示来源

章节来源

性能考量

  • 大数据量分段处理策略:
    • 限制每帧可见数据长度:当可视窗口较短时,使用固定域与占位年份,避免 Recharts 重绘抖动。
    • 使用 useMemo 缓存转换结果(如 DualChartView 将 CashFlowData 转 YearlySnapshot),减少组件重渲染。
    • 动画插值仅在必要范围内计算,避免全量数据参与每帧运算。
  • 数值稳定性:
    • 对资产余额与支出进行圆整,减少浮点误差累积。
    • Y 轴域基于完整时间线计算,避免动画过程中轴范围跳变。
  • 渲染优化:
    • 关闭内部动画(isAnimationActive=false),由外部帧进度驱动,降低 Recharts 内部开销。
    • 使用稳定的配置对象(如 CHART_MARGIN)避免每次渲染创建新对象。

章节来源

故障排查指南

  • 数据不一致:
    • 检查 render-props-types.ts 的 YearlySnapshotSchema 与 CashFlowDataSchema 是否与后端输出一致。
    • 使用 validateRenderProps 或 isRenderProps 进行运行时校验。
  • 图表显示异常:
    • 确认 meta.currencyUnit 与前端 Y 轴单位一致。
    • 若出现坐标轴跳变,检查 Y 轴域计算逻辑(完整时间线 vs 可见数据)。
  • 动画不同步:
    • 确保 DualChartView 使用统一的外部索引与年进度参数传递给两个子图。
  • 事件/临界状态错误:
    • 检查事件成本聚合与 isCritical 标记逻辑,确保资产余额为负时正确标注。

章节来源

结论

本模块通过 FinancialSimulator 将 PDF 输入转化为两条高质量时序数据,借助 YearlySnapshot 与 CashFlowData 的清晰契约,实现了资产耗尽趋势与收支明细的双视图联动渲染。前后端通过 Zod Schema 严格约束数据结构,配合 Recharts 的插值与 HUD 机制,提供了流畅且可解释的财务可视化体验。通过合理的分段处理与缓存策略,可在大数据量场景下保持稳定性能。

附录