feat(admin): 从已有玩家升级代理、修复 i18n 与过期 .js 冲突
- 新建一级代理改为选择已有玩家;新建用户可选一级代理 - 操作日志/注单等扁平 key 翻译;清理 src 内误生成 .js,Vite 优先解析 .ts Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user