# 数据提取规则系统设计文档

> 版本: 2.0.0
> 日期: 2026-01-23
> 作者: AI Assistant (Claude Opus 4.5)

## 一、概述

### 1.1 背景

在电力工程预评价报告生成场景中，用户需要从多个来源文档（PDF、Word、Excel）中提取特定数据，生成标准化的报告。

**核心痛点**：
- 不同工程项目的报告结构相似，但数据不同
- 人工从多个文档中复制粘贴数据，效率低、易出错
- 相同类型的报告需要重复劳动

**解决方案**：
用户上传一份**已完成的真实报告**作为示例，在报告中标记**变量**（如工程名称、批复日期等），并配置每个变量的**数据来源**。之后遇到同类项目，只需替换来源文件，系统自动提取数据生成新报告。

### 1.2 核心概念

| 概念 | 说明 |
| ---- | ---- |
| **模板（Template）** | 基于真实报告创建，包含变量定义和来源文件配置 |
| **来源文件定义（SourceFile）** | 模板需要的来源文件类型，用别名标识（如"可研批复"） |
| **变量（Variable）** | 报告中需要动态替换的内容，绑定到文档中的具体位置 |
| **生成任务（Generation）** | 使用模板生成新报告的一次任务 |

### 1.3 设计原则

1. **示例驱动**：基于真实报告创建模板，所见即所得
2. **数据溯源**：每个提取值都能追溯到来源文档的具体位置
3. **灵活来源**：来源文件数量和类型由用户自定义
4. **一次配置，多次复用**：模板创建后可用于生成任意多份新报告

---

## 二、用户使用流程

### 2.1 流程概览

```
┌─────────────────────────────────────────────────────────────────┐
│                     第一次：创建模板                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  1. 上传示例报告（一份真实的、完整的报告）                        │
│     "襄阳连云110kV预评价报告.docx"                               │
│                                                                  │
│  2. 添加来源文件（自定义数量和别名）                              │
│     ├── 可研批复.pdf      别名："可研批复"                       │
│     ├── 站址报告.docx     别名："站址报告"                       │
│     └── 概算表.xlsx       别名："概算表"                         │
│                                                                  │
│  3. 在示例报告中标记变量                                         │
│     选中文本 "襄阳连云 110kV 输变电工程"                         │
│         → 设为变量 "project_name"                                │
│         → 来源：从【可研批复】第1页 AI提取                       │
│                                                                  │
│  4. 保存模板                                                     │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│                    第二次起：使用模板生成新报告                   │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  1. 选择模板                                                     │
│                                                                  │
│  2. 上传新项目的来源文件（按别名对应）                            │
│     ├── 武汉东湖批复.pdf    → "可研批复"                         │
│     ├── 武汉站址报告.docx   → "站址报告"                         │
│     └── 武汉概算.xlsx       → "概算表"                           │
│                                                                  │
│  3. 点击【生成】                                                 │
│     系统自动：                                                   │
│     - 从新文件提取数据                                           │
│     - 替换模板中的变量                                           │
│     - 生成新报告                                                 │
│                                                                  │
│  4. 预览、确认、下载                                             │
│     "武汉东湖110kV预评价报告.docx"                               │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
```

### 2.2 变量标记交互

用户在文档编辑器中操作：

