85 lines
3.1 KiB
Python
85 lines
3.1 KiB
Python
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)
|
||
parent_id: int | None = Field(default=None, foreign_key="outline.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)
|
||
|
||
|
||
class Character(SQLModel, table=True):
|
||
"""角色表,属于小说的子资源"""
|
||
|
||
id: Optional[int] = Field(default=None, primary_key=True)
|
||
novel_id: int = Field(foreign_key="novel.id", index=True)
|
||
name: str = Field(max_length=100)
|
||
description: str = Field(default="", max_length=1000)
|
||
created_at: datetime = Field(default_factory=_now_utc)
|
||
updated_at: datetime = Field(default_factory=_now_utc)
|
||
|
||
|
||
class Chapter(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)
|
||
title: str = Field(max_length=200)
|
||
content: str = Field(default="", max_length=5000)
|
||
created_at: datetime = Field(default_factory=_now_utc)
|
||
updated_at: datetime = Field(default_factory=_now_utc)
|
||
|
||
|
||
class WorldSetting(SQLModel, table=True):
|
||
"""世界观设定,每部小说一条记录"""
|
||
|
||
id: Optional[int] = Field(default=None, primary_key=True)
|
||
novel_id: int = Field(foreign_key="novel.id", index=True, unique=True)
|
||
content: str = Field(default="", max_length=5000)
|
||
created_at: datetime = Field(default_factory=_now_utc)
|
||
updated_at: datetime = Field(default_factory=_now_utc)
|