docs(regulatory-review): 增加法规核查设计文档

This commit is contained in:
2026-06-06 00:55:54 +08:00
parent f1534b6165
commit ce574048a4
3 changed files with 1881 additions and 0 deletions

View File

@@ -0,0 +1,485 @@
# NMPA 注册资料法规核查与整改闭环工作流数据库设计
## 文档信息
| 项目 | 内容 |
| --- | --- |
| 需求分析文档 | docs/1.需求分析/2.NMPA注册资料法规核查与整改闭环.md |
| 功能设计文档 | docs/2.功能设计/2.NMPA注册资料法规核查与整改闭环.md |
| 数据库类型 | SQLite / Django ORM |
| 表名前缀 | ra_ |
| 设计日期 | 2026-06-06 |
| 设计版本 | V1.0 |
---
## 一、设计原则
| 原则 | 说明 |
| --- | --- |
| 复用汇总批次 | 法规核查不重复保存文件清单,必须关联既有 `ra_file_summary_batch` |
| 独立核查批次 | 同一个文件汇总批次可以产生多次法规核查批次,适用条件变更时创建新批次 |
| 规则版本入库 | 结构化规则版本进入数据库便于追溯规则文件、RAG 索引和启用状态 |
| RAG 不单独建表 | RAG 索引信息挂在规则版本和核查批次字段中,不新增索引表 |
| 枚举存值 | 数据库存英文枚举 value前端或服务层映射为中文展示 |
| 关键字段独立 | 常用查询字段独立存储,其余过程上下文进入 JSON 或文件产物 |
| 大文本不入库 | 过程产物只在数据库保存路径、摘要和 hash大文本内容写入文件 |
| 软删除优先 | 法规核查相关数据采用软删除/归档策略,便于审计和恢复 |
| 过程产物留底 | 条件确认、核查矩阵、风险清单、RAG 结果、通知记录、复核记录均需留底 |
---
## 二、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_REGULATORY_REVIEW_BATCH : reviews
AUTH_USER ||--o{ RA_REGULATORY_REVIEW_BATCH : runs
AUTH_USER ||--o{ RA_REGULATORY_ISSUE : owns
RA_REGULATORY_RULE_VERSION ||--o{ RA_REGULATORY_REVIEW_BATCH : used_by
RA_REGULATORY_REVIEW_BATCH ||--o{ RA_REGULATORY_ISSUE : produces
RA_REGULATORY_REVIEW_BATCH ||--o{ RA_REGULATORY_ARTIFACT : keeps
RA_REGULATORY_REVIEW_BATCH ||--o{ RA_REGULATORY_NOTIFICATION_RECORD : sends
RA_REGULATORY_REVIEW_BATCH ||--o{ RA_EXPORTED_SUMMARY_FILE : exports
RA_REGULATORY_REVIEW_BATCH ||--o{ RA_WORKFLOW_NODE_RUN : tracks
RA_REGULATORY_REVIEW_BATCH ||--o{ RA_WORKFLOW_EVENT : emits
```
说明:`ra_workflow_node_run``ra_workflow_event` 在第一阶段设计中属于文件汇总批次节点记录表。法规核查工作流复用同一套事件机制,采用 `workflow_type``workflow_batch_id` 兼容多工作流;原 `batch_id` 保留用于兼容文件汇总旧逻辑。
---
## 三、表结构设计
### 3.1 ra_regulatory_rule_version
法规结构化规则版本表。规则文件仍以 YAML/JSON 文件形式维护,数据库记录版本元数据、文件 hash、RAG 索引版本和启用状态。
| 字段名 | Django 类型 | SQLite 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| id | BigAutoField | integer | 是 | 主键 |
| version | CharField(80) | varchar(80) | 是 | 规则版本,如 nmpa_ivd_2021_v1 |
| source_url | URLField(500) | varchar(500) | 是 | 法规来源 URL |
| source_path | CharField(500) | varchar(500) | 是 | 本地法规资料路径 |
| effective_date | DateField | date | 否 | 规则生效日期或公告日期 |
| rule_file_path | CharField(500) | varchar(500) | 是 | 结构化规则文件路径 |
| rule_file_hash | CharField(128) | varchar(128) | 是 | 规则文件 hash |
| rag_index_version | CharField(80) | varchar(80) | 否 | RAG 索引版本 |
| rag_index_path | CharField(500) | varchar(500) | 否 | RAG 索引存储路径 |
| is_active | BooleanField | bool | 是 | 是否当前启用版本 |
| created_by_id | ForeignKey(User) | bigint | 否 | 创建人 |
| activated_at | DateTimeField | datetime | 否 | 启用时间 |
| description | TextField | text | 否 | 版本说明 |
| created_at | DateTimeField | datetime | 是 | 创建时间 |
| updated_at | DateTimeField | datetime | 是 | 更新时间 |
| is_deleted | BooleanField | bool | 是 | 软删除标记 |
唯一约束:
| 约束名 | 字段 |
| --- | --- |
| uq_ra_reg_rule_version | version |
索引:
| 索引名 | 字段 | 说明 |
| --- | --- | --- |
| idx_ra_reg_rule_active | is_active, is_deleted | 查询当前启用规则 |
| idx_ra_reg_rule_effective | effective_date | 按生效日期追溯 |
| idx_ra_reg_rule_created | created_at | 查看规则版本历史 |
---
### 3.2 ra_regulatory_review_batch
法规核查批次表。一次法规核查工作流对应一条记录。同一个 `ra_file_summary_batch` 可关联多个法规核查批次,用于适用条件变更或重新核查。
| 字段名 | Django 类型 | SQLite 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| id | BigAutoField | integer | 是 | 主键 |
| conversation_id | ForeignKey | bigint | 是 | 绑定对话 |
| user_id | ForeignKey | bigint | 是 | 发起用户 |
| file_summary_batch_id | ForeignKey | bigint | 是 | 关联文件汇总批次 |
| rule_version_id | ForeignKey | bigint | 否 | 使用的规则版本 |
| batch_no | CharField(64) | varchar(64) | 是 | 法规核查批次编号,唯一 |
| status | CharField(30) | varchar(30) | 是 | pending、running、waiting_user、success、failed、reference_only、partial_success、cancelled |
| product_category | CharField(80) | varchar(80) | 否 | 产品类别 |
| registration_type | CharField(80) | varchar(80) | 否 | 注册类型 |
| clinical_evaluation_path | CharField(120) | varchar(120) | 否 | 临床评价路径 |
| product_name | CharField(200) | varchar(200) | 否 | 产品名称 |
| model_specification | CharField(200) | varchar(200) | 否 | 型号规格 |
| intended_use | TextField | text | 否 | 预期用途 |
| condition_json | JSONField | text/json | 否 | 其他适用条件、用户确认记录和抽取置信度 |
| rule_version_value | CharField(80) | varchar(80) | 否 | 冗余记录规则版本值,便于历史追溯 |
| rule_source_url | URLField(500) | varchar(500) | 否 | 冗余记录法规来源 URL |
| rule_source_path | CharField(500) | varchar(500) | 否 | 冗余记录本地法规资料路径 |
| rag_index_version | CharField(80) | varchar(80) | 否 | 本次使用的 RAG 索引版本 |
| risk_summary_json | JSONField | text/json | 否 | 风险数量摘要 |
| artifact_root | 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_reg_batch_no | batch_no |
索引:
| 索引名 | 字段 | 说明 |
| --- | --- | --- |
| idx_ra_reg_batch_conv_status | conversation_id, status | 查询对话下法规核查批次状态 |
| idx_ra_reg_batch_summary | file_summary_batch_id | 根据文件汇总批次查询法规核查历史 |
| idx_ra_reg_batch_created | created_at | 按创建时间查询 |
| idx_ra_reg_batch_rule | rule_version_value | 规则版本追溯 |
| idx_ra_reg_batch_user_created | user_id, created_at | 查询用户发起记录 |
---
### 3.3 ra_regulatory_issue
法规核查问题表,记录完整性、章节结构、一致性、通知、复核等业务问题及整改状态。
| 字段名 | Django 类型 | SQLite 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| id | BigAutoField | integer | 是 | 主键 |
| batch_id | ForeignKey | bigint | 是 | 所属法规核查批次 |
| owner_id | ForeignKey(User) | bigint | 否 | 责任人,默认上传人 |
| issue_code | CharField(100) | varchar(100) | 是 | 问题编码 |
| issue_type | CharField(40) | varchar(40) | 是 | completeness、structure、consistency、notification、review |
| risk_level | CharField(20) | varchar(20) | 是 | blocking、high、medium、low、info |
| status | CharField(30) | varchar(30) | 是 | pending_confirm、pending_fix、fixed、review_passed、review_failed、closed |
| title | CharField(255) | varchar(255) | 是 | 问题标题 |
| description | TextField | text | 否 | 问题描述 |
| rule_id | CharField(120) | varchar(120) | 否 | 命中的规则 ID |
| regulation_basis | TextField | text | 否 | 法规依据或规则依据 |
| file_item_id | ForeignKey(FileSummaryItem) | bigint | 否 | 关联文件明细,可为空 |
| file_path | CharField(500) | varchar(500) | 否 | 常用证据文件路径 |
| page_no | PositiveIntegerField | integer | 否 | 常用证据页码 |
| field_name | CharField(120) | varchar(120) | 否 | 一致性或字段问题名称 |
| evidence_json | JSONField | text/json | 否 | 证据详情如文本片段、多个来源值、RAG 引用等 |
| suggestion | TextField | text | 否 | 整改建议 |
| source_node | CharField(60) | varchar(60) | 否 | 产生问题的工作流节点 |
| confirmed_by_id | ForeignKey(User) | bigint | 否 | 确认人 |
| confirmed_at | DateTimeField | datetime | 否 | 确认时间 |
| closed_by_id | ForeignKey(User) | bigint | 否 | 关闭人 |
| closed_at | DateTimeField | datetime | 否 | 关闭时间 |
| created_at | DateTimeField | datetime | 是 | 创建时间 |
| updated_at | DateTimeField | datetime | 是 | 更新时间 |
| is_deleted | BooleanField | bool | 是 | 软删除标记 |
唯一约束:
| 约束名 | 字段 |
| --- | --- |
| uq_ra_reg_issue_batch_code | batch_id, issue_code |
索引:
| 索引名 | 字段 | 说明 |
| --- | --- | --- |
| idx_ra_reg_issue_batch | batch_id, created_at | 查询批次问题 |
| idx_ra_reg_issue_risk_status | risk_level, status | 风险列表和整改状态筛选 |
| idx_ra_reg_issue_owner_status | owner_id, status | 责任人待办 |
| idx_ra_reg_issue_rule | rule_id | 规则问题追溯 |
| idx_ra_reg_issue_file | file_item_id | 关联文件问题 |
| idx_ra_reg_issue_field | field_name | 字段一致性问题查询 |
---
### 3.4 ra_regulatory_artifact
法规核查过程产物表。只保存文件元数据,不保存大文本全文。文件内容写入受控存储目录,`file_hash` 必填。
| 字段名 | Django 类型 | SQLite 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| id | BigAutoField | integer | 是 | 主键 |
| batch_id | ForeignKey | bigint | 是 | 所属法规核查批次 |
| artifact_type | CharField(60) | varchar(60) | 是 | condition_record、rule_matrix、risk_list、text_extract_json、rag_result_json、notification_record、review_record |
| file_format | CharField(20) | varchar(20) | 是 | markdown、excel、json |
| file_name | CharField(255) | varchar(255) | 是 | 文件名 |
| storage_path | CharField(500) | varchar(500) | 是 | 存储路径 |
| file_size | BigIntegerField | bigint | 是 | 文件大小 |
| file_hash | CharField(128) | varchar(128) | 是 | 文件 hash用于校验留底文件未被篡改 |
| summary | TextField | text | 否 | 产物摘要 |
| created_by_node | CharField(60) | varchar(60) | 否 | 产生该产物的工作流节点 |
| created_at | DateTimeField | datetime | 是 | 创建时间 |
| is_deleted | BooleanField | bool | 是 | 软删除标记 |
索引:
| 索引名 | 字段 | 说明 |
| --- | --- | --- |
| idx_ra_reg_artifact_batch_type | batch_id, artifact_type | 查询批次过程产物 |
| idx_ra_reg_artifact_format | file_format | 按格式查询 |
| idx_ra_reg_artifact_created | created_at | 按时间追溯 |
---
### 3.5 ra_regulatory_notification_record
法规核查通知记录表,记录飞书 CLI 发送结果。飞书失败不阻断工作流,但需要留痕。
| 字段名 | Django 类型 | SQLite 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| id | BigAutoField | integer | 是 | 主键 |
| batch_id | ForeignKey | bigint | 是 | 所属法规核查批次 |
| recipient_id | ForeignKey(User) | bigint | 是 | 通知对象 |
| channel | CharField(30) | varchar(30) | 是 | feishu_cli、feishu_api、mock |
| risk_levels | JSONField | text/json | 是 | 本次通知包含的风险等级 |
| issue_ids | JSONField | text/json | 是 | 本次通知关联的问题 ID 列表 |
| message_summary | TextField | text | 是 | 通知内容摘要 |
| send_status | CharField(20) | varchar(20) | 是 | pending、success、failed |
| retry_count | PositiveIntegerField | integer | 是 | 已重试次数,最多 3 次 |
| 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_reg_notify_batch | batch_id, created_at | 查询批次通知记录 |
| idx_ra_reg_notify_recipient | recipient_id, send_status | 查询用户通知状态 |
| idx_ra_reg_notify_status | send_status, retry_count | 查询待重试通知 |
---
## 四、枚举设计
### 4.1 RegulatoryReviewBatch.status
| value | 中文展示 | 说明 |
| --- | --- | --- |
| pending | 待执行 | 已创建,等待执行 |
| running | 执行中 | 工作流正在执行 |
| waiting_user | 等待用户 | 等待用户确认适用条件或关闭复核 |
| success | 已完成 | 核查完成且无关键失败 |
| failed | 失败 | 关键节点失败,无法输出有效结果 |
| reference_only | 仅供参考 | 规则文件加载失败,降级为 RAG 辅助核查 |
| partial_success | 部分完成 | 部分节点或通知失败,但已输出主要结果 |
| cancelled | 已取消 | 用户或系统取消执行 |
### 4.2 RegulatoryIssue.status
| value | 中文展示 | 说明 |
| --- | --- | --- |
| pending_confirm | 待确认 | 条件性问题或低置信度问题等待人工确认 |
| pending_fix | 待处理 | 已确认需要补充或整改 |
| fixed | 已补充 | 用户已上传补充资料或声明已处理 |
| review_passed | 复核通过 | 系统复核通过,关闭前仍需人工确认 |
| review_failed | 复核不通过 | 系统复核后问题仍存在 |
| closed | 已关闭 | 用户确认问题解决并关闭 |
### 4.3 RegulatoryIssue.risk_level
| value | 中文展示 | 说明 |
| --- | --- | --- |
| blocking | 阻断项 | 直接影响资料能否进入有效申报或审核 |
| high | 高风险 | 可能导致注册审评补正或重大整改 |
| medium | 中风险 | 需要补充说明或修改 |
| low | 低风险 | 建议修正但影响较小 |
| info | 提示项 | 系统无法充分判断或建议人工关注 |
### 4.4 其他枚举
| 字段 | value |
| --- | --- |
| issue_type | completeness、structure、consistency、notification、review |
| artifact_type | condition_record、rule_matrix、risk_list、text_extract_json、rag_result_json、notification_record、review_record |
| file_format | markdown、excel、json |
| send_status | pending、success、failed |
| channel | feishu_cli、feishu_api、mock |
---
## 五、软删除与归档策略
| 对象 | 策略 |
| --- | --- |
| RegulatoryRuleVersion | 使用 `is_deleted` 软删除;已被批次引用的版本不允许物理删除 |
| RegulatoryReviewBatch | 使用 `is_deleted``archived_at` 归档;归档后默认不在对话主列表展示 |
| RegulatoryIssue | 使用 `is_deleted` 软删除;删除时保留批次摘要和过程产物 |
| RegulatoryArtifact | 使用 `is_deleted` 软删除;正式环境可配合对象存储生命周期归档 |
| RegulatoryNotificationRecord | 使用 `is_deleted` 软删除;保留通知失败原因和重试次数 |
删除 Conversation 时,本期不建议物理级联法规核查数据。应先标记相关批次归档或删除,再由后台清理任务处理文件和产物。
---
## 六、过程产物存储设计
### 6.1 存储目录
法规核查过程产物使用独立目录,按用户、对话、法规核查批次隔离:
```text
media/regulatory_review/{user_id}/{conversation_id}/{batch_id}/
```
示例:
```text
media/regulatory_review/12/1001/2001/
condition_record.md
condition_record.json
rule_matrix.xlsx
risk_list.md
risk_list.json
text_extract.json
rag_result.json
notification_record.md
review_record.json
```
### 6.2 文件 hash
`ra_regulatory_artifact.file_hash` 必填。建议使用 SHA-256。
| 场景 | 处理 |
| --- | --- |
| 文件生成成功 | 计算 hash 后写入记录 |
| hash 计算失败 | 产物生成视为失败,节点进入 partial_success 或 failed |
| 下载文件 | 可选重新计算 hash 校验 |
---
## 七、JSON 字段结构建议
### 7.1 condition_json
```json
{
"extracted": {
"product_category": {"value": "in_vitro_diagnostic", "confidence": 0.92},
"registration_type": {"value": "initial_registration", "confidence": 0.76}
},
"confirmed": {
"confirmed_by": 1,
"confirmed_at": "2026-06-06T00:00:00+08:00",
"source": "dialog_choice"
},
"raw_user_input": "按体外诊断试剂首次注册处理"
}
```
### 7.2 risk_summary_json
```json
{
"blocking": 2,
"high": 1,
"medium": 3,
"low": 4,
"info": 2,
"notified": {
"feishu": 6
}
}
```
### 7.3 evidence_json
```json
{
"matched_rule": {
"rule_id": "ivd_registration_test_report",
"rule_title": "注册检验报告"
},
"matched_files": [
{
"file_item_id": 33,
"relative_path": "注册检验/检验报告.pdf",
"matched_by": "directory_keyword"
}
],
"rag_citations": [
{
"source_file": "体外诊断试剂注册申报资料要求及说明.doc",
"section_title": "注册申报资料要求",
"snippet": "..."
}
]
}
```
---
## 八、与现有表的改造建议
### 8.1 ra_workflow_node_run
第一阶段设计中该表通过 `batch_id` 直接关联文件汇总批次。法规核查复用同一套工作流状态机制,采用通用工作流引用:
| 字段 | 说明 |
| --- | --- |
| workflow_type | 新增,用于区分 file_summary 和 regulatory_review |
| workflow_batch_id | 新增,记录对应工作流批次 ID |
| batch_id | 保留,兼容文件汇总旧逻辑 |
### 8.2 ra_workflow_event
同样增加 `workflow_type``workflow_batch_id`,使 SSE 能同时服务文件汇总和法规核查卡片。
### 8.3 ra_exported_summary_file
最终法规核查报告复用导出文件表。现有 `batch_id` 关联文件汇总批次,需要通用化:
| 字段 | 说明 |
| --- | --- |
| workflow_type | 新增,用于区分 file_summary 和 regulatory_review |
| workflow_batch_id | 新增,记录对应工作流批次 ID |
| batch_id | 保留,兼容文件汇总旧逻辑 |
| export_category | 新增,用于区分 summary_report、risk_report、excel_list、json_package |
最终法规核查报告进入 `ExportedSummaryFile`,过程产物进入 `RegulatoryArtifact`
---
## 九、Django Model 命名建议
| 表名 | Model 名称 |
| --- | --- |
| ra_regulatory_rule_version | RegulatoryRuleVersion |
| ra_regulatory_review_batch | RegulatoryReviewBatch |
| ra_regulatory_issue | RegulatoryIssue |
| ra_regulatory_artifact | RegulatoryArtifact |
| ra_regulatory_notification_record | RegulatoryNotificationRecord |
---
## 十、验收检查点
| 序号 | 检查项 | 验收标准 |
| --- | --- | --- |
| 1 | 规则版本可追溯 | 每个法规核查批次能查到 rule_version、source_path、rule_file_hash 和 rag_index_version |
| 2 | 批次可多次核查 | 同一个 FileSummaryBatch 可创建多个 RegulatoryReviewBatch |
| 3 | 软删除可用 | 归档或删除法规核查批次后,默认列表不展示但历史可追溯 |
| 4 | 问题可筛选 | 可按 risk_level、status、owner 查询待处理问题 |
| 5 | 证据可追溯 | Issue 可查到 file_path、page_no、field_name 和 evidence_json |
| 6 | 产物可校验 | 每个 RegulatoryArtifact 都有 file_hash |
| 7 | 飞书可重试 | NotificationRecord 可记录 retry_count、send_status 和失败原因 |
| 8 | 权限可追溯 | 所有法规核查数据可通过 batch -> conversation -> user 校验访问权限 |
---
## 十一、后续实现注意事项
| 序号 | 问题 | 当前建议 |
| --- | --- | --- |
| 1 | WorkflowNodeRun/Event 通用化 | 已确定新增 workflow_type 和 workflow_batch_id保留 batch_id 兼容文件汇总 |
| 2 | ExportedSummaryFile 通用化 | 已确定新增 workflow_type、workflow_batch_id 和 export_category |
| 3 | RegulatoryArtifact 下载接口 | 按 batch -> conversation -> user 校验权限 |
| 4 | 飞书用户映射 | 暂通过 User 扩展字段或配置表映射飞书 CLI 可识别账号 |
| 5 | 规则文件 hash 计算时机 | 规则导入或激活时计算并写入 RegulatoryRuleVersion |