from datetime import datetime, timezone from typing import Optional from sqlmodel import SQLModel, Field def _now_utc() -> datetime: return datetime.now(timezone.utc) class Novel(SQLModel, table=True): """小说主表""" id: Optional[int] = Field(default=None, primary_key=True) title: str = Field(max_length=200, index=True) description: str = Field(default="", max_length=2000) created_at: datetime = Field(default_factory=_now_utc) updated_at: datetime = Field(default_factory=_now_utc) class AIConfig(SQLModel, table=True): """AI服务配置(单行表)""" id: Optional[int] = Field(default=None, primary_key=True) provider: str = Field(default="openai") # "openai" | "anthropic" base_url: str = Field(default="https://api.openai.com/v1") api_key: str = Field(default="") model: str = Field(default="gpt-4o") updated_at: datetime = Field(default_factory=_now_utc) class ChatMessage(SQLModel, table=True): """聊天消息""" id: Optional[int] = Field(default=None, primary_key=True) novel_id: Optional[int] = Field(default=None, foreign_key="novel.id", index=True) role: str = Field(max_length=20) # "user" | "assistant" content: str = Field(default="") created_at: datetime = Field(default_factory=_now_utc) class Outline(SQLModel, table=True): """大纲表,属于小说的子资源""" id: Optional[int] = Field(default=None, primary_key=True) novel_id: int = Field(foreign_key="novel.id", index=True) sort_order: int = Field(default=0) summary: str = Field(max_length=200) detail: str = Field(default="", max_length=1000) created_at: datetime = Field(default_factory=_now_utc) updated_at: datetime = Field(default_factory=_now_utc)