文章

AI Coding:个人记账助手 - 财务知识?

Concepts

  1. 财年

  2. 收入 、支出 = 流水

  3. 存款余额 = 历史留存

提示词

# 家庭记账应用 - 完整开发提示词 
 
 ## 项目概述 
 
 开发一个本地运行的家庭记账 Web 应用,支持多家庭成员、多财年管理,具备类似 Git 的操作日志回滚机制,提供丰富的数据可视化分析。 
 
 ## 技术栈 
 
 - **前端**: React 18 + TypeScript + Vite 
 - **UI 组件库**: Ant Design 5 
 - **图表库**: ECharts 5(通过 echarts-for-react) 
 - **后端**: Express.js(Node.js) 
 - **数据库**: SQLite(通过 better-sqlite3) 
 - **路由**: React Router DOM 6 
 - **开发工具**: concurrently(同时启动前后端)、tsx(服务端 TS 运行) 
 - **启动方式**: `npm run dev` 同时启动 Vite 前端(5173端口)和 Express 后端(3001端口),Vite 配置代理将 `/api` 请求转发到后端 
 
 ## 项目结构 
 
 ``` 
 family-finance/ 
 ├── package.json 
 ├── vite.config.ts          # Vite 配置,/api 代理到 3001 
 ├── tsconfig.json 
 ├── tsconfig.node.json 
 ├── index.html 
 ├── server/ 
 │   ├── index.ts            # Express 入口,监听 3001 
 │   ├── database.ts         # SQLite 初始化 + 操作日志函数 
 │   └── routes/ 
 │       └── api.ts          # 全部 RESTful API 
 ├── src/ 
 │   ├── main.tsx 
 │   ├── App.tsx             # 路由配置 
 │   ├── index.css           # 全局样式 
 │   ├── App.css             # 布局样式 
 │   ├── utils/ 
 │   │   └── api.ts          # API 请求封装(apiGet/apiPost/apiPut/apiDelete) 
 │   ├── components/ 
 │   │   └── Layout.tsx      # 主布局(侧边栏+顶栏+内容区) 
 │   └── pages/ 
 │       ├── Dashboard.tsx   # 仪表盘 
 │       ├── DataEntry.tsx   # 数据录入 
 │       ├── Analytics.tsx   # 分析报表 
 │       ├── History.tsx     # 操作历史 
 │       └── Settings.tsx    # 系统设置 
 └── database/ 
     └── finance.db          # SQLite 数据库文件 
 ``` 
 
 ## 核心业务概念 
 
 ### 1. 家庭记账(非个人记账) 
 - 收入和支出都需要关联到具体**家庭成员**,或标记为"共同" 
 - 例如:成员A有毛工资和公积金,成员B有花工资和公积金 
 
 ### 2. 财年管理 
 - 财年起始不一定是1月,用户的财年从**每年10月到次年9月** 
 - 支持创建多个财年,可切换查看 
 - 所有业务数据(收入/支出/资产)都通过 `fiscal_year_id` 关联到具体财年 
 
 ### 3. 收入/支出/资产三板块 
 - **收入**: 每月多条记录,每条关联成员+类别(工资/利息/奖金/公积金/其他) 
 - **支出**: 每月多条记录,每条关联成员+类别(生活费/房租/贷款还款/其他)。贷款还款仅做记录,**不计入总资产计算** 
 - **资产余额**: 每月每个账户一条记录,记录的是**月末累计余额**(非当月变动额) 
 
 ### 4. 操作日志回滚(类似 Git) 
 - 每次增删改操作自动记录操作日志,包含操作前后的完整数据快照(JSON) 
 - 支持单条回滚:恢复到操作前的状态 
 - 回滚本身也记录一条 ROLLBACK 类型的日志 
 - 日志不可删除,只能新增回滚记录 
 - 支持查看两个时间点的数据差异(Diff) 
 
 ## 数据库设计(10张表) 
 
 ### 基础配置表 
 1. **members**: id, name, note, created_at 
 2. **fiscal_years**: id, name, start_month, end_month, created_at 
 3. **income_categories**: id, name, created_at 
 4. **expense_categories**: id, name, created_at 
 5. **asset_accounts**: id, name, created_at 
 
 ### 业务数据表 
 6. **income_records**: id, fiscal_year_id, month(1-12), member_id, category_id, amount(正数), note, created_at, updated_at 
 7. **expense_records**: id, fiscal_year_id, month(1-12), member_id, category_id, amount(负数), note, created_at, updated_at 
 8. **asset_snapshots**: id, fiscal_year_id, month(1-12), account_id, balance(正数), created_at, updated_at, UNIQUE(fiscal_year_id, month, account_id) 
 9. **monthly_notes**: id, fiscal_year_id, month(1-12), record_date, note, created_at, updated_at, UNIQUE(fiscal_year_id, month) 
 
 ### 操作日志表 
 10. **operation_logs**: id, timestamp, operation_type(CREATE/UPDATE/DELETE/ROLLBACK), target_module(income/expense/asset/member/category/account/fiscal_year/note), target_id, description, before_data(JSON), after_data(JSON) 
 
 ## API 设计 
 
 统一响应格式:成功 `{ success: true, data: ... }`,失败 `{ success: false, error: "..." }` 
 
 所有写操作(POST/PUT/DELETE)必须在事务中执行,操作前记录 beforeData,操作后记录 afterData。 
 
 ### 基础配置 API(每个实体都有完整 CRUD) 
 - GET/POST `/api/members`,PUT/DELETE `/api/members/:id` 
 - GET/POST `/api/fiscal-years`,PUT/DELETE `/api/fiscal-years/:id` 
 - GET/POST `/api/income-categories`,PUT/DELETE `/api/income-categories/:id` 
 - GET/POST `/api/expense-categories`,PUT/DELETE `/api/expense-categories/:id` 
 - GET/POST `/api/asset-accounts`,PUT/DELETE `/api/asset-accounts/:id` 
 
 ### 业务数据 API 
 - 收入记录: GET(支持 fiscalYearId/month 筛选) / POST / PUT / DELETE `/api/income-records` 
 - 支出记录: GET(支持 fiscalYearId/month 筛选) / POST / PUT / DELETE `/api/expense-records` 
 - 资产快照: GET / POST(**upsert**, 同财年+月份+账户唯一) / PUT `/api/asset-snapshots` 
 - 月度备注: GET / POST(**upsert**, 同财年+月份唯一) / PUT `/api/monthly-notes` 
 
 ### 操作日志 API 
 - GET `/api/operation-logs?module=&limit=20&offset=0`(分页+模块筛选) 
 - POST `/api/operation-logs/rollback/:id`(回滚指定操作) 
 - GET `/api/operation-logs/diff?id1=&id2=`(两点差异) 
 
 ### 汇总分析 API 
 - GET `/api/summary/monthly?fiscalYearId=`(每月:总收入、总支出、净收入、总资产、资产变动) 
 - GET `/api/summary/by-member?fiscalYearId=`(按成员:收入、支出、净收入) 
 - GET `/api/summary/by-category?fiscalYearId=&type=income|expense`(按类别:金额、记录数、占比百分比) 
 
 ### 回滚逻辑 
 - CREATE 回滚 → 删除该记录 
 - UPDATE 回滚 → 用 beforeData 恢复 
 - DELETE 回滚 → 用 beforeData 重新插入 
 - ROLLBACK 类型 → 不可再次回滚 
 
 ## 前端页面详细规格 
 
 ### 路由配置 
 - `/` → Dashboard(仪表盘) 
 - `/entry` → DataEntry(数据录入) 
 - `/analytics` → Analytics(分析报表) 
 - `/history` → History(操作历史) 
 - `/settings` → Settings(系统设置) 
 
 ### 主布局(Layout) 
 - Ant Design Layout 组件,侧边栏 220px(可折叠,收起 80px) 
 - 侧边栏顶部:AccountBookOutlined 图标 + "家庭记账" 文字 
 - 导航菜单:仪表盘 / 数据录入 / 分析报表 / 操作历史 / 系统设置 
 - 侧边栏底部:版本信息 
 - 顶栏:折叠按钮 + 当前页面标题 
 - 窗口 < 768px 时自动折叠侧边栏 
 
 ### 页面1:仪表盘(Dashboard) 
 - 顶部:标题"财务概览" + 财年选择 Select 
 - 4个统计卡片(Row 4列):本月总收入(绿色) / 本月总支出(红色) / 本月净收入(正绿负红) / 总资产(紫色),使用 Statistic 组件,带¥符号和千分位 
 - 收支走势折线图(ReactECharts):X轴月份,双线(收入绿色+支出红色),半透明面积填充,smooth 曲线 
 - 资产增长曲线(ReactECharts):X轴月份,单线(蓝色),半透明面积填充 
 - 收入构成环形图(ReactECharts):radius 40%-70%,中心显示总金额,绿色系 
 - 支出构成环形图(ReactECharts):同上,红色系 
 - 数据源:`/api/summary/monthly` + `/api/summary/by-category` 
 
 ### 页面2:数据录入(DataEntry) 
 - 顶部卡片:财年 Select + 月份 Select(1-12月) + 保存按钮 
 - 收入明细表格(左半):列 = 成员(Select) | 类别(Select) | 金额(InputNumber,正数) | 备注(Input) | 删除按钮 
 - 支出明细表格(右半):同上结构,但金额保存时自动取负 
 - 新增行用浅蓝色背景(#e6f7ff)标记,标记 `_isNew: true` 
 - 资产余额表格(全宽):列 = 账户(Select) | 月末余额(InputNumber) | 删除按钮 
 - 月度备注(全宽):记录时间(DatePicker) + 备注(TextArea) 
 - 保存逻辑:新增行调 POST,已有行调 PUT,资产和备注用 POST(upsert),Promise.all 并行提交 
 - 切换财年/月份自动加载数据 
 
 ### 页面3:分析报表(Analytics) 
 三个 Tab: 
 
 **Tab1 综合分析**(5个图表): 
 1. 月度收支对比柱状图(收入绿/支出红,圆角柱体) 
 2. 净收入趋势折线图(正值绿色/负值红色数据点,零线标记) 
 3. 收入类别占比环形图(中心显示总金额) 
 4. 支出类别占比环形图 
 5. 资产账户分布堆叠面积图(按账户堆叠) 
 
 **Tab2 成员对比**(3个图表): 
 1. 成员收入对比柱状图(每成员一根柱子,顶部数值标签) 
 2. 成员支出对比柱状图 
 3. 成员收支趋势折线图(每成员一条线,不同颜色) 
 
 **Tab3 收入预测**(1图表 + 3卡片): 
 1. 收入预测图:实际收入(蓝色实线) + 趋势线(黄色虚线) + 预测收入(紫色虚线延伸3个月,pin标注) 
 2. 统计卡片:预测下月收入、预测下季度收入、年化收入估算 
 3. 趋势斜率说明 
 
 **预测算法**:前端实现简单线性回归(最小二乘法),基于历史月度总收入数据,预测未来3个月。 
 
 ### 页面4:操作历史(History) 
 - 顶部筛选:模块 Select(全部/收入/支出/资产/成员/类别/账户/财年/备注) + 关键词 Input + 刷新按钮 
 - 时间线(antd Timeline, mode="left"): 
   - 每条:时间戳 + 操作类型Tag + 模块Tag + 描述 
   - 操作类型颜色:CREATE=green, UPDATE=blue, DELETE=red, ROLLBACK=orange 
   - 可折叠区域显示操作前/后数据(JSON 格式化,缩进2空格) 
   - 回滚按钮(Popconfirm确认)+ 对比按钮 
   - ROLLBACK 类型不可再次回滚,显示"查看详情" 
 - Diff 对比 Modal:深色背景,红色删除行/绿色新增行/灰色未变化行(类似 git diff) 
 - 分页:每页20条 
 
 ### 页面5:系统设置(Settings) 
 5个 Tab,每个 Tab 使用通用 CRUD 模式(泛型 Hook `useCrud<T>`): 
 
 | Tab | API路径 | 表格列 | 表单字段 | 
 |-----|---------|--------|----------| 
 | 家庭成员 | /members | 序号/姓名/备注/操作 | 姓名(必填)/备注 | 
 | 收入类别 | /income-categories | 序号/类别名称/操作 | 名称(必填) | 
 | 支出类别 | /expense-categories | 序号/类别名称/操作 | 名称(必填) | 
 | 资产账户 | /asset-accounts | 序号/账户名称/操作 | 名称(必填) | 
 | 财年管理 | /fiscal-years | 序号/财年名称/起始月/结束月/操作 | 名称/起始月(默认10)/结束月(默认9) | 
 
 每个 Tab:添加按钮 → Modal 表单,编辑按钮 → 预填 Modal,删除按钮 → Popconfirm 确认。统一 loading 状态和成功/失败提示。 
 
 ## 样式要求 
 
 - 全局背景色 `#f0f2f5` 
 - 字体栈:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'PingFang SC', 'Microsoft YaHei', sans-serif 
 - 卡片圆角 8px,hover 增强阴影 
 - 按钮和输入框圆角 6px,过渡动画 0.3s 
 - 页面标题左侧 4px 蓝色竖线装饰 
 - 滚动条美化(6px 宽,半透明灰色) 
 - 响应式布局(768px 断点) 
 - 图表配色统一:收入绿色系(#52c41a)、支出红色系(#ff4d4f)、资产蓝色系(#1890ff) 
 
 ## API 工具函数(src/utils/api.ts) 
 
 ```typescript 
 const API_BASE = '/api'; 
 export async function apiGet(path: string) { /* fetch GET */ } 
 export async function apiPost(path: string, data: any) { /* fetch POST, JSON body */ } 
 export async function apiPut(path: string, data: any) { /* fetch PUT, JSON body */ } 
 export async function apiDelete(path: string) { /* fetch DELETE */ } 
 ``` 
 
 ## 关键实现注意事项 
 
 1. **db.transaction() 必须立即调用**:`db.transaction(() => { ... })()` 注意末尾的 `()`,否则返回的是函数而非执行结果 
 2. **资产快照和月度备注使用 upsert**:POST 时先查询是否存在,存在则 UPDATE,不存在则 INSERT 
 3. **支出金额**:前端显示正数,保存时取负数(`-Math.abs`) 
 4. **总资产计算**:总资产 = 各资产账户余额之和,**不包含贷款抵扣** 
 5. **月度汇总的资产变动**:本月资产合计 - 上月资产合计 
 6. **操作日志的 beforeData/afterData**:存储为 JSON 字符串,读取时需要 `JSON.parse` 
 7. **数据库路径**:支持通过环境变量 `DB_PATH` 覆盖默认路径 
 8. **端口**:支持通过环境变量 `PORT` 覆盖默认 3001 
 
 测试数据如图,是2023年数据,你需要离线导入

效果