400 lines
9.4 KiB
Markdown
400 lines
9.4 KiB
Markdown
|
# 个人账单应用设计文档
|
|||
|
|
|||
|
## 概述
|
|||
|
|
|||
|
个人账单应用是一个现代化的财务管理工具,采用 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<void>;
|
|||
|
stopListening(): Promise<void>;
|
|||
|
addListener(
|
|||
|
eventName: 'notificationReceived',
|
|||
|
listenerFunc: (notification: ParsedNotification) => void
|
|||
|
): Promise<PluginListenerHandle>;
|
|||
|
}
|
|||
|
|
|||
|
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 权限最小化原则
|
|||
|
- 通知访问权限说明
|
|||
|
- 用户授权确认机制
|