-- 图片独立表:将原先挤在 chapter.cover_image / chapter_sections.image 的 JSON 拆成独立列 -- 执行顺序: 1) 本文件 2) python -m api.scripts.run_memoir_images_migration -- 执行方式: psql -U -d -f api/migrations/add_memoir_images_table.sql -- ========== 1. 新建 memoir_images 表 ========== CREATE TABLE IF NOT EXISTS memoir_images ( id VARCHAR NOT NULL PRIMARY KEY, chapter_id VARCHAR NOT NULL REFERENCES chapters(id) ON DELETE CASCADE, section_id VARCHAR NULL REFERENCES chapter_sections(id) ON DELETE CASCADE, order_index INTEGER NOT NULL DEFAULT 0, placeholder TEXT, description TEXT, status VARCHAR NOT NULL DEFAULT 'pending', prompt TEXT, url TEXT, storage_key TEXT, provider VARCHAR, style VARCHAR, size VARCHAR, error TEXT, retryable BOOLEAN, created_at TIMESTAMP WITH TIME ZONE, updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); COMMENT ON TABLE memoir_images IS '章节配图与封面:section_id 为空表示章节封面,非空表示该 section 的配图'; COMMENT ON COLUMN memoir_images.order_index IS '章节内唯一:封面=0,段落配图=1,2,3,...(对应 section.order_index+1)'; CREATE INDEX IF NOT EXISTS ix_memoir_images_chapter_id ON memoir_images(chapter_id); CREATE INDEX IF NOT EXISTS ix_memoir_images_section_id ON memoir_images(section_id); CREATE UNIQUE INDEX IF NOT EXISTS ix_memoir_images_chapter_cover ON memoir_images(chapter_id) WHERE section_id IS NULL; CREATE UNIQUE INDEX IF NOT EXISTS ix_memoir_images_section_unique ON memoir_images(section_id) WHERE section_id IS NOT NULL;