from decimal import Decimal from django.conf import settings from rest_framework import serializers from apps.billing.models import RechargeOrder from apps.licensing.models import ClientDevice class GenerateTitleRequestSerializer(serializers.Serializer): prompt = serializers.CharField(trim_whitespace=True, allow_blank=False) model = serializers.CharField( required=False, allow_blank=True, trim_whitespace=True, max_length=64, ) image_url = serializers.URLField(required=False, allow_blank=True) image_base64 = serializers.CharField(required=False, allow_blank=True) resolution = serializers.CharField( required=False, allow_blank=True, trim_whitespace=True, default="1K", ) parameters = serializers.DictField(required=False, default=dict) class GenerateImageRequestSerializer(serializers.Serializer): prompt = serializers.CharField(trim_whitespace=True, allow_blank=False) model = serializers.CharField( required=False, allow_blank=True, trim_whitespace=True, max_length=64, ) image_url = serializers.URLField(required=False, allow_blank=True) image_base64 = serializers.CharField(required=False, allow_blank=True) images = serializers.ListField(required=False, write_only=True) resolution = serializers.CharField( required=False, allow_blank=True, trim_whitespace=True, default="1K", ) aspect_ratio = serializers.CharField( required=False, allow_blank=True, trim_whitespace=True, default="1:1", ) parameters = serializers.DictField(required=False, default=dict) def validate_images(self, value): if not value: raise serializers.ValidationError("images 至少需要一张图片。") max_images = max(1, int(settings.IMAGE_MAX_INPUT_IMAGES)) if len(value) > max_images: raise serializers.ValidationError(f"单次最多上传 {max_images} 张图片。") serializer = ImageInputSerializer(data=value, many=True) serializer.is_valid(raise_exception=True) return serializer.validated_data def validate(self, attrs): has_legacy_image = bool(str(attrs.get("image_url") or "").strip()) or bool( str(attrs.get("image_base64") or "").strip() ) if attrs.get("images") is not None and has_legacy_image: raise serializers.ValidationError( "images 不能与 image_url 或 image_base64 同时提供。" ) return attrs class ImageInputSerializer(serializers.Serializer): image_url = serializers.URLField(required=False, allow_blank=True) image_base64 = serializers.CharField(required=False, allow_blank=True) def validate(self, attrs): has_url = bool(str(attrs.get("image_url") or "").strip()) has_base64 = bool(str(attrs.get("image_base64") or "").strip()) if has_url == has_base64: raise serializers.ValidationError( "每张图片必须且只能提供 image_url 或 image_base64。" ) return attrs class VisionImageInputSerializer(ImageInputSerializer): pass class AnalyzeImagesRequestSerializer(serializers.Serializer): prompt = serializers.CharField(trim_whitespace=True, allow_blank=False) model = serializers.CharField( required=False, allow_blank=True, trim_whitespace=True, max_length=64, ) images = VisionImageInputSerializer(many=True, allow_empty=False) parameters = serializers.DictField(required=False, default=dict) def validate_images(self, value): max_images = max(1, int(settings.VISION_MAX_IMAGES)) if len(value) > max_images: raise serializers.ValidationError(f"单次最多上传 {max_images} 张图片。") return value class RechargeCreateRequestSerializer(serializers.Serializer): amount = serializers.DecimalField( max_digits=12, decimal_places=2, min_value=Decimal("0.01"), ) pay_method = serializers.ChoiceField(choices=RechargeOrder.PayMethod.values) def validate_amount(self, value): max_amount = Decimal(str(settings.RECHARGE_MAX_AMOUNT_CNY)) if value > max_amount: raise serializers.ValidationError(f"单笔充值金额不能超过 {max_amount:.2f} CNY") return value class RechargeStatusRequestSerializer(serializers.Serializer): order_no = serializers.CharField( trim_whitespace=True, allow_blank=False, max_length=64, ) class DeviceRegistrationRequestSerializer(serializers.Serializer): product_code = serializers.ChoiceField(choices=ClientDevice.ProductCode.values) device_id = serializers.CharField( trim_whitespace=True, allow_blank=False, max_length=256, ) device_id_version = serializers.CharField( trim_whitespace=True, allow_blank=False, max_length=32, ) installation_public_key = serializers.CharField( trim_whitespace=True, allow_blank=False, max_length=4096, ) platform = serializers.ChoiceField(choices=ClientDevice.Platform.values) client_version = serializers.CharField( trim_whitespace=True, allow_blank=False, max_length=64, )