feat(admin,player,api): 公共管理与优胜冠军国旗、玩家端内容对接
新增公共内容 CRUD 与批量操作;公告滚动合并管理;优胜冠军内置国家选择与单行保存;玩家端统一 usePlayerHome 对接轮播与跑马灯。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
Get,
|
||||
Post,
|
||||
Put,
|
||||
Patch,
|
||||
Body,
|
||||
Param,
|
||||
Query,
|
||||
@@ -304,6 +305,113 @@ class AddOutrightSelectionDto {
|
||||
@IsNumber()
|
||||
@Min(1.01)
|
||||
odds!: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
logoUrl?: string;
|
||||
}
|
||||
|
||||
class UpdateOutrightSelectionTeamDto {
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
teamCode?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
teamZh?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
teamEn?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
logoUrl?: string | null;
|
||||
}
|
||||
|
||||
class ContentTranslationDto {
|
||||
@IsString()
|
||||
locale!: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
title?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
body?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
imageUrl?: string;
|
||||
}
|
||||
|
||||
class CreateContentDto {
|
||||
@IsString()
|
||||
@IsIn(['BANNER', 'NOTICE', 'TICKER'])
|
||||
contentType!: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
sortOrder?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsIn(['DRAFT', 'ACTIVE', 'INACTIVE'])
|
||||
status?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
linkType?: string | null;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
linkTarget?: string | null;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
startTime?: string | null;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
endTime?: string | null;
|
||||
|
||||
@IsArray()
|
||||
translations!: ContentTranslationDto[];
|
||||
}
|
||||
|
||||
class UpdateContentDto {
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
sortOrder?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsIn(['DRAFT', 'ACTIVE', 'INACTIVE'])
|
||||
status?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
linkType?: string | null;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
linkTarget?: string | null;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
startTime?: string | null;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
endTime?: string | null;
|
||||
|
||||
@IsOptional()
|
||||
@IsArray()
|
||||
translations?: ContentTranslationDto[];
|
||||
}
|
||||
|
||||
class ContentStatusDto {
|
||||
@IsIn(['DRAFT', 'ACTIVE', 'INACTIVE'])
|
||||
status!: string;
|
||||
}
|
||||
|
||||
class CashbackPreviewDto {
|
||||
@@ -790,6 +898,20 @@ export class AdminController {
|
||||
return jsonResponse(data);
|
||||
}
|
||||
|
||||
@Patch('outrights/:matchId/selections/:selectionId')
|
||||
async updateOutrightSelectionTeam(
|
||||
@Param('matchId') matchId: string,
|
||||
@Param('selectionId') selectionId: string,
|
||||
@Body() dto: UpdateOutrightSelectionTeamDto,
|
||||
) {
|
||||
const data = await this.outright.updateSelectionTeam(
|
||||
BigInt(matchId),
|
||||
BigInt(selectionId),
|
||||
dto,
|
||||
);
|
||||
return jsonResponse(data);
|
||||
}
|
||||
|
||||
@Delete('outrights/:matchId/selections/:selectionId')
|
||||
async removeOutrightSelection(
|
||||
@Param('matchId') matchId: string,
|
||||
@@ -875,17 +997,47 @@ export class AdminController {
|
||||
}
|
||||
|
||||
@Get('contents')
|
||||
async listContents(@Query('type') type?: string) {
|
||||
const items = await this.content.listAll(type);
|
||||
async listContents(
|
||||
@Query('type') type?: string,
|
||||
@Query('status') status?: string,
|
||||
) {
|
||||
const items = await this.content.listForAdmin(type, status);
|
||||
return jsonResponse(items);
|
||||
}
|
||||
|
||||
@Get('contents/:id')
|
||||
async getContent(@Param('id') id: string) {
|
||||
const item = await this.content.getForAdmin(BigInt(id));
|
||||
return jsonResponse(item);
|
||||
}
|
||||
|
||||
@Post('contents')
|
||||
async createContent(@Body() dto: Parameters<ContentService['create']>[0]) {
|
||||
async createContent(@Body() dto: CreateContentDto) {
|
||||
const item = await this.content.create(dto);
|
||||
return jsonResponse(item);
|
||||
}
|
||||
|
||||
@Put('contents/:id')
|
||||
async updateContent(@Param('id') id: string, @Body() dto: UpdateContentDto) {
|
||||
const item = await this.content.update(BigInt(id), dto);
|
||||
return jsonResponse(item);
|
||||
}
|
||||
|
||||
@Patch('contents/:id/status')
|
||||
async updateContentStatus(
|
||||
@Param('id') id: string,
|
||||
@Body() dto: ContentStatusDto,
|
||||
) {
|
||||
const item = await this.content.updateStatus(BigInt(id), dto.status);
|
||||
return jsonResponse(item);
|
||||
}
|
||||
|
||||
@Delete('contents/:id')
|
||||
async deleteContent(@Param('id') id: string) {
|
||||
const result = await this.content.remove(BigInt(id));
|
||||
return jsonResponse(result);
|
||||
}
|
||||
|
||||
@Get('i18n/messages')
|
||||
async getMessages(@Query('locale') locale = 'en-US') {
|
||||
const messages = await this.i18n.getMessages(locale);
|
||||
|
||||
Reference in New Issue
Block a user