重构方案 · 评审稿

图文小说应用

一个以「构建世界」为终极目标的图文小说创作平台。本方案基于 22 项确认决策重写, 不沿用旧版实现方式,只借鉴其功能范围。

版本v0.19 · 评审稿
日期2026-09-18
技术栈Python · 原生 JS · SQLite
部署Ubuntu / Docker(公网)
状态待作者确认
01

定位与技术基线

这不是「写一本小说」的工具,而是「构建一个世界」的底座——起步从一个故事开始, 结构上预留扩展成多本、跨代的宇宙。

技术基线

已确认的技术选择
维度选择理由
技术栈沿用现有:Python + 原生 JS + SQLite最稳,改动集中在你已知的痛点上
部署形态公网 · 单账号随时随地上;只你一人用,不做多账号体系
开发环境Windows 10 开发 → Ubuntu / Docker 部署serv00 仅作备选,不为共享主机妥协架构
数据主存数据库为唯一真相,文件仅作导出产物根除「文件与库不同步」这一整类 bug
重构定位

功能参考源码,实现方式按本次讨论。 源码只用来回答「你以前做过哪些功能」以防遗漏;目录结构、命名、数据模型、 接口、UI 组织全部按本方案重做。旧版问题太多,不作为设计依据。

硬性要求

选择公网部署后,必须上 TLS。公网 + 单账号 + 明文密码是不可接受的组合。 此项不随分期推迟,属第 0 期地基的一部分。

02

22 项决策速览

本方案的全部输入。每一条都来自你的确认,不含我的臆测。

Q1 · 技术栈
沿用还是重写
沿用现有栈;有源码,以整改为主
Q2 · 部署
跑在哪
公网,单账号
Q3 · 数据主存
文件还是库
库为唯一真相 + 完成后单向导出;不做实时双写
Q4 · 阅读页
给谁看
读公开、写需登录;保留「预览 / 正式」双模式
Q5 · 存储四区
怎么隔离
「试验→创作→定稿」流水线;物理目录
Q6 · 模型配置
怎么接上游
连接可扩展;职责全局默认+单本覆盖+记忆上次;失败直接停下
Q7 · 内容规模
写多大
起步 1–2 本、之后会多;目标长篇;一章 3–5 图
Q8 · 角色阶段
会变形的角色
单向状态机 + 时间线;「机械飞升」后不退回
Q9 · 模块去留
砍哪些
创意工作台保留;费用全砍;预设库重点强化
Q10 · 流程
怎么推进
一份总纲、按功能块、一次一块、先定验收标准
Q11 · 流转确认
提升/定稿
两个都手动确认;定稿联动触发备份
Q12 · 备份触发
何时备份
重大改动前
Q13 · 一致性
角色不变形
双锚都要(文字+图片),作者选、跟随上次;角色卡按需生成
Q14 · 备份保留
留几份
只留 1 份;超 2 周转回收站;1 个月永久删
Q15 · 重大改动
什么算重大
内容类 + 功能修改 + 代码大量调整
Q16 · 实测
生图链路
已跑通;找出模型全 failed 真因
Q17 · 旧数据
迁不迁
完全不导入,从零开始
Q18 · 分期
怎么分
见第 06 节完整提案
Q19 · 环境
在哪跑
Win10 开发;Ubuntu/Docker 部署;serv00 备选
Q20 · 旧数据复核
再确认
确认:完全不导入
Q21 · 日志
运行日志
找不到,以源码级诊断为准
Q22 · 重构定位
参考到什么程度
以本次讨论为主体重写
03

信息架构

顶层是「世界」,不是「小说」。角色与场景挂在世界下而非单本下——这样同一个角色 才能在你的多本小说里出场。

World 世界(宇宙)
│
├─ 共享设定 (跨小说通用)
│   ├─ Character 角色 ────┐
│   ├─ Scene 场景     ────┼──→ 可被配图点引用(多对多)
│   └─ 世界观 / 力量体系 / 地理  │
│                              │
│                   两者均带 阶段版本(随时间推进)
│
└─ Novel 小说 (世界中的一个故事)
    └─ Volume 卷
        └─ Chapter 章
            └─ SceneSegment 场景段
                └─ IllustrationPoint 配图点
                    └─ Image 图片 (可多版本,含候选)

Revision 修订 (所有正文变更留痕,可回滚)

起步兼容:初期 1 个世界 + 1 本小说,与单本创作体验无差别; 后续新增小说时自动继承共享设定。

04

存储五区与生命周期

四区是「试验→创作→定稿」的三段生命周期加一个隔离区;第五区是回收站—— 让删除变成可恢复的。

数据根目录/
│
├── sandbox/      测试区  AI 试写、生图试验、导入预览
├── workspace/    工作区  正在写的小说、草稿、未完成配图
├── production/   正式储存 已定稿内容,阅读页「正式」模式读这里
├── backup/       备份区  重大改动前的快照
└── trash/        回收站  可恢复;1 个月后永久删除

流转规则

