| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- from typing import Optional, List, Dict
- from enum import Enum
- from pydantic import BaseModel, field_validator
- from datetime import datetime
- from app.core.version import validate_version_code
- # 平台枚举,与前端一致(安卓分平板/手机,苹果含 iPadOS,鸿蒙分电脑/平板/手机)
- class DistributionPlatform(str, Enum):
- ANDROID = "android"
- ANDROID_PHONE = "android_phone" # 安卓手机
- ANDROID_TABLET = "android_tablet" # 安卓平板
- IOS = "ios"
- IPADOS = "ipados" # iPadOS
- WINDOWS = "windows"
- MACOS = "macos"
- HARMONYOS_PC = "harmonyos_pc" # 鸿蒙电脑
- HARMONYOS_PAD = "harmonyos_pad" # 鸿蒙平板
- HARMONYOS_PHONE = "harmonyos_phone" # 鸿蒙手机
- # Distribution Schemas
- class ClientDistributionBase(BaseModel):
- name: str
- description: Optional[str] = None
- icon_url: Optional[str] = None
- class ClientDistributionCreate(ClientDistributionBase):
- pass
- class ClientDistributionUpdate(BaseModel):
- name: Optional[str] = None
- description: Optional[str] = None
- icon_url: Optional[str] = None
- class ClientDistributionResponse(ClientDistributionBase):
- id: int
- owner_id: int
- created_at: datetime
- updated_at: Optional[datetime] = None
- icon_object_key: Optional[str] = None # 原始 object_key,编辑时回传用
- share_id: str = "" # 由 id+created_at 生成的固定无规律分享标识,用于 /d/{share_id}
- class Config:
- from_attributes = True
- class ClientDistributionList(BaseModel):
- total: int
- items: List[ClientDistributionResponse]
- # Version Schemas
- class ClientVersionBase(BaseModel):
- version_code: str
- version_name: Optional[str] = None
- release_notes: Optional[str] = None
- platform: Optional[str] = None
- @field_validator("version_code")
- @classmethod
- def version_code_format(cls, v: str) -> str:
- if not v or not v.strip():
- raise ValueError("版本号不能为空")
- validate_version_code(v)
- return v.strip()
- @field_validator("platform")
- @classmethod
- def platform_enum(cls, v: Optional[str]) -> Optional[str]:
- if v is None or v == "":
- return None
- allowed = {p.value for p in DistributionPlatform}
- if v.strip().lower() not in allowed:
- raise ValueError(f"平台必须是以下之一: {', '.join(sorted(allowed))}")
- return v.strip().lower()
- class ClientVersionCreate(ClientVersionBase):
- object_key: str
- file_size: Optional[int] = None
- class ClientVersionUpdate(BaseModel):
- version_name: Optional[str] = None
- release_notes: Optional[str] = None
- platform: Optional[str] = None
- @field_validator("platform")
- @classmethod
- def platform_enum(cls, v: Optional[str]) -> Optional[str]:
- if v is None or v == "":
- return None
- allowed = {p.value for p in DistributionPlatform}
- if v.strip().lower() not in allowed:
- raise ValueError(f"平台必须是以下之一: {', '.join(sorted(allowed))}")
- return v.strip().lower()
- class ClientVersionResponse(ClientVersionBase):
- id: int
- distribution_id: int
- object_key: str
- file_size: Optional[int] = None
- created_at: datetime
- class Config:
- from_attributes = True
- class ClientVersionList(BaseModel):
- total: int
- items: List[ClientVersionResponse]
- # Open API - Public download page
- class LatestVersionInfo(BaseModel):
- id: int
- version_code: str
- version_name: Optional[str] = None
- release_notes: Optional[str] = None
- file_size: Optional[int] = None
- platform: Optional[str] = None
- created_at: datetime
- download_url: str # Pre-signed URL
- class DistributionPublicResponse(BaseModel):
- id: int
- name: str
- description: Optional[str] = None
- icon_url: Optional[str] = None
- latest_version: Optional[LatestVersionInfo] = None
- # 按平台分组的最新版本,用于分享页 Tab 切换;key 为 platform 枚举值
- latest_versions_by_platform: Optional[Dict[str, LatestVersionInfo]] = None
|