把“章节正文 + 图片”从 chapters 单表/JSON 结构,重构为“章节 chapter + 段落 section + 图片 memoir_images 独立表”的新数据模型,同时联动修改接口、PDF 导出、异步任务、迁移脚本、测试,以及修复 Android 端聊天列表显示问题。 (#9)

* refactor: 表结构重构,新增段落section和图片image新表

* fix: fix android app import error

* refactor: 重构文件名

* fix: 优化提示词

* fix: 消息气泡显示位置异常问题

---------

Co-authored-by: yangshilin <2157598560@qq.com>
This commit is contained in:
Sully
2026-03-13 11:12:10 +08:00
committed by GitHub
parent 1cb804fa37
commit 2eb066dbec
19 changed files with 1280 additions and 624 deletions

View File

@@ -81,16 +81,15 @@ class Segment(Base):
class Chapter(Base):
"""章节表"""
"""章节表(正文与插图存于 chapter_sections"""
__tablename__ = "chapters"
id = Column(String, primary_key=True)
user_id = Column(String, ForeignKey("users.id"), nullable=False)
title = Column(String, nullable=False)
content = Column(Text, nullable=False)
order_index = Column(Integer, nullable=False)
status = Column(String, default="draft") # draft, completed
images = Column(JSON, nullable=True) # 图片元数据对象列表
cover_image = Column(JSON, nullable=True) # 章节封面图(单条图片元数据
updated_at = Column(DateTime(timezone=True), default=utc_now, onupdate=utc_now)
category = Column(String, nullable=True) # 章节分类
is_new = Column(Boolean, default=True) # 是否为新内容(未读)
@@ -99,6 +98,72 @@ class Chapter(Base):
# Relationships
user = relationship("User", back_populates="chapters")
sections = relationship(
"ChapterSection",
back_populates="chapter",
order_by="ChapterSection.order_index",
cascade="all, delete-orphan",
)
images = relationship(
"MemoirImage",
back_populates="chapter",
foreign_keys="MemoirImage.chapter_id",
cascade="all, delete-orphan",
)
class ChapterSection(Base):
"""章节段落表:一章多段,每段一段正文 + 可选一张图"""
__tablename__ = "chapter_sections"
id = Column(String, primary_key=True)
chapter_id = Column(String, ForeignKey("chapters.id", ondelete="CASCADE"), nullable=False)
order_index = Column(Integer, nullable=False)
content = Column(Text, nullable=False) # 本段正文(无占位符)
image_id = Column(String, ForeignKey("memoir_images.id", ondelete="SET NULL"), nullable=True) # 关联 memoir_images.id
updated_at = Column(DateTime(timezone=True), default=utc_now, onupdate=utc_now)
# Relationships
chapter = relationship("Chapter", back_populates="sections")
image_record = relationship(
"MemoirImage",
back_populates="section",
uselist=False,
foreign_keys="ChapterSection.image_id",
cascade="all, delete-orphan",
single_parent=True,
)
class MemoirImage(Base):
"""章节配图与封面字段独立存储section_id 为空表示章节封面,非空表示该 section 的配图"""
__tablename__ = "memoir_images"
id = Column(String, primary_key=True)
chapter_id = Column(String, ForeignKey("chapters.id", ondelete="CASCADE"), nullable=False)
section_id = Column(String, ForeignKey("chapter_sections.id", ondelete="CASCADE"), nullable=True)
order_index = Column(Integer, nullable=False, default=0)
placeholder = Column(Text, nullable=True)
description = Column(Text, nullable=True)
status = Column(String, nullable=False, default="pending")
prompt = Column(Text, nullable=True)
url = Column(Text, nullable=True)
storage_key = Column(Text, nullable=True)
provider = Column(String, nullable=True)
style = Column(String, nullable=True)
size = Column(String, nullable=True)
error = Column(Text, nullable=True)
retryable = Column(Boolean, nullable=True)
created_at = Column(DateTime(timezone=True), nullable=True)
updated_at = Column(DateTime(timezone=True), default=utc_now, onupdate=utc_now)
# Relationships
chapter = relationship("Chapter", back_populates="images")
section = relationship(
"ChapterSection",
back_populates="image_record",
foreign_keys="ChapterSection.image_id",
)
class Book(Base):