perf: 优化 UI

This commit is contained in:
richarjiang
2026-04-06 11:15:10 +08:00
parent 3a9982209f
commit 66d47ec162
24 changed files with 822 additions and 7129 deletions

150
CLAUDE.md
View File

@@ -1,150 +0,0 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## 项目概述
普拉提工作室预约与会员管理的微信小程序。TypeScript monorepo包含三个包
- **packages/server** — NestJS 后端REST API、Prisma ORM、PostgreSQL
- **packages/app** — Vue 3 + Pinia 前端,基于 Uni-app目标平台 mp-weixin
- **packages/shared** — 前后端共用的 TypeScript 类型、枚举和常量
## 常用命令
### 开发
```bash
pnpm dev:server # NestJS watch 模式 (localhost:3000)
pnpm dev:app # 微信小程序开发服务器
pnpm build:shared # 必须先构建 shared再构建 server/app
```
### 测试(仅 server
```bash
cd packages/server
pnpm test # 运行全部测试
pnpm test -- auth.service.spec # 运行单个测试文件
pnpm test:watch # watch 模式
pnpm test:cov # 覆盖率报告
```
Jest 配置内联在 `packages/server/package.json`。测试文件位于 `__tests__/` 子目录(如 `src/auth/__tests__/auth.service.spec.ts`),匹配模式:`*.spec.ts`
### 数据库
```bash
cd packages/server
pnpm prisma:generate # schema 变更后重新生成 Prisma Client
pnpm prisma:migrate # 运行迁移(交互式)
pnpm prisma:seed # 填充种子数据
```
### 代码检查
```bash
pnpm lint # 所有包的 ESLint 检查
```
## 架构
### 数据流
```
微信小程序 → Uni-app (Vue 3) → REST API (NestJS) → Prisma → PostgreSQL
↕ ↕
Pinia stores @nestjs/schedule (定时任务)
```
### 后端模块结构
每个功能是一个 NestJS 模块,遵循 controller → service → Prisma 模式。核心模块:
- **auth** — 微信 OAuth 登录code2Session、JWT 令牌、手机号绑定
- **booking** — 创建/取消预约,含会员卡验证和容量检查
- **time-slot** — 课程时段管理;`SlotGeneratorService` 根据 `WeekTemplate` 自动生成
- **membership** — 基于卡的会员制TIMES 次卡、DURATION 时效卡、TRIAL 体验卡)
- **payment** — 微信支付集成,用于购卡
- **scheduler** — 定时任务02:00 自动生成时段02:30 清理过期时段
### 前端结构
- **pages/** — 按路由组织的页面home、booking、card、profile、admin
- **stores/** — Pinia 状态管理user、booking、studio、admin
- **utils/request.ts** — 封装 `uni.request` 的 HTTP 客户端,自动携带 JWT
- **utils/auth.ts** — 微信登录流程uni.login → 服务端 /auth/login → 存储 token
### Shared 包
所有 API 类型、DTO、枚举和业务常量定义在 `packages/shared/src/`,前后端通过 `@mp-pilates/shared` 引用。路径别名配置在 `tsconfig.base.json` 和 Jest 的 `moduleNameMapper` 中。
### 数据库 Schema
Prisma schema 位于 `packages/server/prisma/schema.prisma`,关键约定:
- Model 用 PascalCase表名用 snake_case`@@map`
- 字段用 camelCase列名用 snake_case`@map`
- 所有 ID 为 UUID
- 金额字段使用 `Decimal(10, 0)`
- 关键唯一约束:`TimeSlot``@@unique([date, startTime, endTime])``Booking``@@unique([userId, timeSlotId])`
### 核心业务规则
- 预约需要有效的会员卡(剩余次数或有效期内)
- 取消预约需在课程开始前 `cancelHoursLimit` 小时(默认 2 小时,可在 StudioConfig 中配置)
- 时段根据 WeekTemplate 自动生成未来 14 天的课程
- 默认时段容量为 1私教课
## 环境配置
需要 Node 20+.nvmrc、pnpm 8+、PostgreSQL。复制 `packages/server/.env.example``.env.local`,需配置 DATABASE_URL、JWT_SECRET 及微信相关凭证APPID、SECRET、MCH_ID、MCH_KEY、证书路径
## 开发约定
- **API 前缀**:所有路由在 `/api`setGlobalPrefix
- **参数校验**:全局 ValidationPipe启用 whitelist + forbidNonWhitelisted + transform
- **鉴权守卫**:受保护路由使用 `@UseGuards(JwtAuthGuard)`,通过 `@Req()` 从 JWT 载荷提取用户
- **角色**MEMBER 和 ADMIN管理员路由使用自定义角色守卫
- **异常处理**:使用 NestJS 内置异常BadRequestException、NotFoundException 等)
- **分页**:统一使用 `PaginatedResponse<T>`,包含 data、total、page、limit
- **pnpm**:使用 `shamefully-hoist=true`.npmrc为 Uni-app 兼容所需
## 前端样式规范
### 主题色变量(必用)
所有色值必须使用 `packages/app/src/uni.scss` 中定义的 SCSS 变量,禁止在 Vue/Scss 文件中硬编码色值。
**主题色系:**
```scss
$primary-color: #a9bfcc; /* 主色-柔雾蓝灰 */
$primary-dark: #7ba5be; /* 主色-深蓝灰 */
$primary-light: #c8d8e4; /* 主色-浅蓝灰 */
$primary-bg: #f0f6f9; /* 页面背景-冷白蓝 */
$primary-border: #d8eaf4; /* 边框-淡蓝灰 */
$primary-selected-bg: #EFF6F9; /* 选中态背景 */
```
**通用语义变量(已同步主题色):**
| 变量 | 值 | 用途 |
|------|----|------|
| `$accent-color` | `#7ba5be` | 强调色 |
| `$warning-color` | `#e8a87c` | 警告色 |
| `$brand-light` | `#c8d8e4` | 品牌浅色 |
| `$border-color` | `rgba(180,160,130,0.2)` | 边框(中性) |
| `$text-primary` | `#4A4035` | 主文字(深棕灰) |
| `$text-secondary` | `#7A6A5A` | 次文字 |
| `$text-hint` | `#A09080` | 弱提示文字 |
### 变量替换规则
| 旧硬编码 | 替换为 |
|---------|--------|
| `#c9a87c`(旧暖棕金) | `$primary-dark` |
| `#d4b896`(旧浅棕金) | `$primary-color` |
| `#C4956A`(旧警告橙棕) | `$warning-color` |
| `#B08050`(旧深棕) | `$accent-color` |
| `#7d6608`(旧深暖绿) | `#5a7a8a`(冷青灰) |
| `#e8c88a``#b49868`(旧暖渐变) | `$primary-color` / `$primary-dark` |
### CSS 变量规范
组件内部的多处共用颜色(如阴影、遮罩)若无法用 SCSS 变量,需用 `rgba($primary-dark, 0.x)` 形式动态构造,不可直接写死十六进制值。
### 新增页面/组件
新增页面或组件时:
1. 优先查阅 `uni.scss` 已有变量
2. 若需要新增语义化变量,先更新 `uni.scss`,再在组件中引用
3. 禁止在 `<style>` 块内直接写十六进制颜色值(背景色、文字色、边框、阴影均需走变量)