# 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字段 |