feat(admin,player,api): 玩家账号密码管理与代理上下分

新增玩家头像、可查密码与全局改密/改账号开关;玩家资料页合并账号密码展示;代理直属玩家列表支持自定义上下分。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-04 11:36:53 +08:00
parent f76728dc3e
commit a8e4ead618
81 changed files with 1763 additions and 217 deletions

View File

@@ -13,6 +13,7 @@ import { JwtAuthGuard, PlayerGuard } from '../../domains/identity/guards';
import { CurrentUser } from '../../shared/common/decorators';
import { jsonResponse } from '../../shared/common/filters';
import { UsersService } from '../../domains/identity/users.service';
import { SystemConfigService } from '../../shared/config/system-config.service';
import { WalletService } from '../../domains/ledger/wallet.service';
import { MatchesService } from '../../domains/catalog/matches.service';
import { OutrightService } from '../../domains/catalog/outright.service';
@@ -72,6 +73,14 @@ class UpdateProfileDto {
@IsOptional()
@IsString()
email?: string;
@IsOptional()
@IsString()
avatarKey?: string;
@IsOptional()
@IsString()
username?: string;
}
@ApiTags('Player')
@@ -87,12 +96,39 @@ export class PlayerController {
private bets: BetsService,
private content: ContentService,
private cashback: CashbackService,
private systemConfig: SystemConfigService,
) {}
private async formatPlayerProfile(user: NonNullable<Awaited<ReturnType<UsersService['findById']>>>) {
const accountSettings = await this.systemConfig.getPlayerAccountSettings();
const prefs = user.preferences;
const viewablePassword = prefs?.managedPassword ?? null;
const safePrefs = prefs
? (({
managedPassword: _m,
allowPasswordChange: _a,
allowUsernameChange: _b,
...rest
}) => rest)(prefs)
: {};
return {
...user,
id: user.id.toString(),
parentId: user.parentId?.toString() ?? null,
preferences: {
...safePrefs,
viewablePassword,
allowPasswordChange: accountSettings.allowPasswordChange,
allowUsernameChange: accountSettings.allowUsernameChange,
},
};
}
@Get('profile')
async profile(@CurrentUser('id') userId: bigint) {
const user = await this.users.findById(userId);
return jsonResponse(user);
if (!user) return jsonResponse(null);
return jsonResponse(await this.formatPlayerProfile(user));
}
@Post('language')
@@ -104,7 +140,8 @@ export class PlayerController {
@Patch('profile')
async updateProfile(@CurrentUser('id') userId: bigint, @Body() dto: UpdateProfileDto) {
const user = await this.users.updateProfile(userId, dto);
return jsonResponse(user);
if (!user) return jsonResponse(null);
return jsonResponse(await this.formatPlayerProfile(user));
}
@Get('home')