Files
xiaocai/CLAUDE.md
wangxiaogang 0de4c9832c feat: 请求日志 + 前端埋点系统
后端:
- 新增 logger 中间件,记录所有请求到 logs/ 目录
- 新增 /api/track 接口接收前端埋点数据

前端:
- 新增 tracker 工具,支持页面访问/操作/错误埋点
- request.ts 添加 API 错误自动埋点
- App.vue 初始化全局错误追踪

文档:
- CLAUDE.md 更新项目结构
- DEV.md 添加埋点和日志说明
2026-06-08 14:28:11 +08:00

252 lines
9.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
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.
# 小菜记账 (Xiaocai Accounting)
可爱 × 高级的个人记账小程序。让记账从负担变成享受。
## Tech Stack
### 前端 (client/)
- **框架**: Uni-app (Vue 3 + Composition API)
- **状态管理**: Pinia
- **样式**: SCSS (Claymorphism 风格)
- **图标**: Lucide Icons (SVG 组件,禁止 emoji)
- **图表**: uCharts (小程序端)
- **目标平台**: 微信小程序 / H5
### 后端 (server/)
- **运行时**: Node.js + Express
- **数据库**: MySQL 8.0 (mysql2 连接池)
- **认证**: HMAC-SHA256 签名 token30 天过期
- **文件上传**: multer (头像,最大 2MB)
- **备份**: Node.js mysql2 导出 (不依赖 mysqldump)
- **CORS**: 已配置,支持 credentials
## Design System
完整设计规格: `docs/superpowers/specs/2026-05-27-xiaocai-design.md`
### 核心设计语言: Claymorphism (软3D粘土风格)
- **主色调**: 珊瑚橙 `#FF8C69` — 温暖、活泼、有亲和力
- **背景色**: 暖奶油 `#FFF8F0` — 比纯白更柔和
- **文字色**: 暖深棕 `#2D1B1B` — 不用纯黑
- **圆角**: 卡片 20px, 按钮 14-16px
- **阴影**: 双层 (外阴影 + 内阴影,模拟粘土质感)
### 字体
- 英文: Fredoka (标题) + Nunito (正文)
- 中文: PingFang SC / 系统默认
- 数字和金额使用 Fredoka等宽数字
### 关键原则
- 最小触摸目标 44×44px
- 禁止使用 emoji 作为图标,统一使用 Icon 组件
- 尊重 prefers-reduced-motion
- 文字对比度 ≥ 4.5:1 (WCAG AA)
### 小程序胶囊适配
- 微信小程序右上角有胶囊按钮,页面顶部右侧元素(图标、按钮)需避开
- 使用 `system.ts` 导出的 `capsuleRight` 计算安全距离
- 导航栏添加动态 padding: `:style="{ paddingRight: capsuleRight + 'px' }"`
- 居中标题页面(统计、账单、我的)不需要处理
- 有右侧元素的页面(首页 bell、编辑页保存按钮必须处理
## Project Conventions
### 命名
- 目录: kebab-case (`category-manage/`, `transaction-item/`)
- 组件: PascalCase (`AmountCard.vue`, `TransactionItem.vue`)
- 变量/函数: camelCase (`totalExpense`, `formatAmount()`)
- 常量: UPPER_SNAKE_CASE (`MAX_BUDGET`, `STORAGE_KEY`)
- CSS 类: BEM 或 Tailwind 风格
### 文件组织
```
client/src/
├── pages/ # 页面 (uni-app 规范)
│ ├── index/ # 首页仪表盘
│ ├── add/ # 添加/编辑记录
│ ├── stats/ # 统计分析
│ ├── bills/ # 全部账单 (下拉刷新/上拉加载)
│ ├── profile/ # 我的(身份切换入口)
│ ├── profile-edit/ # 编辑资料(昵称+头像+签名)
│ ├── group-manage/ # 群组管理(创建/加入/退出/解散)
│ ├── category-manage/ # 分类管理
│ ├── budget/ # 预算设置
│ ├── notifications/ # 通知中心
│ ├── feedback/ # 意见反馈
│ ├── privacy/ # 隐私政策
│ └── admin/ # 管理后台 (index/users/notifications/feedback/config)
├── components/ # 公共组件
│ ├── BudgetBar/ # 预算进度条
│ ├── CategoryIcon/ # 分类图标 (首字+颜色)
│ ├── ChartWrapper/ # uCharts 图表封装
│ ├── Icon/ # 图标组件 (PNG 映射)
│ ├── Numpad/ # 数字键盘
│ ├── SaveSuccess/ # 保存成功动画
│ ├── Skeleton/ # 骨架屏
│ └── TransactionItem/ # 交易列表项
├── stores/ # Pinia stores
│ ├── transaction.ts # 交易 CRUD (自动传递 group_id)
│ ├── category.ts # 分类 CRUD
│ ├── budget.ts # 预算管理
│ ├── stats.ts # 统计概览 (自动传递 group_id)
│ ├── user.ts # 用户信息 (昵称/头像)
│ └── group.ts # 群组管理 (身份切换)
├── api/ # API 封装
│ ├── auth.ts # 登录接口
│ ├── transaction.ts # 交易接口
│ ├── category.ts # 分类接口
│ ├── budget.ts # 预算接口
│ ├── stats.ts # 统计接口
│ ├── user.ts # 用户信息接口 (含头像上传)
│ ├── group.ts # 群组接口
│ ├── notification.ts # 通知接口
│ ├── filter.ts # 筛选方案接口
│ ├── feedback.ts # 反馈接口
│ ├── config.ts # 系统配置接口
│ ├── admin.ts # 管理后台接口
│ └── index.ts # barrel 导出
├── utils/
│ ├── format.ts # 金额/日期格式化
│ ├── request.ts # HTTP 请求封装 (401 自动重登录+队列重试)
│ ├── system.ts # 系统信息 (statusBarHeight, capsuleRight)
│ ├── app-ready.ts # App 启动就绪机制 (waitForReady)
│ └── tracker.ts # 前端埋点 (页面访问/操作/错误)
├── config.ts # 全局配置 (API_BASE)
└── static/icons/ # tabBar 图标 (PNG)
server/src/
├── index.ts # Express 入口 (CORS, JSON, 静态文件, 路由注册)
├── middleware/
│ ├── auth.ts # HMAC token 验证 (timingSafeEqual)
│ └── logger.ts # 请求日志 (记录到 logs/ 目录)
├── routes/
│ ├── auth.ts # 登录 / token 签发 (返回用户信息)
│ ├── transaction.ts # 交易 CRUD (支持 group_id 视图切换)
│ ├── category.ts # 分类 CRUD (默认+自定义)
│ ├── budget.ts # 预算 CRUD (按月)
│ ├── stats.ts # 统计查询 (支持 group_id)
│ ├── user.ts # 用户信息 + 头像上传
│ ├── group.ts # 群组 CRUD (创建/加入/退出/解散)
│ ├── notification.ts # 通知/公告 CRUD
│ ├── filter.ts # 筛选方案 CRUD
│ ├── feedback.ts # 用户反馈 (提交/查询/处理)
│ ├── config.ts # 系统配置 (公开读/管理员写)
│ ├── admin.ts # 管理后台 (仪表盘/用户管理)
│ ├── track.ts # 埋点数据接收
│ └── backup.ts # 备份 API
├── utils/
│ ├── backup.ts # Node.js 数据库备份 (gzip)
│ └── date.ts # 日期工具
└── db/
├── connection.ts # MySQL 连接池
├── init.ts # 建表 + seed + 迁移 (幂等)
├── schema.sql # 表结构
└── seed.sql # 默认分类数据 + 系统配置
```
### 数据库表
- `users` — 用户 (openid, nickname, avatar_url, slogan, role)
- `categories` — 分类 (user_id=0 默认, 其他=自定义)
- `transactions` — 交易记录 (user_id, group_id, amount 分)
- `budgets` — 预算 (user_id, month, amount)
- `groups` — 群组 (name, invite_code, created_by)
- `group_members` — 群组成员 (group_id, user_id, role)
- `notifications` — 通知/公告 (type, title, content, is_pinned, is_urgent)
- `notification_reads` — 公告已读记录 (notification_id, user_id)
- `saved_filters` — 保存的筛选方案 (user_id, name, filters)
- `feedbacks` — 用户反馈 (user_id, type, content, status)
- `sys_config` — 系统配置 (config_key, config_value)
### 金额处理
- 存储单位: 分 (整数,避免浮点精度问题)
- 显示单位: 元 (保留两位小数)
- 格式化: `¥ 1,234.56` (¥ 后空格,千分位分隔)
- 收入前缀 `+`,支出前缀 `-`
- 使用 `formatAmount()` 带 ¥ 前缀,`formatAmountRaw()` 纯数字
### 数据持久化
- 前端本地存储 Key:
- `xc:token` — 认证 token
- `xc:userId` — 用户 ID
- `xc:nickname` — 用户昵称
- `xc:avatar_url` — 头像文件名
- `xc:currentGroupId` — 当前选中群组 ID (null=个人模式)
- 后端 MySQL 数据库
- API 基础地址: `config.ts` 中的 `API_BASE`
### 认证流程
- H5: 页面加载时自动 demo-login 获取 token
- 微信小程序: `App.vue` onLaunch 调用 `wx.login` 获取 code换 token
- Token: HMAC-SHA256 签名30 天过期
- 401 处理: 请求入队 → 自动重登录 → 队列中所有请求重试
- 启动就绪: `app-ready.ts``waitForReady()` 确保页面在登录完成后才加载数据
### 一起记 (群组)
- 群组仅做数据聚合,记录始终属于记录者 (user_id)
- 个人视图: `WHERE user_id = 我` (所有记录)
- 群组视图: `WHERE user_id IN (群组成员)` — 统计所有群组成员的个人账单
- 群组账单 = 所有群组成员的个人账单之和
- 退出群组: 该用户的 group_id 设为 NULL记录回到个人视图
- 身份切换: 「我的」页底部弹窗选择,全局生效
### Git
- 分支: `master``main` (注意远程)
- Commit 风格: 中文描述,简洁明了
- `feat: 添加记账页面`
- `fix: 修复金额计算精度问题`
## Commands
```bash
# 前端开发 (H5)
cd client && npm run dev:h5
# 前端开发 (微信小程序)
cd client && npm run dev:mp-weixin
# 前端构建
cd client && npm run build:mp-weixin
# 后端开发
cd server && npm run dev
# 后端构建
cd server && npm run build
# 数据库初始化
cd server && npm run db:init
```
## 部署
- 开发服务: `dev.xiaocai.j35.site:3000`
- 正式服务: `xiaocai.j35.site`
- MySQL: 本地 3306 端口
- 小程序开发版自动连接 dev 服务,正式版/H5 连接线上 (config.ts)
### 手动部署步骤
```bash
# 1. 本地构建后端
cd server && npm run build
# 2. 复制 dist 目录到服务器
scp -r server/dist/* root@106.14.208.43:/var/www/xiaocai/
# 3. SSH 到服务器
ssh root@106.14.208.43
# 4. 安装依赖(如 node_modules 已存在可跳过)
cd /var/www/xiaocai && npm install --production
# 5. 重启服务
pm2 restart xiaocai-server
# 或直接运行
NODE_ENV=production node dist/index.js
```
## 开发
@DEV.md