# 分享挑战关卡进度记录功能设计 ## 背景 现有好友挑战分享能力支持用户加入分享挑战并获取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; findByParticipantAndLevel(participantId: string, levelId: string): Promise; create(data: Partial): ShareLevelProgress; save(progress: ShareLevelProgress): Promise; } ``` 实现:`src/modules/share/repositories/share-level-progress.repository.ts` ### ShareParticipantRepository 补充方法 ```typescript findByShareConfigAndParticipant( shareConfigId: string, participantId: string, ): Promise; ``` ## 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 ``` ```typescript async reportLevelProgress( @CurrentUser() user: JwtPayload, @Body() dto: ReportLevelProgressDto, ): Promise> ``` ## 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 表) |