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

View File

@@ -0,0 +1,354 @@
# 小菜记账 — 设计规格书
## 概述
**产品名称**: 小菜记账 (Xiaocai Accounting)
**产品类型**: 个人记账小程序
**设计方向**: 可爱 × 高级 (Cute × Premium)
**设计风格**: Claymorphism (软3D粘土风格) + 极简主义融合
**目标平台**: 移动端优先 (微信小程序 / Web App)
---
## 设计理念
"小菜"暗示温暖、家常、轻松。设计需要传递 **「记账也可以很可爱」** 的情感,同时通过精致的细节呈现 **高级感**
### 品牌人格
- **友好温暖** — 不冰冷的财务工具,是陪你记账的小伙伴
- **精致克制** — 可爱但不幼稚,高级但不冷淡
- **轻松治愈** — 让记账从负担变成享受
---
## 色彩系统
| 角色 | 色值 | 用途 |
|------|------|------|
| Primary | `#FF8C69` | 主色调,珊瑚橙,温暖活泼 |
| Primary Light | `#FFB89A` | 浅色变体,背景装饰 |
| Primary Dark | `#E67355` | 深色变体,按下状态 |
| Secondary | `#6C9BCF` | 辅助色,柔和蓝,收入/信任 |
| Accent | `#FFD166` | 强调色,暖金,高亮点缀 |
| Background | `#FFF8F0` | 全局背景,暖奶油色 |
| Surface | `#FFFFFF` | 卡片/面板背景 |
| Surface Warm | `#FFF0E6` | 暖色卡片背景 |
| Text Primary | `#2D1B1B` | 主文字,暖深棕 |
| Text Secondary | `#8B7E7E` | 辅助文字 |
| Text Muted | `#BFB3B3` | 禁用/占位文字 |
| Success | `#7BC67E` | 收入/成功,软绿 |
| Warning | `#FFB347` | 提醒,暖橘 |
| Danger | `#FF6B6B` | 超支/删除,软红 |
| Border | `#F0E0D6` | 分割线/边框 |
### 色彩使用原则
- 主色调占界面约 15-20%,避免过度使用
- 背景保持温暖但不刺眼,`#FFF8F0` 比纯白更有亲和力
- 文字对比度确保 WCAG AA (4.5:1 以上)
- 深棕色文字替代纯黑,与整体暖色调统一
---
## 字体系统
| 用途 | 字体 | 备选 | 权重 |
|------|------|------|------|
| 标题 | Fredoka | PingFang SC (中文) | 500-700 |
| 正文 | Nunito | PingFang SC (中文) | 400-500 |
| 数字/金额 | Fredoka | - | 600-700 |
| 特殊标注 | Caveat (手写体) | - | 400-600 |
### 字号规范
| 级别 | 大小 | 用途 |
|------|------|------|
| H1 | 28px/1.3 | 页面主标题 |
| H2 | 22px/1.3 | 区块标题 |
| H3 | 18px/1.4 | 卡片标题 |
| Body L | 16px/1.6 | 正文 |
| Body | 14px/1.6 | 辅助正文 |
| Caption | 12px/1.5 | 说明文字 |
| Amount XL | 36px/1.2 | 首页总金额 |
| Amount L | 24px/1.2 | 列表金额 |
---
## UI 组件规范
### 粘土风格核心参数
- `border-radius`: 16-24px (卡片), 12-16px (按钮)
- `border`: 2-3px solid (深色边框强调立体感)
- `box-shadow`: 内阴影 + 外阴影双层结构
- 外阴影: `4px 4px 12px rgba(45, 27, 27, 0.08)`
- 内阴影: `inset -2px -2px 6px rgba(45, 27, 27, 0.04)`
- 按钮按下: `inset 2px 2px 6px rgba(45, 27, 27, 0.1)` + scale(0.97)
### 按钮
| 类型 | 样式 |
|------|------|
| Primary | 珊瑚橙背景 + 白字 + 粘土阴影 + 圆角16px |
| Secondary | 白色背景 + 3px珊瑚橙边框 + 粘土阴影 |
| Ghost | 无背景 + 珊瑚橙文字 + hover浅色背景 |
| Danger | 软红背景 + 白字 |
### 卡片
- 白色背景 + 粘土阴影
- 圆角 20px
- 内边距 16-20px
- 点击态: 轻微下沉 (translateY 2px + 阴影缩减)
### 输入框
- 圆角 14px
- 2px 边框 `#F0E0D6`,聚焦时变为 Primary
- 内阴影 `inset 1px 1px 4px rgba(45,27,27,0.04)`
- 高度 48px方便触摸
### 图标
- 使用 **Lucide Icons** (一致的 SVG 图标集)
- 尺寸: 24px (标准), 20px (小), 32px (大)
- 颜色跟随内容层级
---
## 页面结构
### 1. 首页 — 仪表盘
```
┌──────────────────────────┐
│ 👤 头像 小菜记账 📊 │ 顶栏
├──────────────────────────┤
│ 本月支出 │
│ ¥ 3,280.00 │ 金额大卡片 (粘土)
│ ━━━━━━━━━━━━━━ 65% │ 预算进度条
│ 预算剩余 ¥1,720 │
├──────────────────────────┤
│ [收入] [支出] [转账] │ 快捷操作 (3个大按钮)
├──────────────────────────┤
│ 近期账单 │
│ 🍜 午餐 -¥35 今天 │
│ ☕ 咖啡 -¥18 今天 │ 交易列表
│ 💰 工资 +¥8,000 昨天 │
│ 📦 快递 -¥28 昨天 │
├──────────────────────────┤
│ 🏠 📊 💰 👤 │ 底部导航
└──────────────────────────┘
```
### 2. 记账页 — 添加记录
- 大号金额输入区 (居中,大字体)
- 分类选择 (圆形图标网格,粘土风格)
- 日期选择
- 备注输入
- 支出/收入切换标签
### 3. 统计页 — 图表分析
- 月度总览卡片
- 分类饼图/环形图
- 日支出趋势折线图
- 分类排行榜
### 4. 我的 — 设置
- 用户头像和信息
- 预算设置
- 分类管理
- 数据导出
---
## 动效规范
| 类型 | 时长 | 缓动 | 说明 |
|------|------|------|------|
| 按钮按下 | 150ms | ease-out | 轻微下沉 + 缩放 |
| 页面切换 | 250ms | ease-in-out | 淡入 + 上移 8px |
| 数字变化 | 400ms | ease-out | 数字递增动画 |
| 列表出现 | 300ms | ease-out | 错位入场 (stagger 50ms) |
| 悬浮反馈 | 200ms | ease | 阴影加深 + 微上浮 |
### 动画原则
- 尊重 `prefers-reduced-motion`
- 不使用夸张弹跳 (粘土风格的自然按压感即可)
- 数字跳动使用 `font-variant-numeric: tabular-nums` 防止宽度变化
---
## 设计令牌系统
### 间距 (4px 基准)
| Token | 值 | 用途 |
|-------|-----|------|
| `--space-xs` | 4px | 图标与文字间距 |
| `--space-sm` | 8px | 紧凑内边距 |
| `--space-md` | 12px | 按钮内边距 |
| `--space-base` | 16px | 卡片内边距、列表间距 |
| `--space-lg` | 20px | 区块间距 |
| `--space-xl` | 24px | 页面内边距 |
| `--space-2xl` | 32px | 大区块间距 |
### 圆角
| Token | 值 | 用途 |
|-------|-----|------|
| `--radius-sm` | 8px | 标签、小按钮 |
| `--radius-md` | 12px | 输入框、普通按钮 |
| `--radius-lg` | 16px | 主按钮、分类图标 |
| `--radius-xl` | 20px | 卡片 |
| `--radius-full` | 9999px | 圆形头像、药丸标签 |
### 阴影 (粘土风格)
| Token | 值 | 用途 |
|-------|-----|------|
| `--shadow-clay` | `4px 4px 12px rgba(45,27,27,0.08), inset -2px -2px 6px rgba(45,27,27,0.04)` | 卡片默认 |
| `--shadow-clay-hover` | `6px 6px 16px rgba(45,27,27,0.12), inset -2px -2px 6px rgba(45,27,27,0.04)` | 卡片悬浮 |
| `--shadow-clay-pressed` | `inset 2px 2px 6px rgba(45,27,27,0.1)` | 按钮按下 |
| `--shadow-clay-float` | `8px 8px 24px rgba(45,27,27,0.1), inset -3px -3px 8px rgba(45,27,27,0.05)` | 浮动元素 |
---
## 组件库规范
### AmountCard (金额卡片)
显示金额的卡片容器,用于首页总览、统计概览等。
| Prop | 类型 | 说明 |
|------|------|------|
| `title` | string | 标题文字 |
| `amount` | number | 金额 (分) |
| `prefix` | `'+'` \| `'-'` \| `''` | 前缀符号 |
| `variant` | `'default'` \| `'warm'` \| `'primary'` | 样式变体 |
| `trend` | `{ value, direction }` | 趋势数据 |
变体:
- `default`: 白色背景 + 粘土阴影
- `warm`: 背景 `#FFF0E6`
- `primary`: 渐变 `#FF8C69 → #FFB89A`,文字白色
### TransactionItem (交易列表项)
| Prop | 类型 | 说明 |
|------|------|------|
| `icon` | string | Lucide 图标名 |
| `iconColor` | string | 图标颜色 |
| `iconBg` | string | 图标背景色 |
| `name` | string | 交易名称 |
| `category` | string | 分类名 |
| `time` | string | 时间 |
| `amount` | number | 金额 (分) |
| `type` | `'expense'` \| `'income'` | 类型 |
布局: 64px 高flex 对齐gap 12px。按下态: 背景 `#FFF8F0`100ms。
### CategoryIcon (分类图标)
| Prop | 类型 | 说明 |
|------|------|------|
| `name` | string | Lucide 图标名 |
| `size` | `'sm'` \| `'md'` \| `'lg'` | 尺寸 (20/24/28px) |
| `color` | string | 图标颜色 |
| `bgColor` | string | 背景色 |
| `selected` | boolean | 是否选中 |
尺寸映射:
- sm: 容器 32px图标 16px圆角 8px
- md: 容器 44px图标 22px圆角 12px
- lg: 容器 56px图标 28px圆角 14px
### BudgetBar (预算进度条)
| Prop | 类型 | 说明 |
|------|------|------|
| `total` | number | 预算总额 (分) |
| `used` | number | 已用金额 (分) |
| `showLabel` | boolean | 是否显示标签 |
轨道: 高 8px圆角 4px背景 `#F0E0D6`
填充: 渐变 `#FF8C69 → #FFB89A`,宽度 = used/total。
超支态: 填充色变为 `#FF6B6B`
动画: 宽度变化 600ms ease-out。
### BottomNav (底部导航栏)
| Prop | 类型 | 说明 |
|------|------|------|
| `current` | `'home'` \| `'stats'` \| `'profile'` | 当前页 |
| `onNavigate` | function | 导航回调 |
高度: 56px + safe-area。4 个导航项 + 中间浮动 "+" 按钮。
选中态: 图标填充 `#FF8C69`,文字 `#FF8C69` Nunito 600。
默认态: 图标线条 `#BFB3B3`,文字 `#BFB3B3` Nunito 400。
---
## 暗色模式 (v2 预留)
| Token | Light | Dark |
|-------|-------|------|
| Background | `#FFF8F0` | `#1A1412` |
| Surface | `#FFFFFF` | `#2D2422` |
| Surface Warm | `#FFF0E6` | `#3D2E2A` |
| Text Primary | `#2D1B1B` | `#F5EDE8` |
| Text Secondary | `#8B7E7E` | `#A89890` |
| Border | `#F0E0D6` | `#4A3C38` |
| Primary | `#FF8C69` | `#FF8C69` (不变) |
| Shadow | `rgba(45,27,27,0.08)` | `rgba(0,0,0,0.3)` |
---
## 技术选型建议
| 方案 | 技术栈 | 适用场景 |
|------|--------|----------|
| A | Uni-app (Vue3) + Pinia | 跨端小程序,一套代码多平台 |
| B | Taro (React) + Zustand | React 生态,跨端 |
| C | 原生微信小程序 | 纯微信生态,性能最优 |
| D | HTML + Tailwind CSS + Vanilla JS | Web App最快原型 |
**推荐 A (Uni-app)**: 跨端能力 + Vue 生态成熟 + 社区资源丰富,适合快速开发上线。
---
## 反模式 (避免)
- ❌ 使用 emoji 作为 UI 图标 → ✅ 使用 Lucide SVG 图标
- ❌ 纯黑或冷灰色文字 → ✅ 暖棕色调文字
- ❌ 扁平无层次 → ✅ 粘土阴影创造深度
- ❌ 过于幼稚 → ✅ 克制的圆角和色彩饱和度
- ❌ 文字过多 → ✅ 图标+数字为主,文字为辅
- ❌ 弹出式键盘遮挡 → ✅ 金额输入固定在键盘上方
- ❌ 忽略触摸区域 → ✅ 最小 44×44px 触摸目标
---
## 响应式与适配
### 断点
| 断点 | 宽度 | 设备 | 布局调整 |
|------|------|------|----------|
| xs | < 375px | 小屏手机 | 缩小间距,字号减 1px |
| sm | 375-414px | 标准手机 | 基准设计 |
| md | 415-768px | 大手机/小平板 | 内容区 max-width 480px 居中 |
| lg | > 768px | 平板/H5 | 双列布局,侧边导航 |
### 小程序 rpx 换算
设计稿 375px → 750rpx (1px = 2rpx)
| 设计稿 | rpx |
|--------|-----|
| 12px | 24rpx |
| 14px | 28rpx |
| 16px | 32rpx |
| 18px | 36rpx |
| 20px | 40rpx |
| 24px | 48rpx |
| 36px | 72rpx |
| 48px | 96rpx |
### H5 桌面端
- 内容区: `max-width: 420px`,居中
- 背景: `#F0E0D6` (深色底)
- 手机框: 圆角 32px + 阴影,模拟手机外观