feat(admin,api,player): 代理层级管理、额度上下分与玩家钱包详情

新增代理管理器与二级代理体系,完善信用额度/上下分上下文与冻结策略;代理端玩家与子代理管理增强;玩家端新增钱包详情页与交易筛选优化。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-08 15:34:12 +08:00
parent b2216abd0c
commit 414998ce36
54 changed files with 6641 additions and 481 deletions

View File

@@ -0,0 +1,133 @@
import { FormValidationError } from '../../i18n/form-validation';
export interface AgentPlayerCreateForm {
username: string;
password: string;
confirmPassword: string;
phone: string;
email: string;
initialDeposit: number;
remark: string;
}
export interface AgentPlayerRow {
id: string;
username: string;
status: string;
createdAt: string;
wallet?: { availableBalance: string; frozenBalance?: string };
}
export interface AgentPlayerDetail {
id: string;
username: string;
status: string;
phone: string | null;
email: string | null;
managedPassword: string | null;
availableBalance: string;
frozenBalance: string;
lastLoginAt: string | null;
loginFailCount: number;
betCount: number;
totalStake: string;
totalReturn: string;
createdAt: string;
}
export interface AgentPlayerEditForm {
id: string;
username: string;
status: string;
phone: string;
email: string;
managedPassword: string | null;
newPassword: string;
availableBalance: string;
frozenBalance: string;
betCount: number;
totalStake: string;
totalReturn: string;
lastLoginAt: string | null;
loginFailCount: number;
}
export function emptyAgentPlayerCreateForm(): AgentPlayerCreateForm {
return {
username: '',
password: 'Player@123',
confirmPassword: 'Player@123',
phone: '',
email: '',
initialDeposit: 0,
remark: '',
};
}
export function buildAgentCreatePlayerPayload(form: AgentPlayerCreateForm) {
if (!form.username.trim()) throw new FormValidationError('err.username_required');
if (form.password.length < 8) throw new FormValidationError('err.password_min');
if (form.password !== form.confirmPassword) throw new FormValidationError('err.password_mismatch');
if (form.initialDeposit < 0) throw new FormValidationError('err.amount_negative');
return {
username: form.username.trim(),
password: form.password,
phone: form.phone.trim() || undefined,
email: form.email.trim() || undefined,
initialDeposit: form.initialDeposit > 0 ? form.initialDeposit : undefined,
remark: form.remark.trim() || undefined,
};
}
export function emptyAgentPlayerEditForm(): AgentPlayerEditForm {
return {
id: '',
username: '',
status: 'ACTIVE',
phone: '',
email: '',
managedPassword: null,
newPassword: '',
availableBalance: '0',
frozenBalance: '0',
betCount: 0,
totalStake: '0',
totalReturn: '0',
lastLoginAt: null,
loginFailCount: 0,
};
}
export function editFormFromAgentDetail(d: AgentPlayerDetail): AgentPlayerEditForm {
return {
id: d.id,
username: d.username,
status: d.status,
phone: d.phone ?? '',
email: d.email ?? '',
managedPassword: d.managedPassword,
newPassword: '',
availableBalance: d.availableBalance,
frozenBalance: d.frozenBalance,
betCount: d.betCount,
totalStake: d.totalStake,
totalReturn: d.totalReturn,
lastLoginAt: d.lastLoginAt,
loginFailCount: d.loginFailCount,
};
}
export function buildAgentUpdatePlayerPayload(form: AgentPlayerEditForm) {
if (!form.username.trim()) throw new FormValidationError('err.username_required');
if (form.newPassword && form.newPassword.length < 8) {
throw new FormValidationError('err.password_min');
}
return {
username: form.username.trim(),
phone: form.phone.trim() || undefined,
email: form.email.trim() || undefined,
password: form.newPassword.trim() || undefined,
};
}