feat(admin): 从已有玩家升级代理、修复 i18n 与过期 .js 冲突

- 新建一级代理改为选择已有玩家;新建用户可选一级代理

- 操作日志/注单等扁平 key 翻译;清理 src 内误生成 .js,Vite 优先解析 .ts

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-03 15:42:15 +08:00
parent cbfa18d1d3
commit 3b739982a1
27 changed files with 625 additions and 165 deletions

View File

@@ -88,6 +88,20 @@ class CreatePlayerAdminDto {
@IsOptional()
@IsString()
remark?: string;
/** 创建为一级代理(非玩家) */
@IsOptional()
asTier1Agent?: boolean;
@IsOptional()
@IsNumber()
@Min(0)
creditLimit?: number;
@IsOptional()
@IsNumber()
@Min(0)
cashbackRate?: number;
}
class UpdatePlayerAdminDto {
@@ -114,21 +128,14 @@ class UpdatePlayerAdminDto {
}
class CreateAgentAdminDto {
/** 已有玩家用户 ID升级为一级代理 */
@IsString()
username!: string;
@IsString()
@MinLength(8)
password!: string;
userId!: string;
@IsNumber()
@Min(0)
creditLimit!: number;
@IsOptional()
@IsString()
locale?: string;
@IsOptional()
@IsString()
phone?: string;
@@ -331,18 +338,41 @@ export class AdminController {
initialDeposit: dto.initialDeposit,
depositRemark: dto.remark,
depositRequestId: `create-player-${dto.username}-${Date.now()}`,
asTier1Agent: dto.asTier1Agent,
creditLimit: dto.creditLimit,
cashbackRate: dto.cashbackRate,
});
await this.audit.log({
operatorId,
operatorType: 'ADMIN',
action: 'CREATE_PLAYER',
module: 'USERS',
action: dto.asTier1Agent ? 'CREATE_AGENT' : 'CREATE_PLAYER',
module: dto.asTier1Agent ? 'AGENTS' : 'USERS',
targetId: user.id.toString(),
});
if (dto.asTier1Agent) {
const detail = await this.agents.getAgentAdminDetail(user.id);
return jsonResponse(detail);
}
const detail = await this.users.getPlayerAdminDetail(user.id);
return jsonResponse(detail);
}
@Get('users/promotable-for-agent')
async listPromotableForAgent(@Query('keyword') keyword?: string) {
const rows = await this.agents.listPromotablePlayers(keyword);
return jsonResponse(
rows.map((u) => ({
id: u.id.toString(),
username: u.username,
status: u.status,
parentId: u.parentId?.toString() ?? null,
parentUsername: u.parent?.username ?? null,
phone: u.preferences?.phone ?? null,
email: u.preferences?.email ?? null,
})),
);
}
@Get('agents/options')
async listAgentOptions() {
const agents = await this.prisma.user.findMany({
@@ -397,12 +427,8 @@ export class AdminController {
@CurrentUser('id') operatorId: bigint,
@Body() dto: CreateAgentAdminDto,
) {
const user = await this.agents.createAgent(operatorId, {
username: dto.username,
password: dto.password,
level: 1,
const user = await this.agents.promotePlayerToTier1Agent(BigInt(dto.userId), {
creditLimit: dto.creditLimit,
locale: dto.locale,
phone: dto.phone,
email: dto.email,
cashbackRate: dto.cashbackRate,