""" Pydantic 模式定义 """ from pydantic import BaseModel, Field from typing import Optional, List from datetime import datetime # ============ 公司相关 ============ class CompanyBase(BaseModel): """公司基础模式""" stock_code: str = Field(..., description="股票代码", min_length=6, max_length=6) company_name: Optional[str] = Field(None, description="公司名称(可选,系统自动获取)") short_name: Optional[str] = Field(None, description="公司简称") industry: Optional[str] = Field(None, description="所属行业") class CompanyCreate(BaseModel): """创建公司 - 仅需股票代码""" stock_code: str = Field(..., description="股票代码", min_length=6, max_length=6) company_name: Optional[str] = Field(None, description="公司名称(可选,系统自动从巨潮获取)") short_name: Optional[str] = Field(None, description="公司简称") industry: Optional[str] = Field(None, description="所属行业") class CompanyUpdate(BaseModel): """更新公司""" company_name: Optional[str] = None short_name: Optional[str] = None industry: Optional[str] = None is_active: Optional[bool] = None class CompanyResponse(CompanyBase): """公司响应""" id: int org_id: Optional[str] = None is_active: bool created_at: datetime updated_at: datetime report_count: Optional[int] = 0 class Config: from_attributes = True # ============ 报告相关 ============ class ReportBase(BaseModel): """报告基础模式""" title: str report_type: Optional[str] = None report_year: Optional[int] = None report_period: Optional[str] = None class ReportResponse(ReportBase): """报告响应""" id: int company_id: int company_name: Optional[str] = None stock_code: Optional[str] = None announcement_id: Optional[str] = None announcement_time: Optional[datetime] = None pdf_url: Optional[str] = None is_downloaded: bool is_extracted: bool is_analyzed: bool analysis_status: str created_at: datetime class Config: from_attributes = True class ReportDetail(ReportResponse): """报告详情(包含提取内容和分析结果)""" extracted_contents: List["ExtractedContentResponse"] = [] analysis_results: List["AnalysisResultResponse"] = [] # ============ 提取内容相关 ============ class ExtractedContentResponse(BaseModel): """提取内容响应""" id: int report_id: int section_name: Optional[str] = None section_keyword: Optional[str] = None content: Optional[str] = None page_start: Optional[int] = None page_end: Optional[int] = None char_count: Optional[int] = None created_at: datetime class Config: from_attributes = True # ============ 分析结果相关 ============ class AnalysisResultResponse(BaseModel): """分析结果响应""" id: int report_id: int analysis_type: Optional[str] = None section_name: Optional[str] = None ai_model: Optional[str] = None summary: Optional[str] = None key_points: Optional[str] = None is_final: bool token_count: Optional[int] = None created_at: datetime class Config: from_attributes = True class AnalysisRequest(BaseModel): """分析请求""" report_id: int = Field(..., description="报告ID") force: bool = Field(False, description="是否强制重新分析") # ============ 任务日志相关 ============ class TaskLogResponse(BaseModel): """任务日志响应""" id: int task_type: Optional[str] = None task_name: Optional[str] = None status: Optional[str] = None message: Optional[str] = None error: Optional[str] = None started_at: datetime completed_at: Optional[datetime] = None class Config: from_attributes = True # ============ 定时任务相关 ============ class SchedulerStatus(BaseModel): """定时任务状态""" is_running: bool next_run_time: Optional[datetime] = None interval_hours: int last_run_time: Optional[datetime] = None last_run_status: Optional[str] = None class SchedulerConfig(BaseModel): """定时任务配置""" enabled: bool = Field(..., description="是否启用") interval_hours: int = Field(24, description="检查间隔(小时)", ge=1, le=168) # ============ 通用响应 ============ class MessageResponse(BaseModel): """消息响应""" success: bool message: str data: Optional[dict] = None class PaginatedResponse(BaseModel): """分页响应""" total: int page: int page_size: int items: List # 更新前向引用 ReportDetail.model_rebuild()