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) } }