Преглед изворни кода

chore(sql): 新增 template_tables.sql 模板系统表

新增文件:
- template_tables.sql: 模板系统 v2.0 表结构
  - templates: 报告模板
  - source_files: 来源文件定义
  - variables: 模板变量
  - generations: 生成任务

更新:
- supplement_tables.sql: 移除旧版 templates 表定义
- rebuild_all.sh: 添加 template_tables.sql 到执行顺序(步骤6)
何文松 пре 1 месец
родитељ
комит
e929fc39c0
3 измењених фајлова са 226 додато и 41 уклоњено
  1. 22 18
      backend/sql/rebuild_all.sh
  2. 4 23
      backend/sql/supplement_tables.sql
  3. 200 0
      backend/sql/template_tables.sql

+ 22 - 18
backend/sql/rebuild_all.sh

@@ -151,27 +151,32 @@ init_all_tables() {
     local step=1
     
     # 1. 基础表(users, documents 等核心表)
-    log_step "[$step/5] 基础表"
+    log_step "[$step/6] 基础表"
     execute_sql "${SQL_DIR}/init.sql" "基础表 (users, documents, elements, etc.)"
     step=$((step + 1))
     
     # 2. 图谱表(graph_nodes, graph_relations - 先于 supplement_tables)
-    log_step "[$step/5] 图谱表"
+    log_step "[$step/6] 图谱表"
     execute_sql "${SQL_DIR}/graph_tables.sql" "图谱表 (graph_nodes, graph_relations)"
     step=$((step + 1))
     
-    # 3. 补充表(rules, data_sources, templates, text_storage 等)
-    log_step "[$step/5] 补充表"
-    execute_sql "${SQL_DIR}/supplement_tables.sql" "补充表 (rules, data_sources, templates, text_storage)"
+    # 3. 补充表(rules, data_sources, text_storage 等,不含 templates
+    log_step "[$step/6] 补充表"
+    execute_sql "${SQL_DIR}/supplement_tables.sql" "补充表 (rules, data_sources, text_storage)"
     step=$((step + 1))
     
     # 4. RAG 表(text_chunks, vector_embeddings - 可能需要 pgvector)
-    log_step "[$step/5] RAG 表"
+    log_step "[$step/6] RAG 表"
     execute_sql "${SQL_DIR}/rag_tables_compatible.sql" "RAG 表 (text_chunks, vector_embeddings)"
     step=$((step + 1))
     
-    # 5. 执行迁移文件(按文件名排序)
-    log_step "[$step/5] 迁移脚本"
+    # 5. 模板系统表(templates, source_files, variables, generations)
+    log_step "[$step/6] 模板系统表"
+    execute_sql "${SQL_DIR}/template_tables.sql" "模板系统表 (templates, source_files, variables, generations)"
+    step=$((step + 1))
+    
+    # 6. 执行迁移文件(按文件名排序)
+    log_step "[$step/6] 迁移脚本"
     log_title "执行迁移脚本"
     if [ -d "$MIGRATIONS_DIR" ]; then
         local migration_count=0
@@ -290,17 +295,16 @@ show_help() {
     1. 删除所有表、序列、函数
     2. 执行 init.sql(用户、文档、元素等基础表)
     3. 执行 graph_tables.sql(图谱表)
-    4. 执行 supplement_tables.sql(补充表)
+    4. 执行 supplement_tables.sql(补充表,不含 templates
     5. 执行 rag_tables_compatible.sql(RAG表)
-    6. 执行 database/migrations/*.sql(迁移脚本,按名称排序)
-       - V2026_01_21__add_document_blocks_and_entities.sql
-       - V2026_01_21_02__add_document_elements.sql
-       - V2026_01_21_03__enhance_data_sources.sql
-       - V2026_01_22_01__enhance_parse_tasks_stages.sql
-       - V2026_01_22_02__create_extract_tables.sql (旧版 extract 表)
-       - V2026_01_23_01__refactor_extract_to_template.sql (新版 template 表)
-    7. 创建测试用户
-    8. 验证表创建
+    6. 执行 template_tables.sql(模板系统表 v2.0)
+       - templates: 报告模板
+       - source_files: 来源文件定义
+       - variables: 模板变量
+       - generations: 生成任务
+    7. 执行 database/migrations/*.sql(迁移脚本,按名称排序)
+    8. 创建测试用户
+    9. 验证表创建
 
 EOF
 }

+ 4 - 23
backend/sql/supplement_tables.sql

@@ -61,26 +61,9 @@ CREATE INDEX IF NOT EXISTS idx_data_sources_type ON data_sources(type);
 -- ============================================
 -- 5. 模板表(templates)
 -- ============================================
-CREATE TABLE IF NOT EXISTS templates (
-    id VARCHAR(36) PRIMARY KEY,
-    user_id VARCHAR(36) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
-    name VARCHAR(255) NOT NULL,
-    content TEXT NOT NULL, -- 模板内容(带占位符)
-    placeholder_mapping JSONB DEFAULT '{}', -- 占位符到数据源的映射
-    source_template_id VARCHAR(36) REFERENCES templates(id) ON DELETE SET NULL, -- 复制来源
-    status VARCHAR(20) DEFAULT 'active', -- active/inactive
-    metadata JSONB DEFAULT '{}',
-    create_by VARCHAR(36),
-    create_by_name VARCHAR(100),
-    create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
-    update_by VARCHAR(36),
-    update_by_name VARCHAR(100),
-    update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
-);
-
-CREATE INDEX IF NOT EXISTS idx_templates_user_id ON templates(user_id);
-CREATE INDEX IF NOT EXISTS idx_templates_source_template ON templates(source_template_id);
-CREATE INDEX IF NOT EXISTS idx_templates_status ON templates(status);
+-- 注意: templates 表已迁移至 template_tables.sql(v2.0 版本)
+-- 新版包含: templates, source_files, variables, generations
+-- 请勿在此重复定义
 
 -- ============================================
 -- 6. 文本存储路径表(text_storage)
@@ -121,9 +104,7 @@ DROP TRIGGER IF EXISTS update_data_sources_update_time ON data_sources;
 CREATE TRIGGER update_data_sources_update_time BEFORE UPDATE ON data_sources
     FOR EACH ROW EXECUTE FUNCTION update_update_time_column();
 
-DROP TRIGGER IF EXISTS update_templates_update_time ON templates;
-CREATE TRIGGER update_templates_update_time BEFORE UPDATE ON templates
-    FOR EACH ROW EXECUTE FUNCTION update_update_time_column();
+-- templates 触发器已迁移至 template_tables.sql
 
 DROP TRIGGER IF EXISTS update_text_storage_update_time ON text_storage;
 CREATE TRIGGER update_text_storage_update_time BEFORE UPDATE ON text_storage

+ 200 - 0
backend/sql/template_tables.sql

@@ -0,0 +1,200 @@
+-- =====================================================
+-- 报告模板系统表结构 v2.0
+-- 「示例文档驱动」的模板生成系统
+-- PostgreSQL 15+
+-- 
+-- 表列表:
+--   1. templates - 报告模板
+--   2. source_files - 来源文件定义
+--   3. variables - 模板变量
+--   4. generations - 生成任务
+-- 
+-- 创建时间: 2026-01-23
+-- =====================================================
+
+-- ============================================
+-- 1. 报告模板表(templates)
+-- ============================================
+-- 注意: 如果 supplement_tables.sql 中已定义旧版 templates 表,
+-- 需要先删除或重命名
+DROP TABLE IF EXISTS templates CASCADE;
+
+CREATE TABLE templates (
+    id VARCHAR(36) PRIMARY KEY,
+    user_id VARCHAR(36) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
+    name VARCHAR(255) NOT NULL,
+    description TEXT,
+    base_document_id VARCHAR(36) NOT NULL REFERENCES documents(id) ON DELETE RESTRICT,
+    status VARCHAR(32) DEFAULT 'draft',
+    config JSONB DEFAULT '{}',
+    is_public BOOLEAN DEFAULT FALSE,
+    use_count INT DEFAULT 0,
+    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    create_by VARCHAR(36),
+    create_by_name VARCHAR(100),
+    update_by VARCHAR(36),
+    update_by_name VARCHAR(100)
+);
+
+CREATE INDEX idx_templates_user_id ON templates(user_id);
+CREATE INDEX idx_templates_status ON templates(status);
+CREATE INDEX idx_templates_is_public ON templates(is_public);
+CREATE INDEX idx_templates_base_document ON templates(base_document_id);
+
+COMMENT ON TABLE templates IS '报告模板';
+COMMENT ON COLUMN templates.base_document_id IS '示例报告文档ID,关联 documents 表';
+COMMENT ON COLUMN templates.status IS 'draft-草稿, published-已发布, archived-已归档';
+COMMENT ON COLUMN templates.config IS '模板配置,如默认AI模型等';
+COMMENT ON COLUMN templates.is_public IS '是否公开给其他用户使用';
+COMMENT ON COLUMN templates.use_count IS '被使用生成报告的次数';
+
+-- ============================================
+-- 2. 来源文件定义表(source_files)
+-- ============================================
+CREATE TABLE IF NOT EXISTS source_files (
+    id VARCHAR(36) PRIMARY KEY,
+    template_id VARCHAR(36) NOT NULL REFERENCES templates(id) ON DELETE CASCADE,
+    alias VARCHAR(100) NOT NULL,
+    description TEXT,
+    file_types JSONB DEFAULT '["pdf", "docx"]',
+    required BOOLEAN DEFAULT TRUE,
+    example_document_id VARCHAR(36) REFERENCES documents(id) ON DELETE SET NULL,
+    display_order INT DEFAULT 0,
+    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    
+    CONSTRAINT uk_source_files_alias UNIQUE (template_id, alias)
+);
+
+CREATE INDEX idx_source_files_template ON source_files(template_id);
+
+COMMENT ON TABLE source_files IS '来源文件定义';
+COMMENT ON COLUMN source_files.alias IS '用户自定义的别名,用于引用,如"可研批复"';
+COMMENT ON COLUMN source_files.file_types IS '允许上传的文件类型列表';
+COMMENT ON COLUMN source_files.required IS '是否为必须提供的文件';
+COMMENT ON COLUMN source_files.example_document_id IS '创建模板时使用的示例文件,用于预览';
+
+-- ============================================
+-- 3. 模板变量表(variables)
+-- ============================================
+CREATE TABLE IF NOT EXISTS variables (
+    id VARCHAR(36) PRIMARY KEY,
+    template_id VARCHAR(36) NOT NULL REFERENCES templates(id) ON DELETE CASCADE,
+    
+    -- 变量标识
+    name VARCHAR(100) NOT NULL,
+    display_name VARCHAR(200) NOT NULL,
+    variable_group VARCHAR(100),
+    
+    -- 在示例报告中的位置
+    location JSONB NOT NULL,
+    
+    -- 示例值
+    example_value TEXT,
+    value_type VARCHAR(32) DEFAULT 'text',
+    
+    -- 数据来源
+    source_file_alias VARCHAR(100),
+    source_type VARCHAR(32) NOT NULL,
+    source_config JSONB,
+    
+    -- 提取方式
+    extract_type VARCHAR(32),
+    extract_config JSONB,
+    
+    display_order INT DEFAULT 0,
+    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    
+    CONSTRAINT uk_variables_name UNIQUE (template_id, name)
+);
+
+CREATE INDEX idx_variables_template ON variables(template_id);
+CREATE INDEX idx_variables_source_alias ON variables(source_file_alias);
+CREATE INDEX idx_variables_source_type ON variables(source_type);
+
+COMMENT ON TABLE variables IS '模板变量';
+COMMENT ON COLUMN variables.name IS '变量名,模板内唯一,用于程序引用';
+COMMENT ON COLUMN variables.display_name IS '显示名称,用于用户界面';
+COMMENT ON COLUMN variables.location IS '变量在文档中的位置,包含 element_id、偏移量等';
+COMMENT ON COLUMN variables.value_type IS 'text-文本, date-日期, number-数字, table-表格';
+COMMENT ON COLUMN variables.source_type IS 'document-从来源文件提取, manual-手动输入, reference-引用其他变量, fixed-固定值';
+COMMENT ON COLUMN variables.extract_type IS 'direct-直接提取, ai_extract-AI字段提取, ai_summarize-AI总结';
+
+-- ============================================
+-- 4. 生成任务表(generations)
+-- ============================================
+CREATE TABLE IF NOT EXISTS generations (
+    id VARCHAR(36) PRIMARY KEY,
+    template_id VARCHAR(36) NOT NULL REFERENCES templates(id) ON DELETE RESTRICT,
+    user_id VARCHAR(36) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
+    
+    name VARCHAR(255),
+    
+    -- 来源文件映射:别名 → 文档ID
+    source_file_map JSONB NOT NULL,
+    
+    -- 变量提取结果
+    variable_values JSONB,
+    
+    -- 生成的文档
+    output_document_id VARCHAR(36) REFERENCES documents(id) ON DELETE SET NULL,
+    output_file_path VARCHAR(500),
+    
+    status VARCHAR(32) DEFAULT 'pending',
+    error_message TEXT,
+    progress INT DEFAULT 0,
+    
+    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    completed_at TIMESTAMP
+);
+
+CREATE INDEX idx_generations_template ON generations(template_id);
+CREATE INDEX idx_generations_user ON generations(user_id);
+CREATE INDEX idx_generations_status ON generations(status);
+CREATE INDEX idx_generations_create_time ON generations(create_time DESC);
+
+COMMENT ON TABLE generations IS '报告生成任务';
+COMMENT ON COLUMN generations.source_file_map IS '来源文件映射,如 {"可研批复": "doc_123"}';
+COMMENT ON COLUMN generations.variable_values IS '变量提取结果,包含值、置信度、状态等';
+COMMENT ON COLUMN generations.status IS 'pending-待执行, extracting-提取中, review-待确认, completed-已完成, error-错误';
+COMMENT ON COLUMN generations.progress IS '进度百分比 0-100';
+
+-- ============================================
+-- 5. 更新时间触发器
+-- ============================================
+-- 确保 update_update_time_column 函数存在(在 init.sql 中定义)
+-- 如果不存在,创建一个
+CREATE OR REPLACE FUNCTION update_update_time_column()
+RETURNS TRIGGER AS $$
+BEGIN
+    NEW.update_time = CURRENT_TIMESTAMP;
+    RETURN NEW;
+END;
+$$ LANGUAGE plpgsql;
+
+DROP TRIGGER IF EXISTS trigger_templates_update_time ON templates;
+CREATE TRIGGER trigger_templates_update_time
+    BEFORE UPDATE ON templates
+    FOR EACH ROW
+    EXECUTE FUNCTION update_update_time_column();
+
+DROP TRIGGER IF EXISTS trigger_variables_update_time ON variables;
+CREATE TRIGGER trigger_variables_update_time
+    BEFORE UPDATE ON variables
+    FOR EACH ROW
+    EXECUTE FUNCTION update_update_time_column();
+
+-- ============================================
+-- 6. 旧版 extract 表(v1.x 兼容)
+-- ============================================
+-- 以下表将在未来版本中删除,仅保留兼容性
+-- extract_projects, extract_source_documents, extract_rules, 
+-- extract_results, extract_rule_templates
+
+-- 如需要删除旧表,取消以下注释:
+-- DROP TABLE IF EXISTS extract_rule_templates CASCADE;
+-- DROP TABLE IF EXISTS extract_results CASCADE;
+-- DROP TABLE IF EXISTS extract_rules CASCADE;
+-- DROP TABLE IF EXISTS extract_source_documents CASCADE;
+-- DROP TABLE IF EXISTS extract_projects CASCADE;