# 个人账单应用设计文档 ## 概述 个人账单应用是一个现代化的财务管理工具,采用 Vue.js + Node.js + Capacitor.js 技术栈构建。应用的核心特性是通过读取 Android 通知自动捕获交易信息,结合手动记账、云同步和数据分析功能,为用户提供完整的个人财务管理解决方案。 ## 架构 ### 整体架构 ``` ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ Vue.js 前端 │ │ Node.js 后端 │ │ MongoDB 数据库 │ │ │ │ │ │ │ │ - 用户界面 │◄──►│ - RESTful API │◄──►│ - 用户数据 │ │ - 状态管理 │ │ - JWT 认证 │ │ - 交易记录 │ │ - 本地存储 │ │ - 数据验证 │ │ - 分类配置 │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ ▼ ┌─────────────────┐ │ Capacitor.js │ │ │ │ - Android 桥接 │ │ - 通知监听服务 │ │ - 原生功能调用 │ └─────────────────┘ ``` ### 技术栈详细说明 **前端层 (Vue.js)** - Vue 3 with Composition API - Pinia 状态管理 - Vue Router 路由管理 - Tailwind CSS 样式框架 - ECharts 图表库 - SQLite (通过 Capacitor) 本地数据库 **后端层 (Node.js)** - Express.js 框架 - MongoDB + Mongoose ODM - JWT 身份认证 - bcrypt 密码加密 - express-validator 数据验证 **移动端桥接 (Capacitor.js)** - 自定义通知监听插件 - 本地存储插件 - 网络状态检测 ## 组件和接口 ### 前端组件架构 ``` App.vue ├── Layout/ │ ├── AppHeader.vue │ ├── AppNavigation.vue │ └── AppFooter.vue ├── Pages/ │ ├── HomePage.vue │ ├── AddTransactionPage.vue │ ├── AnalyticsPage.vue │ ├── SettingsPage.vue │ └── AuthPage.vue ├── Components/ │ ├── TransactionCard.vue │ ├── CategorySelector.vue │ ├── AmountInput.vue │ ├── DatePicker.vue │ ├── SearchFilter.vue │ ├── ChartComponents/ │ │ ├── PieChart.vue │ │ ├── LineChart.vue │ │ └── BarChart.vue │ └── Common/ │ ├── LoadingSpinner.vue │ ├── EmptyState.vue │ └── ConfirmDialog.vue └── Plugins/ └── NotificationListener.js ``` ### 后端 API 接口 **认证接口** ``` POST /api/auth/register POST /api/auth/login POST /api/auth/refresh POST /api/auth/logout ``` **交易管理接口** ``` GET /api/transactions # 获取交易列表(支持分页和筛选) POST /api/transactions # 创建新交易 GET /api/transactions/:id # 获取单个交易详情 PUT /api/transactions/:id # 更新交易 DELETE /api/transactions/:id # 删除交易 ``` **分类和账户管理** ``` GET /api/categories # 获取分类列表 POST /api/categories # 创建分类 PUT /api/categories/:id # 更新分类 DELETE /api/categories/:id # 删除分类 GET /api/accounts # 获取账户列表 POST /api/accounts # 创建账户 PUT /api/accounts/:id # 更新账户 DELETE /api/accounts/:id # 删除账户 ``` **数据分析接口** ``` GET /api/analytics/summary # 获取汇总数据 GET /api/analytics/trends # 获取趋势数据 GET /api/analytics/categories # 获取分类统计 ``` **同步接口** ``` POST /api/sync/upload # 上传本地更改 GET /api/sync/download # 下载服务器更新 GET /api/sync/status # 获取同步状态 ``` ### Capacitor 插件接口 **通知监听插件** ```typescript interface NotificationListenerPlugin { requestPermission(): Promise<{ granted: boolean }>; startListening(): Promise; stopListening(): Promise; addListener( eventName: 'notificationReceived', listenerFunc: (notification: ParsedNotification) => void ): Promise; } interface ParsedNotification { amount: number; type: 'income' | 'expense'; source: string; merchant?: string; timestamp: string; rawContent: string; } ``` ## 数据模型 ### 用户模型 (User) ```javascript { _id: ObjectId, email: String, password: String, // bcrypt 加密 name: String, createdAt: Date, updatedAt: Date, preferences: { currency: String, language: String, theme: String } } ``` ### 交易模型 (Transaction) ```javascript { _id: ObjectId, userId: ObjectId, amount: Number, type: String, // 'income' | 'expense' category: ObjectId, account: ObjectId, merchant: String, description: String, date: Date, createdAt: Date, updatedAt: Date, syncStatus: String, // 'synced' | 'pending' | 'conflict' source: String, // 'manual' | 'notification' rawNotification: String // 原始通知内容(如果来自通知) } ``` ### 分类模型 (Category) ```javascript { _id: ObjectId, userId: ObjectId, name: String, icon: String, color: String, type: String, // 'income' | 'expense' | 'both' isDefault: Boolean, createdAt: Date, updatedAt: Date } ``` ### 账户模型 (Account) ```javascript { _id: ObjectId, userId: ObjectId, name: String, type: String, // 'cash' | 'alipay' | 'wechat' | 'bank' icon: String, color: String, isDefault: Boolean, createdAt: Date, updatedAt: Date } ``` ## 错误处理 ### 前端错误处理策略 **网络错误** - 自动重试机制(指数退避) - 离线模式切换 - 用户友好的错误提示 **数据验证错误** - 实时表单验证 - 清晰的错误信息显示 - 防止无效数据提交 **通知解析错误** - 记录未识别的通知格式 - 提供手动确认选项 - 持续改进解析规则 ### 后端错误处理 **API 错误响应格式** ```javascript { success: false, error: { code: 'VALIDATION_ERROR', message: '数据验证失败', details: { field: 'amount', message: '金额必须大于0' } } } ``` **错误类型定义** - `VALIDATION_ERROR`: 数据验证错误 - `AUTHENTICATION_ERROR`: 认证失败 - `AUTHORIZATION_ERROR`: 权限不足 - `NOT_FOUND_ERROR`: 资源不存在 - `CONFLICT_ERROR`: 数据冲突 - `INTERNAL_ERROR`: 服务器内部错误 ### 同步冲突处理 **冲突解决策略** 1. 服务器优先:默认采用服务器数据 2. 用户选择:对于重要冲突,让用户选择 3. 合并策略:对于非冲突字段进行合并 4. 备份本地:冲突数据备份到本地 ## 测试策略 ### 单元测试 - Vue 组件测试(Vue Test Utils + Jest) - API 端点测试(Supertest + Jest) - 工具函数测试 - 数据模型验证测试 ### 集成测试 - 前后端 API 集成测试 - 数据库操作测试 - 通知解析功能测试 - 同步机制测试 ### 端到端测试 - 用户注册登录流程 - 交易添加编辑删除流程 - 通知自动记账流程 - 数据同步流程 ### 移动端测试 - Android 设备兼容性测试 - 通知权限申请测试 - 离线功能测试 - 性能测试 ## UI/UX 设计规范 ### 色彩系统 ```css /* 主色调 */ --primary: #F97316; /* 橙色 - 主要交互元素 */ --primary-light: #FB923C; /* 浅橙色 - 悬停状态 */ --primary-dark: #EA580C; /* 深橙色 - 按下状态 */ /* 辅助色 */ --accent-blue: #3B82F6; /* 蓝色 - 收入相关 */ --accent-green: #22C55E; /* 绿色 - 成功状态 */ --accent-red: #EF4444; /* 红色 - 支出相关 */ /* 中性色 */ --background: #F5F5F4; /* 背景色 */ --surface: #FFFFFF; /* 卡片背景 */ --text-primary: #333333; /* 主要文本 */ --text-secondary: #666666; /* 次要文本 */ --border: #E5E5E5; /* 边框色 */ ``` ### 组件设计原则 **卡片设计** - 大圆角 (16px) - 微妙阴影 (0 2px 8px rgba(0,0,0,0.1)) - 充足的内边距 (16px) **按钮设计** - 主按钮:橙色背景,白色文字 - 次要按钮:透明背景,橙色边框 - 悬浮按钮:圆形,橙色,右下角固定 **表单设计** - 圆角输入框 (8px) - 聚焦时橙色边框 - 清晰的标签和占位符 **图标系统** - 使用 Lucide 图标库 - 统一的线条粗细 (2px) - 分类图标支持自定义颜色 ### 动画和交互 **页面转场** - 滑动动画 (300ms ease-out) - 淡入淡出效果 **按钮交互** - 点击时轻微缩放 (0.95) - 悬停时颜色变化 - 加载状态显示 **列表动画** - 项目添加/删除的滑动动画 - 搜索结果的淡入效果 ## 性能优化 ### 前端优化 - 组件懒加载 - 图片懒加载 - 虚拟滚动(大量数据) - 防抖搜索 - 缓存策略 ### 后端优化 - 数据库索引优化 - API 响应缓存 - 分页查询 - 数据压缩 ### 移动端优化 - 本地数据缓存 - 增量同步 - 后台任务优化 - 内存管理 ## 安全考虑 ### 数据安全 - JWT Token 安全存储 - API 请求加密 (HTTPS) - 敏感数据加密存储 - 定期 Token 刷新 ### 隐私保护 - 通知数据本地处理 - 用户数据最小化收集 - 数据删除机制 - 隐私政策合规 ### 权限管理 - Android 权限最小化原则 - 通知访问权限说明 - 用户授权确认机制