重构 API 为 8 领域 + 应用层架构
将后端模块拆分为 domains、applications、shared 三层,结算计算器移入 domain 纯函数目录,API 路径与测试保持不变。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
179
apps/api/src/applications/player/player.controller.ts
Normal file
179
apps/api/src/applications/player/player.controller.ts
Normal file
@@ -0,0 +1,179 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Body,
|
||||
Param,
|
||||
Query,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { JwtAuthGuard, PlayerGuard } from '../../domains/identity/guards';
|
||||
import { CurrentUser } from '../../shared/common/decorators';
|
||||
import { jsonResponse } from '../../shared/common/filters';
|
||||
import { UsersService } from '../../domains/identity/users.service';
|
||||
import { WalletService } from '../../domains/ledger/wallet.service';
|
||||
import { MatchesService } from '../../domains/catalog/matches.service';
|
||||
import { BetsService } from '../../domains/betting/bets.service';
|
||||
import { ContentService } from '../../domains/operations/content/content.service';
|
||||
import { CashbackService } from '../../domains/operations/cashback/cashback.service';
|
||||
import { IsString, IsNumber, IsArray, ValidateNested, Min, IsOptional } from 'class-validator';
|
||||
import { Type } from 'class-transformer';
|
||||
|
||||
class SingleBetDto {
|
||||
@IsString()
|
||||
selectionId!: string;
|
||||
|
||||
@IsString()
|
||||
oddsVersion!: string;
|
||||
|
||||
@IsNumber()
|
||||
@Min(0.01)
|
||||
stake!: number;
|
||||
|
||||
@IsString()
|
||||
requestId!: string;
|
||||
}
|
||||
|
||||
class ParlayLegDto {
|
||||
@IsString()
|
||||
selectionId!: string;
|
||||
|
||||
@IsString()
|
||||
oddsVersion!: string;
|
||||
}
|
||||
|
||||
class ParlayBetDto {
|
||||
@IsArray()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => ParlayLegDto)
|
||||
legs!: ParlayLegDto[];
|
||||
|
||||
@IsNumber()
|
||||
@Min(0.01)
|
||||
stake!: number;
|
||||
|
||||
@IsString()
|
||||
requestId!: string;
|
||||
}
|
||||
|
||||
class LocaleDto {
|
||||
@IsString()
|
||||
locale!: string;
|
||||
}
|
||||
|
||||
@ApiTags('Player')
|
||||
@Controller('player')
|
||||
@UseGuards(JwtAuthGuard, PlayerGuard)
|
||||
@ApiBearerAuth()
|
||||
export class PlayerController {
|
||||
constructor(
|
||||
private users: UsersService,
|
||||
private wallet: WalletService,
|
||||
private matches: MatchesService,
|
||||
private bets: BetsService,
|
||||
private content: ContentService,
|
||||
private cashback: CashbackService,
|
||||
) {}
|
||||
|
||||
@Get('profile')
|
||||
async profile(@CurrentUser('id') userId: bigint) {
|
||||
const user = await this.users.findById(userId);
|
||||
return jsonResponse(user);
|
||||
}
|
||||
|
||||
@Post('language')
|
||||
async setLanguage(@CurrentUser('id') userId: bigint, @Body() dto: LocaleDto) {
|
||||
const result = await this.users.updateLocale(userId, dto.locale);
|
||||
return jsonResponse(result);
|
||||
}
|
||||
|
||||
@Get('home')
|
||||
async home(@CurrentUser('locale') locale: string) {
|
||||
const [banners, notices, ticker, hotMatches, todayMatches] = await Promise.all([
|
||||
this.content.listActive('BANNER', locale),
|
||||
this.content.listActive('NOTICE', locale),
|
||||
this.content.listActive('TICKER', locale),
|
||||
this.matches.listPublished(locale),
|
||||
this.matches.listPublished(locale),
|
||||
]);
|
||||
return jsonResponse({
|
||||
banners,
|
||||
notices,
|
||||
ticker,
|
||||
hotMatches: (hotMatches as Array<{ isHot?: boolean }>).filter((m) => m.isHot),
|
||||
todayMatches,
|
||||
});
|
||||
}
|
||||
|
||||
@Get('matches')
|
||||
async listMatches(
|
||||
@CurrentUser('locale') locale: string,
|
||||
@Query('leagueId') leagueId?: string,
|
||||
) {
|
||||
const items = await this.matches.listPublished(locale, leagueId ? BigInt(leagueId) : undefined);
|
||||
return jsonResponse(items);
|
||||
}
|
||||
|
||||
@Get('matches/:id')
|
||||
async matchDetail(@Param('id') id: string, @CurrentUser('locale') locale: string) {
|
||||
const match = await this.matches.getMatchDetail(BigInt(id), locale);
|
||||
return jsonResponse(match);
|
||||
}
|
||||
|
||||
@Post('bets/single')
|
||||
async singleBet(@CurrentUser('id') userId: bigint, @CurrentUser('parentId') parentId: bigint, @Body() dto: SingleBetDto) {
|
||||
const bet = await this.bets.placeSingleBet(
|
||||
userId,
|
||||
parentId,
|
||||
BigInt(dto.selectionId),
|
||||
BigInt(dto.oddsVersion),
|
||||
dto.stake,
|
||||
dto.requestId,
|
||||
);
|
||||
return jsonResponse(bet);
|
||||
}
|
||||
|
||||
@Post('bets/parlay')
|
||||
async parlayBet(@CurrentUser('id') userId: bigint, @CurrentUser('parentId') parentId: bigint, @Body() dto: ParlayBetDto) {
|
||||
const bet = await this.bets.placeParlayBet(
|
||||
userId,
|
||||
parentId,
|
||||
dto.legs.map((l) => ({ selectionId: BigInt(l.selectionId), oddsVersion: BigInt(l.oddsVersion) })),
|
||||
dto.stake,
|
||||
dto.requestId,
|
||||
);
|
||||
return jsonResponse(bet);
|
||||
}
|
||||
|
||||
@Get('bets')
|
||||
async myBets(
|
||||
@CurrentUser('id') userId: bigint,
|
||||
@Query('status') status?: string,
|
||||
@Query('page') page?: string,
|
||||
) {
|
||||
const result = await this.bets.getUserBets(userId, status, page ? parseInt(page) : 1);
|
||||
return jsonResponse(result);
|
||||
}
|
||||
|
||||
@Get('bets/:betNo')
|
||||
async betDetail(@CurrentUser('id') userId: bigint, @Param('betNo') betNo: string) {
|
||||
const bet = await this.bets.getBetByNo(betNo, userId);
|
||||
return jsonResponse(bet);
|
||||
}
|
||||
|
||||
@Get('wallet/transactions')
|
||||
async transactions(
|
||||
@CurrentUser('id') userId: bigint,
|
||||
@Query('page') page?: string,
|
||||
) {
|
||||
const result = await this.wallet.getTransactions(userId, page ? parseInt(page) : 1);
|
||||
return jsonResponse(result);
|
||||
}
|
||||
|
||||
@Get('cashbacks')
|
||||
async cashbacks(@CurrentUser('id') userId: bigint) {
|
||||
const items = await this.cashback.getUserCashbacks(userId);
|
||||
return jsonResponse(items);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user