// Request DTOs export * from './request'; // Response DTOs export * from './response'; // 其他通用DTOs import { IsString, IsOptional, IsNotEmpty, Matches, IsEnum, IsNumber } from 'class-validator'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; export class AutoLoginDto { @ApiProperty() @IsString() @IsNotEmpty() refreshToken: string; @ApiProperty() @IsString() @IsNotEmpty() deviceId: string; } export class SendSmsCodeDto { @ApiProperty({ example: '13800138000' }) @IsString() @Matches(/^1[3-9]\d{9}$/, { message: '手机号格式错误' }) phoneNumber: string; @ApiProperty({ enum: ['REGISTER', 'LOGIN', 'BIND', 'RECOVER'] }) @IsEnum(['REGISTER', 'LOGIN', 'BIND', 'RECOVER']) type: 'REGISTER' | 'LOGIN' | 'BIND' | 'RECOVER'; } export class RegisterDto { @ApiProperty({ example: '13800138000' }) @IsString() @Matches(/^1[3-9]\d{9}$/, { message: '手机号格式错误' }) phoneNumber: string; @ApiProperty({ example: '123456' }) @IsString() @Matches(/^\d{6}$/, { message: '验证码格式错误' }) smsCode: string; @ApiProperty() @IsString() @IsNotEmpty() deviceId: string; @ApiProperty() @IsString() @IsNotEmpty() provinceCode: string; @ApiProperty() @IsString() @IsNotEmpty() cityCode: string; @ApiPropertyOptional() @IsOptional() @IsString() deviceName?: string; @ApiPropertyOptional() @IsOptional() @IsString() inviterReferralCode?: string; } export class LoginDto { @ApiProperty({ example: '13800138000' }) @IsString() @Matches(/^1[3-9]\d{9}$/, { message: '手机号格式错误' }) phoneNumber: string; @ApiProperty({ example: '123456' }) @IsString() @Matches(/^\d{6}$/, { message: '验证码格式错误' }) smsCode: string; @ApiProperty() @IsString() @IsNotEmpty() deviceId: string; } export class UpdateProfileDto { @ApiPropertyOptional() @IsOptional() @IsString() nickname?: string; @ApiPropertyOptional() @IsOptional() @IsString() avatarUrl?: string; @ApiPropertyOptional() @IsOptional() @IsString() address?: string; } export class BindWalletDto { @ApiProperty({ enum: ['KAVA', 'DST', 'BSC'] }) @IsEnum(['KAVA', 'DST', 'BSC']) chainType: string; @ApiProperty() @IsString() @IsNotEmpty() address: string; } export class RemoveDeviceDto { @ApiProperty() @IsString() @IsNotEmpty() deviceId: string; } // Response DTOs export class AutoCreateAccountResponseDto { @ApiProperty({ example: 100001, description: '用户序列号 (唯一标识)' }) userSerialNum: number; @ApiProperty({ example: 'ABC123', description: '推荐码' }) referralCode: string; @ApiProperty({ example: '榴莲勇士_38472', description: '随机用户名' }) username: string; @ApiProperty({ example: '...', description: '随机SVG头像' }) avatarSvg: string; @ApiProperty({ description: '访问令牌' }) accessToken: string; @ApiProperty({ description: '刷新令牌' }) refreshToken: string; } export class RecoverAccountResponseDto { @ApiProperty() userId: string; @ApiProperty() accountSequence: number; @ApiProperty() nickname: string; @ApiProperty({ nullable: true }) avatarUrl: string | null; @ApiProperty() referralCode: string; @ApiProperty() accessToken: string; @ApiProperty() refreshToken: string; } // 钱包地址响应 export class WalletAddressesDto { @ApiProperty({ example: '0x1234...', description: 'KAVA链地址' }) kava: string; @ApiProperty({ example: 'dst1...', description: 'DST链地址' }) dst: string; @ApiProperty({ example: '0x5678...', description: 'BSC链地址' }) bsc: string; } // 钱包状态响应 (就绪) export class WalletStatusReadyResponseDto { @ApiProperty({ example: 'ready', description: '钱包状态' }) status: 'ready'; @ApiProperty({ type: WalletAddressesDto, description: '三链钱包地址' }) walletAddresses: WalletAddressesDto; @ApiProperty({ example: 'word1 word2 ... word12', description: '助记词 (12词)' }) mnemonic: string; } // 钱包状态响应 (生成中) export class WalletStatusGeneratingResponseDto { @ApiProperty({ example: 'generating', description: '钱包状态' }) status: 'generating'; } export class LoginResponseDto { @ApiProperty() userId: string; @ApiProperty() accountSequence: number; @ApiProperty() accessToken: string; @ApiProperty() refreshToken: string; } // ============ Referral DTOs ============ export class GenerateReferralLinkDto { @ApiPropertyOptional({ description: '渠道标识: wechat, telegram, twitter 等' }) @IsOptional() @IsString() channel?: string; @ApiPropertyOptional({ description: '活动ID' }) @IsOptional() @IsString() campaignId?: string; } export class MeResponseDto { @ApiProperty() userId: string; @ApiProperty({ description: '账户序列号' }) accountSequence: number; @ApiProperty({ nullable: true }) phoneNumber: string | null; @ApiProperty() nickname: string; @ApiProperty({ nullable: true }) avatarUrl: string | null; @ApiProperty({ description: '推荐码' }) referralCode: string; @ApiProperty({ description: '完整推荐链接' }) referralLink: string; @ApiProperty({ description: '钱包地址列表' }) walletAddresses: Array<{ chainType: string; address: string }>; @ApiProperty() kycStatus: string; @ApiProperty() status: string; @ApiProperty() registeredAt: Date; } export class ReferralValidationResponseDto { @ApiProperty({ description: '推荐码是否有效' }) valid: boolean; @ApiPropertyOptional() referralCode?: string; @ApiPropertyOptional({ description: '邀请人信息' }) inviterInfo?: { accountSequence: number; nickname: string; avatarUrl: string | null; }; @ApiPropertyOptional({ description: '错误信息' }) message?: string; } export class ReferralLinkResponseDto { @ApiProperty() linkId: string; @ApiProperty() referralCode: string; @ApiProperty({ description: '短链' }) shortUrl: string; @ApiProperty({ description: '完整链接' }) fullUrl: string; @ApiProperty({ nullable: true }) channel: string | null; @ApiProperty({ nullable: true }) campaignId: string | null; @ApiProperty() createdAt: Date; } export class InviteRecordDto { @ApiProperty() accountSequence: number; @ApiProperty() nickname: string; @ApiProperty({ nullable: true }) avatarUrl: string | null; @ApiProperty() registeredAt: Date; @ApiProperty({ description: '1=直接邀请, 2=间接邀请' }) level: number; } export class ReferralStatsResponseDto { @ApiProperty() referralCode: string; @ApiProperty({ description: '总邀请人数' }) totalInvites: number; @ApiProperty({ description: '直接邀请人数' }) directInvites: number; @ApiProperty({ description: '间接邀请人数 (二级)' }) indirectInvites: number; @ApiProperty({ description: '今日邀请' }) todayInvites: number; @ApiProperty({ description: '本周邀请' }) thisWeekInvites: number; @ApiProperty({ description: '本月邀请' }) thisMonthInvites: number; @ApiProperty({ description: '最近邀请记录', type: [InviteRecordDto] }) recentInvites: InviteRecordDto[]; }