内容如何在五区之间移动
动作方向确认方式
提升测试区 → 工作区手动点「采纳」
定稿工作区 → 正式储存手动点「定稿」,并自动触发备份
快照任一区 → 备份区重大改动前自动;只留最新 1 份
清理备份区 → 回收站超过 2 周自动转移
删除任意 → 回收站手动删除同样进回收站
永久删除回收站 → 消失满 1 个月未被动过
设计意图

物理目录带来三个好处:备份可直接拷走、正式区与工作区物理隔离(误删不波及)、 测试脏数据进不了正式库。这直接根除旧版「测试小说混进正式列表」的问题。

05

一致性机制

这是本项目区别于其他写作工具的关键。要解决的问题只有一个:同一个人, 在不同章节的图里得长得像同一个人。

角色卡:按需生成的稳定资产

角色卡不是每张图都重新生成。读取剧情时生成一次、存档,之后复用。 当角色进入新形态,再手动(或自动)生成一张新阶段的卡,不满意可以反复重生, 满意才存。

阶段状态:单向推进的状态机

角色「沈墨渊」
├─ 阶段 1「筑基期」    第 1 章起    青年修士,黑发,深色袍
├─ 阶段 2「机械飞升」  第 30 章起   一旦进入,后续全部延续此形态
└─ 阶段 3「……」        第 80 章起

给定「第 N 章」,系统应能唯一确定角色当时的形态——不靠你手选。

双锚:文字与图片都要

两种锚,由你选择,且记住上次选择
锚类型机制特点
文字锚角色卡语义 → 编译器 → 提示词通用,不依赖上游;已实测可行
图片锚角色定妆图 / 三视图 → 参考图输入视觉最准,需上游支持

提示词编译器:隔离格式差异

不同上游的生图提示词格式不同——NovelAI 系用标签式,其他用自然语言,中英文支持 也不一致。所以加一层编译器:角色卡只存语义,不存死提示词, 由编译器按目标模型渲染成对应格式。换模型时角色卡不用改。

【语义层】模型无关、语言无关
  角色:阿芷 / 阶段2 / 桃花眼、眼尾绯红
  场景:荒山洞府 / 火光
        │
        ▼  按目标模型适配
【渲染层】模型专属
  NAI 系  → 标签串 + 英文 + 权重语法
  自然语言 → 中文描述句
  其他     → 各连接自定义模板
06

分期提案与验收标准

每期以功能块为单位推进:做完、测完、记录完,才开下一块。 每期结束都是可用状态——不写完也能用。

第 0 期 地基 搭出骨架,让后续每期都有地方放
功能块内容
0.1 项目骨架目录结构、配置、启动入口、依赖锁定
0.2 存储五区五个物理目录自动创建与读写
0.3 数据模型世界→小说→卷→章→场景段→配图点→图
0.4 鉴权单账号登录、会话、CSRF、限流
0.5 部署脚本Ubuntu / Docker 一键部署 + TLS
0.6 规范与总纲命名/目录/接口/提交/测试规范;进度总纲模板
验收标准
  • 空库能启动,健康检查返回 200
  • 五区目录自动创建,写入读取正常
  • 未登录写操作 401;错误来源 403;连续错密码 429
  • HTTPS 可用
  • Ubuntu 与 Docker 上各跑通一次
第 1 期 写作主线 能真正开始写小说——这是最核心的需求
功能块内容
1.1 卷章树小说/卷/章 增删改、归档、软删除
1.2 正文编辑编辑器 + 自动保存(自动保存 ≠ 正式稿)
1.3 修订历史版本列表、差异对比、回滚
1.4 阅读页图文混排;预览 / 正式 双模式
1.5 四区流转提升与定稿,均手动确认
1.6 备份与回收站快照、超期转移、永久删除
验收标准
  • 新建小说 → 建卷 → 建章 → 写正文 → 保存 → 刷新不丢
  • 改错了能回滚到任一历史版本
  • 预览模式看到草稿,正式模式只看到定稿
  • 定稿前自动打快照
  • 删除的东西进回收站,能恢复
第 2 期 设定与一致性 技术护城河,不能砍
功能块内容
2.0 需求确认11 项决定已定;复查发现 9 处结构缺口已补齐
2.1 补结构v2 迁移:新增 4 表 + 18 列;线上数据一条不丢
2.2 角色卡 / 场景卡五字段 + 别名 + 自定义;默认归属不同(角色世界共享 / 场景本书专用)
2.3 阶段状态系统底 + 覆盖;只用章号;只填变化;重叠提示不拦
2.4 设定库界面建卡 / 改卡 / 阶段时间轴 / 按章预览
2.5 引用索引双向可查:看某章知涉及谁;改设定知影响哪些章
2.6 实体关系角色↔角色 / 角色↔地点;含方向与时期
2.7 设定网界面关系图 + 卡片关系 + 正文提及 + 本章涉及
验收标准(已达成)
  • 给一个角色建两个阶段,系统能按章号自动判定该用哪个
  • 场景也能设阶段(如森林 → 烧毁)
  • 改卡时能列出受影响章节;看某章能显示涉及哪些角色
  • 角色卡可手动建;写到某章遇到没卡的地点可当场建
  • 场景默认本书专用,可手动升格为世界级
  • 补结构后,旧数据一条不丢
