feat: 支持通关接口

This commit is contained in:
richarjiang
2026-04-30 16:20:22 +08:00
parent 25d196263b
commit 1f8db6c473
4 changed files with 169 additions and 5 deletions

View File

@@ -0,0 +1,10 @@
import { ApiProperty } from '@nestjs/swagger';
import { NextLevelDto } from './next-level.dto';
export class CompletedLevelDto extends NextLevelDto {
@ApiProperty({ description: '通关时长(秒)' })
timeSpent!: number;
@ApiProperty({ description: '通关时间ISO 8601' })
completedAt!: Date;
}

View File

@@ -1,4 +1,4 @@
import { Body, Controller, Param, Post, UseGuards } from '@nestjs/common';
import { Body, Controller, Get, Param, Post, UseGuards } from '@nestjs/common';
import {
ApiBearerAuth,
ApiOperation,
@@ -11,6 +11,7 @@ import {
CompleteLevelRequestDto,
CompleteLevelResponseDto,
} from './dto/complete-level.dto';
import { CompletedLevelDto } from './dto/completed-level.dto';
import { ApiResponseDto } from '../../common/dto/api-response.dto';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import type { JwtPayload } from '../../common/guards/jwt-auth.guard';
@@ -23,6 +24,21 @@ import { CurrentUser } from '../../common/decorators/current-user.decorator';
export class LevelController {
constructor(private readonly levelService: LevelService) {}
@Get('completed')
@ApiOperation({
summary: '获取已通关关卡列表',
description:
'返回当前用户所有已通关的关卡按关卡顺序sortOrder升序排列。每项包含完整关卡信息 + 通关时长 + 通关时间。',
})
@ApiResponse({ status: 200, description: '成功' })
@ApiResponse({ status: 401, description: '未授权' })
async getCompletedLevels(
@CurrentUser() user: JwtPayload,
): Promise<ApiResponseDto<CompletedLevelDto[]>> {
const data = await this.levelService.getCompletedLevels(user.sub);
return ApiResponseDto.success(data);
}
@Post(':id/enter')
@ApiOperation({
summary: '进入关卡',

View File

@@ -7,6 +7,7 @@ import {
CompleteLevelRequestDto,
CompleteLevelResponseDto,
} from './dto/complete-level.dto';
import { CompletedLevelDto } from './dto/completed-level.dto';
import { pickLevelImageFields } from '../wechat-game/level-fields.helper';
import { findNextUncompletedLevels, toNextLevelDto } from './next-level.helper';
@@ -127,4 +128,38 @@ export class LevelService {
nextLevel: nextLevels[0] ? toNextLevelDto(nextLevels[0]) : null,
};
}
/**
* 获取用户已通关的关卡列表按关卡顺序sortOrder升序返回
*/
async getCompletedLevels(userId: string): Promise<CompletedLevelDto[]> {
const progressList =
await this.userLevelProgressRepository.findByUserId(userId);
if (progressList.length === 0) {
return [];
}
const levelIds = progressList.map((p) => p.levelId);
const levels = await this.levelRepository.findByIds(levelIds);
// 构建 levelId -> progress 映射,便于合并 timeSpent / completedAt
const progressMap = new Map(progressList.map((p) => [p.levelId, p]));
return levels
.slice()
.sort((a, b) => a.sortOrder - b.sortOrder)
.map((level) => {
const progress = progressMap.get(level.id)!;
return {
id: level.id,
level: level.sortOrder,
...pickLevelImageFields(level),
answer: level.answer,
timeLimit: level.timeLimit,
timeSpent: progress.timeSpent,
completedAt: progress.completedAt,
};
});
}
}