""" models.py 数据模型模块:使用 Pydantic 定义请求/响应的数据结构。 FastAPI 会自动用这些模型做参数校验和文档生成。 """ from pydantic import BaseModel, Field from typing import Optional, List from datetime import datetime # ═══════════════════════════════════════════════════════════════ # 请求模型(客户端传入) # ═══════════════════════════════════════════════════════════════ class DeviceCheckRequest(BaseModel): """设备校验请求:APP 启动时携带 SN 进行合法性校验""" sn: str = Field(..., min_length=5, description="设备序列号,如 GD30-20260507-001") class LicenseGenerateRequest(BaseModel): """生成授权文件请求:管理后台为某台设备创建授权""" sn: str = Field(..., description="目标设备 SN") modules: List[str] = Field(default=[], description="激活的模块列表,如 ['1D', '2D']") valid_days: int = Field(default=365, ge=1, le=3650, description="授权有效期(天),默认一年") class ActivateReportRequest(BaseModel): """上报激活状态请求:设备主机首次联网后回传激活结果""" sn: str = Field(..., description="设备序列号") status: str = Field(..., pattern="^(已激活|激活失败)$", description="上报状态:已激活 或 激活失败") # ═══════════════════════════════════════════════════════════════ # 响应模型(服务端返回) # ═══════════════════════════════════════════════════════════════ class DeviceInfo(BaseModel): """设备信息响应""" sn: str status: str activated_at: Optional[str] = None created_at: str class CheckResponse(BaseModel): """设备校验响应:告诉 APP 这台设备是否合法、是否已激活""" valid: bool = Field(..., description="SN 是否存在于平台") activated: bool = Field(..., description="是否已激活") message: str = Field(..., description="给 APP 的提示信息") class LicenseData(BaseModel): """授权文件内的业务数据结构(未加密前)""" version: str = Field(default="1.0", description="授权文件版本") device_sn: str = Field(..., description="绑定的设备 SN") generated_at: str = Field(..., description="生成时间 ISO8601") valid_until: str = Field(..., description="有效期截止时间") modules: List[str] = Field(default=[], description="授权模块列表") status: str = Field(default="active", description="授权状态") class LicenseResponse(BaseModel): """生成授权文件响应:返回加密后的授权文件字符串""" success: bool encrypted_license: Optional[str] = Field(None, description="Base64 编码的加密授权文件") raw_license: Optional[dict] = Field(None, description="明文授权文件(仅调试用,生产环境可去掉)") message: str class ActivateResponse(BaseModel): """上报激活状态响应""" success: bool sn: str new_status: str activated_at: Optional[str] = None message: str