```
┌─────────────────────────────────────────────────────────────────┐
│  📄 示例报告编辑器                                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  一、项目概述                                                    │
│                                                                  │
│  1.1 工程名称：襄阳连云 110kV 输变电工程                         │
│                ═══════════════════════════ ← 用户选中这段文字    │
│                         │                                        │
│                         ▼ 右键菜单                               │
│      ┌────────────────────────────────────┐                     │
│      │ 📌 设为变量                         │                     │
│      │                                    │                     │
│      │ 变量名：project_name               │                     │
│      │ 显示名：工程名称                   │                     │
│      │                                    │                     │
│      │ 当前值：襄阳连云 110kV 输变电工程   │                     │
│      │                                    │                     │
│      │ 数据来源：                         │                     │
│      │ ● 从来源文件提取                   │                     │
│      │   ├─ 来源文件：[可研批复 ▼]        │                     │
│      │   ├─ 定位方式：[按页码 ▼]          │                     │
│      │   ├─ 页码范围：1-2                 │                     │
│      │   └─ 提取方式：[AI提取 ▼]          │                     │
│      │      └─ 提取目标：工程项目名称     │                     │
│      │                                    │                     │
│      │ ○ 手动输入                         │                     │
│      │ ○ 引用其他变量                     │                     │
│      │ ○ 固定值（不变）                   │                     │
│      │                                    │                     │
│      │           [取消]  [确定]           │                     │
│      └────────────────────────────────────┘                     │
│                                                                  │
│  1.2 建设单位：【$construction_unit】← 已标记的变量高亮显示      │
│                                                                  │
│  1.3 批复日期：【$approval_date】                                │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
```

---

## 三、系统架构

### 3.1 整体架构图

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                              前端 (Vue.js / Flutter)                         │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐    │
│  │ 模板管理     │  │ 文档编辑器   │  │ 变量配置     │  │ 报告生成     │    │
│  └──────────────┘  └──────────────┘  └──────────────┘  └──────────────┘    │
└─────────────────────────────────────────────────────────────────────────────┘
                                       │
                                       ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                              API Gateway                                     │
└─────────────────────────────────────────────────────────────────────────────┘
                                       │
          ┌────────────────────────────┼────────────────────────────┐
          ▼                            ▼                            ▼
┌──────────────────────┐  ┌──────────────────────┐  ┌──────────────────────┐
│   template-service   │  │   document-service   │  │     ai-service       │
│   (模板与生成)       │  │   (文档管理)         │  │     (AI提取)         │
│  ┌────────────────┐  │  │  ┌────────────────┐  │  │  ┌────────────────┐  │
│  │ TemplateService│  │  │  │ DocumentService│  │  │  │ DeepSeekClient │  │
│  │ VariableService│  │  │  │ ElementService │  │  │  │ AIExtractService│ │
│  │ GenerationSvc  │  │  │  └────────────────┘  │  │  └────────────────┘  │
│  └────────────────┘  │  └──────────────────────┘  └──────────────────────┘
└──────────────────────┘
          │                            │                            │
          └────────────────────────────┴────────────────────────────┘
                                       │
                                       ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                           PostgreSQL + Redis                                 │
└─────────────────────────────────────────────────────────────────────────────┘
```

### 3.2 模块职责

| 模块 | 职责 | 位置 |
| ---- | ---- | ---- |
| **template-service** | 模板管理、变量配置、报告生成（重构 extract-service） | `backend/extract-service` |
| **document-service** | 文档管理、元素存储（已有） | `backend/document-service` |
| **parse-service** | 文档解析、结构化提取（已有） | `backend/parse-service` |
| **ai-service** | AI 提取、总结（已有） | `backend/ai-service` |

---

## 四、数据库设计

### 4.1 ER 图

```
┌─────────────────┐       ┌─────────────────┐       ┌─────────────────┐
│    templates    │       │  source_files   │       │   variables     │
├─────────────────┤       ├─────────────────┤       ├─────────────────┤
│ id              │◄──────│ template_id     │       │ id              │
│ user_id         │       │ id              │       │ template_id     │──────►│
│ name            │       │ alias           │◄──────│ source_file_alias│      │
│ description     │       │ description     │       │ name            │      │
│ base_document_id│       │ file_types      │       │ display_name    │      │
│ status          │       │ required        │       │ location        │      │
│ config          │       │ example_doc_id  │       │ example_value   │      │
│ created_at      │       │ display_order   │       │ source_type     │      │
│ updated_at      │       └─────────────────┘       │ source_config   │      │
└─────────────────┘                                 │ extract_type    │      │
        │                                           │ extract_config  │      │
        │       ┌─────────────────┐                 │ display_order   │      │
        │       │   generations   │                 └─────────────────┘      │
        │       ├─────────────────┤                                          │
        └──────►│ template_id     │                                          │
                │ id              │◄─────────────────────────────────────────┘
                │ user_id         │       (通过 template_id 关联)
                │ name            │
                │ source_file_map │  ← JSONB: {"可研批复": "doc_123", ...}
                │ variable_values │  ← JSONB: {"project_name": {...}, ...}
                │ output_doc_id   │
                │ status          │
                          │ created_at      │
                │ completed_at    │
                          └─────────────────┘
