Files
xiaocai/docs/ui-design.md
wangxiaogang c7f29aa7a7 feat: 小菜记账 v1.0 - 完整功能实现
核心功能:
- 记账CRUD(支出/收入/分类/备注/日期)
- 统计分析(概览/分类占比/每日趋势)
- 预算管理(按月设置/进度条/超支提醒)
- 数据导出CSV

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

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

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

技术栈:
- 前端:Uni-app (Vue 3 + Pinia)
- 后端:Node.js + Express + MySQL
2026-05-29 16:14:15 +08:00

1101 lines
39 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 小菜记账 — UI 设计稿
> 版本: v1.0 | 日期: 2026-05-27
> 设计风格: Claymorphism (粘土风格) + 极简融合
> 目标尺寸: 375 × 812px (iPhone SE 基准) / 750 × 1624px (小程序 rpx)
---
## 目录
1. [设计令牌 (Design Tokens)](#设计令牌)
2. [页面一: 首页仪表盘](#页面一-首页仪表盘)
3. [页面二: 记账页](#页面二-记账页)
4. [页面三: 统计页](#页面三-统计页)
5. [页面四: 我的](#页面四-我的)
6. [组件库](#组件库)
7. [交互状态](#交互状态)
8. [响应式适配](#响应式适配)
---
## 设计令牌
### 间距系统 (4px 基准)
| Token | 值 | 用途 |
|-------|-----|------|
| `--space-xs` | 4px | 图标与文字间距 |
| `--space-sm` | 8px | 紧凑内边距 |
| `--space-md` | 12px | 按钮内边距 |
| `--space-base` | 16px | 卡片内边距、列表间距 |
| `--space-lg` | 20px | 区块间距 |
| `--space-xl` | 24px | 页面内边距 |
| `--space-2xl` | 32px | 大区块间距 |
| `--space-3xl` | 48px | 页面顶部留白 |
### 圆角系统
| 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)` | 浮动元素 |
---
## 页面一: 首页仪表盘
### 布局结构
```
┌─────────────────────────────────────────┐
│ 状态栏 (系统) │ 0px
├─────────────────────────────────────────┤
│ │
│ ┌─ 顶栏 ──────────────────────────┐ │ 12px padding-top
│ │ [头像] 早上好,小菜 [通知🔔] │ │
│ └──────────────────────────────────┘ │
│ │
│ ┌─ 月度总览卡片 ──────────────────┐ │
│ │ │ │
│ │ 本月支出 │ │ 16px padding
│ │ ¥ 3,280.00 │ │ (Amount XL: 36px Fredoka)
│ │ │ │
│ │ ━━━━━━━━━━━━━━━░░░░ 65% │ │ 预算进度条
│ │ 预算 ¥5,000 · 剩余 ¥1,720 │ │
│ │ │ │
│ │ ┌──────┐ ┌──────┐ │ │
│ │ │收入 │ │支出 │ │ │
│ │ │¥8,000│ │¥3,280│ │ │
│ │ └──────┘ └──────┘ │ │
│ │ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─ 快捷操作 ─────────────────────┐ │
│ │ │ │
│ │ ┌────────┐┌────────┐┌────────┐│ │
│ │ │ 💵 ││ 💸 ││ 🔄 ││ │ 3列等分
│ │ │ 记收入 ││ 记支出 ││ 转账 ││ │ 每个 44px 高
│ │ └────────┘└────────┘└────────┘│ │
│ │ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─ 近期账单 ─────────────────────┐ │
│ │ 今天 查看全部 │ │
│ │ ───────────────────────────── │ │
│ │ ┌────────────────────────────┐│ │
│ │ │ 🍜 午餐 -¥35.00 ││ │ 交易项
│ │ │ 餐饮 · 12:30 ││ │ 高度 64px
│ │ └────────────────────────────┘│ │
│ │ ┌────────────────────────────┐│ │
│ │ │ ☕ 咖啡 -¥18.00 ││ │
│ │ │ 餐饮 · 09:15 ││ │
│ │ └────────────────────────────┘│ │
│ │ │ │
│ │ 昨天 │ │
│ │ ───────────────────────────── │ │
│ │ ┌────────────────────────────┐│ │
│ │ │ 💰 工资 +¥8,000.00 ││ │
│ │ │ 收入 · 10:00 ││ │
│ │ └────────────────────────────┘│ │
│ │ ┌────────────────────────────┐│ │
│ │ │ 📦 快递 -¥28.00 ││ │
│ │ │ 交通 · 15:42 ││ │
│ │ └────────────────────────────┘│ │
│ │ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─ 底部导航栏 ───────────────────┐ │
│ │ [首页] [统计] [+] [我的]│ │ 56px 高
│ │ ● │ │
│ └─────────────────────────────────┘ │
│ │
├─────────────────────────────────────────┤
│ 安全区域 (Home Indicator) │ 34px
└─────────────────────────────────────────┘
```
### 顶栏规格
```
高度: 48px
内边距: 0 24px
对齐: flex, items-center, justify-between
头像: 36×36px, 圆形, 2px 边框 #F0E0D6
标题: 18px Fredoka 500, #2D1B1B
通知: 24×24px Lucide Bell 图标, #8B7E7E
```
### 月度总览卡片规格
```
外边距: 0 20px
内边距: 24px
圆角: 20px
背景: #FFFFFF
阴影: var(--shadow-clay)
边框: 2px solid #F0E0D6
"本月支出" 文字:
字号: 14px Nunito 400, #8B7E7E
下方间距: 4px
金额:
字号: 36px Fredoka 600, #2D1B1B
font-variant-numeric: tabular-nums
下方间距: 16px
进度条:
高度: 8px, 圆角: 4px
背景: #F0E0D6
填充: 渐变 #FF8C69 → #FFB89A
右侧百分比: 14px Fredoka 500, #FF8C69
预算文字:
12px Nunito 400, #8B7E7E
margin-top: 8px
收支小卡片:
容器: flex, gap 12px, margin-top 20px
单卡: flex-1, padding 12px, 圆角 12px, 背景 #FFF8F0
标签: 12px Nunito 400, #8B7E7E
金额: 18px Fredoka 600
收入颜色: #7BC67E
支出颜色: #FF6B6B
```
### 快捷操作规格
```
外边距: 20px 20px 0
容器: flex, gap 12px
单按钮:
flex: 1
高度: 72px
圆角: 16px
背景: #FFFFFF
边框: 2px solid #F0E0D6
阴影: var(--shadow-clay)
flex-direction: column
justify-content: center
align-items: center
gap: 4px
图标: 28×28px, 居中
记收入: #7BC67E (Lucide TrendingUp)
记支出: #FF6B6B (Lucide TrendingDown)
转账: #6C9BCF (Lucide ArrowLeftRight)
文字: 12px Nunito 500, #2D1B1B
按下态:
box-shadow: var(--shadow-clay-pressed)
transform: scale(0.97)
transition: 150ms ease-out
```
### 交易列表规格
```
区块标题栏:
外边距: 24px 20px 12px
flex, justify-between, items-center
日期: 14px Nunito 500, #2D1B1B
"查看全部": 12px Nunito 400, #FF8C69
分割线:
外边距: 0 20px
高度: 1px, 背景: #F0E0D6
交易项:
外边距: 0 20px
内边距: 14px 0
高度: 64px (含分割线)
flex, items-center, gap 12px
分类图标:
40×40px, 圆角 12px
背景: 分类对应浅色
图标: 20×20px, 居中
信息区: flex-1
名称: 14px Nunito 500, #2D1B1B
副信息: 12px Nunito 400, #8B7E7E
(格式: "分类 · 时间")
金额:
16px Fredoka 600
支出: #2D1B1B (带前缀 "-")
收入: #7BC67E (带前缀 "+")
font-variant-numeric: tabular-nums
```
### 底部导航栏规格
```
高度: 56px + 34px (安全区域)
背景: #FFFFFF
顶部阴影: 0 -2px 12px rgba(45,27,27,0.06)
圆角: 顶部 20px
容器: flex, justify-around, items-center
安全区: padding-bottom: env(safe-area-inset-bottom)
导航项 (4个):
flex-direction: column
align-items: center
gap: 2px
图标: 24×24px
首页: Lucide Home
统计: Lucide BarChart3
我的: Lucide User
文字: 10px Nunito 500
默认颜色: #BFB3B3
选中颜色: #FF8C69
选中态: 图标填充 + 文字加粗
中间 "+" 按钮:
52×52px, 圆形
背景: 渐变 #FF8C69 → #E67355
阴影: 0 4px 16px rgba(255,140,105,0.4)
图标: Lucide Plus, 28px, 白色
向上偏移: -12px (悬浮效果)
按下态: scale(0.93), shadow 减弱
```
---
## 页面二: 记账页
### 布局结构
```
┌─────────────────────────────────────────┐
│ 状态栏 │
├─────────────────────────────────────────┤
│ │
│ ┌─ 顶栏 ──────────────────────────┐ │
│ │ [✕ 关闭] 记一笔 [保存 ✓] │ │
│ └──────────────────────────────────┘ │
│ │
│ ┌─ 支出/收入切换 ─────────────────┐ │
│ │ ┌──────────┐ ┌──────────┐ │ │
│ │ │ ● 支出 │ │ 收入 │ │ │
│ │ └──────────┘ └──────────┘ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─ 金额输入区 ────────────────────┐ │
│ │ │ │
│ │ ¥ 0.00 │ │ 48px Fredoka
│ │ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─ 分类选择网格 ─────────────────┐ │
│ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │
│ │ │ 🍜 │ │ ☕ │ │ 🛒 │ │ 🚗 │ │ │ 每行 4 列
│ │ │餐饮 │ │饮品 │ │购物 │ │交通 │ │ │
│ │ └────┘ └────┘ └────┘ └────┘ │ │
│ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │
│ │ │ 🏠 │ │ 💊 │ │ 📚 │ │ 🎬 │ │ │
│ │ │住房 │ │医疗 │ │教育 │ │娱乐 │ │ │
│ │ └────┘ └────┘ └────┘ └────┘ │ │
│ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │
│ │ │ 👕 │ │ 💅 │ │ 📱 │ │ ··· │ │ │
│ │ │服饰 │ │美容 │ │通讯 │ │更多 │ │ │
│ │ └────┘ └────┘ └────┘ └────┘ │ │
│ │ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─ 附加信息 ─────────────────────┐ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ 📅 今天 (5月27日) ▸ │ │ │ 日期选择
│ │ └─────────────────────────┘ │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ 📝 添加备注... ▸ │ │ │ 备注输入
│ │ └─────────────────────────┘ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─ 数字键盘 ─────────────────────┐ │
│ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │
│ │ │ 1 │ │ 2 │ │ 3 │ │ 日期│ │ │
│ │ └────┘ └────┘ └────┘ └────┘ │ │
│ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │
│ │ │ 4 │ │ 5 │ │ 6 │ │ + │ │ │
│ │ └────┘ └────┘ └────┘ └────┘ │ │
│ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │
│ │ │ 7 │ │ 8 │ │ 9 │ │ - │ │ │
│ │ └────┘ └────┘ └────┘ └────┘ │ │
│ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │
│ │ │ . │ │ 0 │ │ ⌫ │ │ = │ │ │
│ │ └────┘ └────┘ └────┘ └────┘ │ │
│ │ │ │
│ │ ┌────────────────────────┐ │ │
│ │ │ ✓ 记好了 │ │ │ 主按钮
│ │ └────────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────┘ │
│ │
├─────────────────────────────────────────┤
│ 安全区域 │
└─────────────────────────────────────────┘
```
### 顶栏规格
```
高度: 48px
内边距: 0 20px
flex, justify-between, items-center
关闭按钮: 32×32px, Lucide X, #8B7E7E
标题: 16px Nunito 500, #2D1B1B
保存按钮: 14px Nunito 600, #FF8C69
```
### 支出/收入切换
```
外边距: 16px 20px
容器: inline-flex, 背景 #FFF0E6, 圆角 12px, padding 4px
标签: 80px 宽, 36px 高, 圆角 10px
默认: 透明背景, 14px Nunito 400, #8B7E7E
选中: #FFFFFF 背景, 14px Nunito 600, #FF8C69
阴影: 2px 2px 8px rgba(45,27,27,0.08)
切换动画: 200ms ease-in-out
```
### 金额输入区规格
```
外边距: 24px 20px
高度: 80px
text-align: center
货币符号: 24px Fredoka 500, #BFB3B3
金额数字: 48px Fredoka 700, #2D1B1B
font-variant-numeric: tabular-nums
letter-spacing: 1px
光标: 2px 宽, #FF8C69, 闪烁动画
输入态变化:
空状态: "¥ 0.00" 灰色
输入中: 数字跟随按键逐位显示
完成: 金额高亮
```
### 分类选择网格规格
```
外边距: 0 20px
容器: 滚动区域, max-height 约 240px
网格: display grid, grid-template-columns: repeat(4, 1fr)
间距: 12px
分类项:
尺寸: 68×68px (触摸友好)
flex-direction: column, align-items: center, justify-content: center
gap: 4px
图标容器:
44×44px, 圆角 14px
背景: 分类对应浅色 (如餐饮 #FFF0E6)
flex, center
图标: 22×22px, 分类对应颜色
文字: 11px Nunito 400, #8B7E7E
选中态:
图标容器: 边框 2px solid #FF8C69
背景: #FFE8E0
文字: #FF8C69, Nunito 600
图标放大: scale(1.1), 200ms ease
按下态:
transform: scale(0.95), 100ms
```
### 附加信息区规格
```
外边距: 16px 20px
行:
高度: 48px
背景: #FFF8F0
圆角: 12px
内边距: 0 16px
flex, items-center, justify-between
左侧:
图标: 18×18px, #8B7E7E
文字: 14px Nunito 400, #2D1B1B
gap: 8px
右侧:
箭头: Lucide ChevronRight, 16px, #BFB3B3
行间距: 8px
```
### 数字键盘规格
```
外边距: 16px 16px 0
背景: #FFFFFF
圆角: 顶部 20px
padding: 16px
按键网格: 4列 × 4行, gap 8px
数字键:
高度: 48px
圆角: 12px
背景: #FFF8F0
文字: 22px Fredoka 500, #2D1B1B
按下态: 背景 #F0E0D6, 100ms
功能键 (日期/+/-/⌫):
同尺寸
背景: #FFE8E0
文字/图标: #FF8C69
按下态: 背景 #FFD0C0
等号键:
同尺寸
背景: #FF8C69
文字: 白色
按下态: 背景 #E67355
主按钮 "记好了":
外边距: 12px 0
高度: 52px
圆角: 16px
背景: 渐变 #FF8C69 → #E67355
文字: 18px Nunito 600, 白色
阴影: 0 4px 16px rgba(255,140,105,0.3)
按下态: scale(0.97), shadow 减弱
禁用态 (金额为0):
opacity: 0.5
pointer-events: none
```
---
## 页面三: 统计页
### 布局结构
```
┌─────────────────────────────────────────┐
│ 状态栏 │
├─────────────────────────────────────────┤
│ │
│ ┌─ 顶栏 ──────────────────────────┐ │
│ │ 统计分析 │ │
│ └──────────────────────────────────┘ │
│ │
│ ┌─ 月份选择器 ────────────────────┐ │
│ │ ◂ 2026年5月 ▸ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─ 支出/收入切换 (同记账页) ──────┐ │
│ │ ┌──────────┐ ┌──────────┐ │ │
│ │ │ ● 支出 │ │ 收入 │ │ │
│ │ └──────────┘ └──────────┘ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─ 月度概览卡片 ─────────────────┐ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ 总支出 ¥3,280.00│ │ │
│ │ │ 日均 ¥122.00│ │ │
│ │ │ 笔数 28笔│ │ │
│ │ └─────────────────────────┘ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─ 分类占比 ─────────────────────┐ │
│ │ 分类占比 │ │
│ │ │ │
│ │ ╭─────────────╮ │ │
│ │ ┌───────┐ ╲ │ │ 环形图
│ │ │ │ ¥3,280 │ │ │ │ 中心显示总额
│ │ │ │ 总支出 │ │ │ │
│ │ ╲ └───────┘ │ │
│ │ ╰─────────────╯ │ │
│ │ │ │
│ │ ● 餐饮 38% ● 购物 22% │ │ 图例
│ │ ● 交通 15% ● 其他 25% │ │
│ │ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─ 每日趋势 ─────────────────────┐ │
│ │ 每日趋势 │ │
│ │ │ │
│ │ ¥200 ┤ │ │
│ │ │ ╭─╮ │ │ 折线图
│ │ ¥150 ┤ ╲ ╭╮ │ │
│ │ │ ╲ │ │
│ │ ¥100 ┤╭╯ ╰╯ ╲ │ │
│ │ │ ╰─ │ │
│ │ ¥50 ┤ │ │
│ │ └──┬──┬──┬──┬──┬──┬── │ │
│ │ 1 5 10 15 20 25 30 │ │
│ │ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─ 分类排行 ─────────────────────┐ │
│ │ 分类排行 │ │
│ │ │ │
│ │ 1 🍜 餐饮 │ │
│ │ ━━━━━━━━━━━━━━ ¥1,246 │ │ 排行条
│ │ 12笔 · 38% │ │
│ │ │ │
│ │ 2 🛒 购物 │ │
│ │ ━━━━━━━━━░░░░░ ¥722 │ │
│ │ 5笔 · 22% │ │
│ │ │ │
│ │ 3 🚗 交通 │ │
│ │ ━━━━━━░░░░░░░░ ¥492 │ │
│ │ 8笔 · 15% │ │
│ │ │ │
│ │ 4 ☕ 饮品 │ │
│ │ ━━━━░░░░░░░░░░ ¥380 │ │
│ │ 6笔 · 12% │ │
│ │ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─ 底部导航栏 ───────────────────┐ │
│ │ [首页] [统计] [+] [我的]│ │
│ └─────────────────────────────────┘ │
│ │
├─────────────────────────────────────────┤
│ 安全区域 │
└─────────────────────────────────────────┘
```
### 月份选择器规格
```
外边距: 12px 20px
高度: 44px
flex, justify-center, items-center, gap 24px
箭头: 24×24px, Lucide ChevronLeft/Right, #8B7E7E
触摸区域: 44×44px (透明扩展)
按下态: scale(0.9)
月份文字: 16px Fredoka 500, #2D1B1B
```
### 月度概览卡片规格
```
外边距: 16px 20px
内边距: 20px
背景: #FFFFFF
圆角: 20px
阴影: var(--shadow-clay)
边框: 2px solid #F0E0D6
网格: display grid, grid-template-columns: repeat(3, 1fr)
文本对齐: center
标签: 12px Nunito 400, #8B7E7E, margin-bottom 4px
金额: 20px Fredoka 600, #2D1B1B
笔数: 20px Fredoka 600, #2D1B1B (无 ¥ 前缀)
```
### 环形图规格
```
外边距: 20px 20px 0
卡片: 同概览卡片样式
标题: 16px Nunito 500, #2D1B1B, margin-bottom 16px
图表:
尺寸: 200×200px, 居中
环宽: 24px
中心文字:
总额: 20px Fredoka 600, #2D1B1B
标签: 12px Nunito 400, #8B7E7E
图例:
margin-top: 16px
flex, wrap, justify-center, gap 16px
每项: flex, items-center, gap 6px
圆点: 10×10px, 圆形, 分类颜色
文字: 12px Nunito 400, #8B7E7E
百分比: 12px Fredoka 500, #2D1B1B
颜色分配:
餐饮: #FF8C69
购物: #FFD166
交通: #6C9BCF
住房: #7BC67E
其他: #BFB3B3
```
### 折线图规格
```
外边距: 16px 20px 0
卡片: 同概览卡片样式
标题: 16px Nunito 500, #2D1B1B, margin-bottom 16px
图表高度: 160px
线条: 2px, #FF8C69, 圆角端点
填充: 渐变, #FF8C69 透明度 15% → 0%
数据点: 6px 圆, #FF8C69, 2px 白色描边
hover: 8px, 带 tooltip
X 轴标签: 11px Nunito 400, #BFB3B3
Y 轴标签: 11px Fredoka 400, #BFB3B3
网格线: 1px dashed #F0E0D6
```
### 分类排行规格
```
外边距: 16px 20px 24px
卡片: 同概览卡片样式
标题: 16px Nunito 500, #2D1B1B, margin-bottom 16px
排行项:
margin-bottom: 16px (最后一项 0)
flex, items-center, gap 12px
排名: 20px Fredoka 600
第1名: #FF8C69
第2名: #FFD166
第3名: #6C9BCF
其他: #BFB3B3
分类图标: 36×36px, 圆角 10px, 分类浅色背景
图标: 18×18px, 居中
信息区: flex-1
名称: 14px Nunito 500, #2D1B1B
进度条:
margin-top: 6px
高度: 6px, 圆角: 3px
背景: #F0E0D6
填充: 分类颜色, 宽度 = 百分比
动画: 600ms ease-out, 延迟 index * 100ms
统计: 12px Nunito 400, #8B7E7E
margin-top: 4px
格式: "X笔 · XX%"
金额:
16px Fredoka 600, #2D1B1B
font-variant-numeric: tabular-nums
```
---
## 页面四: 我的
### 布局结构
```
┌─────────────────────────────────────────┐
│ 状态栏 │
├─────────────────────────────────────────┤
│ │
│ ┌─ 用户信息卡 ────────────────────┐ │
│ │ │ │
│ │ ╭──────╮ │ │
│ │ │ 头像 │ 小菜 │ │ 64px 头像
│ │ ╰──────╯ 记账小能手 │ │
│ │ │ │
│ │ 已记账 128 天 · 累计 526 笔 │ │
│ │ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─ 快捷统计 ─────────────────────┐ │
│ │ ┌────────┐┌────────┐┌────────┐│ │
│ │ │ 本月 ││ 本季 ││ 本年 ││ │
│ │ │ ¥3,280 ││ ¥9,840 ││¥38,500││ │
│ │ └────────┘└────────┘└────────┘│ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─ 功能列表 ─────────────────────┐ │
│ │ │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ 💰 预算设置 ▸ │ │ │
│ │ └─────────────────────────┘ │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ 🏷️ 分类管理 ▸ │ │ │
│ │ └─────────────────────────┘ │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ 📤 数据导出 ▸ │ │ │
│ │ └─────────────────────────┘ │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ 🔄 数据备份 ▸ │ │ │
│ │ └─────────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─ 设置列表 ─────────────────────┐ │
│ │ │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ 🌙 深色模式 [开关] │ │ │
│ │ └─────────────────────────┘ │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ 🔔 记账提醒 [开关] │ │ │
│ │ └─────────────────────────┘ │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ 🌐 语言 中文 ▸│ │ │
│ │ └─────────────────────────┘ │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ 关于小菜 ▸ │ │
│ │ └─────────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─ 底部导航栏 ───────────────────┐ │
│ │ [首页] [统计] [+] [我的]│ │
│ └─────────────────────────────────┘ │
│ │
├─────────────────────────────────────────┤
│ 安全区域 │
└─────────────────────────────────────────┘
```
### 用户信息卡规格
```
外边距: 0 20px
内边距: 24px
背景: 渐变 #FF8C69 → #FFB89A
圆角: 20px
阴影: var(--shadow-clay-float)
头像:
64×64px, 圆形
边框: 3px solid rgba(255,255,255,0.6)
背景: #FFF8F0 (无头像时显示 Lucide User 图标)
用户名:
20px Fredoka 600, 白色
margin-top: 12px (若头像在上方布局)
签名:
14px Nunito 400, rgba(255,255,255,0.8)
统计:
12px Nunito 400, rgba(255,255,255,0.7)
margin-top: 12px
布局: flex, items-center, gap 16px (头像左,文字右)
```
### 快捷统计规格
```
外边距: 16px 20px
容器: flex, gap 12px
单卡:
flex: 1
内边距: 16px 12px
背景: #FFFFFF
圆角: 16px
阴影: var(--shadow-clay)
边框: 2px solid #F0E0D6
text-align: center
标签: 12px Nunito 400, #8B7E7E, margin-bottom 4px
金额: 16px Fredoka 600, #2D1B1B
```
### 功能列表规格
```
外边距: 20px 20px 0
卡片:
背景: #FFFFFF
圆角: 20px
阴影: var(--shadow-clay)
边框: 2px solid #F0E0D6
overflow: hidden
列表项:
高度: 56px
内边距: 0 20px
flex, items-center, justify-between
border-bottom: 1px solid #F0E0D6 (最后一项无)
左侧:
图标: 20×20px, #FF8C69
文字: 14px Nunito 500, #2D1B1B
gap: 12px
右侧:
箭头: Lucide ChevronRight, 16px, #BFB3B3
按下态:
background: #FFF8F0
transition: 150ms
列表间距: 16px (卡片之间)
```
### 开关规格
```
尺寸: 48×28px
圆角: 14px
关闭态:
背景: #F0E0D6
滑块: 22×22px, 白色, 左侧 3px
开启态:
背景: #FF8C69
滑块: 22×22px, 白色, 右侧 3px
切换动画: 200ms ease-in-out
```
---
## 组件库
### AmountCard 组件
```
用途: 显示金额的卡片容器
Props:
- title: string (标题文字)
- amount: number (金额,分)
- prefix: '+' | '-' | '' (前缀)
- variant: 'default' | 'warm' | 'primary'
- trend: { value: number, direction: 'up' | 'down' }
默认态:
背景: #FFFFFF, 阴影: var(--shadow-clay)
变体:
warm: 背景 #FFF0E6
primary: 背景 渐变 #FF8C69 → #FFB89A, 文字白色
```
### TransactionItem 组件
```
用途: 交易列表项
Props:
- icon: string (分类图标名)
- iconColor: string (图标颜色)
- iconBg: string (图标背景色)
- name: string (交易名称)
- category: string (分类名)
- time: string (时间)
- amount: number (金额,分)
- type: 'expense' | 'income'
布局: 64px 高, flex, items-center, gap 12px
点击态: background #FFF8F0, 100ms
```
### CategoryIcon 组件
```
用途: 分类图标
Props:
- 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 组件
```
用途: 预算进度条
Props:
- total: number (预算总额,分)
- used: number (已用金额,分)
- showLabel: boolean (是否显示标签)
结构:
轨道: 高度 8px, 圆角 4px, 背景 #F0E0D6
填充: 渐变 #FF8C69 → #FFB89A, 宽度 = used/total * 100%
超支态: 填充颜色变为 #FF6B6B
标签:
flex, justify-between, margin-top 8px
"预算 ¥X,XXX" 左对齐, 12px Nunito 400, #8B7E7E
"XX%" 右对齐, 14px Fredoka 500, #FF8C69
动画: 宽度变化 600ms ease-out
```
### BottomNav 组件
```
用途: 底部导航栏
Props:
- current: 'home' | 'stats' | 'profile'
- onNavigate: (page) => void
结构: (见首页规格)
高度: 56px + safe-area
4个导航项 + 中间浮动 "+" 按钮
选中态:
图标: 填充色 #FF8C69
文字: #FF8C69, Nunito 600
默认态:
图标: 线条 #BFB3B3
文字: #BFB3B3, Nunito 400
```
---
## 交互状态
### 按钮状态矩阵
| 状态 | Primary | Secondary | Ghost | Danger |
|------|---------|-----------|-------|--------|
| Default | bg #FF8C69, shadow clay | bg white, border #FF8C69 | text #FF8C69 | bg #FF6B6B |
| Hover | bg #E67355 | bg #FFF0E6 | bg #FFF0E6 | bg #E65555 |
| Pressed | scale(0.97), inset shadow | scale(0.97), inset shadow | bg #FFE8E0 | scale(0.97) |
| Disabled | opacity 0.5 | opacity 0.5 | opacity 0.5 | opacity 0.5 |
| Loading | spinner + 文字 | spinner + 文字 | spinner + 文字 | spinner + 文字 |
### 页面切换动画
```
进入: opacity 0→1, translateY 8px→0, 250ms ease-out
离开: opacity 1→0, translateY 0→-8px, 200ms ease-in
Tab 切换: 水平滑动, 250ms ease-in-out
左→右: translateX -20px → 0
右→左: translateX 20px → 0
```
### 列表项交错入场
```
每项延迟: 50ms
动画: opacity 0→1, translateY 12px→0, 300ms ease-out
最大交错: 5项 (250ms)
prefers-reduced-motion: 无动画, 直接显示
```
### 数字变化动画
```
金额变化: 逐位滚动, 400ms ease-out
实现: requestAnimationFrame + easeOutCubic 缓动函数
font-variant-numeric: tabular-nums 防止宽度跳动
预算进度条: 宽度过渡, 600ms ease-out
```
---
## 响应式适配
### 断点
| 断点 | 宽度 | 设备 | 布局调整 |
|------|------|------|----------|
| 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
22px → 44rpx
24px → 48rpx
36px → 72rpx
48px → 96rpx
```
### H5 适配
```
桌面端 (>768px):
内容区: max-width 420px, 居中
背景: #F0E0D6 (深色底)
手机框: 圆角 32px, 阴影, 模拟手机外观
平板端 (768-1024px):
内容区: max-width 480px, 居中
```
---
## 无障碍清单
- [ ] 所有图标按钮有 `aria-label`
- [ ] 颜色对比度 ≥ 4.5:1 (文字)
- [ ] 颜色对比度 ≥ 3:1 (大文字/图标)
- [ ] 触摸目标 ≥ 44×44px
- [ ] 焦点状态可见 (键盘导航)
- [ ] `prefers-reduced-motion` 尊重
- [ ] 表单输入有对应 label
- [ ] 图表提供数据表格替代
- [ ] 金额读屏: "三千二百八十元"
---
## 暗色模式预留
> 暗色模式为 v2 功能,此处仅定义 token 映射
| 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) |