feat(share): 分享挑战关卡进度记录功能
- 新增 Level.timeLimit 字段支持关卡时间限制 - 新增 ShareLevelProgress 实体记录单关通关进度 - 新增 ShareLevelProgressRepository - 新增 DTO: ReportLevelProgressDto, ReportLevelProgressResponseDto - 新增 POST /v1/share/progress 接口用于上报进度 - 支持仅首次通关有效判断 - 支持时间限制内通关判断 - 不可变模式更新进度记录 - 数据库迁移脚本 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
174
docs/superpowers/specs/2026-04-07-share-level-progress-design.md
Normal file
174
docs/superpowers/specs/2026-04-07-share-level-progress-design.md
Normal file
@@ -0,0 +1,174 @@
|
||||
# 分享挑战关卡进度记录功能设计
|
||||
|
||||
## 背景
|
||||
|
||||
现有好友挑战分享能力支持用户加入分享挑战并获取6个关卡的数据。需要在分享挑战场景下记录用户的单关通关进度,为后续的排行统计和规定时间内通关统计提供数据基础。
|
||||
|
||||
## 需求理解
|
||||
|
||||
1. **记录用户在分享挑战下的单关通关数据**(通关时间、是否通过)
|
||||
2. **不包含积分**(积分已有独立体系)
|
||||
3. **仅首次通关有效**(passed=true 时不可覆盖)
|
||||
4. **每个关卡有独立时间限制**(存储在 Level 表的 `timeLimit` 字段)
|
||||
5. **同一关卡在不同分享挑战中分别记录**
|
||||
|
||||
## 数据库设计
|
||||
|
||||
### 1. Level 表扩展
|
||||
|
||||
```sql
|
||||
ALTER TABLE levels ADD COLUMN time_limit INT DEFAULT NULL COMMENT '通关时间限制(秒),NULL 表示无限制';
|
||||
```
|
||||
|
||||
### 2. 新建 ShareLevelProgress 表
|
||||
|
||||
```sql
|
||||
CREATE TABLE share_level_progress (
|
||||
id CHAR(36) PRIMARY KEY,
|
||||
participant_id CHAR(36) NOT NULL COMMENT '关联 share_participants.id',
|
||||
level_id CHAR(191) NOT NULL COMMENT '关卡ID',
|
||||
passed TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否通过',
|
||||
time_spent INT NOT NULL DEFAULT 0 COMMENT '通关时间(秒)',
|
||||
completed_at DATETIME DEFAULT NULL COMMENT '通关时间戳',
|
||||
|
||||
UNIQUE KEY uq_participant_level (participant_id, level_id),
|
||||
INDEX idx_participant_id (participant_id),
|
||||
INDEX idx_level_id (level_id),
|
||||
|
||||
FOREIGN KEY (participant_id) REFERENCES share_participants(id) ON DELETE CASCADE
|
||||
);
|
||||
```
|
||||
|
||||
### 3. ER 关系
|
||||
|
||||
```
|
||||
ShareConfig (1) ──< ShareParticipant (多)
|
||||
│
|
||||
└─< ShareLevelProgress (多) >── Level (1)
|
||||
```
|
||||
|
||||
## 实体设计
|
||||
|
||||
### ShareLevelProgress 实体
|
||||
|
||||
文件:`src/modules/share/entities/share-level-progress.entity.ts`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | uuid | 主键 |
|
||||
| participantId | varchar | 关联 ShareParticipant |
|
||||
| levelId | varchar | 关卡ID |
|
||||
| passed | boolean | 是否通过 |
|
||||
| timeSpent | int | 通关时间(秒) |
|
||||
| completedAt | datetime | 通关时间戳 |
|
||||
|
||||
唯一索引:`uq_participant_level(participant_id, level_id)`
|
||||
|
||||
## Repository 设计
|
||||
|
||||
### IShareLevelProgressRepository 接口
|
||||
|
||||
```typescript
|
||||
interface IShareLevelProgressRepository {
|
||||
findByParticipantId(participantId: string): Promise<ShareLevelProgress[]>;
|
||||
findByParticipantAndLevel(participantId: string, levelId: string): Promise<ShareLevelProgress | null>;
|
||||
create(data: Partial<ShareLevelProgress>): ShareLevelProgress;
|
||||
save(progress: ShareLevelProgress): Promise<ShareLevelProgress>;
|
||||
}
|
||||
```
|
||||
|
||||
实现:`src/modules/share/repositories/share-level-progress.repository.ts`
|
||||
|
||||
### ShareParticipantRepository 补充方法
|
||||
|
||||
```typescript
|
||||
findByShareConfigAndParticipant(
|
||||
shareConfigId: string,
|
||||
participantId: string,
|
||||
): Promise<ShareParticipant | null>;
|
||||
```
|
||||
|
||||
## DTO 设计
|
||||
|
||||
### ReportLevelProgressDto(请求)
|
||||
|
||||
| 字段 | 类型 | 校验 | 说明 |
|
||||
|------|------|------|------|
|
||||
| shareCode | string | @IsString, @IsNotEmpty | 分享码 |
|
||||
| levelId | string | @IsString, @IsNotEmpty | 关卡ID |
|
||||
| passed | boolean | @IsBoolean | 是否通过 |
|
||||
| timeSpent | number | @IsNumber, @Min(0) | 通关时间(秒) |
|
||||
|
||||
### ReportLevelProgressResponseDto(响应)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| passed | boolean | 是否通过 |
|
||||
| timeLimit | number \| null | 该关卡时间限制(秒),null 表示无限制 |
|
||||
| withinTimeLimit | boolean | 是否在时间限制内通过(仅 passed=true 时有效) |
|
||||
|
||||
## Service 层设计
|
||||
|
||||
### 新增方法:reportLevelProgress
|
||||
|
||||
业务逻辑:
|
||||
|
||||
1. 根据 shareCode 查找 ShareConfig
|
||||
2. 查找或创建 ShareParticipant(分享者和参与者都需要)
|
||||
3. 如果 passed=true,检查是否已有通关记录(存在则直接返回,不覆盖)
|
||||
4. 查找关卡获取 timeLimit
|
||||
5. 判断是否在时间限制内通过
|
||||
6. 创建或更新进度记录
|
||||
|
||||
### 核心规则
|
||||
|
||||
- `passed=true` 时仅首次有效,不可覆盖
|
||||
- `passed=false` 时允许重复上报(记录用户重玩)
|
||||
- `withinTimeLimit = passed && (timeLimit === null || timeSpent <= timeLimit)`
|
||||
|
||||
## Controller 设计
|
||||
|
||||
### 接口
|
||||
|
||||
```
|
||||
POST /v1/share/progress
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
```typescript
|
||||
async reportLevelProgress(
|
||||
@CurrentUser() user: JwtPayload,
|
||||
@Body() dto: ReportLevelProgressDto,
|
||||
): Promise<ApiResponseDto<ReportLevelProgressResponseDto>>
|
||||
```
|
||||
|
||||
## Module 变更
|
||||
|
||||
### ShareModule
|
||||
|
||||
- 导入 `ShareLevelProgress` 实体
|
||||
- 注册 `ShareLevelProgressRepository`
|
||||
|
||||
## 后续扩展
|
||||
|
||||
以下功能不在本次范围内,仅记录设计预留:
|
||||
|
||||
1. **排行查询**:按分享挑战统计用户总通关时间排名
|
||||
2. **规定时间内通过关数统计**:统计某用户在挑战中的 withinTimeLimit 关数
|
||||
3. **历史记录**:支持查看用户的重玩记录
|
||||
|
||||
## 文件清单
|
||||
|
||||
| 操作 | 文件路径 |
|
||||
|------|----------|
|
||||
| 新增 | src/modules/share/entities/share-level-progress.entity.ts |
|
||||
| 新增 | src/modules/share/repositories/share-level-progress.repository.interface.ts |
|
||||
| 新增 | src/modules/share/repositories/share-level-progress.repository.ts |
|
||||
| 新增 | src/modules/share/dto/report-level-progress.dto.ts |
|
||||
| 新增 | src/modules/share/dto/share-level-progress-response.dto.ts |
|
||||
| 修改 | src/modules/share/repositories/share-participant.repository.ts |
|
||||
| 修改 | src/modules/share/share.service.ts |
|
||||
| 修改 | src/modules/share/share.controller.ts |
|
||||
| 修改 | src/modules/share/share.module.ts |
|
||||
| 修改 | src/modules/wechat-game/entities/level.entity.ts |
|
||||
| SQL | 数据库迁移脚本(Level 表 + ShareLevelProgress 表) |
|
||||
Reference in New Issue
Block a user