```

### 4.2 表结构定义

#### 4.2.1 templates（模板表）

```sql
CREATE TABLE templates (
    id VARCHAR(36) PRIMARY KEY,
    user_id VARCHAR(36) NOT NULL,
    name VARCHAR(255) NOT NULL COMMENT '模板名称',
    description TEXT COMMENT '模板描述',
    base_document_id VARCHAR(36) NOT NULL COMMENT '示例报告文档ID',
    status VARCHAR(32) DEFAULT 'draft' COMMENT '状态: draft/published/archived',
    config JSONB COMMENT '模板配置',
    is_public BOOLEAN DEFAULT FALSE COMMENT '是否公开',
    use_count INT DEFAULT 0 COMMENT '使用次数',
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    create_by VARCHAR(36),
    update_by VARCHAR(36)
);

CREATE INDEX idx_templates_user_id ON templates(user_id);
CREATE INDEX idx_templates_status ON templates(status);

COMMENT ON TABLE templates IS '报告模板';
```

#### 4.2.2 source_files（来源文件定义表）

```sql
CREATE TABLE source_files (
    id VARCHAR(36) PRIMARY KEY,
    template_id VARCHAR(36) NOT NULL REFERENCES templates(id) ON DELETE CASCADE,
    alias VARCHAR(100) NOT NULL COMMENT '文件别名，如"可研批复"',
    description TEXT COMMENT '文件说明',
    file_types JSONB COMMENT '允许的文件类型: ["pdf", "docx"]',
    required BOOLEAN DEFAULT TRUE COMMENT '是否必须',
    example_document_id VARCHAR(36) COMMENT '创建模板时使用的示例文件',
    display_order INT DEFAULT 0 COMMENT '显示顺序',
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    UNIQUE (template_id, alias)
);

CREATE INDEX idx_source_files_template ON source_files(template_id);

COMMENT ON TABLE source_files IS '来源文件定义';
```

#### 4.2.3 variables（变量表）

```sql
CREATE TABLE variables (
    id VARCHAR(36) PRIMARY KEY,
    template_id VARCHAR(36) NOT NULL REFERENCES templates(id) ON DELETE CASCADE,
    
    -- 变量标识
    name VARCHAR(100) NOT NULL COMMENT '变量名（程序用）',
    display_name VARCHAR(200) NOT NULL COMMENT '显示名称',
    variable_group VARCHAR(100) COMMENT '变量分组',
    
    -- 在示例报告中的位置
    location JSONB NOT NULL COMMENT '文档中的位置',
    -- location 结构：
    -- {
    --   "element_id": "elem_001",
    --   "type": "text" | "table_cell" | "paragraph",
    --   "start_offset": 10,
    --   "end_offset": 35,
    --   "row_index": 2,        -- 表格行
    --   "col_index": 1         -- 表格列
    -- }
    
    -- 示例值（原文档中的值）
    example_value TEXT COMMENT '示例值',
    value_type VARCHAR(32) DEFAULT 'text' COMMENT '值类型: text/date/number/table',
    
    -- 数据来源
    source_file_alias VARCHAR(100) COMMENT '来源文件别名',
    source_type VARCHAR(32) NOT NULL COMMENT '来源类型: document/manual/reference/fixed',
    source_config JSONB COMMENT '来源配置',
    -- source_config 示例（document类型）：
    -- {
    --   "location": {
    --     "type": "page",
    --     "pageStart": 1,
    --     "pageEnd": 2
    --   }
    -- }
    
    -- 提取方式
    extract_type VARCHAR(32) COMMENT '提取类型: direct/ai_extract/ai_summarize',
    extract_config JSONB COMMENT '提取配置',
    -- extract_config 示例（ai_extract类型）：
    -- {
    --   "targetDescription": "提取工程名称",
    --   "fieldType": "text",
    --   "expectedFormat": "XX市XX工程"
    -- }
    
    display_order INT DEFAULT 0 COMMENT '显示顺序',
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    UNIQUE (template_id, name)
);

