# 产品关键信息提取与申报文件自动填表数据库设计 ## 文档信息 | 项目 | 内容 | | --- | --- | | 需求分析文档 | docs/1.需求分析/3.产品关键信息提取与申报文件自动填表.md | | 功能设计文档 | docs/2.功能设计/3.产品关键信息提取与申报文件自动填表.md | | 数据库类型 | SQLite / Django ORM | | 表名前缀 | ra_ | | 设计日期 | 2026-06-07 | | 设计版本 | V1.0 | --- ## 一、设计原则 | 原则 | 说明 | | --- | --- | | 独立填表批次 | 自动填表作为独立工作流,使用独立批次表,不强绑法规核查批次 | | 复用文件来源 | 填表批次必须关联一个成功的 `FileSummaryBatch`,不重复保存文件清单 | | 可选复用法规条件 | 如当前对话已有已确认法规核查批次,可通过可空外键复用注册类型等条件 | | 导出记录复用 | Word、Excel、JSON、PDF 等下载文件继续进入 `ExportedSummaryFile` | | 过程产物独立 | 自动填表过程产物单独建表,避免和法规核查 `RegulatoryArtifact` 混用 | | 通知记录独立 | 自动填表飞书通知单独建表,字段风格与法规通知记录保持一致 | | 大文本不入库 | 字段抽取 JSON、追溯清单和模板副本保存为文件,数据库仅保存路径、hash 和摘要 | | 字段明细暂不入库 | 本期不新增字段级明细表;字段结果保存在 JSON/Excel 产物与批次摘要中 | | SQLite 兼容 | 字段类型、索引和约束优先保证当前 SQLite + Django ORM 可运行 | --- ## 二、ER 图 ```mermaid erDiagram AUTH_USER ||--o{ CONVERSATION : owns CONVERSATION ||--o{ RA_FILE_SUMMARY_BATCH : has RA_FILE_SUMMARY_BATCH ||--o{ RA_FILE_SUMMARY_ITEM : produces RA_FILE_SUMMARY_BATCH ||--o{ RA_APPLICATION_FORM_FILL_BATCH : feeds RA_REGULATORY_REVIEW_BATCH ||--o{ RA_APPLICATION_FORM_FILL_BATCH : optionally_confirms AUTH_USER ||--o{ RA_APPLICATION_FORM_FILL_BATCH : runs CONVERSATION ||--o{ RA_APPLICATION_FORM_FILL_BATCH : has MESSAGE ||--o{ RA_APPLICATION_FORM_FILL_BATCH : triggers RA_APPLICATION_FORM_FILL_BATCH ||--o{ RA_APPLICATION_FORM_FILL_ARTIFACT : keeps RA_APPLICATION_FORM_FILL_BATCH ||--o{ RA_APPLICATION_FORM_FILL_NOTIFICATION_RECORD : sends RA_APPLICATION_FORM_FILL_BATCH ||--o{ RA_EXPORTED_SUMMARY_FILE : exports RA_APPLICATION_FORM_FILL_BATCH ||--o{ RA_WORKFLOW_NODE_RUN : tracks RA_APPLICATION_FORM_FILL_BATCH ||--o{ RA_WORKFLOW_EVENT : emits ``` 说明:`ra_workflow_node_run`、`ra_workflow_event`、`ra_exported_summary_file` 已在第二批中被通用化,通过 `workflow_type` 与 `workflow_batch_id` 支持多工作流。本功能使用 `workflow_type=application_form_fill`。 --- ## 三、表结构设计 ### 3.1 ra_application_form_fill_batch 一次自动填表工作流批次。该表记录本次触发来源、选择模板、输出类型、注册类型、产品名称、冲突摘要、工作目录和状态。 | 字段名 | Django 类型 | SQLite 类型 | 必填 | 说明 | | --- | --- | --- | --- | --- | | id | BigAutoField | integer | 是 | 主键 | | conversation_id | ForeignKey | bigint | 是 | 绑定对话 | | user_id | ForeignKey | bigint | 是 | 发起用户 | | trigger_message_id | ForeignKey | bigint | 否 | 触发填表工作流的用户消息 | | source_summary_batch_id | ForeignKey | bigint | 是 | 文件来源汇总批次 | | source_regulatory_batch_id | ForeignKey | bigint | 否 | 可选,复用已确认法规核查批次条件 | | batch_no | CharField(64) | varchar(64) | 是 | 填表批次编号,唯一 | | status | CharField(30) | varchar(30) | 是 | pending、running、waiting_user、success、partial_success、failed、cancelled | | requested_templates | JSONField | text/json | 是 | 用户指定模板编码列表;未指定为空数组 | | selected_templates | JSONField | text/json | 是 | 系统实际选择模板编码列表 | | output_types | JSONField | text/json | 是 | 请求输出类型,如 word、excel、json、pdf | | registration_type | CharField(80) | varchar(80) | 否 | 识别出的注册类型 | | registration_type_source | CharField(40) | varchar(40) | 否 | user_message、regulatory_batch、file_extract、unknown | | product_name | CharField(200) | varchar(200) | 否 | 产品名称 | | conflict_summary | JSONField | text/json | 是 | 冲突字段摘要 | | risk_notes | JSONField | text/json | 是 | 不适用模板、低置信度、PDF 待生成等提示 | | template_config_version | CharField(80) | varchar(80) | 否 | 模板配置版本 | | template_config_hash | CharField(128) | varchar(128) | 否 | 模板配置文件 hash | | work_dir | CharField(500) | varchar(500) | 否 | 批次工作目录 | | error_message | TextField | text | 否 | 批次异常说明 | | created_at | DateTimeField | datetime | 是 | 创建时间 | | started_at | DateTimeField | datetime | 否 | 开始时间 | | finished_at | DateTimeField | datetime | 否 | 完成时间 | | archived_at | DateTimeField | datetime | 否 | 归档时间 | | is_deleted | BooleanField | bool | 是 | 软删除标记 | 唯一约束: | 约束名 | 字段 | | --- | --- | | uq_ra_aff_batch_no | batch_no | 索引: | 索引名 | 字段 | 说明 | | --- | --- | --- | | idx_ra_aff_batch_conv_status | conversation_id, status | 查询对话下填表批次状态 | | idx_ra_aff_batch_summary | source_summary_batch_id | 根据文件汇总批次查询填表历史 | | idx_ra_aff_batch_regulatory | source_regulatory_batch_id | 根据法规核查批次查询关联填表历史 | | idx_ra_aff_batch_user_created | user_id, created_at | 查询用户发起记录 | | idx_ra_aff_batch_created | created_at | 按创建时间查询 | --- ### 3.2 ra_application_form_fill_artifact 自动填表过程产物表。仅保存文件元数据,不保存字段抽取大 JSON 的全文。 | 字段名 | Django 类型 | SQLite 类型 | 必填 | 说明 | | --- | --- | --- | --- | --- | | id | BigAutoField | integer | 是 | 主键 | | batch_id | ForeignKey | bigint | 是 | 所属自动填表批次 | | artifact_type | CharField(60) | varchar(60) | 是 | template_copy、field_extract_result、merged_fields、traceability、filled_template、notification_record | | file_format | CharField(20) | varchar(20) | 是 | json、excel、docx、pdf、markdown | | name | CharField(160) | varchar(160) | 是 | 产物名称 | | file_name | CharField(255) | varchar(255) | 是 | 文件名 | | storage_path | CharField(500) | varchar(500) | 是 | 存储路径 | | file_size | BigIntegerField | bigint | 是 | 文件大小 | | content_hash | CharField(128) | varchar(128) | 是 | 文件 SHA-256 hash | | metadata | JSONField | text/json | 是 | 模板编码、输出类型、生成状态、错误摘要等 | | created_by_node | CharField(60) | varchar(60) | 否 | 产生该产物的节点 | | created_at | DateTimeField | datetime | 是 | 创建时间 | | is_deleted | BooleanField | bool | 是 | 软删除标记 | 索引: | 索引名 | 字段 | 说明 | | --- | --- | --- | | idx_ra_aff_artifact_batch_type | batch_id, artifact_type | 查询批次过程产物 | | idx_ra_aff_artifact_format | file_format | 按文件格式查询 | | idx_ra_aff_artifact_created | created_at | 按时间追溯 | --- ### 3.3 ra_application_form_fill_notification_record 自动填表飞书通知记录表。通知失败不阻断文件下载,但需要留痕和支持后续重试。 | 字段名 | Django 类型 | SQLite 类型 | 必填 | 说明 | | --- | --- | --- | --- | --- | | id | BigAutoField | integer | 是 | 主键 | | batch_id | ForeignKey | bigint | 是 | 所属自动填表批次 | | recipient_id | ForeignKey(User) | bigint | 是 | 通知对象,默认上传人/发起人 | | channel | CharField(30) | varchar(30) | 是 | feishu_cli、feishu_api、mock | | template_codes | JSONField | text/json | 是 | 本次通知涉及模板 | | export_ids | JSONField | text/json | 是 | 本次通知关联导出文件 ID | | message_summary | TextField | text | 是 | 通知摘要 | | send_status | CharField(20) | varchar(20) | 是 | pending、success、failed | | retry_count | PositiveIntegerField | integer | 是 | 已重试次数 | | external_message_id | CharField(120) | varchar(120) | 否 | 飞书外部消息 ID | | error_message | TextField | text | 否 | 失败原因 | | sent_at | DateTimeField | datetime | 否 | 发送成功时间 | | created_at | DateTimeField | datetime | 是 | 创建时间 | | updated_at | DateTimeField | datetime | 是 | 更新时间 | | is_deleted | BooleanField | bool | 是 | 软删除标记 | 索引: | 索引名 | 字段 | 说明 | | --- | --- | --- | | idx_ra_aff_notify_batch | batch_id, created_at | 查询批次通知记录 | | idx_ra_aff_notify_recipient | recipient_id, send_status | 查询用户通知状态 | | idx_ra_aff_notify_status | send_status, retry_count | 查询待重试通知 | --- ## 四、既有表扩展 ### 4.1 ra_exported_summary_file 继续复用导出文件表,需扩展导出类型。 | 字段/枚举 | 处理 | | --- | --- | | export_type | 增加 `word`、`pdf` | | workflow_type | 使用 `application_form_fill` | | workflow_batch_id | 记录 `ApplicationFormFillBatch.id` | | export_category | 使用 `filled_template`、`traceability`、`extract_result` | 导出类型枚举: | value | 中文展示 | 说明 | | --- | --- | --- | | markdown | Markdown | 既有报告 | | excel | Excel | 追溯清单 | | json | JSON | 字段抽取结果包 | | word | Word | 填好的 Word 模板 | | pdf | PDF | Word 转换后的 PDF,P1 预留 | ### 4.2 ra_workflow_node_run 本功能使用通用工作流字段: | 字段 | 值 | | --- | --- | | workflow_type | application_form_fill | | workflow_batch_id | ApplicationFormFillBatch.id | | node_group | form_fill | | batch_id | 可为空或兼容性填充 source_summary_batch_id | ### 4.3 ra_workflow_event 本功能事件写入: | 字段 | 值 | | --- | --- | | workflow_type | application_form_fill | | workflow_batch_id | ApplicationFormFillBatch.id | | conversation_id | 当前对话 ID | | payload | 节点状态、模板列表、冲突数量、导出文件等 | --- ## 五、枚举设计 ### 5.1 ApplicationFormFillBatch.status | value | 中文展示 | 说明 | | --- | --- | --- | | pending | 待执行 | 批次已创建,等待执行 | | running | 执行中 | 工作流正在执行 | | waiting_user | 等待用户 | 缺少文件汇总批次或关键条件 | | success | 成功 | Word 和必要追溯产物生成成功 | | partial_success | 部分成功 | 部分模板、PDF、追溯清单或通知失败 | | failed | 失败 | 所有目标 Word 模板均生成失败 | | cancelled | 已取消 | 用户或系统取消执行 | ### 5.2 artifact_type | value | 说明 | | --- | --- | | template_copy | 模板副本 | | field_extract_result | 规则/正则与 LLM 抽取原始结果 | | merged_fields | 合并后的最终字段和冲突 | | traceability | 字段来源追溯清单 | | filled_template | 已填写模板 | | notification_record | 通知记录产物 | ### 5.3 registration_type_source | value | 说明 | | --- | --- | | user_message | 用户话语明确指定 | | regulatory_batch | 复用已确认法规核查条件 | | file_extract | 从文件内容抽取 | | unknown | 未识别 | ### 5.4 通知枚举 | 字段 | value | | --- | --- | | channel | feishu_cli、feishu_api、mock | | send_status | pending、success、failed | --- ## 六、JSON 字段结构建议 ### 6.1 requested_templates / selected_templates ```json ["registration_certificate", "essential_principles"] ``` ### 6.2 output_types ```json ["word", "excel", "json"] ``` PDF 作为 P1 预留,可在后续加入: ```json ["word", "pdf", "excel", "json"] ``` ### 6.3 conflict_summary ```json [ { "field_key": "storage_condition", "field_label": "产品储存条件及有效期", "selected_value": "2-8℃保存,有效期12个月", "selected_source": "说明书.docx", "conflict_values": [ { "value": "-20℃保存", "source_file": "产品技术要求.docx", "evidence": "储存条件:-20℃保存" } ], "handling": "说明书优先,模板内黄底红字高亮" } ] ``` ### 6.4 risk_notes ```json [ { "type": "template_registration_mismatch", "message": "用户指定变更注册(备案)文件,但系统识别注册类型为首次注册,需人工确认。" }, { "type": "pdf_pending", "message": "PDF 转换为后续增强项,本次优先生成 Word。" } ] ``` ### 6.5 artifact.metadata ```json { "template_code": "registration_certificate", "output_type": "word", "node_code": "word_fill", "status": "success", "conflict_count": 2 } ``` --- ## 七、存储路径设计 自动填表工作目录按用户、对话和批次隔离: ```text media/application_form_fill/{user_id}/{conversation_id}/{batch_no}/ ``` 目录结构: ```text media/application_form_fill/12/1001/AFF-20260607153000-a1b2c3/ templates/ registration_certificate.source.docx essential_principles.source.docx filled/ AFF-20260607153000-a1b2c3-甲胎蛋白检测试剂盒-注册证格式.docx exports/ AFF-20260607153000-a1b2c3-甲胎蛋白检测试剂盒-字段来源追溯清单.xlsx field_extract_result.json merged_fields.json notifications/ notification_record.json ``` 所有产物写入 `ApplicationFormFillArtifact` 时必须记录 SHA-256 hash。 --- ## 八、权限与查询规则 ### 8.1 批次访问权限 ```text ApplicationFormFillBatch -> conversation -> user 必须等于当前 request.user ``` ### 8.2 导出下载权限 ```text ExportedSummaryFile.workflow_type == application_form_fill -> workflow_batch_id -> ApplicationFormFillBatch.conversation.user ``` 若 `workflow_type=file_summary` 或 `regulatory_review`,仍按既有逻辑校验。 ### 8.3 文件读取权限 自动填表只能读取 `source_summary_batch.items` 对应的文件,不允许从其他对话或其他批次随意读取文件。 --- ## 九、字段级数据库表暂缓说明 本期不新增 `ApplicationFormFillField` 字段级明细表。原因: | 原因 | 说明 | | --- | --- | | Demo 主链路更轻 | 字段结果以 JSON 和 Excel 追溯清单即可满足下载复核 | | 避免过早建模 | 字段结构依赖模板配置和后续人工修改交互,暂不固化表结构 | | 查询需求有限 | 本期主要按批次下载文件,不做字段级统计和在线编辑 | 后续如需要在线确认、人工修改、字段级审计或批量统计,再新增字段级表。该事项写入 `docs/6.待办计划/第二阶段暂缓事项.md`。 --- ## 十、Django Model 命名建议 | 表名 | Model 名称 | | --- | --- | | ra_application_form_fill_batch | ApplicationFormFillBatch | | ra_application_form_fill_artifact | ApplicationFormFillArtifact | | ra_application_form_fill_notification_record | ApplicationFormFillNotificationRecord | 建议模型仍集中放在 `review_agent/models.py`,与前两批现有模型保持一致;业务逻辑放在 `review_agent/application_form_fill/`。 --- ## 十一、验收检查点 | 序号 | 检查项 | 验收标准 | | --- | --- | --- | | 1 | 独立批次 | 触发填表后生成 `ApplicationFormFillBatch` | | 2 | 文件来源 | 每个填表批次都关联一个成功的 `FileSummaryBatch` | | 3 | 可选法规条件 | 如有关联法规核查批次,可记录 `source_regulatory_batch` | | 4 | 过程产物 | 字段抽取 JSON、合并结果、追溯清单、模板副本均可留底 | | 5 | 导出复用 | 填好的 Word 和追溯清单进入 `ExportedSummaryFile` | | 6 | 导出类型 | `ExportedSummaryFile.ExportType` 支持 `word`、`pdf` | | 7 | 通知记录 | 飞书通知记录能保存状态、重试次数、失败原因 | | 8 | 权限隔离 | A 对话的填表批次和导出文件不能被 B 对话访问 | | 9 | 字段表暂缓 | 字段级结果不入库,但能从 JSON/Excel 追溯产物复核 | --- ## 十二、开发顺序建议 1. 扩展 `ExportedSummaryFile.ExportType`,增加 `word`、`pdf`。 2. 新增 `ApplicationFormFillBatch`、`ApplicationFormFillArtifact`、`ApplicationFormFillNotificationRecord`。 3. 为新增状态字段定义 Django `TextChoices`。 4. 配置表名、索引和唯一约束。 5. 执行 `python manage.py makemigrations review_agent` 和 `python manage.py migrate`。 6. 编写模型测试,覆盖批次创建、产物 hash、通知重试字段、导出权限查询。 7. 将字段级数据库表和 PDF 转换能力写入待办计划。