"""Pydantic 请求/响应模型。""" from datetime import datetime from pydantic import BaseModel, ConfigDict class ScreenCreate(BaseModel): name: str = "未命名屏幕" location: str = "" device_id: str | None = None # 可选:预建屏幕时手动指定客户端设备 ID class ScreenUpdate(BaseModel): name: str | None = None location: str | None = None class ScreenOut(BaseModel): model_config = ConfigDict(from_attributes=True) id: int name: str device_id: str location: str status: str last_seen: datetime | None created_at: datetime class ScreenDetail(ScreenOut): """屏幕详情:附带当前绑定的节目。""" playlist: "PlaylistOut | None" = None class AssetOut(BaseModel): model_config = ConfigDict(from_attributes=True) id: int name: str type: str url: str size: int duration: int created_at: datetime class PlaylistItemIn(BaseModel): asset_id: int duration: int | None = None # None 表示使用素材默认时长 class PlaylistCreate(BaseModel): name: str description: str = "" items: list[PlaylistItemIn] = [] class PlaylistUpdate(BaseModel): name: str | None = None description: str | None = None items: list[PlaylistItemIn] | None = None class PlaylistItemOut(BaseModel): model_config = ConfigDict(from_attributes=True) id: int asset_id: int sort_order: int duration: int | None asset: AssetOut class PlaylistOut(BaseModel): model_config = ConfigDict(from_attributes=True) id: int name: str description: str created_at: datetime items: list[PlaylistItemOut] = [] class BindRequest(BaseModel): playlist_id: int class LoginRequest(BaseModel): username: str password: str class LoginResponse(BaseModel): token: str # ---------------- 客户端接口模型 ---------------- class ClientRegisterRequest(BaseModel): device_id: str name: str | None = None class ClientConfigItem(BaseModel): asset_id: int type: str # image / video url: str # 相对路径,客户端拼接服务器 base_url name: str duration: int # 秒;视频为 0 表示按视频自身时长 class ClientConfigResponse(BaseModel): configured: bool # False 表示该屏幕尚未绑定节目 playlist_id: int | None = None playlist_name: str | None = None version: int # 绑定更新计数,客户端可缓存判断 items: list[ClientConfigItem] = [] class ClientHeartbeatRequest(BaseModel): device_id: str class CrashReportRequest(BaseModel): device_id: str stacktrace: str ScreenDetail.model_rebuild()