rwadurian/backend/services/identity-service/src/api/dto/index.ts

343 lines
7.5 KiB
TypeScript

// 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: '<svg>...</svg>', 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[];
}