enterprise-saa-s-dashboard-.../python_backend/models.py

339 lines
16 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
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="授权有效期(天),默认一年")
config_id: Optional[int] = Field(None, description="关联的配置文件 ID授权文件中会嵌入该配置")
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
# ═══════════════════════════════════════════════════════════════
# 配置文件相关模型
# ═══════════════════════════════════════════════════════════════
class ConfigFileCreateRequest(BaseModel):
"""创建配置文件请求"""
name: str = Field(..., description="配置名称,如 GD30-2024-标准参数")
model: str = Field(..., description="适用设备型号,如 GD30-2024")
version: str = Field(default="v1.0", description="配置版本号")
status: str = Field(default="生效", description="状态:生效/失效")
# 发射参数
max_tx_voltage: Optional[str] = Field(None, description="最大发射电压,如 1200V / 1500V")
max_tx_current: Optional[str] = Field(None, description="最大发射电流,如 6A / 10A")
tx_waveform: Optional[str] = Field(None, description="发射波形,如 0+0- / +0-0 / +-")
tx_pulse_width: Optional[str] = Field(None, description="发射脉宽,如 0.25s/0.5s/1s/2s/4s/8s/16s")
# 采集参数
acq_channels: Optional[str] = Field(None, description="支持通道数,如 1 / 6 / 12")
acq_sample_rate: Optional[str] = Field(None, description="采样率,如 50Hz/60Hz/100Hz/1000Hz")
acq_voltage_range: Optional[str] = Field(None, description="电压测量量程,如 ±2.5V/±80V / ±80V/±600V")
full_waveform_capture: Optional[str] = Field(None, description="全波形采集,如 支持 / 不支持")
# 网络参数
ssid_prefix: Optional[str] = Field(None, description="WiFi SSID前缀如 GD30-AP")
class ConfigFileUpdateRequest(BaseModel):
"""更新配置文件请求"""
name: Optional[str] = Field(None, description="配置名称")
model: Optional[str] = Field(None, description="适用设备型号")
version: Optional[str] = Field(None, description="配置版本号")
status: Optional[str] = Field(None, description="状态:生效/失效")
# 发射参数
max_tx_voltage: Optional[str] = Field(None, description="最大发射电压")
max_tx_current: Optional[str] = Field(None, description="最大发射电流")
tx_waveform: Optional[str] = Field(None, description="发射波形")
tx_pulse_width: Optional[str] = Field(None, description="发射脉宽")
# 采集参数
acq_channels: Optional[str] = Field(None, description="支持通道数")
acq_sample_rate: Optional[str] = Field(None, description="采样率")
acq_voltage_range: Optional[str] = Field(None, description="电压测量量程")
full_waveform_capture: Optional[str] = Field(None, description="全波形采集")
# 网络参数
ssid_prefix: Optional[str] = Field(None, description="WiFi SSID前缀")
class ConfigFileInfo(BaseModel):
"""配置文件信息响应"""
id: int
name: str
model: str
version: str
status: str
# 发射参数
max_tx_voltage: Optional[str] = None
max_tx_current: Optional[str] = None
tx_waveform: Optional[str] = None
tx_pulse_width: Optional[str] = None
# 采集参数
acq_channels: Optional[str] = None
acq_sample_rate: Optional[str] = None
acq_voltage_range: Optional[str] = None
full_waveform_capture: Optional[str] = None
# 网络参数
ssid_prefix: Optional[str] = None
created_at: Optional[str] = None
updated_at: Optional[str] = None
# ═══════════════════════════════════════════════════════════════
# 校准文件相关模型
# ═══════════════════════════════════════════════════════════════
class CalibChannelData(BaseModel):
"""校准通道数据"""
ChannelId: int = Field(..., description="通道ID")
factor_80v: float = Field(..., description="80V量程校准系数")
offset_80v: float = Field(..., description="80V量程偏移量")
factor_2_5v: float = Field(..., description="2.5V量程校准系数")
offset_2_5v: float = Field(..., description="2.5V量程偏移量")
class CalibrationUploadRequest(BaseModel):
"""校准文件上传请求JSON格式由Windows校准软件调用"""
SN: str = Field(..., description="校准文件中的SN")
UID: str = Field(..., description="校准文件中的UID")
CalibrateFactor: List[dict] = Field(..., description="各通道校准系数数组")
class CalibrationFileInfo(BaseModel):
"""校准文件信息响应"""
id: int
material_sn: str = Field(..., description="关联物料SN")
sn: Optional[str] = Field(None, description="校准SN")
uid: Optional[str] = Field(None, description="校准UID")
file_name: Optional[str] = Field(None, description="文件名")
file_size: Optional[int] = Field(None, description="文件大小(字节)")
md5: Optional[str] = Field(None, description="文件MD5")
result: Optional[str] = Field(None, description="校准结果:合格/不合格")
operator: Optional[str] = Field(None, description="操作员")
remark: Optional[str] = Field(None, description="备注")
upload_time: Optional[str] = Field(None, description="上传时间")
channels_count: Optional[int] = Field(None, description="通道数量")
channels: Optional[List[dict]] = Field(None, description="通道详细数据")
class CalibrationUpdateRequest(BaseModel):
"""校准文件更新请求"""
operator: Optional[str] = Field(None, description="操作员")
remark: Optional[str] = Field(None, description="备注")
result: Optional[str] = Field(None, description="校准结果")
# ═══════════════════════════════════════════════════════════════
# APP 版本相关模型
# ═══════════════════════════════════════════════════════════════
class AppVersionCreateRequest(BaseModel):
"""创建 APP 版本请求"""
app_name: str = Field(..., description="应用名称,如 GeoData Mobile")
package_name: Optional[str] = Field(None, description="包名,如 com.geomative.geodata")
platform_type: int = Field(default=2, description="平台类型1=iOS, 2=Android")
version_name: str = Field(..., description="版本号名称,如 1.2.0")
major_version: int = Field(default=1, ge=0)
minor_version: int = Field(default=0, ge=0)
patch_version: int = Field(default=0, ge=0)
file_type: str = Field(default="apk", description="文件类型apk / ipa")
distribution_type: str = Field(default="direct", description="分发方式direct / appstore")
os_min_version: Optional[str] = Field(None, description="最低系统版本要求")
is_force_update: bool = Field(default=False, description="是否强制更新")
changelog: Optional[List[str]] = Field(None, description="更新日志列表")
status: int = Field(default=1, description="状态0=草稿, 1=已发布, 2=已下架")
class AppVersionUpdateRequest(BaseModel):
"""更新 APP 版本请求"""
app_name: Optional[str] = Field(None, description="应用名称")
package_name: Optional[str] = Field(None, description="包名")
version_name: Optional[str] = Field(None, description="版本号")
platform_type: Optional[int] = Field(None, description="平台类型")
os_min_version: Optional[str] = Field(None, description="最低系统版本")
is_force_update: Optional[bool] = Field(None, description="是否强制更新")
changelog: Optional[List[str]] = Field(None, description="更新日志")
status: Optional[int] = Field(None, description="状态0=草稿, 1=已发布, 2=已下架")
class AppVersionInfo(BaseModel):
"""APP 版本信息响应"""
id: int
app_name: str
package_name: Optional[str] = None
platform_type: int
version_name: str
major_version: int
minor_version: int
patch_version: int
file_name: Optional[str] = None
file_size: Optional[int] = None
file_type: Optional[str] = None
distribution_type: Optional[str] = None
primary_url: Optional[str] = None
os_min_version: Optional[str] = None
is_force_update: bool = False
changelog: Optional[str] = None
status: int
created_at: Optional[str] = None
updated_at: Optional[str] = None
class AppDownloadQuery(BaseModel):
"""APP 下载查询参数"""
app_name: Optional[str] = Field(None, description="应用名称")
platform_type: Optional[int] = Field(None, description="平台类型1=iOS, 2=Android")
version_name: Optional[str] = Field(None, description="指定版本号")
class AppCheckUpdateRequest(BaseModel):
"""APP 检查更新请求"""
app_name: str = Field(..., description="应用名称")
platform_type: int = Field(..., description="平台类型1=iOS, 2=Android")
current_version: str = Field(..., description="当前版本号,如 1.1.0")
class AppCheckUpdateResponse(BaseModel):
"""APP 检查更新响应"""
has_update: bool = Field(..., description="是否有更新")
force_update: bool = Field(..., description="是否强制更新")
version_name: Optional[str] = Field(None, description="最新版本号")
download_url: Optional[str] = Field(None, description="下载地址")
changelog: Optional[List[str]] = Field(None, description="更新日志")
file_size: Optional[int] = Field(None, description="文件大小")
# ═══════════════════════════════════════════════════════════════
# 固件版本相关模型
# ═══════════════════════════════════════════════════════════════
class FirmwareCreateRequest(BaseModel):
"""创建固件版本请求"""
version: str = Field(..., description="固件版本号,如 v3.2.1")
firmware_type: str = Field(..., description="固件类型:采集板/发射板/主协板/主机服务")
board_model: Optional[str] = Field(None, description="板卡型号,如 GD30-ACQ-01")
device_model: Optional[str] = Field(None, description="设备型号,如 GD30-2024")
hw_range: Optional[str] = Field(None, description="硬件适用范围")
upgrade_type: str = Field(default="可选", description="升级类型:强制/可选")
signed: bool = Field(default=False, description="是否已签名")
notes: Optional[List[str]] = Field(None, description="更新说明列表")
status: str = Field(default="已发布", description="状态:草稿/已发布/已下架/兼容")
class FirmwareUpdateRequest(BaseModel):
"""更新固件版本请求"""
version: Optional[str] = Field(None, description="版本号")
firmware_type: Optional[str] = Field(None, description="固件类型")
board_model: Optional[str] = Field(None, description="板卡型号")
device_model: Optional[str] = Field(None, description="设备型号")
hw_range: Optional[str] = Field(None, description="硬件适用范围")
upgrade_type: Optional[str] = Field(None, description="升级类型")
signed: Optional[bool] = Field(None, description="是否已签名")
notes: Optional[List[str]] = Field(None, description="更新说明")
status: Optional[str] = Field(None, description="状态")
class FirmwareInfo(BaseModel):
"""固件版本信息响应"""
id: int
version: str
firmware_type: str
board_model: Optional[str] = None
device_model: Optional[str] = None
file_name: Optional[str] = None
file_size: Optional[int] = None
hw_range: Optional[str] = None
upgrade_type: Optional[str] = None
signed: bool = False
notes: Optional[str] = None
status: str
created_at: Optional[str] = None
updated_at: Optional[str] = None
class FirmwareDownloadQuery(BaseModel):
"""固件下载查询参数"""
firmware_type: str = Field(..., description="固件类型")
device_model: Optional[str] = Field(None, description="设备型号")
board_model: Optional[str] = Field(None, description="板卡型号")
class FirmwareCheckUpdateRequest(BaseModel):
"""固件检查更新请求"""
firmware_type: str = Field(..., description="固件类型")
device_model: Optional[str] = Field(None, description="设备型号")
board_model: Optional[str] = Field(None, description="板卡型号")
current_version: str = Field(..., description="当前版本号")
class FirmwareCheckUpdateResponse(BaseModel):
"""固件检查更新响应"""
has_update: bool = Field(..., description="是否有更新")
force_update: bool = Field(..., description="是否强制更新")
version: Optional[str] = Field(None, description="最新版本号")
download_url: Optional[str] = Field(None, description="下载地址")
notes: Optional[List[str]] = Field(None, description="更新说明")
file_size: Optional[int] = Field(None, description="文件大小")