# 资料包导入Skill 设计

## 1. Skill 定位

`资料包导入Skill` 是资料包导入工作流的总入口 Skill，负责把用户上传的文件集合转化为一个可处理的资料包批次，并协调解包、扫描、文档登记、页数统计、章节点识别和目录汇总。

它不直接处理法规完整性，不调用 LLM，不执行 RAG 入库。

英文实现标识建议使用 `SubmissionPackageImportSkill`，用于 Python 类名和 Tool Registry 注册处理器。

## 2. 触发场景

1. 用户在 Web 工作台上传单文件。
2. 用户批量上传多个文件。
3. 用户上传压缩包。
4. 飞书入口后续触发资料包导入任务。
5. 管理员导入平台内置法规资料。

## 3. 输入

```python
@dataclass
class SubmissionPackageImportInput:
    files: list[UploadedFileRef]
    batch_name: str
    workflow_type: str = "registration"
    source_role: str = "submission"
    created_by_id: int | None = None
    import_options: dict = field(default_factory=dict)
```

字段说明：

| 字段 | 说明 |
|---|---|
| `files` | 用户上传文件引用 |
| `batch_name` | 资料包批次名称 |
| `workflow_type` | 注册流程类型，V1 默认 `registration` |
| `source_role` | `submission` 或 `regulation` |
| `created_by_id` | 操作人 |
| `import_options` | 是否立即页数统计、是否跳过不支持文件等选项 |

## 4. 输出

```python
@dataclass
class SubmissionPackageImportOutput:
    batch_id: int
    batch_no: str
    status: str
    overview_report: dict
    warnings: list[dict]
    failed_items: list[dict]
```

## 5. 依赖 Skill

1. `压缩包解包Skill`
2. `资料包扫描Skill`
3. `文档页数统计Skill`
4. `章节点识别Skill`
5. `目录汇总Skill`

## 6. 核心方法

### 6.1 `run(input) -> SubmissionPackageImportOutput`

主入口方法。

执行顺序：

1. 创建 `SubmissionBatch`。
2. 保存上传文件到批次隔离目录。
3. 对压缩包调用 `压缩包解包Skill`。
4. 调用 `资料包扫描Skill` 扫描批次目录。
5. 创建 `RegistrationDocument` 记录。
6. 调用 `文档页数统计Skill`。
7. 调用 `章节点识别Skill`。
8. 调用 `目录汇总Skill`。
9. 更新批次状态。
10. 返回目录汇总结果。

### 6.2 `create_batch(input) -> SubmissionBatch`

创建资料包批次。

状态：

1. 初始为 `created`。
2. 文件保存开始后更新为 `importing`。
3. 汇总阶段更新为 `summarizing`。
4. 成功后更新为 `completed` 或 `partial_completed`。

### 6.3 `save_uploaded_files(batch, files) -> list[StoredUpload]`

保存原始上传文件，并记录上传文件来源。

安全要求：

1. 过滤路径穿越。
2. 原始文件名只用于展示。
3. 真实存储路径使用批次目录和安全文件名。

### 6.4 `create_document_records(batch, scanned_files) -> list[RegistrationDocument]`

把扫描结果落库为文档主数据。

落库字段：

1. `original_filename`
2. `relative_path`
3. `file_type`
4. `file_size`
5. `file_hash`
6. `source_archive_name`
7. `source_role`
8. `workflow_type`
9. `processing_status`

### 6.5 `finalize_batch_status(batch, overview_report) -> str`

根据结果决定批次状态。

规则：

1. 全部成功：`completed`
2. 存在待人工复核：`partial_completed`
3. 存在不支持文件但有有效文件：`partial_completed`
4. 无有效文件：`failed`

## 7. 技术实现

使用技术：

1. Django ORM
2. Django Storage
3. `pathlib`
4. `dataclasses` 或 Pydantic
5. Tool Registry

建议注册名：

```python
tool_registry.register(
    name="submission_package_import",
    handler=SubmissionPackageImportSkill().run,
)
```

## 8. 异常处理

| 异常 | 处理 |
|---|---|
| 上传文件为空 | 拒绝该文件，记录失败项 |
| 批次目录创建失败 | 整体失败 |
| 解包失败 | 批次部分失败或整体失败 |
| 无支持文件 | 批次失败 |
| 页数统计部分失败 | 批次部分完成 |
| 章节点识别失败 | 文档标记待人工确认 |

## 9. 测试要点

1. 单文件导入成功。
2. 多文件导入共用同一批次。
3. 压缩包导入保留相对路径。
4. 不支持文件不会阻断有效文件。
5. 部分失败时批次为 `partial_completed`。
6. 输出包含 `overview_report`。
