AI 小说生成工作台:分层流水线 + 故事圣经(一期完整实现)
- 后端:Node/Express + node:sqlite,人物/世界观/分卷/细纲/正文 8 阶段生成流水线(SSE 流式 + zod 校验 + 重试) - 前端:React 18 + Vite + antd 三栏工作台:流水线引导、章节树、编辑器(快切章节/段落改写)、故事圣经面板 - 写作工艺注入:人物声口/内在冲突/秘密,细纲 POV/情绪曲线/功能/张力,正文专业规则 - 自动回写故事圣经(摘要/设定/人物变化/伏笔/时间线),TXT/EPUB 导出,token 成本日志
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
import { db } from './connection.js'
|
||||
|
||||
export function migrate() {
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS llm_config (
|
||||
id INTEGER PRIMARY KEY CHECK (id = 1),
|
||||
base_url TEXT NOT NULL,
|
||||
api_key TEXT NOT NULL DEFAULT '',
|
||||
model TEXT NOT NULL,
|
||||
temperature REAL NOT NULL DEFAULT 0.8,
|
||||
max_tokens INTEGER NOT NULL DEFAULT 12000,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS projects (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
genre TEXT NOT NULL DEFAULT '',
|
||||
premise TEXT NOT NULL DEFAULT '',
|
||||
style_notes TEXT NOT NULL DEFAULT '',
|
||||
style_sample TEXT NOT NULL DEFAULT '',
|
||||
target_chapter_words INTEGER NOT NULL DEFAULT 3000,
|
||||
target_chapter_count INTEGER NOT NULL DEFAULT 30,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS characters (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
aliases TEXT NOT NULL DEFAULT '',
|
||||
role TEXT NOT NULL DEFAULT '配角',
|
||||
appearance TEXT NOT NULL DEFAULT '',
|
||||
personality TEXT NOT NULL DEFAULT '',
|
||||
background TEXT NOT NULL DEFAULT '',
|
||||
goals TEXT NOT NULL DEFAULT '',
|
||||
arc_notes TEXT NOT NULL DEFAULT '',
|
||||
sort INTEGER NOT NULL DEFAULT 0,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS world_entries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
category TEXT NOT NULL DEFAULT '其他',
|
||||
title TEXT NOT NULL,
|
||||
content TEXT NOT NULL DEFAULT '',
|
||||
sort INTEGER NOT NULL DEFAULT 0,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS volumes (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
title TEXT NOT NULL,
|
||||
summary TEXT NOT NULL DEFAULT '',
|
||||
sort INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS beats (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
volume_id INTEGER REFERENCES volumes(id) ON DELETE SET NULL,
|
||||
sort INTEGER NOT NULL DEFAULT 0,
|
||||
title TEXT NOT NULL,
|
||||
events TEXT NOT NULL DEFAULT '',
|
||||
involved_characters TEXT NOT NULL DEFAULT '[]',
|
||||
foreshadow_plan TEXT NOT NULL DEFAULT ''
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS chapters (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
beat_id INTEGER REFERENCES beats(id) ON DELETE SET NULL,
|
||||
volume_id INTEGER REFERENCES volumes(id) ON DELETE SET NULL,
|
||||
sort INTEGER NOT NULL DEFAULT 0,
|
||||
title TEXT NOT NULL,
|
||||
content TEXT NOT NULL DEFAULT '',
|
||||
status TEXT NOT NULL DEFAULT 'empty',
|
||||
summary TEXT NOT NULL DEFAULT '',
|
||||
word_count INTEGER NOT NULL DEFAULT 0,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS foreshadows (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
description TEXT NOT NULL,
|
||||
planted_chapter_id INTEGER REFERENCES chapters(id) ON DELETE SET NULL,
|
||||
paid_chapter_id INTEGER REFERENCES chapters(id) ON DELETE SET NULL,
|
||||
status TEXT NOT NULL DEFAULT 'planted',
|
||||
notes TEXT NOT NULL DEFAULT '',
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS timeline_events (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
chapter_id INTEGER REFERENCES chapters(id) ON DELETE SET NULL,
|
||||
story_time TEXT NOT NULL DEFAULT '',
|
||||
title TEXT NOT NULL,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
sort INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS generation_logs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE,
|
||||
stage TEXT NOT NULL,
|
||||
model TEXT NOT NULL DEFAULT '',
|
||||
prompt_tokens INTEGER NOT NULL DEFAULT 0,
|
||||
completion_tokens INTEGER NOT NULL DEFAULT 0,
|
||||
ok INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL
|
||||
);
|
||||
`)
|
||||
|
||||
// 增量迁移:为旧库补齐新增列(写作专业字段)
|
||||
const addColumns: [string, string, string][] = [
|
||||
['projects', 'narrative_pov', "ALTER TABLE projects ADD COLUMN narrative_pov TEXT NOT NULL DEFAULT ''"],
|
||||
['projects', 'taboos', "ALTER TABLE projects ADD COLUMN taboos TEXT NOT NULL DEFAULT ''"],
|
||||
['characters', 'speech_pattern', "ALTER TABLE characters ADD COLUMN speech_pattern TEXT NOT NULL DEFAULT ''"],
|
||||
['characters', 'inner_conflict', "ALTER TABLE characters ADD COLUMN inner_conflict TEXT NOT NULL DEFAULT ''"],
|
||||
['characters', 'secret', "ALTER TABLE characters ADD COLUMN secret TEXT NOT NULL DEFAULT ''"],
|
||||
['beats', 'pov', "ALTER TABLE beats ADD COLUMN pov TEXT NOT NULL DEFAULT ''"],
|
||||
['beats', 'emotional_arc', "ALTER TABLE beats ADD COLUMN emotional_arc TEXT NOT NULL DEFAULT ''"],
|
||||
['beats', 'purpose', "ALTER TABLE beats ADD COLUMN purpose TEXT NOT NULL DEFAULT ''"],
|
||||
['beats', 'tension', 'ALTER TABLE beats ADD COLUMN tension INTEGER NOT NULL DEFAULT 0']
|
||||
]
|
||||
for (const [table, col, ddl] of addColumns) {
|
||||
const cols = db.prepare(`PRAGMA table_info(${table})`).all() as unknown as { name: string }[]
|
||||
if (!cols.some((c) => c.name === col)) db.exec(ddl)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user