CREATE INDEX idx_variables_template ON variables(template_id);

COMMENT ON TABLE variables IS '模板变量';
```

#### 4.2.4 generations（生成任务表）

```sql
CREATE TABLE generations (
    id VARCHAR(36) PRIMARY KEY,
    template_id VARCHAR(36) NOT NULL REFERENCES templates(id),
    user_id VARCHAR(36) NOT NULL,
    
    name VARCHAR(255) COMMENT '任务名称',
    
    -- 来源文件映射：别名 → 文档ID
    source_file_map JSONB NOT NULL COMMENT '来源文件映射',
    -- 示例：{"可研批复": "doc_123", "站址报告": "doc_456"}
    
    -- 变量提取结果
    variable_values JSONB COMMENT '变量值',
    -- 示例：
    -- {
    --   "project_name": {
    --     "value": "武汉东湖 110kV 输变电工程",
    --     "confidence": 0.96,
    --     "source_preview": "...",
    --     "status": "extracted"
    --   }
    -- }
    
    -- 生成的文档
    output_document_id VARCHAR(36) COMMENT '输出文档ID',
    
    status VARCHAR(32) DEFAULT 'pending' COMMENT '状态: pending/extracting/review/completed/error',
    error_message TEXT COMMENT '错误信息',
    
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    completed_at TIMESTAMP COMMENT '完成时间'
);

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

