- 建立基础的 Git 仓库结构 - 配置适用于 Vue.js + Node.js + Android 的 .gitignore - 添加项目说明文档和开发计划 - 包含 Kiro IDE 规格文档和项目计划
9.4 KiB
9.4 KiB
个人账单应用设计文档
概述
个人账单应用是一个现代化的财务管理工具,采用 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 插件接口
通知监听插件
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)
{
_id: ObjectId,
email: String,
password: String, // bcrypt 加密
name: String,
createdAt: Date,
updatedAt: Date,
preferences: {
currency: String,
language: String,
theme: String
}
}
交易模型 (Transaction)
{
_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)
{
_id: ObjectId,
userId: ObjectId,
name: String,
icon: String,
color: String,
type: String, // 'income' | 'expense' | 'both'
isDefault: Boolean,
createdAt: Date,
updatedAt: Date
}
账户模型 (Account)
{
_id: ObjectId,
userId: ObjectId,
name: String,
type: String, // 'cash' | 'alipay' | 'wechat' | 'bank'
icon: String,
color: String,
isDefault: Boolean,
createdAt: Date,
updatedAt: Date
}
错误处理
前端错误处理策略
网络错误
- 自动重试机制(指数退避)
- 离线模式切换
- 用户友好的错误提示
数据验证错误
- 实时表单验证
- 清晰的错误信息显示
- 防止无效数据提交
通知解析错误
- 记录未识别的通知格式
- 提供手动确认选项
- 持续改进解析规则
后端错误处理
API 错误响应格式
{
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
: 服务器内部错误
同步冲突处理
冲突解决策略
- 服务器优先:默认采用服务器数据
- 用户选择:对于重要冲突,让用户选择
- 合并策略:对于非冲突字段进行合并
- 备份本地:冲突数据备份到本地
测试策略
单元测试
- Vue 组件测试(Vue Test Utils + Jest)
- API 端点测试(Supertest + Jest)
- 工具函数测试
- 数据模型验证测试
集成测试
- 前后端 API 集成测试
- 数据库操作测试
- 通知解析功能测试
- 同步机制测试
端到端测试
- 用户注册登录流程
- 交易添加编辑删除流程
- 通知自动记账流程
- 数据同步流程
移动端测试
- Android 设备兼容性测试
- 通知权限申请测试
- 离线功能测试
- 性能测试
UI/UX 设计规范
色彩系统
/* 主色调 */
--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 权限最小化原则
- 通知访问权限说明
- 用户授权确认机制