import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger' import { IsString, IsInt, IsBoolean, IsOptional, IsDateString, Min, Matches, IsEnum } from 'class-validator' import { Type, Transform } from 'class-transformer' import { Platform } from '@/domain/enums/platform.enum' export class UploadVersionDto { @ApiProperty({ enum: ['android', 'ios', 'ANDROID', 'IOS'], description: '平台 (android/ios)' }) @Transform(({ value }) => (typeof value === 'string' ? value.toUpperCase() : value)) @IsEnum(Platform) platform: Platform @ApiPropertyOptional({ description: '版本号 (可从APK/IPA自动检测)', example: 100, minimum: 1 }) @IsOptional() @Type(() => Number) @IsInt() @Min(1) versionCode?: number @ApiPropertyOptional({ description: '版本名称 (可从APK/IPA自动检测)', example: '1.0.0' }) @IsOptional() @IsString() @Matches(/^\d+\.\d+\.\d+(\.\d+)?$/, { message: 'versionName must be in format x.y.z or x.y.z.w' }) versionName?: string @ApiPropertyOptional({ description: '构建号 (可从APK/IPA自动检测)', example: '100' }) @IsOptional() @IsString() buildNumber?: string @ApiPropertyOptional({ description: '更新日志', default: '' }) @IsOptional() @IsString() changelog?: string @ApiPropertyOptional({ description: '是否强制更新', default: false }) @IsOptional() @Transform(({ obj }) => { // Access the raw value directly from the source object // This bypasses enableImplicitConversion which incorrectly converts "false" string to true const rawValue = obj.isForceUpdate // Handle string "true"/"false" from FormData if (typeof rawValue === 'string') { return rawValue.toLowerCase() === 'true' } // Handle undefined/null - default to false if (rawValue === undefined || rawValue === null) { return false } // Handle actual boolean value return rawValue === true }) @IsBoolean() isForceUpdate?: boolean @ApiPropertyOptional({ description: '最低操作系统版本 (可从APK/IPA自动检测)', example: '10.0' }) @IsOptional() @IsString() minOsVersion?: string @ApiPropertyOptional({ description: '发布日期', example: '2025-12-02T10:00:00Z' }) @IsOptional() @IsDateString() releaseDate?: string }