Files
ai_game/server/app/models/story.py

132 lines
5.1 KiB
Python

"""
故事相关ORM模型
"""
from sqlalchemy import Column, Integer, String, Text, Boolean, TIMESTAMP, ForeignKey, Enum, JSON
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from app.database import Base
import enum
class Story(Base):
"""故事主表"""
__tablename__ = "stories"
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(100), nullable=False)
cover_url = Column(String(255), default="")
description = Column(Text)
author_id = Column(Integer, default=0)
category = Column(String(50), nullable=False)
play_count = Column(Integer, default=0)
like_count = Column(Integer, default=0)
is_featured = Column(Boolean, default=False)
status = Column(Integer, default=1)
created_at = Column(TIMESTAMP, server_default=func.now())
updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now())
nodes = relationship("StoryNode", back_populates="story", cascade="all, delete-orphan")
characters = relationship("StoryCharacter", back_populates="story", cascade="all, delete-orphan")
class StoryCharacter(Base):
"""故事角色表"""
__tablename__ = "story_characters"
id = Column(Integer, primary_key=True, autoincrement=True)
story_id = Column(Integer, ForeignKey("stories.id", ondelete="CASCADE"), nullable=False)
name = Column(String(50), nullable=False)
role_type = Column(String(20), default="supporting") # protagonist/antagonist/supporting
gender = Column(String(10), default="")
age_range = Column(String(20), default="")
appearance = Column(Text) # 外貌描述
personality = Column(Text) # 性格描述
background = Column(Text) # 背景故事
avatar_prompt = Column(Text) # AI绘图提示词
avatar_url = Column(String(500), default="")
created_at = Column(TIMESTAMP, server_default=func.now())
updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now())
story = relationship("Story", back_populates="characters")
class StoryNode(Base):
"""故事节点表"""
__tablename__ = "story_nodes"
id = Column(Integer, primary_key=True, autoincrement=True)
story_id = Column(Integer, ForeignKey("stories.id", ondelete="CASCADE"), nullable=False)
node_key = Column(String(50), nullable=False)
content = Column(Text, nullable=False)
speaker = Column(String(50), default="")
background_image = Column(String(255), default="")
character_image = Column(String(255), default="")
bgm = Column(String(255), default="")
is_ending = Column(Boolean, default=False)
ending_name = Column(String(100), default="")
ending_score = Column(Integer, default=0)
ending_type = Column(String(20), default="")
sort_order = Column(Integer, default=0)
created_at = Column(TIMESTAMP, server_default=func.now())
story = relationship("Story", back_populates="nodes")
choices = relationship("StoryChoice", back_populates="node", cascade="all, delete-orphan")
class StoryChoice(Base):
"""故事选项表"""
__tablename__ = "story_choices"
id = Column(Integer, primary_key=True, autoincrement=True)
node_id = Column(Integer, ForeignKey("story_nodes.id", ondelete="CASCADE"), nullable=False)
story_id = Column(Integer, nullable=False)
text = Column(String(200), nullable=False)
next_node_key = Column(String(50), nullable=False)
sort_order = Column(Integer, default=0)
is_locked = Column(Boolean, default=False)
created_at = Column(TIMESTAMP, server_default=func.now())
node = relationship("StoryNode", back_populates="choices")
class DraftStatus(enum.Enum):
"""草稿状态枚举"""
pending = "pending"
processing = "processing"
completed = "completed"
failed = "failed"
class StoryDraft(Base):
"""AI改写草稿表"""
__tablename__ = "story_drafts"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
story_id = Column(Integer, ForeignKey("stories.id", ondelete="CASCADE"), nullable=False)
title = Column(String(100), default="")
# 用户输入
path_history = Column(JSON, default=None) # 用户之前的选择路径
current_node_key = Column(String(50), default="")
current_content = Column(Text, default="")
user_prompt = Column(String(500), nullable=False)
# AI生成结果
ai_nodes = Column(JSON, default=None) # AI生成的新节点
entry_node_key = Column(String(50), default="")
tokens_used = Column(Integer, default=0)
# 状态
status = Column(Enum(DraftStatus), default=DraftStatus.pending)
error_message = Column(String(500), default="")
is_read = Column(Boolean, default=False) # 用户是否已查看
published_to_center = Column(Boolean, default=False) # 是否发布到创作中心
draft_type = Column(String(20), default="rewrite") # 草稿类型: rewrite/continue/create
created_at = Column(TIMESTAMP, server_default=func.now())
completed_at = Column(TIMESTAMP, default=None)
# 关联
story = relationship("Story")