feat: split admin dashboard, improve match ops, and player closed-match UX

Admin: add match/player overview sub-nav; refine settlement flow and league
match management UI; improve action button enabled/disabled styles; enhance
logo upload and outright odds sync.

API: expose matchPhase/bettingOpen for closed matches; league publish guards;
settlement preview with auto score save; outright team auto-sync.

Player: watermark for closed/settled states; keep match and bet details visible;
remove default login credentials.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-10 13:00:14 +08:00
parent 6124313369
commit 03f54ca689
43 changed files with 2787 additions and 519 deletions

View File

@@ -98,14 +98,14 @@ class TransferDto {
@IsString()
requestId!: string;
}
class CreditDto extends TransferDto {
@IsOptional()
@IsString()
remark?: string;
}
class CreditDto extends TransferDto {}
class UpdateSubAgentDto {
@IsOptional()
@IsString()
@@ -249,7 +249,13 @@ export class AgentPortalController {
@Param('id') playerId: string,
@Body() dto: TransferDto,
) {
const result = await this.agents.depositToPlayer(agentId, BigInt(playerId), dto.amount, dto.requestId);
const result = await this.agents.depositToPlayer(
agentId,
BigInt(playerId),
dto.amount,
dto.requestId,
dto.remark,
);
return jsonResponse(result);
}
@@ -259,7 +265,13 @@ export class AgentPortalController {
@Param('id') playerId: string,
@Body() dto: TransferDto,
) {
const result = await this.agents.withdrawFromPlayer(agentId, BigInt(playerId), dto.amount, dto.requestId);
const result = await this.agents.withdrawFromPlayer(
agentId,
BigInt(playerId),
dto.amount,
dto.requestId,
dto.remark,
);
return jsonResponse(result);
}
@@ -335,10 +347,7 @@ export class AgentPortalController {
const p = Math.max(1, page ? parseInt(page, 10) : 1);
const size = Math.min(Math.max(1, pageSize ? parseInt(pageSize, 10) : 10), 100);
const skip = (p - 1) * size;
const descendants = await this.prisma.agentClosure.findMany({
where: { ancestorId: agentId },
});
const agentIds = descendants.map((d) => d.descendantId);
const agentIds = await this.agents.getSubtreeAgentIds(agentId);
const [items, total] = await Promise.all([
this.prisma.bet.findMany({