refactor: 拆分核心玩法模块并优化代码质量

将 WechatGame 单体模块拆分为独立的 User、Level、GameConfig 模块,
新增体力值系统、关卡闯关流程,并修复多项代码质量问题:
- 体力不足错误码从 401 修正为 400
- enterLevel 改用 findById 替代全表扫描
- consumeStamina 增加原子更新防止并发竞态
- 并行化独立数据库查询 (Promise.all)
- 移除 WechatGameService/Controller 死代码
This commit is contained in:
richarjiang
2026-04-10 09:07:50 +08:00
parent c775d5c6b0
commit fe2c13258e
33 changed files with 1681 additions and 978 deletions

View File

@@ -1,31 +1,19 @@
import { Body, Controller, Get, Post, UseGuards } from '@nestjs/common';
import { Body, Controller, Post } from '@nestjs/common';
import {
ApiBearerAuth,
ApiOperation,
ApiResponse,
ApiTags,
} from '@nestjs/swagger';
import { AuthService } from './auth.service';
import { WxLoginRequestDto, WxLoginResponseDto } from './dto/wx-login.dto';
import {
ConsumePointRequestDto,
EarnPointRequestDto,
GameDataResponseDto,
UserAssetsResponseDto,
} from './dto/user-assets.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';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
@ApiTags('用户认证与资产')
@Controller('v1')
@ApiTags('认证')
@Controller('v1/auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
// ==================== 公开接口 ====================
@Post('auth/wx-login')
@Post('wx-login')
@ApiOperation({
summary: '微信登录',
description: '使用微信 wx.login 返回的 code 换取 JWT 令牌',
@@ -38,73 +26,4 @@ export class AuthController {
const data = await this.authService.wxLogin(dto.code);
return ApiResponseDto.success(data);
}
// ==================== 需要鉴权的接口 ====================
@Get('user/assets')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOperation({
summary: '获取用户积分',
description: '获取当前登录用户的积分信息',
})
@ApiResponse({ status: 200, description: '成功' })
@ApiResponse({ status: 401, description: '未授权' })
async getUserAssets(
@CurrentUser() user: JwtPayload,
): Promise<ApiResponseDto<UserAssetsResponseDto>> {
const data = await this.authService.getUserAssets(user.sub);
return ApiResponseDto.success(data);
}
@Post('user/assets/consume')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOperation({
summary: '消耗积分',
description: '消耗 1 积分(用于解锁提示)',
})
@ApiResponse({ status: 200, description: '消耗成功' })
@ApiResponse({ status: 400, description: '积分不足' })
@ApiResponse({ status: 401, description: '未授权' })
async consumePoint(
@CurrentUser() user: JwtPayload,
@Body() dto: ConsumePointRequestDto,
): Promise<ApiResponseDto<UserAssetsResponseDto>> {
const data = await this.authService.consumePoint(user.sub, dto);
return ApiResponseDto.success(data);
}
@Post('user/assets/earn')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOperation({
summary: '获得积分',
description: '通关获得 1 积分(同一关卡不重复奖励)',
})
@ApiResponse({ status: 200, description: '获得成功' })
@ApiResponse({ status: 401, description: '未授权' })
async earnPoint(
@CurrentUser() user: JwtPayload,
@Body() dto: EarnPointRequestDto,
): Promise<ApiResponseDto<UserAssetsResponseDto>> {
const data = await this.authService.earnPoint(user.sub, dto);
return ApiResponseDto.success(data);
}
@Get('user/game-data')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOperation({
summary: '获取游戏数据',
description: '获取用户积分和通关进度Loading 页面使用)',
})
@ApiResponse({ status: 200, description: '成功' })
@ApiResponse({ status: 401, description: '未授权' })
async getGameData(
@CurrentUser() user: JwtPayload,
): Promise<ApiResponseDto<GameDataResponseDto>> {
const data = await this.authService.getGameData(user.sub);
return ApiResponseDto.success(data);
}
}