COMMENT ON TABLE generations IS '报告生成任务';
```

---

## 五、变量来源类型

### 5.1 来源类型总览

| 来源类型 | 说明 | 适用场景 |
| -------- | ---- | -------- |
| `document` | 从来源文件提取 | 工程名称、批复日期等需要从文档中获取的信息 |
| `manual` | 手动输入 | 联系人、特殊备注等无法自动获取的信息 |
| `reference` | 引用其他变量 | 组合已提取的值，如"《{project_name}可行性研究报告》" |
| `fixed` | 固定值 | 不随项目变化的固定文本 |

### 5.2 document 类型配置

```json
{
  "source_file_alias": "可研批复",
  "source_type": "document",
  "source_config": {
  "location": {
      "type": "page",           // page | chapter | element
    "pageStart": 1,
    "pageEnd": 2,
      "paragraphKeyword": null  // 可选：段落关键词过滤
    }
  },
  "extract_type": "ai_extract",
  "extract_config": {
    "targetDescription": "从批复文件中提取工程项目的完整名称",
    "fieldType": "text",
    "expectedFormat": "XX市XX工程",
    "examples": ["襄阳连云220千伏输变电工程"]
  }
}
```

### 5.3 manual 类型配置

```json
{
  "source_type": "manual",
  "source_config": {
    "placeholder": "请输入项目联系人姓名",
    "required": true,
    "defaultValue": "",
    "inputType": "text",        // text | textarea | date | number
    "validation": {
      "maxLength": 50,
      "pattern": "^[\\u4e00-\\u9fa5]{2,10}$"
    }
  }
}
```

### 5.4 reference 类型配置

```json
{
  "source_type": "reference",
  "source_config": {
    "referenceVariables": ["project_name", "design_unit", "report_date"],
    "combineTemplate": "《{project_name}可行性研究报告》由{design_unit}于{report_date}编制",
  "transform": {
      "type": "format",
      "formatPattern": "{0}"
    }
  }
}
```

### 5.5 fixed 类型配置

```json
{
  "source_type": "fixed",
  "source_config": {
    "fixedValue": "本报告依据《电力建设工程预算编制办法》（2018版）编制。"
  }
}
```

---

## 六、提取类型

### 6.1 提取类型总览

| 提取类型 | 说明 | 适用场景 |
| -------- | ---- | -------- |
| `direct` | 直接提取 | 定位到的内容直接使用 |
| `ai_extract` | AI字段提取 | 从一段文本中提取特定字段 |
| `ai_summarize` | AI总结 | 对内容进行总结提炼 |

### 6.2 direct 配置

```json
{
  "extract_type": "direct",
  "extract_config": {
    "trimWhitespace": true,
    "removeLineBreaks": false,
    "mergeSpaces": true
  }
}
```

### 6.3 ai_extract 配置

```json
{
  "extract_type": "ai_extract",
  "extract_config": {
    "targetDescription": "从批复文件中提取可研批复的日期",
  "fieldType": "date",
  "expectedFormat": "YYYY年MM月DD日",
  "examples": ["2024年5月15日", "2023年12月1日"]
}
}
```

### 6.4 ai_summarize 配置

```json
{
  "extract_type": "ai_summarize",
  "extract_config": {
  "summarizePrompt": "请对以下内容进行总结，重点描述项目建设的必要性",
  "focusPoints": ["建设背景", "现状问题", "建设目的"],
    "rules": ["使用正式的工程报告语言", "保留关键的数据和指标"],
  "style": "formal",
    "maxLength": 300
  }
}
```

---

## 七、API 设计

### 7.1 模板管理 API

| 方法 | 路径 | 说明 |
| ---- | ---- | ---- |
| POST | `/api/v1/templates` | 创建模板 |
| GET | `/api/v1/templates` | 获取模板列表 |
| GET | `/api/v1/templates/{id}` | 获取模板详情 |
| PUT | `/api/v1/templates/{id}` | 更新模板 |
| DELETE | `/api/v1/templates/{id}` | 删除模板 |
| POST | `/api/v1/templates/{id}/publish` | 发布模板 |
| POST | `/api/v1/templates/{id}/duplicate` | 复制模板 |

### 7.2 来源文件定义 API

| 方法 | 路径 | 说明 |
| ---- | ---- | ---- |
| POST | `/api/v1/templates/{templateId}/source-files` | 添加来源文件定义 |
| GET | `/api/v1/templates/{templateId}/source-files` | 获取来源文件定义列表 |
| PUT | `/api/v1/templates/{templateId}/source-files/{id}` | 更新来源文件定义 |
| DELETE | `/api/v1/templates/{templateId}/source-files/{id}` | 删除来源文件定义 |
| POST | `/api/v1/templates/{templateId}/source-files/reorder` | 调整顺序 |

### 7.3 变量 API

| 方法 | 路径 | 说明 |
| ---- | ---- | ---- |
| POST | `/api/v1/templates/{templateId}/variables` | 创建变量 |
| GET | `/api/v1/templates/{templateId}/variables` | 获取变量列表 |
| GET | `/api/v1/templates/{templateId}/variables/{id}` | 获取变量详情 |
| PUT | `/api/v1/templates/{templateId}/variables/{id}` | 更新变量 |
| DELETE | `/api/v1/templates/{templateId}/variables/{id}` | 删除变量 |
| POST | `/api/v1/templates/{templateId}/variables/{id}/preview` | 预览提取结果 |

### 7.4 生成任务 API

| 方法 | 路径 | 说明 |
| ---- | ---- | ---- |
| POST | `/api/v1/generations` | 创建生成任务 |
| GET | `/api/v1/generations` | 获取生成任务列表 |
| GET | `/api/v1/generations/{id}` | 获取任务详情 |
| POST | `/api/v1/generations/{id}/execute` | 执行提取 |
| GET | `/api/v1/generations/{id}/progress` | 获取执行进度 |
| PUT | `/api/v1/generations/{id}/variables/{varName}` | 修改变量值 |
| POST | `/api/v1/generations/{id}/confirm` | 确认并生成文档 |
| GET | `/api/v1/generations/{id}/download` | 下载生成的文档 |

---

## 八、核心流程

### 8.1 创建模板流程

```
1. 用户上传示例报告
   POST /api/v1/parse/upload
   → 返回 document_id
   