第 3 期 配图 把文字变成图 · 执行顺序已确认
执行顺序内容状态
地基v3 迁移(职位库 / 预设分条 / 流水线骨架 / 检测报告)已上线
后端3.1 配图点 | 3.2 定妆图 | 3.3 提示词编译器 | 3.4 生图已上线
① 流水线页三个独立 tab:上游与模型 / 预设 / 职位与编排;范围切换(全局默认 / 本书覆盖)已上线
② 配图面板生图 + 逐张确认(另提供自动确认出全章);候选审核(历史对比 / 采用 / 拒绝 / 回收站)已上线
③ 定妆图界面上传本地图 或 从生成结果指定一张;卡面显示最新、可查历史已上线
④ 参考图引导双锚(文字锚 + 图片锚):任意图自动处理成 1024×1536 黑底 PNG(处理要告知),生图时定妆图当参考图已上线
验收标准
  • 从章节选一段,生成可编辑提示词
  • 同一段用标签式和自然语言模型各生一张,都不报错
  • 生成失败时当场报错,不静默
  • 采用后图出现在阅读页;拒绝的进回收站
  • 参考图能上传并实际生效
  • 角色卡能看到形象图历史;点图能跳到出处章节
第 4 期 AI 辅助与任务 把 AI 用起来,并且可靠
功能块内容
4.1 连接管理可扩展多上游;显式测试与具体失败原因
4.2 职责绑定写作/提示词/生图;全局默认 + 单本覆盖 + 记忆上次
4.3 任务队列持久化;失败落库;可重试;禁止静默回退
4.4 创意工作台对话式创作,保留并打磨
4.5 导入导出Markdown 导入;完整包导出(含正文+配图)
验收标准
  • 新加一个上游连接,能测试、能生图
  • 连接挂了显示具体原因,不是只标 failed
  • 任务失败后状态是 failed 且有错误信息,能重试
  • 导出包解开后有正文 md 和图片文件
  • 对话式创作能产出候选,人工采用后才入正文
第 5 期 收尾 安全、适配、验收
功能块内容
5.1 安全加固TLS、密钥管理、日志脱敏
5.2 平台适配Linux / Docker 验证;serv00 备选适配
5.3 端到端验收双小说完整走查
5.4 文档用户手册、部署文档
验收标准
  • 双小说完整走查通过(新建→写→配图→阅读→导出)
  • 两本小说数据完全不串
  • 导出后能作为新副本导入
07

旧问题 → 新对策

实测旧版时发现的九个根因问题,逐条对应新系统中的处理方式。

R1 数据源分裂阅读页有内容,工作台是空的
对策单一数据模型(库为唯一真相);旧数据完全不导入,不背历史包袱
R2 模型连接全部 failed失败被静默吞掉
对策失败必须落库并显式报错;连接健康检查给出具体原因
R3 职责模型未绑定每本单独配,容易漏
对策全局默认 + 单本可覆盖 + 记忆上次选择
R4 导出不含正文图片「完整项目包」名不副实
对策导出必含正文 md 与图片文件,列为验收项
R5 配图重复绑定多张图挤在同一场景
对策配图点与图多对多但带排序与主次;候选需人工采用
R6 测试数据混入正式列表没有环境隔离
对策存储五区物理隔离,测试数据进不了正式库
R7 按钮热区重叠点「下一章」弹出登录框
对策点击区 ≥ 44px;布局规范写进 UI 原则
R8 场景标题跳号第一章缺「一」
对策场景段由系统统一编号,不依赖人工输入
R9 内容字段语义混淆「当前内容」与「草稿」分离
对策明确区分「自动保存草稿」与「正式修订」两级
08

附录:源码级诊断

对旧版「模型静默失败」的根因定位。此诊断仅用于理解旧问题,新系统按第 07 节对策实现。

现象

提交生图任务后,任务状态一直是「排队中」——不报错、不推进、不提示。 连接健康状态显示为 failed。

根因

worker 主循环捕获了执行器的异常,但只把任务 id 加进一个进程内存集合, 然后静默把状态改回排队——不写错误码、不记日志、不转失败状态。 该集合被用于排除认领,于是在本次进程生命周期内,这个任务永远不会再被处理。

# 简化示意
try:
    self.executor(task, self)
except Exception:
    self._failed_tasks.add(task["id"])   # 仅内存,重启即丢
    self._safe_abandon(task)             # 静默改回 queued

影响面

问题表现
任务永久卡死状态是「排队」,实际不再被认领
失败不可见没有任何错误信息可查
不能重试重试接口只接受失败态任务,而卡住的不算失败
重启后复发内存集合清空 → 重新认领 → 再失败一次

新系统的处理

失败必须落库(错误码 + 可读错误信息 + 状态转失败);失败任务可重试; 禁止静默回退——失败就是失败,不假装回队。这条写进了第 0 期地基与第 4 期任务队列的验收标准。