大量更新
This commit is contained in:
21
16-ProjectMoneyM-转FireFlyIII/1-原始需求/0-产品经理-prompt.md
Normal file
21
16-ProjectMoneyM-转FireFlyIII/1-原始需求/0-产品经理-prompt.md
Normal file
@@ -0,0 +1,21 @@
|
||||
你现在是一名策略产品经理,你擅长进行市场研究和竞品分析,以制定产品策略。你能把握行业趋势,了解用户需求,并在此基础上优化产品功能和用户体验。请在这个角色下为我解答以下问题。
|
||||
|
||||
----
|
||||
|
||||
你是一名出色的产品经理,能够根据用户的初始需求,理解用户需求的真实需求意图,改善客户不够完善的需求,形成专业、简练的需求文档。并且能够在基础需求上优化产品的额设计和功能
|
||||
|
||||
请根据要求,进行深度的思考,优化[1-初始需求稿.md],直接给出优化后的PRD
|
||||
|
||||
注意及要求如下
|
||||
1. 括号内的内容需要关注,需要根据括号内的内容进行修改,是你需要给出建议的内容,正式文档中应该去掉括号及内容
|
||||
2. 必要时候应该联网搜索,查询开源的项目实现等
|
||||
|
||||
----
|
||||
|
||||
你是一名出色的产品经理,请你根据[1-初始需求稿.md]客户的原始需求,审查[2-优化产品需求文档PRD.md],检查PRD文档是否完全满足原始需求;如果有更加优秀的设计方案,请给出修改建议
|
||||
|
||||
----
|
||||
|
||||
你是一名出色的产品经理,能够根据用户的初始需求,理解用户需求的真实需求意图,改善客户不够完善的需求,形成专业、简练的需求文档。并且能够在基础需求上优化产品的额设计和功能
|
||||
|
||||
你之前根据[1-初始需求稿.md]输出了[2-优化产品需求文档PRD.md], 目前初始需求有一些更新,见[1.1-初始需求稿.md],请你详细对比[1.1-初始需求稿.md]和[1-初始需求稿.md]之间的差异, 修改[2-优化产品需求文档PRD.md],得到新的需求文档
|
||||
83
16-ProjectMoneyM-转FireFlyIII/1-原始需求/1-初始需求稿.md
Normal file
83
16-ProjectMoneyM-转FireFlyIII/1-原始需求/1-初始需求稿.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# 个人财务分析系统
|
||||
``` 项目名称: ProjectMoneyM ```
|
||||
``` 项目版本: v1.0 ```
|
||||
``` 项目编制日期: 2026-02-26 ```
|
||||
|
||||
## 数据来源
|
||||
|
||||
1. 数据来源
|
||||
| 数据来源 | 最长周期 | 文件格式 | 说明 | 数据维度 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 支付宝账单 | 1年 | csv | 第一来源 | 最全 |
|
||||
| 微信账单 | 3个月 | csv | 第二来源 | 第二全 |
|
||||
| 招商银行 | 1年 | pdf | 第三来源 | 第三全 |
|
||||
| 京东商城 | 1年 | pdf | 第四来源 | 第四全 |
|
||||
|
||||
2. 数据解析工具
|
||||
1. 能够读取不同格式的账单来源
|
||||
2. 能够通过OCR的方式解析特定的收入数据
|
||||
|
||||
|
||||
## 数据清洗及标准化
|
||||
|
||||
1. 时间维度清洗
|
||||
1. 需要统一时间维度,统一为东八区时间,格式为yyyy-MM-dd HH:mm:ss
|
||||
2. 数据展示环节 需要能够通过时间段进行筛选查询收支数据
|
||||
2. 支付项目清洗
|
||||
1. 需要过滤重复的支付项
|
||||
2. 需要明确支付途径和支付卡
|
||||
3. 例如,一笔支出,银行账单会记录支出,支付宝或者微信会记录支出,需要将这些重复的支付项合并
|
||||
4. 支付途径为: 支付宝,微信,云闪付,京东,美团,拼多多
|
||||
5. 实际支付卡为: 信用卡,借记卡,余额宝,微信钱包,支付宝钱包
|
||||
6. 支出项目的账本归类
|
||||
1. 一笔支出可以归于一个或者多个账本
|
||||
2. 一笔支出需要在日常开支中进行分析,也需要在过年支出这种特殊的账本中进行分析
|
||||
3. 支付金额清洗
|
||||
1. 需要统一为标准的数据格式
|
||||
4. 支出去向清洗
|
||||
1. 需要将支出进行分类
|
||||
2. 请参考支付宝的支出分类
|
||||
|
||||
|
||||
## 收支情况 展示内容
|
||||
```此部分重要使用前端图表工具进行绘图展示```
|
||||
|
||||
### 收支分析(请给出能够展示的图形类型)
|
||||
1. 需要直观的看出结余情况, 收入大于支出,支出大于收入的对比
|
||||
2. 时间维度为,月度,季度,年度,重点展示月度收支情况
|
||||
3. 收支的最小维度为月度
|
||||
|
||||
|
||||
### 收入分析(请给出能够展示的图形类型)
|
||||
|
||||
#### 收入趋势
|
||||
1. 能够根据不同的时间维度进行收入的对比
|
||||
2. 能够直观的展示收入的趋势
|
||||
#### 收入总览
|
||||
1. 收入来源占比分析
|
||||
2. 时间维度,重点展示年度收入,季度收入
|
||||
3. 收入的最小维度为月度
|
||||
|
||||
#### 收入
|
||||
|
||||
### 支出分析(请给出能够展示的图形类型)
|
||||
#### 支出趋势
|
||||
1. 能够根据不同的时间维度进行支出的对比
|
||||
2. 能够直观的展示支出的趋势
|
||||
#### 支出总览
|
||||
1. 支出去向占比分析
|
||||
2. 时间维度,重点展示年度支出,季度支出
|
||||
3. 支出的最小维度为月度
|
||||
|
||||
|
||||
### 展示内容导出
|
||||
1. 支持将展示内容导出为图片
|
||||
2. 支持将展示内容导出为PDF文件
|
||||
|
||||
## 技术栈
|
||||
1. Golang
|
||||
2. Vue
|
||||
3. TypeScript
|
||||
4. SQLite
|
||||
5. ECharts(寻找适合的图表工具,不限于ECharts)
|
||||
|
||||
106
16-ProjectMoneyM-转FireFlyIII/1-原始需求/2-1-优化产品需求文档PRD.md
Normal file
106
16-ProjectMoneyM-转FireFlyIII/1-原始需求/2-1-优化产品需求文档PRD.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# 产品需求文档 (PRD): ProjectMoneyX 个人全景财务分析系统
|
||||
|
||||
| 文档属性 | 详情 |
|
||||
| --- | --- |
|
||||
| **项目名称** | ProjectMoneyX |
|
||||
| **版本号** | v1.2 (基于开源 ETL 架构优化版) |
|
||||
| **编制日期** | 2026-02-26 |
|
||||
| **文档状态** | 进行中 |
|
||||
|
||||
## 1. 项目背景与目标
|
||||
|
||||
### 1.1 项目背景
|
||||
|
||||
随着移动支付的普及,个人财务数据分散在支付宝、微信、各家银行及电商平台中。用户面临“账单碎片化”、“流水重复记录”等痛点。传统的记账软件通常依赖手动记录或单一的账单导入,缺乏灵活的规则引擎来处理复杂的跨账户对账。
|
||||
|
||||
### 1.2 项目目标
|
||||
|
||||
构建一套自动化、高精度的个人财务分析系统。借鉴开源社区成熟的双轨制记账流转架构,通过引入 `Provider` 解析器与 `Translate` 规则引擎,实现多源数据的标准化转换(IR),并利用算法解决跨账户流水重复问题,提供多维度的收支分析与预算管理功能。
|
||||
|
||||
---
|
||||
|
||||
## 2. 核心系统架构:ETL 数据工作流
|
||||
|
||||
参考业内成熟方案,系统底层采用高度解耦的管道架构,确保后续极强的可扩展性:
|
||||
|
||||
**数据流转路径:** `原始账单 (Raw Files) -> 提供方解析 (Provider) -> 中间表示 (IR) -> 规则转换 (Translate) -> 数据库标准账单`
|
||||
|
||||
* **Provider 层:** 专注于“读”。屏蔽不同账单格式(CSV, PDF, Excel)的差异。
|
||||
* **IR 层 (Intermediate Representation):** 统一的数据结构协议,作为 Provider 和 Translate 的桥梁。
|
||||
* **Translate 层:** 专注于“洗”。基于 YAML/JSON 规则配置,执行分类映射、时间标准化与账户归属。
|
||||
|
||||
---
|
||||
|
||||
## 3. 数据采集与 Provider 模块 (Data Ingestion)
|
||||
|
||||
针对不同来源的账单,建立独立的 Provider 适配器。当某银行账单格式更新时,仅需修改或新增对应的 Provider,不影响系统核心逻辑。
|
||||
|
||||
| 提供方 (Provider) | 原始格式 | 核心提取字段 | 数据权重 | 提取说明 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| **Alipay (支付宝)** | CSV | 订单号、商户、商品明细、金额 | **L1 (最高)** | 标准 CSV 解析,作为消费类主数据。 |
|
||||
| **WeChat (微信支付)** | CSV | 交易单号、交易对方、交易类型 | **L2** | 预处理跳过表头,提取转账与红包标记。 |
|
||||
| **Banks (招商/工行等)** | PDF/XLS | 交易日、交易摘要、收支金额 | **L3** | 作为资金实际扣款核对依据 (Reconciliation)。 |
|
||||
| **JD/Meituan (电商)** | PDF/CSV | 订单明细、支付通道 | **L3** | 重点关注白条/月付等信用支付记录。 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 数据转换与清洗逻辑 (Translate & Cleaning)
|
||||
|
||||
Translate 层是数据质量的核心把控者,负责将 IR 数据转换为最终的财务记录,并解决数据冲突。
|
||||
|
||||
### 4.1 Translate 规则引擎
|
||||
|
||||
建立基于配置文件的映射规则,实现自动化数据归位:
|
||||
|
||||
* **时间与时区标准化:** 统一转换为 ISO 8601 格式,所有国内交易归一化为东八区时间。
|
||||
* **账户路由 (Account Routing):** * *规则示例:* 当 Provider 为 `Alipay`,且原始数据中的支付方式为“招商银行信用卡”时,资金来源(Funding Source)自动映射至用户的“招行信用卡”实体账户。
|
||||
* **智能分类映射 (Category Mapping):**
|
||||
* 根据交易对方 (Peer) 或 商品说明 (Item) 进行正则匹配。
|
||||
* *规则示例:* `Peer` 包含“星巴克”或“瑞幸” -> 映射分类为 [餐饮-咖啡]。
|
||||
|
||||
|
||||
|
||||
### 4.2 交易链路合并与去重算法 (De-duplication)
|
||||
|
||||
同一笔交易会在支付平台(如微信)和资金源(如银行卡)各产生一条流水。系统通过**时间窗与金额双重校验**进行链路合并,而非粗暴删除。
|
||||
|
||||
**核心算法逻辑:**
|
||||
设高权重账单记录为 $T_{primary}$(如支付宝),低权重账单记录为 $T_{secondary}$(如银行卡)。
|
||||
当同时满足以下条件时,判定为同一条交易链路:
|
||||
|
||||
$$| Time(T_{primary}) - Time(T_{secondary}) | \le \Delta t \quad (\text{建议 } \Delta t = 120s)$$
|
||||
|
||||
$$Amount(T_{primary}) = Amount(T_{secondary})$$
|
||||
|
||||
**处理策略:**
|
||||
|
||||
1. 将两条记录在底层数据库建立关联(Parent-Child 或 LinkID)。
|
||||
2. 前端展示时,**合并为一笔记录**。保留 $T_{primary}$ 的丰富消费明细(如分类、商户名),将 $T_{secondary}$ 的账户信息作为该笔消费的资金出处。
|
||||
|
||||
---
|
||||
|
||||
## 5. 核心功能模块详述
|
||||
|
||||
### 5.1 全景仪表盘 (Dashboard)
|
||||
|
||||
* **资产负债表:** 实时聚合各账户总资产、总负债(信用卡/白条),计算净资产。
|
||||
* **现金流概览:** 本月总收入 vs 总支出,环比上月 (MoM) 增减百分比。
|
||||
|
||||
### 5.2 账单查询与多维分析
|
||||
|
||||
* **组合漏斗筛选:** 支持时间范围、金额区间、支付渠道、资金账户、交易分类的多条件交叉查询。
|
||||
* **可视化图表:**
|
||||
* **消费结构:** 饼图展示各大类的支出占比。
|
||||
* **资金流向 (Sankey Diagram):** 桑基图直观展示“收入源 -> 资金池 (账户) -> 支出分类”的完整链路。
|
||||
|
||||
|
||||
### 5.3 预算管理
|
||||
|
||||
* **精细化限额:** 支持全局预算和分类预算(例如:设定“交通”每月额度 1000 元)。
|
||||
* **阈值预警:** 当分类支出进度达到 80% 和 100% 时,系统触发视觉高亮预警。
|
||||
|
||||
---
|
||||
|
||||
## 6. 非功能需求 (NFR)
|
||||
|
||||
* **数据隐私 (Local-First):** 财务数据极其敏感,系统解析 (Provider) 和转换 (Translate) 过程应优先在客户端(本地环境)执行,拒绝未经加密的云端明文传输。
|
||||
139
16-ProjectMoneyM-转FireFlyIII/1-原始需求/2-优化产品需求文档PRD.md
Normal file
139
16-ProjectMoneyM-转FireFlyIII/1-原始需求/2-优化产品需求文档PRD.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# 产品需求文档 (PRD): ProjectMoneyX 个人全景财务分析系统
|
||||
|
||||
| 文档属性 | 详情 |
|
||||
| --- | --- |
|
||||
| **项目名称** | ProjectMoneyX |
|
||||
| **版本号** | v1.1 (优化版) |
|
||||
| **编制日期** | 2026-02-26 |
|
||||
|
||||
## 1. 项目背景与目标
|
||||
|
||||
### 1.1 项目背景
|
||||
|
||||
随着移动支付的普及,个人财务数据分散在支付宝、微信、各家银行APP及电商平台中。用户难以通过单一平台获取全景财务状况,面临“账单碎片化”、“流水重复记录”、“统计维度单一”等痛点。
|
||||
|
||||
### 1.2 项目目标
|
||||
|
||||
构建一套自动化、高精度的个人财务分析系统。通过ETL(抽取、转换、加载)技术整合多源数据,利用算法解决跨账户流水重复问题,提供多维度的收支分析、资产趋势及预算管理功能,帮助用户实现“上帝视角”的财务管控。
|
||||
|
||||
---
|
||||
|
||||
## 2. 数据源与采集规范 (Data Ingestion)
|
||||
|
||||
系统需支持多格式、多来源的账单导入,并建立可扩展的解析适配器模式。
|
||||
|
||||
| 数据来源 | 原始格式 | 数据周期 | 解析策略 | 数据权重 | 备注 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| **支付宝** | CSV | 1年 | Pandas直接读取 | **L1 (最高)** | 包含商品明细,作为消费类主数据 |
|
||||
| **微信支付** | CSV | 3个月 | Pandas预处理 (表头清洗) | **L2** | 包含转账与社交红包,需特殊标记 |
|
||||
| **招商银行** | PDF | 1年 | 文本流解析 (pdfplumber) | **L3** | 作为资金来源核对依据 (Reconciliation) |
|
||||
| **京东金融** | PDF/XLS | 1年 | 文本流解析 / OCR辅助 | **L3** | 重点关注“白条”类信贷数据 |
|
||||
| **云闪付** | PDF/CSV | 1年 | 适配器解析 | **L3** | 银联通道补充数据 |
|
||||
|
||||
**功能要求:**
|
||||
|
||||
* **适配器模式(Adapter Pattern):** 针对不同来源开发独立的解析类(Parser Class),当银行账单格式变更时,仅需更新对应解析器。
|
||||
* **OCR 增强解析:** 针对图片格式的账单或非标准的扫描版PDF,集成 OCR 引擎(如 PaddleOCR)进行关键字段(日期、金额、商户)提取。
|
||||
|
||||
---
|
||||
|
||||
## 3. 数据清洗与核心逻辑 (Data Cleaning & Logic)
|
||||
|
||||
这是本系统的核心壁垒,重点解决多渠道数据冲突与标准化问题。
|
||||
|
||||
### 3.1 时间维度标准化
|
||||
|
||||
* **存储标准:** 所有交易时间戳统一转换为 **ISO 8601** 格式存储。
|
||||
* **时区处理:** 统一归一化为 `UTC+8`。若涉及跨国交易(如外币信用卡),需保留原始交易币种和时间,并记录当期汇率。
|
||||
* **查询支持:** 数据库层需支持基于时间窗口(Time Window)的聚合查询(如:`BETWEEN '2026-02-01' AND '2026-02-28'`)。
|
||||
|
||||
### 3.2 交易去重与链路合并 (De-duplication & Linkage)
|
||||
|
||||
初始需求中提到的“重复项”实际上是“同一笔交易在不同账户的映射”。系统不应简单删除,而应建立**交易链路(Transaction Linkage)**。
|
||||
|
||||
**核心算法逻辑:**
|
||||
设支付宝账单记录为 $T_{ali}$,银行账单记录为 $T_{bank}$。
|
||||
当满足以下条件时,判定为同一笔交易:
|
||||
|
||||
$$| Time(T_{ali}) - Time(T_{bank}) | \le \Delta t \quad (\text{建议 } \Delta t = 120s)$$
|
||||
|
||||
$$Amount(T_{ali}) = Amount(T_{bank})$$
|
||||
|
||||
**处理策略:**
|
||||
|
||||
1. **合并展示:** 将两条记录关联。
|
||||
* **主记录(保留):** 支付宝/微信记录(因其包含具体的商户名、商品名、消费分类)。
|
||||
* **辅记录(隐藏/标记):** 银行卡记录标记为“资金划转(Transfer)”或“支付源扣款”。
|
||||
|
||||
|
||||
2. **账户归属明确:**
|
||||
* **支付渠道(Payment Channel):** 支付宝、微信、云闪付、美团。
|
||||
* **资金账户(Funding Source):** 招商银行信用卡、工商银行储蓄卡、京东白条、余额宝。
|
||||
* *示例:* 用户在淘宝买衣服,用支付宝绑定的招行卡支付。系统记录为:**支出 200元 (分类:服饰)**,支付渠道:**支付宝**,资金来源:**招行信用卡**。
|
||||
|
||||
|
||||
|
||||
### 3.3 智能分类 (Smart Categorization)
|
||||
|
||||
* **多级分类体系:**
|
||||
* 一级分类:餐饮、交通、购物、居住、娱乐、医疗、金融。
|
||||
* 二级分类:早餐/正餐、地铁/打车、数码/服饰、房租/水电。
|
||||
|
||||
|
||||
* **关键词映射:** 建立 `Merchant_Keyword_Map` 表。
|
||||
* 例:包含“星巴克”、“瑞幸” -> 自动归类为 [餐饮-咖啡]。
|
||||
* 例:包含“中国石油” -> 自动归类为 [交通-加油]。
|
||||
|
||||
|
||||
* **人工修正与学习:** 用户手动修改某一笔交易分类后,系统询问“是否将该商户后续交易默认应用此分类”。
|
||||
|
||||
---
|
||||
|
||||
## 4. 功能模块详述
|
||||
|
||||
### 4.1 仪表盘 (Dashboard)
|
||||
|
||||
* **全景资产卡片:** 显示总资产、总负债(信用卡+白条+花呗)、净资产。
|
||||
* **本月收支概览:** * 当月支出 vs 上月同期环比 (MoM)。
|
||||
* 预算执行进度条(如:本月预算剩余 30%)。
|
||||
|
||||
|
||||
* **收支趋势图:** 折线图展示近12个月的收支波动。
|
||||
|
||||
### 4.2 账单查询与分析
|
||||
|
||||
* **高级筛选器:** 支持组合条件筛选:
|
||||
* 时间范围(自定义/本周/本月/本年)。
|
||||
* 金额区间(如:> 1000元的大额支出)。
|
||||
* 支付渠道 & 资金账户。
|
||||
* 交易分类。
|
||||
* 关键词搜索(如:“京东”)。
|
||||
|
||||
|
||||
* **多维图表:**
|
||||
* [饼图] 消费结构分析(哪类钱花得最多)。
|
||||
* [堆叠柱状图] 支付渠道依赖度分析。
|
||||
* [桑基图 (Sankey Diagram)] 资金流向可视化(从收入 -> 账户 -> 支出类别)。
|
||||
|
||||
|
||||
|
||||
### 4.3 预算与预警
|
||||
|
||||
* **预算设置:** 支持总预算及分分类预算(如:“餐饮”每月限额 3000元)。
|
||||
* **超支预警:** 当某一类别支出达到预算的 80% 时,界面高亮提示。
|
||||
|
||||
---
|
||||
|
||||
## 5. 非功能需求 (NFR)
|
||||
|
||||
### 5.1 数据隐私与安全
|
||||
|
||||
* **本地优先(Local-First):** 鉴于财务数据极度敏感,建议所有数据解析、清洗、存储默认在用户本地电脑中完成。
|
||||
|
||||
---
|
||||
## 技术栈
|
||||
1. Golang
|
||||
2. Vue
|
||||
3. TypeScript
|
||||
4. SQLite
|
||||
5. ECharts(寻找适合的图表工具,不限于ECharts)
|
||||
33
16-ProjectMoneyM-转FireFlyIII/2-概要详细设计/0-概要设计prompt.md
Normal file
33
16-ProjectMoneyM-转FireFlyIII/2-概要详细设计/0-概要设计prompt.md
Normal file
@@ -0,0 +1,33 @@
|
||||
你是一名资深的软件系统架构师,具备以下核心职责与能力,绘图请使用mermaid语言:
|
||||
|
||||
## 需求分析与理解
|
||||
|
||||
- 深度解读产品需求文档(PRD),识别业务目标、功能需求与非功能性需求
|
||||
- 分析需求间的依赖关系与优先级,识别潜在的技术风险与挑战
|
||||
|
||||
## 架构设计与规划
|
||||
|
||||
- 设计高可用、可扩展、高性能的系统架构,确保系统健壮性与安全性
|
||||
- 制定技术选型方案,包括开发语言、框架、中间件、数据库等关键技术栈
|
||||
- 绘制多层次架构图(系统架构图、数据流图、组件交互图)
|
||||
- 定义模块划分、接口规范、数据模型与核心算法策略
|
||||
- 规划系统分层结构(展现层、业务层、数据层),明确各层职责边界
|
||||
|
||||
## 方案设计与输出
|
||||
|
||||
- 针对核心需求点提供详细的技术解决方案,包含实现路径与备选方案
|
||||
- 设计关键业务流程的时序图与状态机,确保逻辑清晰完整
|
||||
- 输出规范化的《系统详细设计说明书》,包含架构设计、接口定义、数据库设计等完整文档
|
||||
|
||||
## 技术栈说明
|
||||
- 后端开发技术栈 Golang GROM GIN
|
||||
- 前端开发技术栈 Vue3 TypeScript Vuetify
|
||||
|
||||
## 参考项目
|
||||
- 项目有非常完善的数据清洗工具,基本满足了数据读取部分,可以摘取此项目的数据translate provider部分代码 [double-entry-generator](https://github.com/deb-sig/double-entry-generator)
|
||||
|
||||
请根据[2-优化产品需求文档PRD.md],按照上述的要求,输出系统详细设计说明书
|
||||
|
||||
|
||||
|
||||
你之前根据[2-优化产品需求文档PRD.md]输出了[3-详细设计说明书.md], 目前PRD需求有一些更新,见[2.1-优化产品需求文档PRD.md],请你详细对比[2.1-优化产品需求文档PRD.md]和[2-优化产品需求文档PRD.md]之间的差异, 修改[3-详细设计说明书.md],得到新的需求文档.要求尽量不改动[3-详细设计说明书.md]的初始设计,只改动差异化部分的设计
|
||||
1785
16-ProjectMoneyM-转FireFlyIII/2-概要详细设计/3-详细设计说明书.md
Normal file
1785
16-ProjectMoneyM-转FireFlyIII/2-概要详细设计/3-详细设计说明书.md
Normal file
File diff suppressed because it is too large
Load Diff
106
16-ProjectMoneyM-转FireFlyIII/3-实现详细稿/1-ProjectMoneyM-PRD.md
Normal file
106
16-ProjectMoneyM-转FireFlyIII/3-实现详细稿/1-ProjectMoneyM-PRD.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# 产品需求文档 (PRD): ProjectMoneyX 个人全景财务分析系统
|
||||
|
||||
| 文档属性 | 详情 |
|
||||
| --- | --- |
|
||||
| **项目名称** | ProjectMoneyX |
|
||||
| **版本号** | v1.2 (基于开源 ETL 架构优化版) |
|
||||
| **编制日期** | 2026-02-26 |
|
||||
| **文档状态** | 进行中 |
|
||||
|
||||
## 1. 项目背景与目标
|
||||
|
||||
### 1.1 项目背景
|
||||
|
||||
随着移动支付的普及,个人财务数据分散在支付宝、微信、各家银行及电商平台中。用户面临“账单碎片化”、“流水重复记录”等痛点。传统的记账软件通常依赖手动记录或单一的账单导入,缺乏灵活的规则引擎来处理复杂的跨账户对账。
|
||||
|
||||
### 1.2 项目目标
|
||||
|
||||
构建一套自动化、高精度的个人财务分析系统。借鉴开源社区成熟的双轨制记账流转架构,通过引入 `Provider` 解析器与 `Translate` 规则引擎,实现多源数据的标准化转换(IR),并利用算法解决跨账户流水重复问题,提供多维度的收支分析与预算管理功能。
|
||||
|
||||
---
|
||||
|
||||
## 2. 核心系统架构:ETL 数据工作流
|
||||
|
||||
参考业内成熟方案,系统底层采用高度解耦的管道架构,确保后续极强的可扩展性:
|
||||
|
||||
**数据流转路径:** `原始账单 (Raw Files) -> 提供方解析 (Provider) -> 中间表示 (IR) -> 规则转换 (Translate) -> 数据库标准账单`
|
||||
|
||||
* **Provider 层:** 专注于“读”。屏蔽不同账单格式(CSV, PDF, Excel)的差异。
|
||||
* **IR 层 (Intermediate Representation):** 统一的数据结构协议,作为 Provider 和 Translate 的桥梁。
|
||||
* **Translate 层:** 专注于“洗”。基于 YAML/JSON 规则配置,执行分类映射、时间标准化与账户归属。
|
||||
|
||||
---
|
||||
|
||||
## 3. 数据采集与 Provider 模块 (Data Ingestion)
|
||||
|
||||
针对不同来源的账单,建立独立的 Provider 适配器。当某银行账单格式更新时,仅需修改或新增对应的 Provider,不影响系统核心逻辑。
|
||||
|
||||
| 提供方 (Provider) | 原始格式 | 核心提取字段 | 数据权重 | 提取说明 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| **Alipay (支付宝)** | CSV | 订单号、商户、商品明细、金额 | **L1 (最高)** | 标准 CSV 解析,作为消费类主数据。 |
|
||||
| **WeChat (微信支付)** | CSV | 交易单号、交易对方、交易类型 | **L2** | 预处理跳过表头,提取转账与红包标记。 |
|
||||
| **Banks (招商/工行等)** | PDF/XLS | 交易日、交易摘要、收支金额 | **L3** | 作为资金实际扣款核对依据 (Reconciliation)。 |
|
||||
| **JD/Meituan (电商)** | PDF/CSV | 订单明细、支付通道 | **L3** | 重点关注白条/月付等信用支付记录。 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 数据转换与清洗逻辑 (Translate & Cleaning)
|
||||
|
||||
Translate 层是数据质量的核心把控者,负责将 IR 数据转换为最终的财务记录,并解决数据冲突。
|
||||
|
||||
### 4.1 Translate 规则引擎
|
||||
|
||||
建立基于配置文件的映射规则,实现自动化数据归位:
|
||||
|
||||
* **时间与时区标准化:** 统一转换为 ISO 8601 格式,所有国内交易归一化为东八区时间。
|
||||
* **账户路由 (Account Routing):** * *规则示例:* 当 Provider 为 `Alipay`,且原始数据中的支付方式为“招商银行信用卡”时,资金来源(Funding Source)自动映射至用户的“招行信用卡”实体账户。
|
||||
* **智能分类映射 (Category Mapping):**
|
||||
* 根据交易对方 (Peer) 或 商品说明 (Item) 进行正则匹配。
|
||||
* *规则示例:* `Peer` 包含“星巴克”或“瑞幸” -> 映射分类为 [餐饮-咖啡]。
|
||||
|
||||
|
||||
|
||||
### 4.2 交易链路合并与去重算法 (De-duplication)
|
||||
|
||||
同一笔交易会在支付平台(如微信)和资金源(如银行卡)各产生一条流水。系统通过**时间窗与金额双重校验**进行链路合并,而非粗暴删除。
|
||||
|
||||
**核心算法逻辑:**
|
||||
设高权重账单记录为 $T_{primary}$(如支付宝),低权重账单记录为 $T_{secondary}$(如银行卡)。
|
||||
当同时满足以下条件时,判定为同一条交易链路:
|
||||
|
||||
$$| Time(T_{primary}) - Time(T_{secondary}) | \le \Delta t \quad (\text{建议 } \Delta t = 120s)$$
|
||||
|
||||
$$Amount(T_{primary}) = Amount(T_{secondary})$$
|
||||
|
||||
**处理策略:**
|
||||
|
||||
1. 将两条记录在底层数据库建立关联(Parent-Child 或 LinkID)。
|
||||
2. 前端展示时,**合并为一笔记录**。保留 $T_{primary}$ 的丰富消费明细(如分类、商户名),将 $T_{secondary}$ 的账户信息作为该笔消费的资金出处。
|
||||
|
||||
---
|
||||
|
||||
## 5. 核心功能模块详述
|
||||
|
||||
### 5.1 全景仪表盘 (Dashboard)
|
||||
|
||||
* **资产负债表:** 实时聚合各账户总资产、总负债(信用卡/白条),计算净资产。
|
||||
* **现金流概览:** 本月总收入 vs 总支出,环比上月 (MoM) 增减百分比。
|
||||
|
||||
### 5.2 账单查询与多维分析
|
||||
|
||||
* **组合漏斗筛选:** 支持时间范围、金额区间、支付渠道、资金账户、交易分类的多条件交叉查询。
|
||||
* **可视化图表:**
|
||||
* **消费结构:** 饼图展示各大类的支出占比。
|
||||
* **资金流向 (Sankey Diagram):** 桑基图直观展示“收入源 -> 资金池 (账户) -> 支出分类”的完整链路。
|
||||
|
||||
|
||||
### 5.3 预算管理
|
||||
|
||||
* **精细化限额:** 支持全局预算和分类预算(例如:设定“交通”每月额度 1000 元)。
|
||||
* **阈值预警:** 当分类支出进度达到 80% 和 100% 时,系统触发视觉高亮预警。
|
||||
|
||||
---
|
||||
|
||||
## 6. 非功能需求 (NFR)
|
||||
|
||||
* **数据隐私 (Local-First):** 财务数据极其敏感,系统解析 (Provider) 和转换 (Translate) 过程应优先在客户端(本地环境)执行,拒绝未经加密的云端明文传输。
|
||||
951
16-ProjectMoneyM-转FireFlyIII/3-实现详细稿/2-ProjectMoneyM-DDS.md
Normal file
951
16-ProjectMoneyM-转FireFlyIII/3-实现详细稿/2-ProjectMoneyM-DDS.md
Normal file
@@ -0,0 +1,951 @@
|
||||
# 系统详细设计说明书 (DDS): ProjectMoneyX 个人全景财务分析系统
|
||||
|
||||
| 文档属性 | 详情 |
|
||||
| --- | --- |
|
||||
| **项目名称** | ProjectMoneyX |
|
||||
| **版本号** | v1.0 |
|
||||
| **编制日期** | 2026-02-26 |
|
||||
| **文档状态** | 初稿 |
|
||||
| **技术栈** | Golang (Gin + GORM) / Vue3 + TypeScript + Vuetify / ECharts |
|
||||
| **参考项目** | [double-entry-generator](https://github.com/deb-sig/double-entry-generator) |
|
||||
|
||||
---
|
||||
|
||||
## 1. 系统总体架构
|
||||
|
||||
### 1.1 架构概览
|
||||
|
||||
系统采用前后端分离的 B/S 架构,后端以 Golang Gin 框架提供 RESTful API,前端以 Vue3 + Vuetify 构建 SPA 应用。核心数据处理流程借鉴 `double-entry-generator` 的 **Provider → IR → Translate** 管道模式,将其从命令行工具改造为 Web 服务。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph Frontend["前端 (Vue3 + Vuetify + ECharts)"]
|
||||
UI_Upload["账单上传"]
|
||||
UI_Dashboard["全景仪表盘"]
|
||||
UI_Query["账单查询与分析"]
|
||||
UI_Budget["预算管理"]
|
||||
UI_Account["账户管理"]
|
||||
UI_Rule["规则配置"]
|
||||
end
|
||||
|
||||
subgraph Backend["后端 (Golang Gin)"]
|
||||
API["RESTful API Layer (Gin Router)"]
|
||||
SVC["Service Layer"]
|
||||
ETL["ETL Pipeline"]
|
||||
subgraph ETL_Detail["ETL 管道"]
|
||||
Provider["Provider 解析层"]
|
||||
IR["IR 中间表示层"]
|
||||
Translate["Translate 规则引擎"]
|
||||
Dedup["去重引擎"]
|
||||
end
|
||||
REPO["Repository Layer (GORM)"]
|
||||
end
|
||||
|
||||
subgraph Storage["数据存储"]
|
||||
DB["SQLite / MySQL"]
|
||||
FileStore["本地文件存储"]
|
||||
end
|
||||
|
||||
Frontend -->|HTTP/JSON| API
|
||||
API --> SVC
|
||||
SVC --> ETL
|
||||
ETL_Detail --> REPO
|
||||
SVC --> REPO
|
||||
REPO --> DB
|
||||
Provider --> FileStore
|
||||
```
|
||||
|
||||
### 1.2 分层架构说明
|
||||
|
||||
| 层级 | 职责 | 技术选择 |
|
||||
| --- | --- | --- |
|
||||
| **展现层 (Presentation)** | UI 渲染、用户交互、数据可视化 | Vue3 + Vuetify + ECharts |
|
||||
| **API 层 (API Gateway)** | 路由分发、参数校验、认证鉴权、响应封装 | Gin Framework |
|
||||
| **业务层 (Service)** | 核心业务逻辑编排、ETL 流程调度 | Go Service |
|
||||
| **数据处理层 (ETL Pipeline)** | Provider 解析、IR 转换、Translate 规则、去重合并 | Go (参考 double-entry-generator) |
|
||||
| **数据访问层 (Repository)** | ORM 映射、数据库 CRUD | GORM |
|
||||
| **数据存储层 (Storage)** | 持久化存储 | SQLite (默认, Local-First) / MySQL (可选) |
|
||||
|
||||
---
|
||||
|
||||
## 2. 后端详细设计
|
||||
|
||||
### 2.1 项目目录结构
|
||||
|
||||
```
|
||||
projectmoneyx-server/
|
||||
├── main.go # 程序入口
|
||||
├── config/
|
||||
│ └── config.go # 配置加载 (YAML)
|
||||
├── internal/
|
||||
│ ├── api/ # API 层 (Gin Handler)
|
||||
│ │ ├── router.go # 路由注册
|
||||
│ │ ├── middleware/ # 中间件 (CORS, Logger, Auth)
|
||||
│ │ ├── handler/
|
||||
│ │ │ ├── bill_handler.go
|
||||
│ │ │ ├── account_handler.go
|
||||
│ │ │ ├── budget_handler.go
|
||||
│ │ │ ├── dashboard_handler.go
|
||||
│ │ │ ├── category_handler.go
|
||||
│ │ │ └── rule_handler.go
|
||||
│ │ └── dto/ # 请求/响应 DTO
|
||||
│ │ ├── request.go
|
||||
│ │ └── response.go
|
||||
│ ├── service/ # 业务层
|
||||
│ │ ├── bill_service.go
|
||||
│ │ ├── account_service.go
|
||||
│ │ ├── budget_service.go
|
||||
│ │ ├── dashboard_service.go
|
||||
│ │ └── import_service.go # ETL 编排
|
||||
│ ├── etl/ # ETL 管道 (核心)
|
||||
│ │ ├── pipeline.go # 管道编排器
|
||||
│ │ ├── provider/ # Provider 层 (参考 double-entry-generator)
|
||||
│ │ │ ├── interface.go # Provider 接口定义
|
||||
│ │ │ ├── alipay/
|
||||
│ │ │ │ ├── alipay.go
|
||||
│ │ │ │ └── parse.go
|
||||
│ │ │ ├── wechat/
|
||||
│ │ │ │ ├── wechat.go
|
||||
│ │ │ │ └── parse.go
|
||||
│ │ │ └── bank/
|
||||
│ │ │ ├── cmb.go # 招商银行
|
||||
│ │ │ └── icbc.go # 工商银行
|
||||
│ │ ├── ir/ # IR 中间表示
|
||||
│ │ │ └── ir.go
|
||||
│ │ ├── translate/ # Translate 规则引擎
|
||||
│ │ │ ├── engine.go
|
||||
│ │ │ ├── category.go
|
||||
│ │ │ └── account.go
|
||||
│ │ └── dedup/ # 去重引擎
|
||||
│ │ └── dedup.go
|
||||
│ ├── model/ # GORM 数据模型
|
||||
│ │ ├── bill.go
|
||||
│ │ ├── account.go
|
||||
│ │ ├── category.go
|
||||
│ │ ├── budget.go
|
||||
│ │ └── rule.go
|
||||
│ └── repository/ # 数据访问层
|
||||
│ ├── bill_repo.go
|
||||
│ ├── account_repo.go
|
||||
│ └── budget_repo.go
|
||||
├── configs/
|
||||
│ ├── app.yaml # 应用配置
|
||||
│ └── rules/ # Translate 规则配置
|
||||
│ ├── category_rules.yaml
|
||||
│ └── account_rules.yaml
|
||||
└── uploads/ # 上传文件临时存储
|
||||
```
|
||||
|
||||
### 2.2 ETL 管道核心设计
|
||||
|
||||
#### 2.2.1 Provider 接口定义
|
||||
|
||||
借鉴 `double-entry-generator` 的 Provider 模式,定义统一接口:
|
||||
|
||||
```go
|
||||
// internal/etl/provider/interface.go
|
||||
package provider
|
||||
|
||||
import "projectmoneyx/internal/etl/ir"
|
||||
|
||||
// Provider 定义账单解析器的通用接口
|
||||
type Provider interface {
|
||||
// Translate 将原始账单文件解析为 IR 中间表示
|
||||
Translate(filename string) (*ir.IR, error)
|
||||
// Name 返回 Provider 名称
|
||||
Name() string
|
||||
// SupportedFormats 返回支持的文件格式
|
||||
SupportedFormats() []string
|
||||
}
|
||||
|
||||
// ProviderFactory Provider 工厂,根据类型创建对应 Provider
|
||||
func NewProvider(providerType string) (Provider, error) {
|
||||
switch providerType {
|
||||
case "alipay":
|
||||
return alipay.New(), nil
|
||||
case "wechat":
|
||||
return wechat.New(), nil
|
||||
case "cmb":
|
||||
return bank.NewCMB(), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported provider: %s", providerType)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2.2 IR 中间表示结构
|
||||
|
||||
参考 `double-entry-generator` 的 `ir.Order` 结构,针对个人财务场景扩展:
|
||||
|
||||
```go
|
||||
// internal/etl/ir/ir.go
|
||||
package ir
|
||||
|
||||
import "time"
|
||||
|
||||
// IR 中间表示,作为 Provider 与 Translate 的桥梁
|
||||
type IR struct {
|
||||
Orders []Order `json:"orders"`
|
||||
}
|
||||
|
||||
// Order 统一的订单中间表示
|
||||
type Order struct {
|
||||
// --- 基础字段 (对齐 double-entry-generator) ---
|
||||
Peer string `json:"peer"` // 交易对方
|
||||
Item string `json:"item"` // 商品说明
|
||||
Category string `json:"category"` // 原始分类
|
||||
Money float64 `json:"money"` // 交易金额
|
||||
PayTime time.Time `json:"pay_time"` // 支付时间 (ISO 8601)
|
||||
Type TxType `json:"type"` // 收/支/其他
|
||||
TypeOriginal string `json:"type_original"` // 原始交易类型文本
|
||||
Method string `json:"method"` // 支付方式
|
||||
MerchantOrderID string `json:"merchant_order_id"` // 商户订单号
|
||||
OrderID string `json:"order_id"` // 交易单号
|
||||
Status string `json:"status"` // 交易状态
|
||||
Note string `json:"note"` // 备注
|
||||
|
||||
// --- ProjectMoneyX 扩展字段 ---
|
||||
ProviderName string `json:"provider_name"` // 来源 Provider
|
||||
DataWeight int `json:"data_weight"` // 数据权重 (L1=1, L2=2, L3=3)
|
||||
Currency string `json:"currency"` // 币种,默认 CNY
|
||||
Metadata map[string]string `json:"metadata"` // 扩展元数据
|
||||
}
|
||||
|
||||
// TxType 交易方向
|
||||
type TxType string
|
||||
const (
|
||||
TxTypeSend TxType = "Send" // 支出
|
||||
TxTypeRecv TxType = "Recv" // 收入
|
||||
TxTypeUnknown TxType = "Unknown" // 未知
|
||||
)
|
||||
```
|
||||
|
||||
#### 2.2.3 Translate 规则引擎
|
||||
|
||||
```go
|
||||
// internal/etl/translate/engine.go
|
||||
package translate
|
||||
|
||||
// TranslateEngine 规则引擎核心
|
||||
type TranslateEngine struct {
|
||||
CategoryRules []CategoryRule `yaml:"category_rules"`
|
||||
AccountRules []AccountRule `yaml:"account_rules"`
|
||||
}
|
||||
|
||||
// CategoryRule 分类映射规则
|
||||
type CategoryRule struct {
|
||||
Match MatchCondition `yaml:"match"`
|
||||
Category string `yaml:"category"` // 目标分类 (如 "餐饮-咖啡")
|
||||
Priority int `yaml:"priority"` // 规则优先级
|
||||
}
|
||||
|
||||
// AccountRule 账户路由规则
|
||||
type AccountRule struct {
|
||||
Provider string `yaml:"provider"` // Provider 名称 (如 "alipay")
|
||||
MethodMatch string `yaml:"method_match"` // 支付方式正则
|
||||
AccountID uint `yaml:"account_id"` // 目标账户 ID
|
||||
}
|
||||
|
||||
// MatchCondition 匹配条件
|
||||
type MatchCondition struct {
|
||||
Field string `yaml:"field"` // 匹配字段: peer / item / category
|
||||
Pattern string `yaml:"pattern"` // 正则表达式
|
||||
}
|
||||
|
||||
// Apply 对 IR 应用规则转换
|
||||
func (e *TranslateEngine) Apply(irData *ir.IR) ([]model.Bill, error) {
|
||||
// 1. 时间标准化 (ISO 8601, UTC+8)
|
||||
// 2. 遍历每条 Order,匹配 CategoryRules 进行分类
|
||||
// 3. 遍历每条 Order,匹配 AccountRules 进行账户路由
|
||||
// 4. 转换为 model.Bill 结构
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2.4 去重引擎
|
||||
|
||||
```go
|
||||
// internal/etl/dedup/dedup.go
|
||||
package dedup
|
||||
|
||||
import "time"
|
||||
|
||||
const DefaultTimeDelta = 120 * time.Second // 默认时间窗口 120 秒
|
||||
|
||||
// DedupEngine 交易链路去重引擎
|
||||
type DedupEngine struct {
|
||||
TimeDelta time.Duration
|
||||
}
|
||||
|
||||
// Process 执行去重合并
|
||||
// 算法: 按 DataWeight 升序排列,低权重记录尝试匹配高权重记录
|
||||
// 匹配条件: |Time(Tp) - Time(Ts)| <= Δt AND Amount(Tp) == Amount(Ts)
|
||||
func (d *DedupEngine) Process(bills []model.Bill) []model.Bill {
|
||||
// 1. 按 DataWeight 分组: primary (L1) vs secondary (L2, L3)
|
||||
// 2. 双层循环匹配: 时间窗 + 金额精确匹配
|
||||
// 3. 匹配成功: 建立 LinkID 关联, 标记 secondary 为 linked
|
||||
// 4. 返回合并后的结果集
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2.5 Pipeline 编排
|
||||
|
||||
```go
|
||||
// internal/etl/pipeline.go
|
||||
package etl
|
||||
|
||||
// Pipeline ETL 管道编排器
|
||||
type Pipeline struct {
|
||||
providerRegistry map[string]provider.Provider
|
||||
translateEngine *translate.TranslateEngine
|
||||
dedupEngine *dedup.DedupEngine
|
||||
}
|
||||
|
||||
// Run 执行完整 ETL 流程
|
||||
func (p *Pipeline) Run(providerType, filePath string) (*ImportResult, error) {
|
||||
// Step 1: Provider 解析 -> IR
|
||||
prov, err := provider.NewProvider(providerType)
|
||||
irData, err := prov.Translate(filePath)
|
||||
|
||||
// Step 2: Translate 规则转换 -> []Bill
|
||||
bills, err := p.translateEngine.Apply(irData)
|
||||
|
||||
// Step 3: Dedup 去重合并
|
||||
mergedBills := p.dedupEngine.Process(bills)
|
||||
|
||||
// Step 4: 持久化入库
|
||||
return p.save(mergedBills)
|
||||
}
|
||||
```
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as 用户
|
||||
participant FE as 前端
|
||||
participant API as Gin API
|
||||
participant SVC as ImportService
|
||||
participant P as Provider
|
||||
participant T as Translate
|
||||
participant D as DedupEngine
|
||||
participant DB as Database
|
||||
|
||||
U->>FE: 上传账单文件 + 选择来源类型
|
||||
FE->>API: POST /api/v1/bills/import (multipart)
|
||||
API->>SVC: ImportBill(providerType, file)
|
||||
SVC->>P: Translate(filePath)
|
||||
P-->>SVC: IR (中间表示)
|
||||
SVC->>T: Apply(IR)
|
||||
T-->>SVC: []Bill (标准账单)
|
||||
SVC->>D: Process([]Bill)
|
||||
D->>DB: 查询已有账单 (时间窗)
|
||||
DB-->>D: 存量数据
|
||||
D-->>SVC: 去重后 []Bill
|
||||
SVC->>DB: 批量写入
|
||||
DB-->>SVC: 写入结果
|
||||
SVC-->>API: ImportResult(成功/跳过/失败数)
|
||||
API-->>FE: JSON Response
|
||||
FE-->>U: 导入结果报告
|
||||
```
|
||||
|
||||
### 2.3 数据模型设计 (GORM)
|
||||
|
||||
#### 2.3.1 ER 关系图
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
USER ||--o{ ACCOUNT : owns
|
||||
USER ||--o{ BUDGET : sets
|
||||
ACCOUNT ||--o{ BILL : "fund_source"
|
||||
CATEGORY ||--o{ BILL : classifies
|
||||
CATEGORY ||--o{ BUDGET : limits
|
||||
BILL ||--o| BILL_LINK : linked
|
||||
CATEGORY ||--o{ CATEGORY : "parent-child"
|
||||
USER ||--o{ TRANSLATE_RULE : configures
|
||||
|
||||
USER {
|
||||
uint id PK
|
||||
string username
|
||||
string password_hash
|
||||
timestamp created_at
|
||||
}
|
||||
|
||||
ACCOUNT {
|
||||
uint id PK
|
||||
uint user_id FK
|
||||
string name
|
||||
string type "debit/credit/ewallet"
|
||||
float64 balance
|
||||
string currency
|
||||
bool is_active
|
||||
}
|
||||
|
||||
BILL {
|
||||
uint id PK
|
||||
uint user_id FK
|
||||
uint account_id FK
|
||||
uint category_id FK
|
||||
string provider_name
|
||||
string order_id UK
|
||||
string merchant_order_id
|
||||
string peer
|
||||
string item
|
||||
float64 amount
|
||||
string tx_type "income/expense/transfer"
|
||||
string method
|
||||
string status
|
||||
string note
|
||||
string link_id
|
||||
int data_weight
|
||||
timestamp pay_time
|
||||
timestamp created_at
|
||||
}
|
||||
|
||||
CATEGORY {
|
||||
uint id PK
|
||||
uint parent_id FK
|
||||
string name
|
||||
string icon
|
||||
int sort_order
|
||||
string type "income/expense"
|
||||
}
|
||||
|
||||
BUDGET {
|
||||
uint id PK
|
||||
uint user_id FK
|
||||
uint category_id FK "nullable, null=全局"
|
||||
float64 amount
|
||||
string period "monthly/yearly"
|
||||
string month "2026-02"
|
||||
}
|
||||
|
||||
BILL_LINK {
|
||||
uint id PK
|
||||
string link_id UK
|
||||
uint primary_bill_id FK
|
||||
uint secondary_bill_id FK
|
||||
}
|
||||
|
||||
TRANSLATE_RULE {
|
||||
uint id PK
|
||||
uint user_id FK
|
||||
string rule_type "category/account"
|
||||
string match_field
|
||||
string match_pattern
|
||||
string target_value
|
||||
int priority
|
||||
bool is_active
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.3.2 核心 Model 定义
|
||||
|
||||
```go
|
||||
// internal/model/bill.go
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Bill struct {
|
||||
gorm.Model
|
||||
UserID uint `gorm:"index;not null" json:"user_id"`
|
||||
AccountID uint `gorm:"index" json:"account_id"`
|
||||
CategoryID uint `gorm:"index" json:"category_id"`
|
||||
ProviderName string `gorm:"size:32" json:"provider_name"`
|
||||
OrderID string `gorm:"size:128;uniqueIndex" json:"order_id"`
|
||||
MerchantOrderID string `gorm:"size:128" json:"merchant_order_id"`
|
||||
Peer string `gorm:"size:256" json:"peer"`
|
||||
Item string `gorm:"size:512" json:"item"`
|
||||
Amount float64 `gorm:"type:decimal(12,2);not null" json:"amount"`
|
||||
TxType string `gorm:"size:16;not null" json:"tx_type"`
|
||||
Method string `gorm:"size:64" json:"method"`
|
||||
Status string `gorm:"size:32" json:"status"`
|
||||
Note string `gorm:"size:512" json:"note"`
|
||||
LinkID string `gorm:"size:64;index" json:"link_id"`
|
||||
DataWeight int `gorm:"default:1" json:"data_weight"`
|
||||
PayTime time.Time `gorm:"index;not null" json:"pay_time"`
|
||||
|
||||
// 关联
|
||||
Account Account `gorm:"foreignKey:AccountID" json:"account,omitempty"`
|
||||
Category Category `gorm:"foreignKey:CategoryID" json:"category,omitempty"`
|
||||
}
|
||||
|
||||
// internal/model/account.go
|
||||
type Account struct {
|
||||
gorm.Model
|
||||
UserID uint `gorm:"index;not null" json:"user_id"`
|
||||
Name string `gorm:"size:128;not null" json:"name"`
|
||||
Type string `gorm:"size:32;not null" json:"type"` // debit/credit/ewallet
|
||||
Balance float64 `gorm:"type:decimal(14,2);default:0" json:"balance"`
|
||||
Currency string `gorm:"size:8;default:CNY" json:"currency"`
|
||||
IsActive bool `gorm:"default:true" json:"is_active"`
|
||||
}
|
||||
|
||||
// internal/model/category.go
|
||||
type Category struct {
|
||||
gorm.Model
|
||||
ParentID *uint `gorm:"index" json:"parent_id"`
|
||||
Name string `gorm:"size:64;not null" json:"name"`
|
||||
Icon string `gorm:"size:64" json:"icon"`
|
||||
SortOrder int `gorm:"default:0" json:"sort_order"`
|
||||
Type string `gorm:"size:16" json:"type"` // income/expense
|
||||
Children []Category `gorm:"foreignKey:ParentID" json:"children,omitempty"`
|
||||
}
|
||||
|
||||
// internal/model/budget.go
|
||||
type Budget struct {
|
||||
gorm.Model
|
||||
UserID uint `gorm:"index;not null" json:"user_id"`
|
||||
CategoryID *uint `gorm:"index" json:"category_id"` // nil = 全局预算
|
||||
Amount float64 `gorm:"type:decimal(12,2);not null" json:"amount"`
|
||||
Period string `gorm:"size:16;default:monthly" json:"period"`
|
||||
Month string `gorm:"size:8;not null" json:"month"` // "2026-02"
|
||||
}
|
||||
```
|
||||
|
||||
### 2.4 API 接口设计
|
||||
|
||||
#### 2.4.1 接口总表
|
||||
|
||||
| 模块 | Method | Path | 描述 |
|
||||
| --- | --- | --- | --- |
|
||||
| **账单导入** | POST | `/api/v1/bills/import` | 上传并导入账单文件 |
|
||||
| | GET | `/api/v1/bills/import-history` | 导入历史记录 (导入质量图数据) |
|
||||
| **账单管理** | GET | `/api/v1/bills` | 多条件查询账单列表 |
|
||||
| | GET | `/api/v1/bills/:id` | 查询账单详情 |
|
||||
| | PUT | `/api/v1/bills/:id` | 修改账单 (手动调整分类等) |
|
||||
| | DELETE | `/api/v1/bills/:id` | 删除账单 |
|
||||
| **仪表盘** | GET | `/api/v1/dashboard/summary` | 资产负债 + 现金流概览 |
|
||||
| | GET | `/api/v1/dashboard/trend` | 收支趋势 + 净资产趋势 (按月) |
|
||||
| | GET | `/api/v1/dashboard/asset-composition` | 各账户资产构成 (堆叠图数据) |
|
||||
| **分析** | GET | `/api/v1/analysis/category` | 分类占比 (饼图, 支持 type=income/expense) |
|
||||
| | GET | `/api/v1/analysis/sankey` | 资金流向 (桑基图数据) |
|
||||
| | GET | `/api/v1/analysis/heatmap` | 日消费热力图数据 |
|
||||
| | GET | `/api/v1/analysis/category-trend` | 分类支出趋势 (多折线图数据) |
|
||||
| **账户** | GET | `/api/v1/accounts` | 账户列表 |
|
||||
| | POST | `/api/v1/accounts` | 创建账户 |
|
||||
| | PUT | `/api/v1/accounts/:id` | 修改账户 |
|
||||
| | DELETE | `/api/v1/accounts/:id` | 删除账户 |
|
||||
| | GET | `/api/v1/accounts/:id/waterfall` | 账户收支瀑布图数据 |
|
||||
| **预算** | GET | `/api/v1/budgets` | 预算列表 (含执行进度) |
|
||||
| | POST | `/api/v1/budgets` | 创建/更新预算 |
|
||||
| | DELETE | `/api/v1/budgets/:id` | 删除预算 |
|
||||
| **分类** | GET | `/api/v1/categories` | 分类树 |
|
||||
| | POST | `/api/v1/categories` | 新增分类 |
|
||||
| **规则** | GET | `/api/v1/rules` | 规则列表 |
|
||||
| | POST | `/api/v1/rules` | 新增规则 |
|
||||
| | PUT | `/api/v1/rules/:id` | 修改规则 |
|
||||
| | DELETE | `/api/v1/rules/:id` | 删除规则 |
|
||||
|
||||
#### 2.4.2 核心接口详细定义
|
||||
|
||||
**POST /api/v1/bills/import — 账单导入**
|
||||
|
||||
```
|
||||
Request: multipart/form-data
|
||||
- file: 账单文件 (CSV/XLS/PDF)
|
||||
- provider: string ("alipay" | "wechat" | "cmb" | "icbc" | "jd" | "meituan")
|
||||
|
||||
Response 200:
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"total": 150, // 解析总条数
|
||||
"imported": 132, // 新导入条数
|
||||
"duplicated": 15, // 去重跳过条数
|
||||
"linked": 3, // 链路合并条数
|
||||
"failed": 0 // 失败条数
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**GET /api/v1/bills — 账单查询**
|
||||
|
||||
```
|
||||
Query Params:
|
||||
- start_date: string (2026-01-01)
|
||||
- end_date: string (2026-01-31)
|
||||
- min_amount: float64
|
||||
- max_amount: float64
|
||||
- tx_type: string (income/expense)
|
||||
- category_id: uint
|
||||
- account_id: uint
|
||||
- provider: string
|
||||
- keyword: string (模糊搜索 peer/item)
|
||||
- page: int (default 1)
|
||||
- page_size: int (default 20)
|
||||
|
||||
Response 200:
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"total": 500,
|
||||
"items": [ { ...Bill } ]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**GET /api/v1/dashboard/summary — 仪表盘概览**
|
||||
|
||||
```
|
||||
Query Params:
|
||||
- month: string (2026-02, 默认当月)
|
||||
|
||||
Response 200:
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"total_assets": 125000.00,
|
||||
"total_liabilities": 8500.00,
|
||||
"net_worth": 116500.00,
|
||||
"month_income": 15000.00,
|
||||
"month_expense": 8200.00,
|
||||
"income_mom_pct": 5.2,
|
||||
"expense_mom_pct": -3.1,
|
||||
"accounts": [ { "name": "招行储蓄卡", "balance": 80000.00, "type": "debit" } ]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**GET /api/v1/analysis/sankey — 桑基图数据**
|
||||
|
||||
```
|
||||
Query Params:
|
||||
- start_date / end_date
|
||||
|
||||
Response 200:
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"nodes": [
|
||||
{ "name": "工资" }, { "name": "招行储蓄卡" }, { "name": "餐饮" }
|
||||
],
|
||||
"links": [
|
||||
{ "source": "工资", "target": "招行储蓄卡", "value": 15000 },
|
||||
{ "source": "招行储蓄卡", "target": "餐饮", "value": 3200 }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 前端详细设计
|
||||
|
||||
### 3.1 页面结构与路由
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph Layout["AppLayout"]
|
||||
Sidebar["侧边导航栏"]
|
||||
Header["顶部栏"]
|
||||
Main["主内容区"]
|
||||
end
|
||||
|
||||
Main --> Dashboard["/dashboard 仪表盘"]
|
||||
Main --> Bills["/bills 账单管理"]
|
||||
Main --> Import["/import 账单导入"]
|
||||
Main --> Accounts["/accounts 账户管理"]
|
||||
Main --> Budgets["/budgets 预算管理"]
|
||||
Main --> Analysis["/analysis 多维分析"]
|
||||
Main --> Rules["/rules 规则配置"]
|
||||
```
|
||||
|
||||
### 3.2 前端项目结构
|
||||
|
||||
```
|
||||
projectmoneyx-web/
|
||||
├── src/
|
||||
│ ├── main.ts
|
||||
│ ├── App.vue
|
||||
│ ├── router/
|
||||
│ │ └── index.ts
|
||||
│ ├── api/ # Axios 接口封装
|
||||
│ │ ├── request.ts # Axios 实例 + 拦截器
|
||||
│ │ ├── bill.ts
|
||||
│ │ ├── account.ts
|
||||
│ │ ├── dashboard.ts
|
||||
│ │ ├── analysis.ts
|
||||
│ │ ├── budget.ts
|
||||
│ │ └── rule.ts
|
||||
│ ├── views/
|
||||
│ │ ├── DashboardView.vue # 全景仪表盘
|
||||
│ │ ├── BillListView.vue # 账单查询
|
||||
│ │ ├── ImportView.vue # 账单导入
|
||||
│ │ ├── AccountView.vue # 账户管理
|
||||
│ │ ├── BudgetView.vue # 预算管理
|
||||
│ │ ├── AnalysisView.vue # 多维分析 (桑基图/饼图)
|
||||
│ │ └── RuleView.vue # 规则配置
|
||||
│ ├── components/
|
||||
│ │ ├── charts/
|
||||
│ │ │ ├── NetWorthTrendChart.vue # 图表1: 净资产趋势折线图
|
||||
│ │ │ ├── CashFlowBarChart.vue # 图表2: 现金流对比柱状图
|
||||
│ │ │ ├── AssetCompositionChart.vue # 图表3: 资产构成堆叠图
|
||||
│ │ │ ├── ExpensePieChart.vue # 图表4: 支出结构环形图
|
||||
│ │ │ ├── CalendarHeatmap.vue # 图表5: 收支日历热力图
|
||||
│ │ │ ├── CategoryTrendChart.vue # 图表6: 分类支出趋势折线图
|
||||
│ │ │ ├── SankeyChart.vue # 图表7: 资金流向桑基图
|
||||
│ │ │ ├── IncomePieChart.vue # 图表8: 收入来源环形图
|
||||
│ │ │ ├── BudgetGauge.vue # 图表9: 预算进度仪表盘
|
||||
│ │ │ ├── BudgetCompareChart.vue # 图表10: 预算vs实际对比图
|
||||
│ │ │ ├── AccountWaterfallChart.vue # 图表11: 账户收支瀑布图
|
||||
│ │ │ └── ImportQualityChart.vue # 图表12: 导入质量统计图
|
||||
│ │ ├── BillFilterPanel.vue # 账单筛选面板
|
||||
│ │ ├── ImportUploader.vue # 文件上传组件
|
||||
│ │ └── AccountCard.vue # 账户卡片
|
||||
│ ├── stores/ # Pinia 状态管理
|
||||
│ │ ├── bill.ts
|
||||
│ │ ├── account.ts
|
||||
│ │ └── dashboard.ts
|
||||
│ └── types/ # TypeScript 类型定义
|
||||
│ ├── bill.d.ts
|
||||
│ ├── account.d.ts
|
||||
│ └── api.d.ts
|
||||
```
|
||||
|
||||
### 3.3 核心页面设计
|
||||
|
||||
#### 3.3.1 全景仪表盘 (DashboardView)
|
||||
|
||||
* **资产负债表:** 实时聚合各账户总资产、总负债(信用卡/白条),计算净资产。
|
||||
* **现金流概览:** 本月总收入 vs 总支出,环比上月 (MoM) 增减百分比。
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ [净资产卡片] [本月收入卡片] [本月支出卡片] │
|
||||
│ ¥116,500 ¥15,000 ↑5.2% ¥8,200 ↓3.1% │
|
||||
├──────────────────────────┬──────────────────────────────┤
|
||||
│ 收支趋势折线图 (ECharts) │ 消费结构饼图 (ECharts) │
|
||||
│ (近12个月) │ (本月各分类占比) │
|
||||
├──────────────────────────┴──────────────────────────────┤
|
||||
│ 各账户余额一栏表 (v-data-table) │
|
||||
│ 招行储蓄卡 ¥80,000 | 支付宝余额 ¥5,000 | ... │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### 3.3.2 账单导入页 (ImportView)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Step 1: 选择来源 ○ 支付宝 ○ 微信 ○ 招商银行 ... │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ Step 2: 上传文件 [拖拽区域 / 点击选择文件] │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ Step 3: 导入结果 │
|
||||
│ ✅ 解析 150 条 | 导入 132 条 | 去重 15 条 | 合并 3 条 │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### 3.3.3 多维分析页 (AnalysisView)
|
||||
|
||||
* **组合漏斗筛选:** 支持时间范围、金额区间、支付渠道、资金账户、交易分类的多条件交叉查询。
|
||||
* **可视化图表:**
|
||||
* **消费结构:** 饼图展示各大类的支出占比。
|
||||
* **资金流向 (Sankey Diagram):** 桑基图直观展示“收入源 -> 资金池 (账户) -> 支出分类”的完整链路。
|
||||
|
||||
桑基图核心配置:
|
||||
|
||||
```typescript
|
||||
// components/charts/SankeyChart.vue
|
||||
const option: EChartsOption = {
|
||||
series: [{
|
||||
type: 'sankey',
|
||||
data: nodes, // [{ name: '工资' }, { name: '招行卡' }, { name: '餐饮' }]
|
||||
links: links, // [{ source: '工资', target: '招行卡', value: 15000 }]
|
||||
emphasis: { focus: 'adjacency' },
|
||||
lineStyle: { color: 'gradient', curveness: 0.5 },
|
||||
label: { position: 'right' }
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 关键业务流程
|
||||
|
||||
### 4.1 账单导入全流程状态机
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> FileUploaded: 用户上传文件
|
||||
FileUploaded --> Parsing: 开始解析
|
||||
Parsing --> ParseSuccess: Provider 解析成功
|
||||
Parsing --> ParseFailed: 格式错误/文件损坏
|
||||
|
||||
ParseSuccess --> Translating: 规则引擎转换
|
||||
Translating --> TranslateSuccess: 转换完成
|
||||
TranslateSuccess --> Deduplicating: 去重处理
|
||||
|
||||
Deduplicating --> ImportComplete: 写入数据库
|
||||
ImportComplete --> [*]: 返回导入报告
|
||||
|
||||
ParseFailed --> [*]: 返回错误信息
|
||||
```
|
||||
|
||||
### 4.2 预算预警触发流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant SVC as BudgetService
|
||||
participant DB as Database
|
||||
participant FE as 前端
|
||||
|
||||
Note over SVC: 每次账单写入后触发
|
||||
SVC->>DB: 查询本月已用 (SUM by category)
|
||||
DB-->>SVC: 已用金额
|
||||
SVC->>DB: 查询预算限额
|
||||
DB-->>SVC: 预算配置
|
||||
|
||||
alt 已用 >= 100% 限额
|
||||
SVC-->>FE: 超支预警 (红色标记)
|
||||
else 已用 >= 80% 限额
|
||||
SVC-->>FE: 临近预警 (橙色标记)
|
||||
else 正常
|
||||
SVC-->>FE: 正常状态 (绿色)
|
||||
end
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Translate 规则配置规范
|
||||
|
||||
### 5.1 分类规则配置示例 (YAML)
|
||||
|
||||
```yaml
|
||||
# configs/rules/category_rules.yaml
|
||||
category_rules:
|
||||
# --- 餐饮 ---
|
||||
- match: { field: "peer", pattern: "星巴克|瑞幸|Luckin" }
|
||||
category: "餐饮-咖啡"
|
||||
priority: 10
|
||||
|
||||
- match: { field: "peer", pattern: "美团|饿了么|美团外卖" }
|
||||
category: "餐饮-外卖"
|
||||
priority: 10
|
||||
|
||||
- match: { field: "item", pattern: "早餐|午餐|晚餐|堂食" }
|
||||
category: "餐饮-正餐"
|
||||
priority: 5
|
||||
|
||||
# --- 交通 ---
|
||||
- match: { field: "peer", pattern: "滴滴|高德打车|T3出行" }
|
||||
category: "交通-打车"
|
||||
priority: 10
|
||||
|
||||
- match: { field: "peer", pattern: "12306|铁路" }
|
||||
category: "交通-火车"
|
||||
priority: 10
|
||||
|
||||
# --- 购物 ---
|
||||
- match: { field: "peer", pattern: "淘宝|天猫|拼多多" }
|
||||
category: "购物-电商"
|
||||
priority: 3
|
||||
|
||||
# --- 兜底规则 ---
|
||||
- match: { field: "peer", pattern: ".*" }
|
||||
category: "其他-未分类"
|
||||
priority: 0
|
||||
```
|
||||
|
||||
### 5.2 账户路由配置示例 (YAML)
|
||||
|
||||
```yaml
|
||||
# configs/rules/account_rules.yaml
|
||||
account_rules:
|
||||
- provider: "alipay"
|
||||
method_match: "招商银行信用卡"
|
||||
account_name: "招行信用卡"
|
||||
|
||||
- provider: "alipay"
|
||||
method_match: "花呗"
|
||||
account_name: "花呗"
|
||||
|
||||
- provider: "alipay"
|
||||
method_match: "余额宝|账户余额"
|
||||
account_name: "支付宝余额"
|
||||
|
||||
- provider: "wechat"
|
||||
method_match: "零钱"
|
||||
account_name: "微信零钱"
|
||||
|
||||
- provider: "wechat"
|
||||
method_match: "招商银行"
|
||||
account_name: "招行储蓄卡"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 非功能性设计
|
||||
|
||||
### 6.1 数据隐私 (Local-First)
|
||||
|
||||
| 设计要点 | 实现方式 |
|
||||
| --- | --- |
|
||||
| 本地部署 | 默认使用 SQLite,单一二进制文件部署,无需外部数据库 |
|
||||
| 文件处理 | 上传的原始账单文件仅在本地解析后即删除,不持久存储原始文件 |
|
||||
| 无远程调用 | ETL 管道全过程本地执行,不依赖任何云端 API |
|
||||
| 可选 MySQL | 如需多端访问,可配置切换到 MySQL,但建议内网部署 |
|
||||
|
||||
### 6.2 性能设计
|
||||
|
||||
| 场景 | 指标 | 措施 |
|
||||
| --- | --- | --- |
|
||||
| 账单导入 | 1000 条/秒 | GORM 批量插入 (CreateInBatches) |
|
||||
| 账单列表查询 | < 200ms | 复合索引 (user_id, pay_time, category_id) |
|
||||
| 仪表盘聚合 | < 500ms | 数据库聚合查询 + 前端缓存 (Pinia) |
|
||||
| 去重匹配 | O(n·m) | 按时间窗口分桶预排序,减少比较次数 |
|
||||
|
||||
### 6.3 可扩展性设计
|
||||
|
||||
- **新增 Provider**:实现 `provider.Provider` 接口,注册到工厂即可
|
||||
- **新增规则**:YAML 配置热加载,无需重启
|
||||
- **新增图表**:ECharts 组件化封装,新图表只需新建 Vue 组件
|
||||
|
||||
---
|
||||
|
||||
## 7. 参考项目代码复用说明
|
||||
|
||||
### 7.1 从 double-entry-generator 复用的部分
|
||||
|
||||
| 模块 | 源路径 | 复用说明 |
|
||||
| --- | --- | --- |
|
||||
| IR 结构 | `pkg/ir/ir.go` | 复用 `Order` 结构体核心字段,扩展 `ProviderName`、`DataWeight` 等字段 |
|
||||
| Alipay Provider | `pkg/provider/alipay/` | 复用 CSV 解析、GBK 编码处理、字段映射逻辑 |
|
||||
| WeChat Provider | `pkg/provider/wechat/` | 复用 CSV/XLSX 解析、跳过表头逻辑 |
|
||||
| 退款后处理 | `alipay.postProcess()` | 复用退款订单匹配和交易关闭处理逻辑 |
|
||||
|
||||
### 7.2 需要新增/改造的部分
|
||||
|
||||
| 模块 | 改造说明 |
|
||||
| --- | --- |
|
||||
| Provider 接口 | 从直接函数调用改为 Web API 触发,增加文件上传处理 |
|
||||
| Translate 层 | 原项目的 Compiler 输出 Beancount 文本,改为输出数据库 Model |
|
||||
| 去重引擎 | 原项目不涉及,需完全新写 |
|
||||
| 规则配置 | 原项目配置固定,改为数据库存储 + YAML 双模式,支持用户自定义 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 部署架构
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph Local["本地部署 (推荐)"]
|
||||
Binary["Go 单体二进制"]
|
||||
SQLite["SQLite 数据库文件"]
|
||||
StaticFiles["Vue 前端静态文件 (embed)"]
|
||||
Binary --> SQLite
|
||||
Binary --> StaticFiles
|
||||
end
|
||||
|
||||
subgraph Docker["Docker 部署 (可选)"]
|
||||
Container["Docker Container"]
|
||||
Volume["Data Volume"]
|
||||
Container --> Volume
|
||||
end
|
||||
|
||||
User["浏览器"] -->|http://localhost:8080| Binary
|
||||
User -->|http://host:8080| Container
|
||||
```
|
||||
|
||||
> **推荐部署方式**:使用 Go 的 `embed` 包将编译后的 Vue 前端静态资源嵌入后端二进制文件,实现**单文件部署**,配合 SQLite 达到真正的 Local-First 体验。
|
||||
637
16-ProjectMoneyM-转FireFlyIII/3-实现详细稿/3-DataGrip-DDS.md
Normal file
637
16-ProjectMoneyM-转FireFlyIII/3-实现详细稿/3-DataGrip-DDS.md
Normal file
@@ -0,0 +1,637 @@
|
||||
# ProjectMoneyX 数据可视化详细设计说明书
|
||||
|
||||
| 文档属性 | 详情 |
|
||||
| --- | --- |
|
||||
| **所属系统** | ProjectMoneyX 个人全景财务分析系统 |
|
||||
| **关联文档** | [2-ProjectMoneyX-DDS.md](./2-ProjectMoneyX-DDS.md) §3 前端详细设计 |
|
||||
| **技术框架** | ECharts 5.x + Vue3 Composition API + TypeScript |
|
||||
| **编制日期** | 2026-02-26 |
|
||||
|
||||
---
|
||||
|
||||
## 0. 图表总览与需求覆盖矩阵
|
||||
|
||||
下表将 PRD 中的核心分析需求映射到具体图表实现,确保**多维度全覆盖**:
|
||||
|
||||
| PRD 需求 | 分析维度 | 实现图表 | 所在页面 |
|
||||
|---|---|---|---|
|
||||
| 资产负债表 | 总资产/负债/净资产趋势 | 图表1: 净资产趋势折线图 | Dashboard |
|
||||
| 现金流概览 (MoM) | 月度收入 vs 支出对比 | 图表2: 现金流对比柱状图 | Dashboard |
|
||||
| 各账户资产构成 | 账户维度的资金分布 | 图表3: 资产构成堆叠图 | Dashboard |
|
||||
| 消费结构 (饼图) | 分类维度的支出占比 | 图表4: 支出结构环形图 | Analysis |
|
||||
| 消费规律识别 | 时间维度的消费强度 | 图表5: 收支日历热力图 | Analysis |
|
||||
| 分类趋势对比 | 分类×时间交叉分析 | 图表6: 分类支出趋势折线图 | Analysis |
|
||||
| 资金流向 (Sankey) | 收入→账户→支出全链路 | 图表7: 资金流向桑基图 ⭐ | Analysis |
|
||||
| 收入结构分析 | 收入来源维度的占比 | 图表8: 收入来源环形图 | Analysis |
|
||||
| 预算管理 (阈值预警) | 预算执行进度 | 图表9: 预算进度仪表盘 | Budget |
|
||||
| 预算执行趋势 | 预算 vs 实际的偏差跟踪 | 图表10: 预算 vs 实际对比图 | Budget |
|
||||
| 账户交易分析 | 单账户维度的流水趋势 | 图表11: 账户收支瀑布图 | Account |
|
||||
| 去重链路可视化 | ETL 导入质量监控 | 图表12: 导入质量统计图 | Import |
|
||||
|
||||
### 图表与页面分布
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph Dashboard["仪表盘 (DashboardView)"]
|
||||
C1["图表1: 净资产趋势折线图"]
|
||||
C2["图表2: 现金流对比柱状图"]
|
||||
C3["图表3: 资产构成堆叠图"]
|
||||
end
|
||||
|
||||
subgraph Analysis["多维分析 (AnalysisView)"]
|
||||
C4["图表4: 支出结构环形图"]
|
||||
C5["图表5: 收支日历热力图"]
|
||||
C6["图表6: 分类支出趋势折线图"]
|
||||
C7["图表7: 资金流向桑基图 ⭐"]
|
||||
C8["图表8: 收入来源环形图"]
|
||||
end
|
||||
|
||||
subgraph Budget["预算管理 (BudgetView)"]
|
||||
C9["图表9: 预算进度仪表盘"]
|
||||
C10["图表10: 预算 vs 实际对比图"]
|
||||
end
|
||||
|
||||
subgraph Account["账户管理 (AccountView)"]
|
||||
C11["图表11: 账户收支瀑布图"]
|
||||
end
|
||||
|
||||
subgraph Import["账单导入 (ImportView)"]
|
||||
C12["图表12: 导入质量统计图"]
|
||||
end
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 仪表盘总览区 (DashboardView)
|
||||
|
||||
### 图表1:净资产趋势折线图
|
||||
|
||||
**图表类型:** `ECharts Line Chart`(面积折线图,Area Line)
|
||||
|
||||
**用途:** 展示净资产随时间的增长趋势,是资产健康度的核心指标。
|
||||
|
||||
| 配置项 | 说明 |
|
||||
|---|---|
|
||||
| `xAxis.type` | `'category'`,数据为月份标签 `['2024-06', ..., '2026-02']` |
|
||||
| `yAxis.type` | `'value'`,单位 CNY,开启 `scale: true` 避免从0开始压缩曲线 |
|
||||
| `series.type` | `'line'`,开启 `areaStyle` 填充半透明渐变区域 |
|
||||
| `series.smooth` | `true`,平滑曲线更符合财务趋势感 |
|
||||
| 关键数据字段 | `{ month: string, netWorth: number, totalAssets: number, totalLiabilities: number }[]` |
|
||||
| 多线配置 | 叠加三条线:净资产(主线蓝 `#4F6EF7`)、总资产(绿虚线 `#10B981`)、总负债(红虚线 `#EF4444`),用 `markLine` 标注最高/最低点 |
|
||||
|
||||
**ECharts 高级能力:** 使用 `visualMap` 组件,当净资产低于某阈值时自动将线段变红预警。
|
||||
|
||||
**后端接口:** `GET /api/v1/dashboard/trend?range=12m`
|
||||
|
||||
```json
|
||||
// Response
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"months": ["2025-03", "2025-04", "..."],
|
||||
"net_worth": [98000, 101000, "..."],
|
||||
"total_assets": [120000, 125000, "..."],
|
||||
"total_liabilities": [22000, 24000, "..."]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 图表2:月度现金流对比柱状图
|
||||
|
||||
**图表类型:** `ECharts Bar Chart`(分组柱 + 折线混合)
|
||||
|
||||
**用途:** 直观对比每月收入/支出,突出结余(净现金流)。
|
||||
|
||||
| 配置项 | 说明 |
|
||||
|---|---|
|
||||
| `xAxis` | 近12个月,`type: 'category'` |
|
||||
| `series[0]` | 收入柱,`barMaxWidth: 20`,颜色 `#10B981`(绿) |
|
||||
| `series[1]` | 支出柱,同组排列,颜色 `#EF4444`(红) |
|
||||
| `series[2]` | 结余折线(叠加 `type: 'line'`),颜色 `#4F6EF7`(蓝),`z: 10` 置于顶层 |
|
||||
| `tooltip.formatter` | 自定义:同时显示收入、支出、结余、环比变化(MoM%) |
|
||||
| `markArea` | 标记亏损月(收入 < 支出)的柱背景为浅红色区域 |
|
||||
|
||||
**后端接口:** 复用 `GET /api/v1/dashboard/trend?range=12m`,数据中应增加 `month_income[]` 和 `month_expense[]` 数组。
|
||||
|
||||
---
|
||||
|
||||
### 图表3:资产构成堆叠柱 / 堆叠面积图
|
||||
|
||||
**图表类型:** `ECharts Bar Chart (stack)` 或 `Line Chart (stack + areaStyle)`
|
||||
|
||||
**用途:** 展示各账户资产随时间的构成变化,如活期、基金、信用卡负债各占比的演变。
|
||||
|
||||
| 配置项 | 说明 |
|
||||
|---|---|
|
||||
| `series[n].stack` | 统一设为 `'total'`,触发堆叠模式 |
|
||||
| 账户数据字段 | `{ month, accounts: { name: string, balance: number }[] }[]` |
|
||||
| `series` 中负债处理 | 负债账户(信用卡/白条)使用负值,自动向下延伸,形成正负对称的资产负债视图 |
|
||||
| `legend` | 开启可点击切换,方便单独聚焦某账户 |
|
||||
|
||||
**后端接口:** `GET /api/v1/dashboard/asset-composition?range=12m`
|
||||
|
||||
```json
|
||||
// Response
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"months": ["2025-03", "2025-04"],
|
||||
"series": [
|
||||
{ "name": "招行储蓄卡", "type": "debit", "data": [80000, 82000] },
|
||||
{ "name": "支付宝余额", "type": "ewallet", "data": [5000, 4500] },
|
||||
{ "name": "招行信用卡", "type": "credit", "data": [-8000, -7500] }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 支出分析区 (AnalysisView - Tab1: 支出)
|
||||
|
||||
### 图表4:支出结构环形图(Donut)
|
||||
|
||||
**图表类型:** `ECharts Pie Chart`(`radius: ['40%', '70%']` 环形)
|
||||
|
||||
**用途:** 展示选定时间段内各消费分类占比,支持二级下钻。
|
||||
|
||||
| 配置项 | 说明 |
|
||||
|---|---|
|
||||
| `series.radius` | `['40%', '70%']` 形成环形,中心显示总支出金额 |
|
||||
| `series.label` | 外侧显示分类名 + 百分比,`labelLine` 引导线 |
|
||||
| `graphic`(中心文字) | 使用 ECharts `graphic` 组件在环心渲染「总支出 / ¥9,820」 |
|
||||
| `series.emphasis` | 鼠标悬停时扇区放大 `scaleSize: 10`,联动下方账单表格筛选 |
|
||||
| 数据字段 | `{ name: string, value: number, percentage: number }[]` |
|
||||
| 二级下钻 | 点击一级分类(餐饮)→ 触发 `series.data` 替换为二级分类(外卖/堂食/咖啡),配合 Vue3 `ref` 响应式切换,面包屑导航返回上级 |
|
||||
|
||||
**后端接口:** `GET /api/v1/analysis/category?type=expense&start_date=&end_date=&parent_id=`
|
||||
|
||||
```json
|
||||
// Response
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"total": 9820.50,
|
||||
"items": [
|
||||
{ "category_id": 1, "name": "餐饮", "value": 3200, "percentage": 32.6, "has_children": true },
|
||||
{ "category_id": 2, "name": "购物", "value": 2500, "percentage": 25.5, "has_children": true },
|
||||
{ "category_id": 3, "name": "交通", "value": 1200, "percentage": 12.2, "has_children": false }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 图表5:收支日历热力图
|
||||
|
||||
**图表类型:** `ECharts HeatMap`(日历坐标系)
|
||||
|
||||
**用途:** 以日历形式展示每日消费强度,快速识别高消费日/周期性支出规律(如固定还款日、周末消费高峰)。
|
||||
|
||||
| 配置项 | 说明 |
|
||||
|---|---|
|
||||
| `calendar.range` | 设置为当前选中月份或全年,如 `'2026'` 或 `'2026-02'` |
|
||||
| `series.coordinateSystem` | `'calendar'`,与 `calendar` 组件绑定 |
|
||||
| `series.data` | `[['2026-02-15', 420], ['2026-02-16', 85], ...]`(日期 + 消费金额) |
|
||||
| `visualMap` | 连续型,从浅绿(低消费 `#E8F5E9`)到深红(高消费 `#C62828`)渐变,阈值按数据自适应 |
|
||||
| `tooltip` | 显示该日消费总额和前3笔最大账单 |
|
||||
|
||||
**后端接口:** `GET /api/v1/analysis/heatmap?year=2026&type=expense`
|
||||
|
||||
```json
|
||||
// Response
|
||||
{
|
||||
"code": 0,
|
||||
"data": [
|
||||
["2026-02-01", 156.50],
|
||||
["2026-02-02", 320.00],
|
||||
["2026-02-14", 899.00]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 图表6:分类支出趋势多折线图
|
||||
|
||||
**图表类型:** `ECharts Line Chart`(多系列)
|
||||
|
||||
**用途:** 对比各支出分类(餐饮、购物、交通)近 N 个月的趋势,找出异常增长的分类。
|
||||
|
||||
| 配置项 | 说明 |
|
||||
|---|---|
|
||||
| `legend` | 开启可交互,默认只显示前5大分类,其余折叠于 `legend.selector` |
|
||||
| `xAxis` | 月份,近12个月 |
|
||||
| 每条 `series` | 对应一个支出分类,最多显示 6 条线,其余归入"其他" |
|
||||
| `dataZoom` | 开启 X 轴缩放 (`type: 'slider'`),支持拖拽查看任意时间段 |
|
||||
| 颜色规范 | 自定义 10 色 palette,**与环形图(图表4)保持颜色一致**保证跨图表认知一致性 |
|
||||
| `markPoint` | 自动标注各分类的月度最大值 (`type: 'max'`) |
|
||||
|
||||
**后端接口:** `GET /api/v1/analysis/category-trend?type=expense&range=12m&top=6`
|
||||
|
||||
```json
|
||||
// Response
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"months": ["2025-03", "2025-04", "..."],
|
||||
"series": [
|
||||
{ "name": "餐饮", "data": [3200, 2800, "..."] },
|
||||
{ "name": "购物", "data": [2500, 3100, "..."] },
|
||||
{ "name": "交通", "data": [1200, 1100, "..."] }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 资金流向区 (AnalysisView - Tab2: 流向)
|
||||
|
||||
### 图表7:资金流向桑基图(Sankey)⭐ 核心图
|
||||
|
||||
**图表类型:** `ECharts Sankey Diagram`
|
||||
|
||||
**用途:** 唯一能完整展示「收入源 → 资金池(账户) → 支出分类」全链路的图表,是个人收支系统最有价值的可视化。
|
||||
|
||||
```typescript
|
||||
// 核心数据结构(TypeScript)
|
||||
interface SankeyNode {
|
||||
name: string // 节点名称
|
||||
itemStyle?: { color: string }
|
||||
depth?: number // 强制分层: 0=收入源, 1=账户, 2=支出分类
|
||||
}
|
||||
|
||||
interface SankeyLink {
|
||||
source: string // 来源节点 name
|
||||
target: string // 目标节点 name
|
||||
value: number // 流量金额(CNY)
|
||||
}
|
||||
|
||||
// 三列节点分组示例
|
||||
const nodes: SankeyNode[] = [
|
||||
// 收入源(左列, depth=0)
|
||||
{ name: '工资薪酬', itemStyle: { color: '#10B981' }, depth: 0 },
|
||||
{ name: '兼职收入', itemStyle: { color: '#34D399' }, depth: 0 },
|
||||
{ name: '投资收益', itemStyle: { color: '#6EE7B7' }, depth: 0 },
|
||||
// 账户池(中列, depth=1)
|
||||
{ name: '招行储蓄', itemStyle: { color: '#4F6EF7' }, depth: 1 },
|
||||
{ name: '支付宝', itemStyle: { color: '#818CF8' }, depth: 1 },
|
||||
{ name: '微信钱包', itemStyle: { color: '#A5B4FC' }, depth: 1 },
|
||||
// 支出分类(右列, depth=2)
|
||||
{ name: '餐饮', itemStyle: { color: '#EF4444' }, depth: 2 },
|
||||
{ name: '购物', itemStyle: { color: '#F97316' }, depth: 2 },
|
||||
{ name: '居住', itemStyle: { color: '#F59E0B' }, depth: 2 },
|
||||
{ name: '储蓄/投资',itemStyle: { color: '#10B981' }, depth: 2 },
|
||||
]
|
||||
```
|
||||
|
||||
| 关键配置项 | 说明 |
|
||||
|---|---|
|
||||
| `series.type` | `'sankey'` |
|
||||
| `series.layout` | `'none'`(禁用自动布局),通过 `depth` 属性手动控制三列分层 |
|
||||
| `series.nodeGap` | `12`(节点间距) |
|
||||
| `series.nodeWidth` | `20`(节点宽度) |
|
||||
| `series.lineStyle.color` | `'gradient'`(从源到目标渐变色,ECharts 内置支持) |
|
||||
| `series.lineStyle.opacity` | `0.4`,悬停时 `emphasis.lineStyle.opacity: 0.8` |
|
||||
| `series.emphasis.focus` | `'adjacency'`(高亮相邻节点和链接,淡化其他) |
|
||||
| `series.label.position` | 左列 `'left'`,右列 `'right'`,中列 `'inside'` |
|
||||
| `tooltip.formatter` | 自定义显示:节点→`账户名: 总额 ¥X,XXX`;链接→`源 → 目标: ¥X,XXX(占XX%)` |
|
||||
|
||||
**后端接口:** `GET /api/v1/analysis/sankey?start_date=&end_date=`(已在 DDS 中定义)
|
||||
|
||||
---
|
||||
|
||||
## 4. 收入分析区 (AnalysisView - Tab3: 收入)
|
||||
|
||||
### 图表8:收入来源环形图
|
||||
|
||||
**图表类型:** `ECharts Pie Chart`(`radius: ['40%', '70%']` 环形)
|
||||
|
||||
**用途:** 展示选定时间段内各收入来源占比(如:工资、兼职、理财收益、转账收款等),与支出环形图(图表4)形成对称分析。
|
||||
|
||||
| 配置项 | 说明 |
|
||||
|---|---|
|
||||
| `series.radius` | `['40%', '70%']` 形成环形,中心显示总收入金额 |
|
||||
| `series.color` | 使用绿色系 palette(与支出红色系区分),如 `['#10B981', '#34D399', '#6EE7B7', '#A7F3D0']` |
|
||||
| `graphic`(中心文字) | 在环心渲染「总收入 / ¥15,000」 |
|
||||
| `series.emphasis` | 悬停扇区放大,tooltip 显示收入来源明细 |
|
||||
| 数据字段 | `{ name: string, value: number, percentage: number }[]` |
|
||||
|
||||
**后端接口:** 复用 `GET /api/v1/analysis/category?type=income&start_date=&end_date=`
|
||||
|
||||
> **设计说明:** PRD 原文重点描述了支出维度的分析,但收入来源的结构分析是完整财务画像不可缺少的一环。用户需要了解"钱从哪来"的占比分布,才能做出更好的财务规划决策。
|
||||
|
||||
---
|
||||
|
||||
## 5. 预算管理区 (BudgetView)
|
||||
|
||||
### 图表9:预算进度仪表盘(多量规阵列)
|
||||
|
||||
**图表类型:** `ECharts Gauge Chart`(多个仪表盘组成阵列)
|
||||
|
||||
**用途:** 直观展示每个预算分类的执行进度百分比,配合 DDS 中定义的 80%/100% 阈值预警逻辑。
|
||||
|
||||
| 配置项 | 说明 |
|
||||
|---|---|
|
||||
| `series.type` | `'gauge'` |
|
||||
| `series.progress.show` | `true`,显示进度弧 |
|
||||
| `series.axisLine.lineStyle.color` | 三段式渐变:`[[0.8, '#10B981'], [1.0, '#F59E0B'], [1.0+, '#EF4444']]`(绿→橙→红) |
|
||||
| `series.detail.formatter` | `'{value}%'`,中心显示百分比 |
|
||||
| `series.title.text` | 分类名称(如"餐饮"、"交通") |
|
||||
| `series.data` | `[{ value: 75, name: '餐饮' }]`,表示已用 75% |
|
||||
| 布局 | 使用 `v-row` + `v-col` 阵列,每个分类一个小仪表盘,全局预算用大号仪表盘 |
|
||||
|
||||
**阈值预警联动(对齐 DDS §4.2):**
|
||||
- `0% ~ 79%` → 绿色弧 `#10B981` + 正常文字
|
||||
- `80% ~ 99%` → 橙色弧 `#F59E0B` + 橙色警告徽章
|
||||
- `≥ 100%` → 红色弧 `#EF4444` + 红色超支提示 + 弧度超出刻度线
|
||||
|
||||
```typescript
|
||||
// BudgetGauge.vue 核心 option
|
||||
const getGaugeOption = (budget: BudgetItem): EChartsOption => ({
|
||||
series: [{
|
||||
type: 'gauge',
|
||||
startAngle: 200,
|
||||
endAngle: -20,
|
||||
min: 0,
|
||||
max: 100,
|
||||
progress: { show: true, width: 12 },
|
||||
pointer: { show: false },
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 12,
|
||||
color: [[0.8, '#10B981'], [1, '#F59E0B'], [1.2, '#EF4444']] // 允许超出100%
|
||||
}
|
||||
},
|
||||
axisTick: { show: false },
|
||||
splitLine: { show: false },
|
||||
axisLabel: { show: false },
|
||||
detail: {
|
||||
valueAnimation: true,
|
||||
formatter: `{value}%\n¥${budget.used} / ¥${budget.limit}`,
|
||||
fontSize: 14
|
||||
},
|
||||
title: { text: budget.categoryName, offsetCenter: [0, '80%'] },
|
||||
data: [{ value: Math.round((budget.used / budget.limit) * 100) }]
|
||||
}]
|
||||
})
|
||||
```
|
||||
|
||||
**后端接口:** `GET /api/v1/budgets?month=2026-02`(已在 DDS 中定义),响应需扩展:
|
||||
|
||||
```json
|
||||
// Response
|
||||
{
|
||||
"code": 0,
|
||||
"data": [
|
||||
{
|
||||
"id": 1, "category_name": "全局", "category_id": null,
|
||||
"limit": 10000, "used": 8200, "percentage": 82,
|
||||
"status": "warning"
|
||||
},
|
||||
{
|
||||
"id": 2, "category_name": "餐饮", "category_id": 1,
|
||||
"limit": 3000, "used": 2400, "percentage": 80,
|
||||
"status": "warning"
|
||||
},
|
||||
{
|
||||
"id": 3, "category_name": "交通", "category_id": 3,
|
||||
"limit": 1000, "used": 650, "percentage": 65,
|
||||
"status": "normal"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 图表10:预算 vs 实际对比柱状图
|
||||
|
||||
**图表类型:** `ECharts Bar Chart`(分组柱状图)
|
||||
|
||||
**用途:** 对比各分类的预算限额与实际支出,直观发现超支和节省的分类,辅助下月预算调整。
|
||||
|
||||
| 配置项 | 说明 |
|
||||
|---|---|
|
||||
| `xAxis` | 各预算分类名称 `type: 'category'` |
|
||||
| `series[0]` | 预算限额柱,颜色 `#93C5FD`(浅蓝),`barMaxWidth: 24` |
|
||||
| `series[1]` | 实际支出柱,颜色动态:未超支 `#10B981`(绿),超支 `#EF4444`(红) |
|
||||
| `series[1].itemStyle.color` | 使用 `function(params)` 回调,根据是否超支动态着色 |
|
||||
| `markLine` | 在 100% 预算位置画水平参考线 |
|
||||
| `tooltip` | 显示:`分类名 | 预算: ¥X | 实际: ¥Y | 差额: ±¥Z (XX%)` |
|
||||
|
||||
**后端接口:** 复用 `GET /api/v1/budgets?month=2026-02`
|
||||
|
||||
---
|
||||
|
||||
## 6. 账户管理区 (AccountView)
|
||||
|
||||
### 图表11:账户收支瀑布图
|
||||
|
||||
**图表类型:** `ECharts Bar Chart`(瀑布图,使用透明柱实现)
|
||||
|
||||
**用途:** 展示选定账户在某月内余额的逐日/逐笔变化过程,帮助用户理解"钱是怎么花没的"。
|
||||
|
||||
| 配置项 | 说明 |
|
||||
|---|---|
|
||||
| 实现方式 | 使用 ECharts 堆叠柱模拟瀑布:底部透明柱 (`itemStyle.color: 'transparent'`) + 上方有色柱 |
|
||||
| `xAxis` | 日期或交易序号 |
|
||||
| 颜色逻辑 | 收入笔→绿色柱向上增长,支出笔→红色柱向下减少,最终柱→蓝色(期末余额) |
|
||||
| `tooltip` | 显示:`日期 | 交易对方 | ±金额 | 余额` |
|
||||
| `series.label` | 在柱体上方/下方显示金额增减 |
|
||||
|
||||
**后端接口:** `GET /api/v1/accounts/:id/waterfall?month=2026-02`
|
||||
|
||||
```json
|
||||
// Response
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"account_name": "招行储蓄卡",
|
||||
"opening_balance": 80000,
|
||||
"closing_balance": 82500,
|
||||
"transactions": [
|
||||
{ "date": "2026-02-01", "peer": "工资", "amount": 15000, "type": "income", "balance": 95000 },
|
||||
{ "date": "2026-02-03", "peer": "房租", "amount": -5500, "type": "expense", "balance": 89500 },
|
||||
{ "date": "2026-02-05", "peer": "美团外卖", "amount": -35, "type": "expense", "balance": 89465 }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 导入质量区 (ImportView)
|
||||
|
||||
### 图表12:导入质量统计图
|
||||
|
||||
**图表类型:** `ECharts Bar Chart`(堆叠柱状图)
|
||||
|
||||
**用途:** 每次导入后展示本次及历史导入的数据质量分布(新增/去重/链路合并/失败),帮助用户监控 ETL 管道健康度。
|
||||
|
||||
| 配置项 | 说明 |
|
||||
|---|---|
|
||||
| `xAxis` | 导入批次(按时间倒序,最近 10 次) |
|
||||
| `series[0]` | 新导入数,颜色 `#10B981`(绿),`stack: 'total'` |
|
||||
| `series[1]` | 去重跳过数,颜色 `#F59E0B`(橙),`stack: 'total'` |
|
||||
| `series[2]` | 链路合并数,颜色 `#4F6EF7`(蓝),`stack: 'total'` |
|
||||
| `series[3]` | 失败数,颜色 `#EF4444`(红),`stack: 'total'` |
|
||||
| `tooltip` | 显示各类明细和总解析条数 |
|
||||
|
||||
**后端接口:** `GET /api/v1/bills/import-history?limit=10`
|
||||
|
||||
```json
|
||||
// Response
|
||||
{
|
||||
"code": 0,
|
||||
"data": [
|
||||
{
|
||||
"batch_id": "20260226-001",
|
||||
"provider": "alipay",
|
||||
"imported_at": "2026-02-26T19:30:00+08:00",
|
||||
"total": 150, "imported": 132, "duplicated": 15, "linked": 3, "failed": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 全局设计规范
|
||||
|
||||
### 8.1 统一色彩系统
|
||||
|
||||
为保证跨图表的**视觉一致性**和**认知连贯性**,所有图表使用统一的语义化色板:
|
||||
|
||||
| 语义 | 色值 | 用途场景 |
|
||||
|---|---|---|
|
||||
| **收入/正向/安全** | `#10B981` (Emerald-500) | 收入柱、正常进度、储蓄类 |
|
||||
| **支出/负向/危险** | `#EF4444` (Red-500) | 支出柱、超支预警、失败 |
|
||||
| **警告/临近阈值** | `#F59E0B` (Amber-500) | 80% 预算警告、去重跳过 |
|
||||
| **中性/信息** | `#4F6EF7` (Indigo-500) | 结余线、链路合并、账户主色 |
|
||||
| **辅助蓝** | `#818CF8` (Violet-400) | 辅助信息、次要指标 |
|
||||
| **背景辅助** | `#F8FAFC` (Slate-50) | 图表背景、空白区域 |
|
||||
|
||||
**分类色板**(饼图/折线图/桑基图多分类通用,共 10 色循环):
|
||||
|
||||
```typescript
|
||||
const CATEGORY_PALETTE = [
|
||||
'#4F6EF7', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6',
|
||||
'#EC4899', '#06B6D4', '#F97316', '#84CC16', '#6366F1'
|
||||
]
|
||||
```
|
||||
|
||||
### 8.2 ECharts 公共配置封装
|
||||
|
||||
```typescript
|
||||
// composables/useECharts.ts
|
||||
import * as echarts from 'echarts/core'
|
||||
import { ref, onMounted, onUnmounted, watch } from 'vue'
|
||||
|
||||
export function useECharts(containerRef: Ref<HTMLElement | null>) {
|
||||
const chartInstance = ref<echarts.ECharts | null>(null)
|
||||
let resizeObserver: ResizeObserver | null = null
|
||||
|
||||
onMounted(() => {
|
||||
if (containerRef.value) {
|
||||
chartInstance.value = echarts.init(containerRef.value)
|
||||
// 响应式 resize
|
||||
resizeObserver = new ResizeObserver(() => {
|
||||
chartInstance.value?.resize()
|
||||
})
|
||||
resizeObserver.observe(containerRef.value)
|
||||
}
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
resizeObserver?.disconnect()
|
||||
chartInstance.value?.dispose()
|
||||
})
|
||||
|
||||
const setOption = (option: echarts.EChartsOption) => {
|
||||
chartInstance.value?.setOption(option, { notMerge: true })
|
||||
}
|
||||
|
||||
return { chartInstance, setOption }
|
||||
}
|
||||
```
|
||||
|
||||
### 8.3 图表联动设计
|
||||
|
||||
12 张图在 Vue3 中的协作方式:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Store["Pinia: dateRangeStore"] -->|watch dateRange| C1["图表1~3 (Dashboard)"]
|
||||
Store -->|watch dateRange| C4["图表4~8 (Analysis)"]
|
||||
Store -->|watch month| C9["图表9~10 (Budget)"]
|
||||
|
||||
C4 -->|"emit('category-filter')"| BillTable["账单列表表格"]
|
||||
C4 -->|"emit('category-filter')"| C7["图表7: 桑基图高亮"]
|
||||
|
||||
C9 -->|"点击分类仪表盘"| C10["图表10: 对应分类高亮"]
|
||||
```
|
||||
|
||||
| 联动机制 | 实现方式 |
|
||||
|---|---|
|
||||
| **全局时间筛选器** | Pinia store 存储 `dateRange`,所有图表 `watch` 该变量触发 API 重新请求并刷新 |
|
||||
| **分类联动** | 点击环形图扇区 → `emits('category-filter', categoryId)` → 账单表格过滤 + 桑基图高亮对应节点 |
|
||||
| **图表 resize** | 统一在 `useECharts` composable 中使用 `ResizeObserver` 处理,配合 Vuetify 响应式断点 |
|
||||
| **数据懒加载** | 桑基图和热力图数据量较大,使用 `defineAsyncComponent` 延迟渲染,进入视口后加载 |
|
||||
| **颜色同步** | 跨图表的相同分类使用 `CATEGORY_PALETTE` 通过 `categoryId % 10` 索引取色,保证颜色映射一致 |
|
||||
|
||||
### 8.4 ECharts 组件注册清单
|
||||
|
||||
采用 ECharts 按需引入,减少打包体积:
|
||||
|
||||
```typescript
|
||||
// plugins/echarts.ts
|
||||
import * as echarts from 'echarts/core'
|
||||
import {
|
||||
LineChart, // 图表1, 6
|
||||
BarChart, // 图表2, 3, 10, 11, 12
|
||||
PieChart, // 图表4, 8
|
||||
HeatmapChart, // 图表5
|
||||
SankeyChart, // 图表7
|
||||
GaugeChart, // 图表9
|
||||
} from 'echarts/charts'
|
||||
import {
|
||||
TitleComponent, TooltipComponent, LegendComponent,
|
||||
GridComponent, DataZoomComponent, VisualMapComponent,
|
||||
CalendarComponent, MarkLineComponent, MarkPointComponent,
|
||||
MarkAreaComponent, GraphicComponent, ToolboxComponent
|
||||
} from 'echarts/components'
|
||||
import { CanvasRenderer } from 'echarts/renderers'
|
||||
|
||||
echarts.use([
|
||||
LineChart, BarChart, PieChart, HeatmapChart, SankeyChart, GaugeChart,
|
||||
TitleComponent, TooltipComponent, LegendComponent,
|
||||
GridComponent, DataZoomComponent, VisualMapComponent,
|
||||
CalendarComponent, MarkLineComponent, MarkPointComponent,
|
||||
MarkAreaComponent, GraphicComponent, ToolboxComponent,
|
||||
CanvasRenderer
|
||||
])
|
||||
|
||||
export default echarts
|
||||
```
|
||||
|
||||
### 8.5 前端组件与后端 API 完整映射
|
||||
|
||||
| Vue 组件 | ECharts 图表类型 | 后端 API |
|
||||
|---|---|---|
|
||||
| `NetWorthTrendChart.vue` | Line (Area) | `GET /api/v1/dashboard/trend` |
|
||||
| `CashFlowBarChart.vue` | Bar + Line (混合) | `GET /api/v1/dashboard/trend` |
|
||||
| `AssetCompositionChart.vue` | Bar (Stack) | `GET /api/v1/dashboard/asset-composition` |
|
||||
| `ExpensePieChart.vue` | Pie (Donut) | `GET /api/v1/analysis/category?type=expense` |
|
||||
| `CalendarHeatmap.vue` | Heatmap (Calendar) | `GET /api/v1/analysis/heatmap` |
|
||||
| `CategoryTrendChart.vue` | Line (Multi) | `GET /api/v1/analysis/category-trend` |
|
||||
| `SankeyChart.vue` | Sankey | `GET /api/v1/analysis/sankey` |
|
||||
| `IncomePieChart.vue` | Pie (Donut) | `GET /api/v1/analysis/category?type=income` |
|
||||
| `BudgetGauge.vue` | Gauge | `GET /api/v1/budgets` |
|
||||
| `BudgetCompareChart.vue` | Bar (Grouped) | `GET /api/v1/budgets` |
|
||||
| `AccountWaterfallChart.vue` | Bar (Waterfall) | `GET /api/v1/accounts/:id/waterfall` |
|
||||
| `ImportQualityChart.vue` | Bar (Stack) | `GET /api/v1/bills/import-history` |
|
||||
@@ -0,0 +1,566 @@
|
||||
# DDS 文档 → Google Stitch UI 设计 Prompt 转换指南
|
||||
|
||||
> 本文档提供一套系统化的方法论,用于将软件系统的 **DDS(详细设计说明书)** 转换为 **Google Stitch** 能够理解并生成高质量 UI 设计的 prompt。
|
||||
|
||||
---
|
||||
|
||||
## 一、转换方法论总览
|
||||
|
||||
### 核心思路:Zoom-Out → Zoom-In 分层提取
|
||||
|
||||
```
|
||||
DDS 文档
|
||||
├── 第1层:系统全局上下文(Zoom-Out) → Stitch 全局系统 prompt
|
||||
├── 第2层:页面级结构提取 → Stitch 逐页设计 prompt
|
||||
├── 第3层:组件级细节提取 → Stitch 组件精修 prompt
|
||||
└── 第4层:交互与联动提取 → Stitch 交互追加 prompt
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Google Stitch 的最佳实践是**分步生成、逐步精修**,不要试图一次性生成整个系统的 UI。建议按页面逐一生成,每个页面先生成骨架,再通过迭代精修细节。
|
||||
|
||||
### DDS 信息提取清单
|
||||
|
||||
从 DDS 文档中需要提取的 UI 相关信息:
|
||||
|
||||
| 提取维度 | DDS 中的对应章节 | 提取要点 |
|
||||
|---|---|---|
|
||||
| **系统定位与目标用户** | §1 项目背景 / PRD | 产品类型、面向人群、核心价值主张 |
|
||||
| **页面结构与路由** | §3.1 页面结构与路由 | 有哪些页面、层级关系、导航结构 |
|
||||
| **页面布局** | §3.3 核心页面设计 | ASCII 布局图、区域划分、信息层级 |
|
||||
| **图表与数据可视化** | 数据可视化 DDS | 图表类型、数据维度、色彩规范 |
|
||||
| **色彩系统** | §8.1 统一色彩系统 | 语义化色板、分类色板、品牌色 |
|
||||
| **组件清单** | §3.2 项目结构 | Vue 组件列表、功能定义 |
|
||||
| **数据模型** | §2.3 数据模型 | 实体关系、字段定义(用于理解界面数据) |
|
||||
| **API 接口** | §2.4 API 接口 | 数据结构(用于理解界面需要展示什么数据) |
|
||||
|
||||
---
|
||||
|
||||
## 二、Prompt 模板体系
|
||||
|
||||
### 🔹 Step 0:全局 Design Token Prompt(系统级,仅需执行一次)
|
||||
|
||||
> 目的:为 Stitch 建立设计系统的基础约束,后续每个页面 prompt 可引用此上下文。
|
||||
|
||||
```
|
||||
【系统设计基调 Prompt】
|
||||
|
||||
我正在设计一个名为「ProjectMoneyX」的个人全景财务分析系统的 Web 端 UI。
|
||||
|
||||
### 产品定位
|
||||
- 这是一款面向个人用户的财务数据分析工具
|
||||
- 核心功能:多源账单导入(支付宝/微信/银行)→ 智能去重 → 多维可视化分析 → 预算管理
|
||||
- 用户画像:25-40岁的白领/自由职业者,关注个人财务健康,有一定数据分析意识
|
||||
- 使用场景:主要在桌面端浏览器使用,每周查看1-2次财务报告
|
||||
|
||||
### 设计风格要求
|
||||
- 整体风格:现代金融科技(FinTech)风格,专业但不冰冷
|
||||
- 设计语言:类似 Material Design 3 的圆角卡片式布局
|
||||
- 色彩基调:
|
||||
- 主色/中性蓝:#4F6EF7(Indigo-500),用于品牌调性和信息展示
|
||||
- 正向/收入色:#10B981(Emerald-500),用于收入、正常状态
|
||||
- 负向/支出色:#EF4444(Red-500),用于支出、超支预警
|
||||
- 警告色:#F59E0B(Amber-500),用于临近阈值提醒
|
||||
- 背景色:#F8FAFC(浅灰白),卡片背景白色
|
||||
- 字体:使用系统字体 + Noto Sans SC(中文)
|
||||
- 布局:左侧固定导航栏 + 右侧主内容区的经典 Dashboard 布局
|
||||
- 深色模式支持:需要考虑暗色主题的兼容性
|
||||
|
||||
### 导航结构(侧边栏菜单)
|
||||
1. 📊 仪表盘(Dashboard)— 默认首页
|
||||
2. 📋 账单管理(Bills)
|
||||
3. 📤 账单导入(Import)
|
||||
4. 🏦 账户管理(Accounts)
|
||||
5. 💰 预算管理(Budget)
|
||||
6. 📈 多维分析(Analysis)
|
||||
7. ⚙️ 规则配置(Rules)
|
||||
|
||||
请为这个系统设计一致的视觉风格。所有页面文字使用中文。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🔹 Step 1:仪表盘页面(DashboardView)
|
||||
|
||||
> 从 DDS §3.3.1 + 数据可视化 DDS §1 提取
|
||||
|
||||
```
|
||||
【仪表盘页面设计 Prompt】
|
||||
|
||||
为「ProjectMoneyX 个人全景财务分析系统」设计仪表盘(Dashboard)页面。
|
||||
|
||||
### 页面目标
|
||||
用户打开系统后的第一个页面,需要在一屏内快速获取个人财务健康全貌。
|
||||
|
||||
### 页面布局(从上到下)
|
||||
|
||||
**第一行:核心指标卡片区(3个等宽卡片)**
|
||||
- 卡片1「净资产」:显示 ¥116,500,下方小字"较上月 ↑3.2%",背景带有淡蓝色渐变
|
||||
- 卡片2「本月收入」:显示 ¥15,000,下方 ↑5.2%(绿色箭头),图标用收入符号
|
||||
- 卡片3「本月支出」:显示 ¥8,200,下方 ↓3.1%(绿色箭头表示支出减少是好事),图标用支出符号
|
||||
- 每个卡片都有圆角、微弱阴影、悬停时轻微上浮动画
|
||||
|
||||
**第二行:图表区(2列布局,左宽右窄,比例约 6:4)**
|
||||
- 左侧「净资产趋势图」:面积折线图,展示近12个月的净资产、总资产、总负债三条线
|
||||
- 净资产线为实线蓝色(#4F6EF7)带半透明渐变填充
|
||||
- 总资产为绿色虚线(#10B981)
|
||||
- 总负债为红色虚线(#EF4444)
|
||||
- 图表上方有标题"净资产趋势"和时间范围选择器(近6月/近12月/全部)
|
||||
- 右侧「月度现金流对比」:柱状图+折线图混合
|
||||
- 绿色柱=收入,红色柱=支出,蓝色折线=结余
|
||||
- 亏损月份的柱状图背景有淡红色标记
|
||||
|
||||
**第三行:资产构成区(全宽)**
|
||||
- 「各账户资产构成」:堆叠面积图,展示各账户余额随时间的构成变化
|
||||
- 包含:招行储蓄卡、支付宝余额、微信零钱等正向资产(向上堆叠)
|
||||
- 以及:招行信用卡、花呗等负债(负值向下延伸)
|
||||
- 图表外框是白色卡片容器,有圆角和阴影
|
||||
|
||||
### 视觉要求
|
||||
- 卡片之间有 16px 间距
|
||||
- 图表容器统一使用白色圆角卡片(border-radius: 12px)
|
||||
- 页面顶部有"仪表盘"标题和全局时间筛选器
|
||||
- 所有数字使用等宽字体,金额显示千分位分隔符
|
||||
- 页面内容使用中文
|
||||
|
||||
请生成一个专业的、现代化的仪表盘页面设计。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🔹 Step 2:账单导入页(ImportView)
|
||||
|
||||
> 从 DDS §3.3.2 + 数据可视化 DDS §7 提取
|
||||
|
||||
```
|
||||
【账单导入页设计 Prompt】
|
||||
|
||||
为「ProjectMoneyX」设计账单导入页面。
|
||||
|
||||
### 页面目标
|
||||
引导用户完成账单文件的上传和导入,展示导入结果和历史导入质量。
|
||||
|
||||
### 页面布局
|
||||
|
||||
**上半部分:导入操作区(卡片式步骤引导,Step 1-2-3 横向流程)**
|
||||
|
||||
- Step 1「选择来源」:
|
||||
- 展示 4-6 个可选来源的图标卡片(横向排列)
|
||||
- 每个卡片包含图标和名称:支付宝(蓝色)、微信支付(绿色)、招商银行(红色)、工商银行(红色)、京东(红色)、美团(黄色)
|
||||
- 选中状态:卡片边框高亮 + 勾选标记
|
||||
- 卡片之间 12px 间距,悬停有缩放效果
|
||||
|
||||
- Step 2「上传文件」:
|
||||
- 大尺寸拖拽上传区域(虚线边框,中间云上传图标 + 文字"拖拽文件到此处,或点击选择")
|
||||
- 支持的格式提示文字:CSV / XLS / PDF
|
||||
- 上传中显示进度条
|
||||
|
||||
- Step 3「导入结果」:
|
||||
- 导入成功后显示统计卡片行:
|
||||
- ✅ 解析 150 条(蓝色)
|
||||
- ✅ 新导入 132 条(绿色)
|
||||
- ⚠️ 去重跳过 15 条(橙色)
|
||||
- 🔗 链路合并 3 条(蓝色)
|
||||
- ❌ 失败 0 条(灰色)
|
||||
|
||||
**下半部分:导入历史质量图表(全宽卡片)**
|
||||
- 标题:「导入质量趋势」
|
||||
- 堆叠柱状图:X轴为最近10次导入批次,Y轴为条数
|
||||
- 绿色段=新导入数,橙色段=去重数,蓝色段=合并数,红色段=失败数
|
||||
- 图表下方有最近导入记录表格,显示时间、来源、各项统计
|
||||
|
||||
### 视觉要求
|
||||
- 步骤之间用连接线或箭头串联,当前步骤高亮
|
||||
- 未到达的步骤灰化处理
|
||||
- 整体卡片式布局,白色圆角卡片 + 淡灰背景
|
||||
- 页面所有文字使用中文
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🔹 Step 3:多维分析页(AnalysisView)
|
||||
|
||||
> 从 DDS §3.3.3 + 数据可视化 DDS §2-4 提取
|
||||
|
||||
```
|
||||
【多维分析页设计 Prompt】
|
||||
|
||||
为「ProjectMoneyX」设计多维分析页面,这是系统中数据可视化最丰富的页面。
|
||||
|
||||
### 页面目标
|
||||
提供深度的收支分析能力,帮助用户理解"钱花在哪了"和"钱从哪来"。
|
||||
|
||||
### 页面结构
|
||||
|
||||
**顶部:全局筛选栏**
|
||||
- 时间范围选择器(日期区间 picker)
|
||||
- 快捷选项按钮组:本月 / 近3月 / 近6月 / 近1年 / 自定义
|
||||
- 页面标题左侧显示"多维分析"
|
||||
|
||||
**Tab 标签页切换(3个 Tab)**
|
||||
|
||||
---
|
||||
|
||||
**Tab 1:支出分析**
|
||||
- 左右两列布局(5:5)
|
||||
- 左侧「支出结构环形图」:
|
||||
- 大尺寸环形图(Donut),中心显示"总支出 ¥9,820"
|
||||
- 外侧标签:餐饮 32.6%、购物 25.5%、交通 12.2% 等
|
||||
- 支持点击某分类后下钻到二级分类(如 餐饮→外卖/堂食/咖啡)
|
||||
- 下钻后顶部出现面包屑导航 "全部 > 餐饮"
|
||||
- 颜色使用分类色板:#4F6EF7、#10B981、#F59E0B、#EF4444、#8B5CF6...
|
||||
- 右侧「分类支出趋势折线图」:
|
||||
- 多条折线,每条代表一个支出分类
|
||||
- 默认展示前5大分类,其余折叠
|
||||
- 底部有缩放滑块,支持拖拽查看任意时间段
|
||||
- 颜色与左侧环形图一致(跨图表颜色同步)
|
||||
|
||||
- 下方全宽「收支日历热力图」:
|
||||
- 日历格子视图,展示每日消费强度
|
||||
- 颜色从浅绿(低消费)渐变到深红(高消费)
|
||||
- 悬停显示该日总额和前3笔最大账单
|
||||
- 支持月份/年份切换
|
||||
|
||||
---
|
||||
|
||||
**Tab 2:资金流向**
|
||||
- 全宽展示「资金流向桑基图」(Sankey Diagram)⭐ 核心图表
|
||||
- 三列布局:左列=收入来源(工资、兼职、投资收益),中列=资金池/账户(招行储蓄、支付宝、微信),右列=支出分类(餐饮、购物、居住、储蓄)
|
||||
- 流线颜色使用源到目标的渐变色
|
||||
- 悬停高亮相邻节点和链接,淡化其他
|
||||
- 节点标签:左列左对齐,中列居中,右列右对齐
|
||||
- 整体图表高度 500px 以上,确保信息清晰
|
||||
|
||||
---
|
||||
|
||||
**Tab 3:收入分析**
|
||||
- 「收入来源环形图」:与支出环形图对称设计
|
||||
- 中心显示"总收入 ¥15,000"
|
||||
- 使用绿色系配色:#10B981、#34D399、#6EE7B7、#A7F3D0
|
||||
- 分类:工资、兼职收入、理财收益、转账收款等
|
||||
|
||||
### 视觉要求
|
||||
- Tab 切换使用底部指示线动画
|
||||
- 所有图表统一白色卡片容器,带标题栏
|
||||
- 图表标题栏右侧可放置图表操作图标(下载、全屏等)
|
||||
- 页面所有文字使用中文
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🔹 Step 4:预算管理页(BudgetView)
|
||||
|
||||
> 从 DDS §4.2 + 数据可视化 DDS §5 提取
|
||||
|
||||
```
|
||||
【预算管理页设计 Prompt】
|
||||
|
||||
为「ProjectMoneyX」设计预算管理页面。
|
||||
|
||||
### 页面目标
|
||||
直观展示各分类预算执行进度,快速识别超支和节省项。
|
||||
|
||||
### 页面布局
|
||||
|
||||
**顶部:月份选择器 + 操作按钮**
|
||||
- 左侧:月份选择器(< 2026年2月 >),可左右切换
|
||||
- 右侧:「设置预算」按钮(主色调),点击弹出预算编辑弹窗
|
||||
|
||||
**第一行:全局预算仪表盘(居中,大号)**
|
||||
- 单个大尺寸仪表盘(Gauge),展示全局预算使用率
|
||||
- 弧形进度条:0-79% 绿色 → 80-99% 橙色 → ≥100% 红色
|
||||
- 中心显示百分比数字 + "¥8,200 / ¥10,000"
|
||||
- 标题"全局预算"在仪表盘下方
|
||||
|
||||
**第二行:分类预算仪表盘阵列(网格布局,3-4列)**
|
||||
- 每个分类一个小号仪表盘卡片,包含:
|
||||
- 分类图标 + 分类名称
|
||||
- 环形进度条(同样三段变色逻辑)
|
||||
- 中心数字:82% + "¥2,400/¥3,000"
|
||||
- 超支的卡片有红色边框闪烁效果
|
||||
- 示例分类:餐饮(80%⚠️)、交通(65%✅)、购物(110%🔴)、居住(45%✅)、娱乐(30%✅)
|
||||
|
||||
**第三行:预算 vs 实际对比柱状图(全宽卡片)**
|
||||
- 分组柱状图:每个分类两根柱子
|
||||
- 浅蓝柱=预算限额
|
||||
- 动态色柱=实际支出(未超支绿色,超支红色)
|
||||
- 100% 预算位置有水平参考虚线
|
||||
- tooltip 显示差额和百分比
|
||||
|
||||
### 视觉要求
|
||||
- 仪表盘弧度动画:页面加载时从0动画填充到目标值
|
||||
- 超支项有强烈的红色视觉提示(不仅是颜色,还有图标/徽章)
|
||||
- 分类卡片支持悬停展开详情
|
||||
- 页面所有文字使用中文
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🔹 Step 5:账户管理页(AccountView)
|
||||
|
||||
> 从 DDS §3.1 + 数据可视化 DDS §6 提取
|
||||
|
||||
```
|
||||
【账户管理页设计 Prompt】
|
||||
|
||||
为「ProjectMoneyX」设计账户管理页面。
|
||||
|
||||
### 页面目标
|
||||
管理用户的所有资金账户,查看各账户余额和交易流水。
|
||||
|
||||
### 页面布局
|
||||
|
||||
**顶部:账户总览卡片行**
|
||||
- 横向卡片滚动/网格,每个账户一个卡片:
|
||||
- 卡片上半部分:账户图标 + 账户名称 + 账户类型标签(储蓄卡/信用卡/电子钱包)
|
||||
- 卡片下半部分:当前余额(大字加粗)
|
||||
- 储蓄卡类:蓝色系渐变背景
|
||||
- 信用卡类:红色系渐变背景,额外显示"已用额度/总额度"
|
||||
- 电子钱包类:紫色系渐变背景
|
||||
- 右上角有编辑和删除小图标
|
||||
- 最右侧有一个虚线框的「+ 添加账户」卡片
|
||||
|
||||
**下半部分:选中账户的详情区**
|
||||
- 选中某个账户卡片后,下方展示该账户的详情:
|
||||
|
||||
- 左侧(6/10宽度)「账户收支瀑布图」:
|
||||
- 瀑布柱状图,展示月内余额逐笔变化
|
||||
- 起始柱(月初余额)→ 绿色向上柱(收入)→ 红色向下柱(支出)→ 蓝色终止柱(月末余额)
|
||||
- 每根柱子上方/下方标注金额变化
|
||||
- 月份选择器在图表标题栏
|
||||
|
||||
- 右侧(4/10宽度):账户信息卡片
|
||||
- 账户名称、类型、币种
|
||||
- 本月收入合计 / 支出合计 / 净变化
|
||||
- 最近 5 笔交易列表
|
||||
|
||||
### 视觉要求
|
||||
- 账户卡片类似银行卡片造型,有微光泽/渐变效果
|
||||
- 选中账户卡片有高亮边框 + 下方指示箭头
|
||||
- 页面所有文字使用中文
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🔹 Step 6:账单管理页(BillListView)
|
||||
|
||||
```
|
||||
【账单管理页设计 Prompt】
|
||||
|
||||
为「ProjectMoneyX」设计账单管理页面。
|
||||
|
||||
### 页面目标
|
||||
支持多维条件筛选和查看所有账单记录。
|
||||
|
||||
### 页面布局
|
||||
|
||||
**顶部:高级筛选面板(可展开/收起的卡片)**
|
||||
- 第一行筛选项:时间范围(日期区间)、交易类型(收入/支出/全部 按钮组)
|
||||
- 第二行筛选项:金额区间(最小~最大)、账户(下拉选择)、分类(级联选择器)、来源(支付宝/微信等 多选)
|
||||
- 第三行:关键词搜索框(搜索交易对方/商品说明)+ 「查询」按钮 + 「重置」按钮
|
||||
- 展开/收起按钮,默认只显示第一行
|
||||
|
||||
**主体:账单数据表格**
|
||||
- 表头列:日期、交易对方、商品说明、金额、交易类型、分类、账户、来源
|
||||
- 金额列:收入行显示绿色正数,支出行显示红色负数
|
||||
- 交易类型列:使用小标签(tag),收入=绿tag,支出=红tag
|
||||
- 来源列:显示对应图标(支付宝/微信等小logo)
|
||||
- 每行末尾有操作列:查看详情、编辑、删除
|
||||
- 表格支持列排序(点击表头)
|
||||
- 底部分页器:显示总条数,每页20/50/100条切换
|
||||
|
||||
**表格上方工具栏**
|
||||
- 左侧:显示匹配结果数"共 500 条记录"
|
||||
- 右侧:导出按钮、列设置按钮
|
||||
|
||||
### 视觉要求
|
||||
- 表格偶数行有浅灰背景(斑马纹)
|
||||
- 悬停行高亮
|
||||
- 支出和收入行的金额颜色区分明显
|
||||
- 页面所有文字使用中文
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🔹 Step 7:规则配置页(RuleView)
|
||||
|
||||
```
|
||||
【规则配置页设计 Prompt】
|
||||
|
||||
为「ProjectMoneyX」设计规则配置页面。
|
||||
|
||||
### 页面目标
|
||||
让用户管理自动分类映射规则和账户路由规则,控制 ETL 数据清洗行为。
|
||||
|
||||
### 页面布局
|
||||
|
||||
**Tab 切换:分类规则 / 账户路由规则**
|
||||
|
||||
---
|
||||
|
||||
**Tab 1:分类映射规则**
|
||||
- 顶部:「+ 新增规则」按钮
|
||||
- 规则列表(卡片式,非表格):
|
||||
- 每条规则一个卡片,显示:
|
||||
- 匹配条件:标识标签 "交易对方" 或 "商品说明",后面显示正则表达式(代码样式)
|
||||
- 箭头 →
|
||||
- 目标分类:"餐饮-咖啡" (带分类颜色标签)
|
||||
- 优先级数字徽章
|
||||
- 启用/禁用切换开关
|
||||
- 编辑/删除操作图标
|
||||
- 规则按优先级降序排列,高优先级规则排在前面
|
||||
- 支持拖拽排序调整优先级
|
||||
|
||||
---
|
||||
|
||||
**Tab 2:账户路由规则**
|
||||
- 类似的卡片式列表:
|
||||
- 来源标签:"支付宝"(蓝色标签)
|
||||
- 匹配方式:支付方式包含 "招商银行信用卡"
|
||||
- 箭头 →
|
||||
- 目标账户:"招行信用卡" (带账户类型图标)
|
||||
|
||||
**新增/编辑弹窗**
|
||||
- 表单弹窗:选择匹配字段、输入正则表达式、选择目标分类/账户、设置优先级
|
||||
- 有"测试规则"按钮,可输入样例文本测试匹配结果
|
||||
|
||||
### 视觉要求
|
||||
- 规则卡片之间有清晰的分隔
|
||||
- 正则表达式用等宽字体 + 代码背景色展示
|
||||
- 箭头使用 → 图标表达映射关系
|
||||
- 页面所有文字使用中文
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、迭代精修 Prompt 模板
|
||||
|
||||
在 Stitch 生成初版设计后,使用以下追加 prompt 进行精修:
|
||||
|
||||
### 3.1 交互动效精修
|
||||
|
||||
```
|
||||
请为当前设计添加以下交互效果:
|
||||
1. 卡片悬停时轻微上浮(translateY: -2px)+ 阴影加深
|
||||
2. 数字指标在页面加载时有从0到目标值的计数动画
|
||||
3. Tab 切换时有滑动过渡效果
|
||||
4. 图表区域在进入视口时有淡入+上滑的入场动画
|
||||
5. 按钮点击有涟漪扩散效果(Material Design ripple)
|
||||
```
|
||||
|
||||
### 3.2 响应式适配
|
||||
|
||||
```
|
||||
请调整当前设计的响应式布局:
|
||||
- 桌面端(≥1280px):侧边栏固定展开 + 主内容区自适应
|
||||
- 平板端(768-1279px):侧边栏收起为图标模式,主内容区全宽
|
||||
- 移动端(<768px):侧边栏变为底部 Tab 导航,卡片竖向堆叠
|
||||
- 仪表盘的三列卡片在移动端变为单列
|
||||
- 图表在小屏下高度等比缩小,保持可读性
|
||||
```
|
||||
|
||||
### 3.3 暗色模式
|
||||
|
||||
```
|
||||
请为当前设计创建暗色模式版本:
|
||||
- 背景色从 #F8FAFC 变为 #0F172A(深蓝灰)
|
||||
- 卡片背景从白色变为 #1E293B
|
||||
- 文字颜色从深灰变为 #E2E8F0
|
||||
- 图表背景透明,网格线使用 rgba(255,255,255,0.1)
|
||||
- 色彩系统中的语义色(绿/红/橙/蓝)保持不变但亮度微调
|
||||
- 阴影从灰色阴影变为更深的投影
|
||||
- 侧边栏背景 #1E293B,选中项高亮使用主色半透明
|
||||
```
|
||||
|
||||
### 3.4 空状态设计
|
||||
|
||||
```
|
||||
请为以下场景设计空状态界面:
|
||||
1. 首次使用 - 仪表盘无数据:显示插画 + "开始导入您的第一份账单" + 引导按钮
|
||||
2. 账单列表搜索无结果:显示搜索插画 + "未找到匹配的账单记录"
|
||||
3. 预算页面未设置预算:显示图标 + "您还未设置任何预算" + "立即设置"按钮
|
||||
4. 分析页面数据不足:显示图表插画 + "数据量不足,建议导入更多账单后查看分析"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、高级技巧
|
||||
|
||||
### 4.1 使用 DDS 中的 ASCII 布局图
|
||||
|
||||
> DDS 中常包含 ASCII 格式的页面布局草图,可以直接转化为 Stitch 的结构描述。
|
||||
|
||||
**DDS 原文示例:**
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ [净资产卡片] [本月收入卡片] [本月支出卡片] │
|
||||
│ ¥116,500 ¥15,000 ↑5.2% ¥8,200 ↓3.1% │
|
||||
├──────────────────────────┬──────────────────────────────┤
|
||||
│ 收支趋势折线图 (ECharts) │ 消费结构饼图 (ECharts) │
|
||||
│ (近12个月) │ (本月各分类占比) │
|
||||
├──────────────────────────┴──────────────────────────────┤
|
||||
│ 各账户余额一栏表 (v-data-table) │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**转化手法:** 将 ASCII 图的区块关系、比例、信息层级直接翻译为自然语言的空间描述(上/下、左/右、占比等),如上述各页面 prompt 所示。
|
||||
|
||||
### 4.2 从 API Response 推导界面数据
|
||||
|
||||
> DDS 中的 API 响应结构直接告诉我们界面需要展示哪些字段。
|
||||
|
||||
```json
|
||||
// 从 DDS 的 API 响应结构
|
||||
{
|
||||
"total_assets": 125000.00, → UI: "总资产 ¥125,000"
|
||||
"total_liabilities": 8500.00, → UI: "总负债 ¥8,500"
|
||||
"net_worth": 116500.00, → UI: "净资产 ¥116,500"(核心指标卡片)
|
||||
"income_mom_pct": 5.2, → UI: "↑5.2%"(环比增长标签)
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 从色彩系统构建 Stitch Prompt
|
||||
|
||||
> DDS §8.1 的色彩系统应该完整传递给 Stitch,确保生成的设计色彩一致。
|
||||
|
||||
**关键做法:** 在每个页面 prompt 中引用完整的语义化色彩映射(收入=绿、支出=红、警告=橙、中性=蓝),而不是仅给出色值。
|
||||
|
||||
### 4.4 Stitch 的 Experimental Mode 高级用法
|
||||
|
||||
如果你有系统的线框图或草图,可以使用 Stitch 的 **Experimental Mode**:
|
||||
1. 将 DDS 中的 Mermaid 图表导出为图片
|
||||
2. 将 ASCII 布局图在画图工具中绘制为简单线框
|
||||
3. 配合文字 prompt 一起上传到 Stitch Experimental Mode
|
||||
4. 这种图文并茂的方式能获得更精准的布局结果
|
||||
|
||||
---
|
||||
|
||||
## 五、完整工作流程
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A["1. 阅读 DDS 文档"] --> B["2. 提取 UI 相关信息"]
|
||||
B --> C["3. 编写全局设计 Token Prompt"]
|
||||
C --> D["4. 按页面逐一生成设计"]
|
||||
D --> E["5. 使用迭代 Prompt 精修"]
|
||||
E --> F{"6. 满意?"}
|
||||
F -->|否| E
|
||||
F -->|是| G["7. 导出为 Figma/HTML"]
|
||||
G --> H["8. 结合 DDS 技术选型进行开发"]
|
||||
```
|
||||
|
||||
### 推荐执行顺序
|
||||
|
||||
| 步骤 | Prompt | 预期产出 |
|
||||
|---|---|---|
|
||||
| 1 | Step 0: 设计基调 | 确定整体风格,不需要实际页面 |
|
||||
| 2 | Step 1: 仪表盘 | 最重要的页面,奠定视觉基调 |
|
||||
| 3 | Step 3: 多维分析 | 最复杂的页面,包含最多图表 |
|
||||
| 4 | Step 4: 预算管理 | 仪表盘风格的延伸 |
|
||||
| 5 | Step 2: 账单导入 | 流程导向页面 |
|
||||
| 6 | Step 5: 账户管理 | 卡片+图表混合 |
|
||||
| 7 | Step 6: 账单管理 | 表格导向页面 |
|
||||
| 8 | Step 7: 规则配置 | 配置类页面 |
|
||||
|
||||
> [!TIP]
|
||||
> **先攻克最重要+最复杂的页面**(仪表盘和多维分析),这两个页面的设计语言确立后,其他页面可以快速复用。
|
||||
Reference in New Issue
Block a user