2. 创建模板
   POST /api/v1/templates
   {
     "name": "110kV输变电工程预评价模板",
     "baseDocumentId": "doc_001"
   }
   → 返回 template_id

3. 添加来源文件定义
   POST /api/v1/templates/{templateId}/source-files
   {
     "alias": "可研批复",
     "description": "可研批复文件",
     "fileTypes": ["pdf", "docx"],
     "required": true,
     "exampleDocumentId": "doc_002"
   }

4. 创建变量（前端在编辑器中操作，调用此API）
   POST /api/v1/templates/{templateId}/variables
   {
     "name": "project_name",
     "displayName": "工程名称",
     "location": {
       "elementId": "elem_001",
       "type": "text",
       "startOffset": 10,
       "endOffset": 35
     },
     "exampleValue": "襄阳连云 110kV 输变电工程",
     "sourceFileAlias": "可研批复",
     "sourceType": "document",
     "sourceConfig": { ... },
     "extractType": "ai_extract",
     "extractConfig": { ... }
   }

5. 发布模板
   POST /api/v1/templates/{templateId}/publish
```

### 8.2 生成报告流程

```
1. 创建生成任务
   POST /api/v1/generations
   {
     "templateId": "tpl_001",
     "name": "武汉东湖110kV预评价",
     "sourceFileMap": {
       "可研批复": "doc_123",
       "站址报告": "doc_456"
     }
   }
   → 返回 generation_id

2. 执行提取
   POST /api/v1/generations/{generationId}/execute
   
3. 查询进度
   GET /api/v1/generations/{generationId}/progress
   → { "total": 10, "completed": 6, "currentVariable": "geology_summary" }

4. 查看提取结果，可修改
   GET /api/v1/generations/{generationId}
   PUT /api/v1/generations/{generationId}/variables/project_name
   { "value": "修正后的值" }

5. 确认并生成文档
   POST /api/v1/generations/{generationId}/confirm
   
6. 下载
   GET /api/v1/generations/{generationId}/download
```

---

## 九、与现有系统集成

### 9.1 复用已有服务

| 已有服务 | 复用内容 |
| -------- | -------- |
| document-service | 文档存储、DocumentElement 结构 |
| parse-service | 文档解析、结构化提取 |
| ai-service | DeepSeek API 调用、AI 提取 |
| graph-service | 可选：将变量注册为数据源 |

### 9.2 重构 extract-service

现有 `extract-service` 的代码需要重构：

| 原概念 | 新概念 | 说明 |
| ------ | ------ | ---- |
| Project | Template | 模板取代项目 |
| SourceDocument | SourceFile | 来源文件**定义**，不是具体文件 |
| ExtractRule | Variable | 变量，绑定到文档位置 |
| ExtractResult | Generation.variable_values | 生成任务中的变量值 |
| - | Generation | 新增：生成任务 |

---

## 十、未来扩展

### 10.1 模板市场

- 用户可将模板设为公开
- 其他用户可基于公开模板创建自己的模板
- 模板评分和使用统计

### 10.2 批量生成

- 上传多组来源文件
- 一次生成多份报告
- 生成任务队列管理

### 10.3 版本控制

- 模板版本管理
- 生成任务关联模板版本
- 版本对比和回滚

---

> 文档结束
