Checkpoint: v2.0完整版本:新增社区排行榜、每日打卡、24种成就徽章、实时摄像头姿势分析、在线录制(稳定压缩流/断线重连/自动剪辑)、移动端全面适配。47个测试通过。包含完整开发文档。

这个提交包含在:
Manus
2026-03-14 08:04:00 -04:00
父节点 36907d1110
当前提交 2c418b482e
修改 22 个文件,包含 4370 行新增41 行删除

204
docs/DATABASE.md 普通文件
查看文件

@@ -0,0 +1,204 @@
# Tennis Training Hub - 数据库设计文档
## 概述
本项目使用MySQL/TiDB数据库,通过Drizzle ORM进行数据访问。数据库包含9张核心表,支持用户管理、训练计划、视频分析、评分系统、打卡和徽章等功能。
## ER关系图
```
users (1) ──── (N) username_accounts
├──── (N) training_plans
├──── (N) training_videos (1) ──── (1) pose_analyses
├──── (N) training_records
├──── (N) rating_history
├──── (N) daily_checkins
└──── (N) user_badges
```
## 表结构详解
### 1. `users` - 用户表
核心用户表,支持OAuth和用户名两种登录方式。
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| id | INT | PK, AUTO_INCREMENT | 主键 |
| openId | VARCHAR(64) | UNIQUE, NOT NULL | OAuth标识符 |
| name | TEXT | - | 用户名 |
| email | VARCHAR(320) | - | 邮箱 |
| loginMethod | VARCHAR(64) | - | 登录方式 |
| role | ENUM('user','admin') | DEFAULT 'user' | 角色 |
| skillLevel | ENUM('beginner','intermediate','advanced') | DEFAULT 'beginner' | 技能水平 |
| trainingGoals | TEXT | - | 训练目标 |
| ntrpRating | FLOAT | DEFAULT 1.5 | NTRP评分 |
| totalSessions | INT | DEFAULT 0 | 总训练次数 |
| totalMinutes | INT | DEFAULT 0 | 总训练分钟 |
| currentStreak | INT | DEFAULT 0 | 当前连续打卡天数 |
| longestStreak | INT | DEFAULT 0 | 最长连续打卡天数 |
| totalShots | INT | DEFAULT 0 | 总击球数 |
| createdAt | TIMESTAMP | DEFAULT NOW | 创建时间 |
| updatedAt | TIMESTAMP | ON UPDATE NOW | 更新时间 |
| lastSignedIn | TIMESTAMP | DEFAULT NOW | 最后登录 |
### 2. `username_accounts` - 用户名账户表
简单用户名登录的映射表,将用户名映射到users表的用户。
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| id | INT | PK, AUTO_INCREMENT | 主键 |
| username | VARCHAR(64) | UNIQUE, NOT NULL | 用户名 |
| userId | INT | NOT NULL | 关联用户ID |
| createdAt | TIMESTAMP | DEFAULT NOW | 创建时间 |
### 3. `training_plans` - 训练计划表
存储AI生成的训练计划,支持版本追踪和自动调整。
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| id | INT | PK, AUTO_INCREMENT | 主键 |
| userId | INT | NOT NULL | 用户ID |
| title | VARCHAR(256) | NOT NULL | 计划标题 |
| skillLevel | ENUM | NOT NULL | 技能水平 |
| durationDays | INT | DEFAULT 7 | 计划天数 |
| exercises | JSON | NOT NULL | 训练内容JSON数组 |
| isActive | INT | DEFAULT 1 | 是否激活 |
| adjustmentNotes | TEXT | - | AI调整说明 |
| version | INT | DEFAULT 1 | 版本号 |
| createdAt | TIMESTAMP | DEFAULT NOW | 创建时间 |
| updatedAt | TIMESTAMP | ON UPDATE NOW | 更新时间 |
**exercises JSON结构**
```json
[
{
"day": 1,
"name": "正手影子挥拍",
"category": "挥拍练习",
"duration": 15,
"description": "...",
"tips": "...",
"sets": 3,
"reps": 20
}
]
```
### 4. `training_videos` - 训练视频表
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| id | INT | PK, AUTO_INCREMENT | 主键 |
| userId | INT | NOT NULL | 用户ID |
| title | VARCHAR(256) | NOT NULL | 视频标题 |
| fileKey | VARCHAR(512) | NOT NULL | S3文件键 |
| url | TEXT | NOT NULL | CDN访问URL |
| format | VARCHAR(16) | NOT NULL | 格式(webm/mp4) |
| fileSize | INT | - | 文件大小(字节) |
| duration | FLOAT | - | 时长(秒) |
| exerciseType | VARCHAR(64) | - | 动作类型 |
| analysisStatus | ENUM | DEFAULT 'pending' | 分析状态 |
| createdAt | TIMESTAMP | DEFAULT NOW | 创建时间 |
| updatedAt | TIMESTAMP | ON UPDATE NOW | 更新时间 |
### 5. `pose_analyses` - 姿势分析表
参考tennis_analysis项目设计,包含击球统计、挥拍速度、运动轨迹等高级分析字段。
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| id | INT | PK, AUTO_INCREMENT | 主键 |
| videoId | INT | NOT NULL | 视频ID |
| userId | INT | NOT NULL | 用户ID |
| overallScore | FLOAT | - | 总体评分(0-100) |
| poseMetrics | JSON | - | 关节角度详细指标 |
| detectedIssues | JSON | - | 检测到的问题 |
| corrections | JSON | - | 矫正建议 |
| exerciseType | VARCHAR(64) | - | 动作类型 |
| framesAnalyzed | INT | - | 分析帧数 |
| shotCount | INT | DEFAULT 0 | 击球次数 |
| avgSwingSpeed | FLOAT | - | 平均挥拍速度 |
| maxSwingSpeed | FLOAT | - | 最大挥拍速度 |
| totalMovementDistance | FLOAT | - | 总移动距离 |
| strokeConsistency | FLOAT | - | 击球一致性(0-100) |
| footworkScore | FLOAT | - | 脚步评分(0-100) |
| fluidityScore | FLOAT | - | 流畅性评分(0-100) |
| keyMoments | JSON | - | 关键时刻标记 |
| movementTrajectory | JSON | - | 运动轨迹数据 |
| createdAt | TIMESTAMP | DEFAULT NOW | 创建时间 |
### 6. `training_records` - 训练记录表
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| id | INT | PK, AUTO_INCREMENT | 主键 |
| userId | INT | NOT NULL | 用户ID |
| planId | INT | - | 关联计划ID |
| exerciseName | VARCHAR(128) | NOT NULL | 训练名称 |
| durationMinutes | INT | - | 时长(分钟) |
| completed | INT | DEFAULT 0 | 是否完成 |
| notes | TEXT | - | 备注 |
| poseScore | FLOAT | - | 姿势评分 |
| trainingDate | TIMESTAMP | DEFAULT NOW | 训练日期 |
| createdAt | TIMESTAMP | DEFAULT NOW | 创建时间 |
### 7. `rating_history` - 评分历史表
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| id | INT | PK, AUTO_INCREMENT | 主键 |
| userId | INT | NOT NULL | 用户ID |
| rating | FLOAT | NOT NULL | NTRP评分 |
| reason | VARCHAR(256) | - | 评分原因 |
| dimensionScores | JSON | - | 五维度分数明细 |
| analysisId | INT | - | 关联分析ID |
| createdAt | TIMESTAMP | DEFAULT NOW | 创建时间 |
**dimensionScores JSON结构**
```json
{
"poseAccuracy": 75.5,
"strokeConsistency": 68.2,
"footwork": 72.0,
"fluidity": 65.8,
"power": 58.3
}
```
### 8. `daily_checkins` - 每日打卡表
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| id | INT | PK, AUTO_INCREMENT | 主键 |
| userId | INT | NOT NULL | 用户ID |
| checkinDate | VARCHAR(10) | NOT NULL | 日期(YYYY-MM-DD) |
| streakCount | INT | DEFAULT 1 | 当时连续天数 |
| notes | TEXT | - | 打卡备注 |
| minutesTrained | INT | DEFAULT 0 | 当日训练分钟 |
| createdAt | TIMESTAMP | DEFAULT NOW | 创建时间 |
### 9. `user_badges` - 用户徽章表
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| id | INT | PK, AUTO_INCREMENT | 主键 |
| userId | INT | NOT NULL | 用户ID |
| badgeKey | VARCHAR(64) | NOT NULL | 徽章标识键 |
| earnedAt | TIMESTAMP | DEFAULT NOW | 获得时间 |
## 迁移历史
| 版本 | 文件 | 内容 |
|------|------|------|
| 0001 | `0001_public_prowler.sql` | 初始表创建users扩展、username_accounts、training_plans、training_videos、pose_analyses、training_records、rating_history |
| 0002 | `0002_overrated_shriek.sql` | 添加totalShots字段 |
| 0003 | `0003_married_iron_lad.sql` | 添加daily_checkins和user_badges表、用户streak字段 |