feat: 小菜记账 v1.0 - 完整功能实现

核心功能:
- 记账CRUD(支出/收入/分类/备注/日期)
- 统计分析(概览/分类占比/每日趋势)
- 预算管理(按月设置/进度条/超支提醒)
- 数据导出CSV

安全与认证:
- HMAC-SHA256签名token认证
- 用户数据隔离
- 输入验证与错误处理
- CORS配置

前端优化:
- 骨架屏加载
- 账单按日期分组
- 预算页面重构(快捷预设+Numpad)
- SvgIcon组件(H5+微信双端适配)
- 下拉刷新

后端优化:
- 共享日期工具函数
- 数据库连接池优化
- 健康检查端点
- 优雅关闭处理

技术栈:
- 前端:Uni-app (Vue 3 + Pinia)
- 后端:Node.js + Express + MySQL
This commit is contained in:
2026-05-29 16:14:15 +08:00
commit c7f29aa7a7
70 changed files with 32282 additions and 0 deletions

490
docs/development-plan.md Normal file
View File

@@ -0,0 +1,490 @@
# 小菜记账 — 小程序开发方案
> 版本: v1.0 | 日期: 2026-05-27
> UI 原型稿: `docs/mockup/index.html`
---
## 一、项目概述
| 项目 | 说明 |
|------|------|
| 产品名称 | 小菜记账 |
| 产品类型 | 个人记账微信小程序 |
| AppID | wx854804dff2928c53 |
| 设计风格 | Claymorphism (粘土风格) |
| 目标用户 | 18-35岁年轻人注重生活品质 |
---
## 二、技术架构
### 前端 (小程序)
| 技术 | 选型 | 说明 |
|------|------|------|
| 框架 | Uni-app (Vue 3 + Composition API) | 一套代码,跨端运行 |
| 状态管理 | Pinia | 轻量、TypeScript 友好 |
| 样式 | UnoCSS + SCSS | 原子化 + 变量系统 |
| 图标 | Lucide Icons (SVG) | 统一图标集 |
| 图表 | uCharts (qiun-data-charts) | 小程序端图表组件 |
| 字体 | Fredoka + Nunito | 通过 @font-face 加载 |
### 后端 (阿里云 2H2G)
| 技术 | 选型 | 说明 |
|------|------|------|
| 运行时 | Node.js 20 LTS | 轻量高效 |
| 框架 | Express.js | 简单可靠 |
| 数据库 | MySQL 8.0 | 成熟稳定,生态丰富 |
| ORM | Prisma | 类型安全,迁移方便 |
| 缓存 | 无 (内存足够) | 2G 内存可支撑 |
| 部署 | PM2 + Nginx | 进程管理 + 反向代理 |
---
## 三、功能清单
### P0 (MVP - 第一版)
| 模块 | 功能 | 说明 |
|------|------|------|
| 记账 | 添加支出/收入 | 金额、分类、日期、备注 |
| 记账 | 分类选择 | 预设 12 个分类 + 自定义 |
| 首页 | 月度总览 | 本月支出、预算进度 |
| 首页 | 近期账单 | 最近 20 条交易 |
| 统计 | 分类占比 | 环形图 |
| 统计 | 每日趋势 | 折线图 |
| 我的 | 预算设置 | 月度预算 |
| 我的 | 数据导出 | CSV 格式 |
### P1 (第二版)
| 模块 | 功能 | 说明 |
|------|------|------|
| 记账 | 图片识别 | 拍照识别金额 |
| 统计 | 周/月/年切换 | 多维度分析 |
| 我的 | 数据备份 | 云同步 |
| 我的 | 深色模式 | 主题切换 |
### P2 (第三版)
| 模块 | 功能 | 说明 |
|------|------|------|
| 高级 | 多账本 | 不同场景分类 |
| 高级 | 预算提醒 | 超支通知 |
| 高级 | 团队记账 | AA 记账 |
---
## 四、数据库设计
### MySQL 安装 (阿里云服务器)
```bash
# 安装 MySQL 8.0
sudo apt update
sudo apt install -y mysql-server
# 安全配置
sudo mysql_secure_installation
# 创建数据库和用户
sudo mysql -u root -p
CREATE DATABASE xiaocai DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'xiaocai'@'localhost' IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON xiaocai.* TO 'xiaocai'@'localhost';
FLUSH PRIVILEGES;
EXIT;
```
### 核心表
```sql
-- 分类表
CREATE TABLE categories (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
icon VARCHAR(50) NOT NULL,
color VARCHAR(20) NOT NULL,
type ENUM('expense', 'income') NOT NULL,
sort_order INT DEFAULT 0,
is_custom TINYINT(1) DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 交易表
CREATE TABLE transactions (
id INT AUTO_INCREMENT PRIMARY KEY,
amount INT NOT NULL COMMENT '单位:分',
type ENUM('expense', 'income') NOT NULL,
category_id INT,
note VARCHAR(200),
date DATE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_date (date),
INDEX idx_type (type),
FOREIGN KEY (category_id) REFERENCES categories(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 预算表
CREATE TABLE budgets (
id INT AUTO_INCREMENT PRIMARY KEY,
amount INT NOT NULL COMMENT '单位:分',
month VARCHAR(7) NOT NULL COMMENT '格式2026-05',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_month (month)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 用户表 (预留微信登录)
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
openid VARCHAR(100) UNIQUE,
session_key VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### 预设分类数据
| 分类 | 图标 (Lucide) | 颜色 | 类型 |
|------|---------------|------|------|
| 餐饮 | Coffee | #FF8C69 | 支出 |
| 饮品 | Coffee | #FF8C69 | 支出 |
| 购物 | ShoppingBag | #FFB347 | 支出 |
| 交通 | Car | #6C9BCF | 支出 |
| 住房 | Home | #7BC67E | 支出 |
| 医疗 | Heart | #FF6B6B | 支出 |
| 教育 | BookOpen | #6C9BCF | 支出 |
| 娱乐 | Film | #B39DDB | 支出 |
| 服饰 | Shirt | #FFD166 | 支出 |
| 美容 | Smile | #FF8C69 | 支出 |
| 通讯 | Smartphone | #6C9BCF | 支出 |
| 其他 | MoreHorizontal | #BFB3B3 | 支出 |
| 工资 | DollarSign | #7BC67E | 收入 |
| 副业 | TrendingUp | #7BC67E | 收入 |
| 理财 | PieChart | #7BC67E | 收入 |
| 其他收入 | Plus | #BFB3B3 | 收入 |
---
## 五、API 设计
### 基础信息
- 基础 URL: `https://your-domain.com/api`
- 认证: 微信登录 (code2session)
- 响应格式: JSON
### 接口列表
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /auth/login | 微信登录 |
| GET | /categories | 获取分类列表 |
| POST | /transactions | 添加交易 |
| GET | /transactions | 查询交易列表 |
| PUT | /transactions/:id | 更新交易 |
| DELETE | /transactions/:id | 删除交易 |
| GET | /stats/overview | 月度概览 |
| GET | /stats/category | 分类统计 |
| GET | /stats/trend | 每日趋势 |
| GET | /budget | 获取预算 |
| POST | /budget | 设置预算 |
| GET | /export/csv | 导出 CSV |
### 响应示例
```json
// 成功
{
"code": 0,
"data": { ... },
"message": "success"
}
// 失败
{
"code": 40001,
"data": null,
"message": "参数错误"
}
```
---
## 六、项目结构
```
xiaocai/
├── client/ # 小程序端
│ ├── src/
│ │ ├── pages/
│ │ │ ├── index/ # 首页
│ │ │ ├── add/ # 记账
│ │ │ ├── stats/ # 统计
│ │ │ ├── bills/ # 账单
│ │ │ └── profile/ # 我的
│ │ ├── components/
│ │ │ ├── AmountCard/
│ │ │ ├── TransactionItem/
│ │ │ ├── CategoryIcon/
│ │ │ ├── BudgetBar/
│ │ │ ├── BottomNav/
│ │ │ ├── Numpad/
│ │ │ └── Chart/
│ │ ├── stores/
│ │ │ ├── transaction.ts
│ │ │ ├── category.ts
│ │ │ └── budget.ts
│ │ ├── utils/
│ │ │ ├── format.ts
│ │ │ ├── storage.ts
│ │ │ └── request.ts
│ │ ├── static/
│ │ │ └── fonts/
│ │ ├── App.vue
│ │ ├── main.ts
│ │ ├── manifest.json
│ │ ├── pages.json
│ │ └── uni.scss
│ ├── package.json
│ └── vite.config.ts
├── server/ # 后端
│ ├── src/
│ │ ├── routes/
│ │ │ ├── auth.ts
│ │ │ ├── transaction.ts
│ │ │ ├── category.ts
│ │ │ ├── stats.ts
│ │ │ └── budget.ts
│ │ ├── db/
│ │ │ ├── schema.sql
│ │ │ └── seed.sql
│ │ ├── middleware/
│ │ │ └── auth.ts
│ │ └── index.ts
│ ├── data/ # 数据库迁移文件
│ ├── package.json
│ └── tsconfig.json
├── docs/ # 文档
│ ├── mockup/ # UI 原型
│ ├── ui-design.md # 设计规格
│ └── development-plan.md # 本文件
└── deploy/ # 部署脚本
├── nginx.conf
├── ecosystem.config.js # PM2 配置
└── setup.sh # 服务器初始化
```
---
## 七、开发计划
### 阶段一: 基础搭建 (第 1 周)
| 任务 | 说明 | 产出 |
|------|------|------|
| 项目初始化 | Uni-app 项目 + 后端项目 | 可运行的空项目 |
| 数据库设计 | MySQL 建表 + 种子数据 | 数据库就绪 |
| 微信登录 | code2session 对接 | 登录流程 |
| API 框架 | Express + 中间件 | API 可调用 |
### 阶段二: 核心功能 (第 2-3 周)
| 任务 | 说明 | 产出 |
|------|------|------|
| 记账功能 | 添加/编辑/删除交易 | 核心记账流程 |
| 分类管理 | 预设分类 + 自定义 | 12 个分类 |
| 首页展示 | 月度总览 + 账单列表 | 首页完整 |
| 预算功能 | 设置/展示预算 | 预算进度条 |
### 阶段三: 统计分析 (第 4 周)
| 任务 | 说明 | 产出 |
|------|------|------|
| 分类统计 | 环形图 + 排行 | 分类占比 |
| 趋势分析 | 折线图 | 每日趋势 |
| 数据导出 | CSV 导出 | 可导出数据 |
### 阶段四: 优化上线 (第 5 周)
| 任务 | 说明 | 产出 |
|------|------|------|
| UI 细节 | 动画、交互优化 | 精细化 |
| 性能优化 | 首屏加载、缓存 | 流畅体验 |
| 服务器部署 | Nginx + PM2 | 上线运行 |
| 微信审核 | 提交审核 | 正式发布 |
---
## 八、服务器部署方案
### 环境配置
```bash
# 系统: Ubuntu 22.04 LTS
# 配置: 2 核 CPU, 2GB 内存
# 安装 Node.js 20
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
# 安装 MySQL 8.0
sudo apt install -y mysql-server
sudo mysql_secure_installation
# 安装 Nginx
sudo apt install -y nginx
# 安装 PM2
sudo npm install -g pm2
# 创建部署目录
sudo mkdir -p /var/www/xiaocai
sudo chown $USER:$USER /var/www/xiaocai
```
### Nginx 配置
```nginx
server {
listen 80;
server_name your-domain.com;
# 小程序 API
location /api/ {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# SSL (上线前配置)
# listen 443 ssl;
# ssl_certificate /path/to/cert.pem;
# ssl_certificate_key /path/to/key.pem;
}
```
### PM2 配置
```javascript
// ecosystem.config.js
module.exports = {
apps: [{
name: 'xiaocai-server',
script: './dist/index.js',
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '300M',
env: {
NODE_ENV: 'production',
PORT: 3000
}
}]
};
```
### 性能预估 (2H2G)
| 指标 | 预估 |
|------|------|
| 并发用户 | 50-100 |
| QPS | 200-500 |
| 内存占用 | Node.js 150MB + MySQL 300MB |
| 响应时间 | < 100ms |
| 数据库大小 | < 100MB/年 |
**内存分配**: MySQL 约 300MBNode.js 约 150MB系统约 500MB剩余可用约 1GB。
---
## 九、微信小程序配置
### manifest.json
```json
{
"mp-weixin": {
"appid": "wx854804dff2928c53",
"setting": {
"urlCheck": true,
"es6": true,
"postcss": true,
"minified": true
},
"usingComponents": true,
"permission": {
"scope.userLocation": {
"desc": "用于获取您的位置信息"
}
}
}
}
```
### pages.json
```json
{
"pages": [
{ "path": "pages/index/index", "style": { "navigationBarTitleText": "小菜记账" } },
{ "path": "pages/add/index", "style": { "navigationBarTitleText": "记一笔" } },
{ "path": "pages/stats/index", "style": { "navigationBarTitleText": "统计分析" } },
{ "path": "pages/bills/index", "style": { "navigationBarTitleText": "全部账单" } },
{ "path": "pages/profile/index", "style": { "navigationBarTitleText": "我的" } }
],
"tabBar": {
"color": "#BFB3B3",
"selectedColor": "#FF8C69",
"list": [
{ "pagePath": "pages/index/index", "text": "首页", "iconPath": "static/icons/home.png", "selectedIconPath": "static/icons/home-active.png" },
{ "pagePath": "pages/stats/index", "text": "统计", "iconPath": "static/icons/chart.png", "selectedIconPath": "static/icons/chart-active.png" },
{ "pagePath": "pages/bills/index", "text": "账单", "iconPath": "static/icons/bill.png", "selectedIconPath": "static/icons/bill-active.png" },
{ "pagePath": "pages/profile/index", "text": "我的", "iconPath": "static/icons/user.png", "selectedIconPath": "static/icons/user-active.png" }
]
}
}
```
---
## 十、风险与应对
| 风险 | 影响 | 应对方案 |
|------|------|----------|
| 2G 内存不足 | 服务崩溃 | 监控内存,必要时升级配置 |
| 微信审核不通过 | 延迟上线 | 提前了解审核规范 |
| 数据丢失 | 用户体验差 | 每日自动备份 MySQL (mysqldump) |
| 并发量突增 | 响应变慢 | PM2 自动重启 + 限流 |
---
## 十一、预算
| 项目 | 费用 |
|------|------|
| 阿里云服务器 | 已有 (2H2G) |
| 域名 | ¥55/年 (.com) |
| SSL 证书 | 免费 (Let's Encrypt) |
| 微信认证 | ¥300/年 (企业) |
| **总计** | ¥355/年 |
---
## 十二、下一步行动
1. **立即开始**: 初始化 Uni-app 项目 + 后端项目
2. **本周完成**: 数据库设计 + 微信登录 + API 框架
3. **下周目标**: 完成记账核心功能
4. **月底目标**: 完成全部 P0 功能,提交微信审核
---
*文档版本: v1.0 | 最后更新: 2026-05-27*