494 lines
21 KiB
Python
494 lines
21 KiB
Python
from pathlib import Path
|
||
|
||
import yaml
|
||
from django.conf import settings
|
||
|
||
|
||
def _governance_defaults() -> dict:
|
||
return {
|
||
"owner_mappings": [
|
||
{
|
||
"owner_role": "注册资料负责人",
|
||
"owner_name": "张三",
|
||
"department": "注册事务部",
|
||
"chapter_scope": "CH1",
|
||
"risk_scope": "字段冲突 / 缺失项",
|
||
"feishu_user_id": "ou_demo_1",
|
||
"feishu_open_id": "on_demo_1",
|
||
"feishu_name": "张三",
|
||
"notify_enabled": "是",
|
||
},
|
||
{
|
||
"owner_role": "注册申报负责人",
|
||
"owner_name": "李四",
|
||
"department": "临床注册组",
|
||
"chapter_scope": "CH2-CH6",
|
||
"risk_scope": "完整性风险 / 导出阻断",
|
||
"feishu_user_id": "ou_demo_2",
|
||
"feishu_open_id": "on_demo_2",
|
||
"feishu_name": "李四",
|
||
"notify_enabled": "是",
|
||
},
|
||
],
|
||
"feishu_configs": [
|
||
{
|
||
"config_name": "注册审核完成通知",
|
||
"notify_reason": "task_completed",
|
||
"channel": "群机器人",
|
||
"message_template": "审核完成摘要 + @处理人",
|
||
"status": "启用",
|
||
},
|
||
{
|
||
"config_name": "注册审核异常通知",
|
||
"notify_reason": "task_failed",
|
||
"channel": "群机器人",
|
||
"message_template": "异常摘要 + @处理人",
|
||
"status": "启用",
|
||
},
|
||
],
|
||
"template_mappings": [
|
||
{
|
||
"template_name": "注册证导出模板",
|
||
"output_type": "registration_word_export_report",
|
||
"version": "V1.0",
|
||
"placeholder_count": 18,
|
||
"status": "启用",
|
||
"field_mapping_summary": "产品名称 / 注册人 / 适用机型 / 储存条件",
|
||
},
|
||
{
|
||
"template_name": "风险摘要导出模板",
|
||
"output_type": "registration_word_export_report",
|
||
"version": "V0.9",
|
||
"placeholder_count": 10,
|
||
"status": "待校验",
|
||
"field_mapping_summary": "风险等级 / 批次号 / 责任人 / 证据摘要",
|
||
},
|
||
],
|
||
}
|
||
|
||
|
||
def _read_governance_yaml() -> dict:
|
||
raw_path = getattr(settings, "GOVERNANCE_CONFIG_PATH", "")
|
||
if not raw_path:
|
||
return {}
|
||
config_path = Path(raw_path)
|
||
if not config_path.exists() or not config_path.is_file():
|
||
return {}
|
||
with config_path.open("r", encoding="utf-8") as file:
|
||
return yaml.safe_load(file) or {}
|
||
|
||
|
||
def _load_governance_config() -> dict:
|
||
defaults = _governance_defaults()
|
||
config = _read_governance_yaml()
|
||
for key, default_value in defaults.items():
|
||
configured_value = config.get(key)
|
||
if isinstance(default_value, list) and configured_value:
|
||
defaults[key] = configured_value
|
||
return defaults
|
||
|
||
|
||
def get_platform_demo_context():
|
||
batch = {
|
||
"name": "2026Q2-呼吸道多联检测试剂注册批次",
|
||
"product_name": "呼吸道病原体核酸联合检测试剂盒(PCR-荧光探针法)",
|
||
"owner": "临床注册事务组",
|
||
"stage": "法规完整性复核中",
|
||
"completion": "74%",
|
||
"next_action": "补齐 CH1.11.5 沟通记录并确认产品列表版本",
|
||
}
|
||
metrics = [
|
||
{"label": "资料齐套率", "value": "82%", "note": "42 / 51 个目录项已命中"},
|
||
{"label": "法规命中率", "value": "89%", "note": "公告附件包 6 类规则已生效"},
|
||
{"label": "字段抽取完成度", "value": "67%", "note": "48 个核心字段已进入统一字段池"},
|
||
{"label": "高风险问题", "value": "03", "note": "2 个缺失项,1 个跨文档冲突"},
|
||
]
|
||
workflow_overview = [
|
||
{"title": "资料进入系统", "detail": "批量上传 18 份申报资料与 6 份法规原文"},
|
||
{"title": "规则与知识装载", "detail": "按章-条-要求项-模板字段建立知识底座"},
|
||
{"title": "解析与切片", "detail": "页数统计、目录识别、表格抽取、Chroma 入库"},
|
||
{"title": "Agent 审核执行", "detail": "完整性检查、字段抽取、一致性核查"},
|
||
{"title": "结论输出", "detail": "形成风险清单、证据引用、责任人动作建议"},
|
||
]
|
||
risk_board = [
|
||
{"level": "高", "title": "CH1.11.5 沟通记录缺失", "owner": "监管信息专员", "action": "补充 NMPA 沟通留痕"},
|
||
{"level": "高", "title": "产品名称跨文档表述不一致", "owner": "产品资料负责人", "action": "统一申请表与说明书命名"},
|
||
{"level": "中", "title": "2 份 Word 页数为估算值", "owner": "文控支持", "action": "补做版式校验"},
|
||
]
|
||
quick_links = [
|
||
{"title": "知识库配置", "url_name": "platform_ui:knowledge-base", "desc": "维护法规规则树与切片策略"},
|
||
{"title": "文件中心", "url_name": "documents:list", "desc": "查看上传、解析、切片与异常状态"},
|
||
{"title": "审核工作台", "url_name": "chat:index", "url_arg": "document_review", "desc": "发起审核、抽取与一致性核查演示"},
|
||
{"title": "工作台大屏", "url_name": "platform_ui:command-center", "desc": "面向演示的 Agent 流程解释大屏"},
|
||
]
|
||
knowledge_sources = [
|
||
{
|
||
"code": "KB-001",
|
||
"name": "公告附件包 / 资料要求说明",
|
||
"type": "法规依据",
|
||
"scope": "registration",
|
||
"updated_at": "今天 09:20",
|
||
"status": "已生效",
|
||
"owner": "法规专员",
|
||
},
|
||
{
|
||
"code": "KB-002",
|
||
"name": "批准证明文件格式要求",
|
||
"type": "模板规则",
|
||
"scope": "registration",
|
||
"updated_at": "今天 09:35",
|
||
"status": "已生效",
|
||
"owner": "模板管理员",
|
||
},
|
||
{
|
||
"code": "KB-003",
|
||
"name": "安全和性能基本原则清单",
|
||
"type": "原则规则",
|
||
"scope": "registration",
|
||
"updated_at": "今天 10:02",
|
||
"status": "待人工校订",
|
||
"owner": "法规专员",
|
||
},
|
||
{
|
||
"code": "KB-004",
|
||
"name": "CH1 监管信息目录样例",
|
||
"type": "业务资料",
|
||
"scope": "batch",
|
||
"updated_at": "今天 10:30",
|
||
"status": "已入库",
|
||
"owner": "文控专员",
|
||
},
|
||
]
|
||
rule_tree = [
|
||
{
|
||
"code": "RULE-001",
|
||
"chapter": "CH1 监管信息",
|
||
"item": "CH1.2 监管信息目录",
|
||
"requirement": "必须提供目录与页码映射",
|
||
"field": "目录文件 / 页码可信度",
|
||
"status": "启用",
|
||
},
|
||
{
|
||
"code": "RULE-002",
|
||
"chapter": "CH1 监管信息",
|
||
"item": "CH1.4 申请表",
|
||
"requirement": "申请表字段需与说明书一致",
|
||
"field": "产品名称 / 规格 / 申请人",
|
||
"status": "启用",
|
||
},
|
||
{
|
||
"code": "RULE-003",
|
||
"chapter": "CH1 监管信息",
|
||
"item": "CH1.11.5 沟通记录",
|
||
"requirement": "涉及沟通事项时需补齐记录",
|
||
"field": "沟通对象 / 时间 / 结论",
|
||
"status": "待校订",
|
||
},
|
||
{
|
||
"code": "RULE-004",
|
||
"chapter": "批准证明文件格式",
|
||
"item": "注册证输出模板",
|
||
"requirement": "字段映射需满足版式模板",
|
||
"field": "注册证字段池 / Word 模板",
|
||
"status": "启用",
|
||
},
|
||
]
|
||
knowledge_stats = [
|
||
{"label": "法规知识源", "value": "06"},
|
||
{"label": "结构化规则项", "value": "128"},
|
||
{"label": "业务资料切片", "value": "342"},
|
||
{"label": "最近人工校订", "value": "2 次"},
|
||
]
|
||
governance_sections = [
|
||
{"title": "法规规则包", "desc": "维护章节规则、要求项与模板字段映射。"},
|
||
{"title": "RAG 文档源", "desc": "统一管理法规资料、业务资料和模板来源。"},
|
||
{"title": "RAG 切片", "desc": "查看切片摘要、召回状态和证据命中历史。"},
|
||
{"title": "字段 Schema", "desc": "维护强一致字段、回填字段和来源优先级。"},
|
||
{"title": "责任人映射", "desc": "按章节和风险类型维护飞书责任人实体。"},
|
||
{"title": "飞书通知配置", "desc": "固定支持 task_completed / task_failed 两类通知。"},
|
||
]
|
||
rag_chunks = [
|
||
{
|
||
"chunk_id": "chunk-001",
|
||
"document_name": "资料要求说明",
|
||
"chapter": "CH1",
|
||
"summary": "CH1.11.5 沟通记录需保留可追溯留痕。",
|
||
"status": "已启用",
|
||
},
|
||
{
|
||
"chunk_id": "chunk-002",
|
||
"document_name": "批准证明文件格式要求",
|
||
"chapter": "CH1",
|
||
"summary": "注册证输出模板需满足固定版式字段映射。",
|
||
"status": "待重建",
|
||
},
|
||
]
|
||
field_schemas = [
|
||
{
|
||
"field_code": "product_name",
|
||
"field_name": "产品名称",
|
||
"field_type": "string",
|
||
"fillable": "是",
|
||
"strict_consistency": "是",
|
||
"status": "启用",
|
||
},
|
||
{
|
||
"field_code": "storage_condition",
|
||
"field_name": "储存条件",
|
||
"field_type": "string",
|
||
"fillable": "是",
|
||
"strict_consistency": "否",
|
||
"status": "待校订",
|
||
},
|
||
]
|
||
governance_config = _load_governance_config()
|
||
owner_mappings = governance_config["owner_mappings"]
|
||
feishu_configs = governance_config["feishu_configs"]
|
||
template_mappings = governance_config["template_mappings"]
|
||
mcp_connectors = [
|
||
{"name": "飞书任务通知", "kind": "协同办公", "auth": "App Token", "status": "已连接", "sync": "5 分钟前"},
|
||
{"name": "法规规则源导入", "kind": "法规服务", "auth": "文件轮询", "status": "待验证", "sync": "今天 08:50"},
|
||
{"name": "Word 模板服务", "kind": "文档服务", "auth": "API Key", "status": "已连接", "sync": "刚刚"},
|
||
{"name": "企业主数据源", "kind": "业务系统", "auth": "MCP Bridge", "status": "未启用", "sync": "未同步"},
|
||
]
|
||
skills = [
|
||
{"name": "完整性检查 Skill", "trigger": "目录齐套性 / 章节点核查", "tools": "规则树 + RAG + 风险映射", "status": "发布中"},
|
||
{"name": "字段抽取 Skill", "trigger": "申请表 / 说明书 / 产品列表抽取", "tools": "表格抽取 + 字段池", "status": "已发布"},
|
||
{"name": "一致性核查 Skill", "trigger": "跨文档字段冲突检查", "tools": "字段比对 + 解释生成", "status": "灰度测试"},
|
||
{"name": "Word 回填 Skill", "trigger": "报送版 Word 输出", "tools": "模板映射 + 导出服务", "status": "待校验"},
|
||
]
|
||
workflow_steps = [
|
||
{"time": "09:32", "title": "载入批次资料", "detail": "识别 18 份业务资料与 6 份法规原文,建立本轮审核上下文。"},
|
||
{"time": "09:34", "title": "规则树装载", "detail": "按注册申报主流程装载 CH1 监管信息与批准证明文件格式规则。"},
|
||
{"time": "09:36", "title": "字段池初始化", "detail": "从申请表、说明书、产品列表抽取统一字段并建立来源映射。"},
|
||
{"time": "09:39", "title": "一致性检查", "detail": "检测到产品名称和样本类型存在跨文档冲突,升级为人工复核。"},
|
||
{"time": "09:42", "title": "风险输出", "detail": "生成 3 条风险项、2 条补件建议与 1 条责任人通知任务。"},
|
||
]
|
||
command_batch = {
|
||
"id": "2025IVD-CL-0520-001",
|
||
"status": "进行中",
|
||
"workflow": "境内第三类",
|
||
"class": "III 类",
|
||
"created_at": "2025-05-20",
|
||
"applicant": "某某生物科技有限公司",
|
||
"reviewer": "张审评员",
|
||
"role": "审评专家",
|
||
"standard": "《体外诊断试剂注册与备案管理办法》及配套技术指导原则",
|
||
"version": "V2.1(2025-04-01)",
|
||
}
|
||
command_metrics = [
|
||
{
|
||
"key": "completeness",
|
||
"label": "资料包完整性得分",
|
||
"value": "68",
|
||
"suffix": "/100",
|
||
"level": "较差",
|
||
"detail": "上次得分 61(2025-05-19)",
|
||
},
|
||
{
|
||
"key": "health",
|
||
"label": "资料包健康度",
|
||
"value": "62",
|
||
"suffix": "项检查项",
|
||
"segments": [
|
||
{"label": "完整", "value": "28", "hint": "45%"},
|
||
{"label": "部分缺失", "value": "18", "hint": "29%"},
|
||
{"label": "缺失", "value": "16", "hint": "26%"},
|
||
],
|
||
},
|
||
{
|
||
"key": "risk",
|
||
"label": "风险分布",
|
||
"value": "22",
|
||
"suffix": "项风险",
|
||
"segments": [
|
||
{"label": "高风险", "value": "3", "tone": "danger"},
|
||
{"label": "中风险", "value": "7", "tone": "warning"},
|
||
{"label": "低风险", "value": "12", "tone": "success"},
|
||
],
|
||
},
|
||
{
|
||
"key": "progress",
|
||
"label": "审核进度",
|
||
"value": "46",
|
||
"suffix": "%",
|
||
"detail": "已完成 24 / 52 项任务",
|
||
},
|
||
]
|
||
command_flow = [
|
||
{"step": "1", "title": "资料准备", "date": "2025-05-20", "state": "done"},
|
||
{"step": "2", "title": "形式审查", "date": "2025-05-21", "state": "done"},
|
||
{"step": "3", "title": "技术审评", "date": "进行中", "state": "active"},
|
||
{"step": "4", "title": "核查检验", "date": "待开始", "state": "todo"},
|
||
{"step": "5", "title": "综合评审", "date": "待开始", "state": "todo"},
|
||
{"step": "6", "title": "行政审批", "date": "待开始", "state": "todo"},
|
||
{"step": "7", "title": "制证发证", "date": "待开始", "state": "todo"},
|
||
]
|
||
command_tabs = [
|
||
{"id": "completeness", "label": "注册完整性核查"},
|
||
{"id": "consistency", "label": "字段一致性"},
|
||
{"id": "risk", "label": "风险准入结论"},
|
||
{"id": "evidence", "label": "证据引用"},
|
||
{"id": "feishu", "label": "飞书通知状态"},
|
||
]
|
||
command_checks = [
|
||
{
|
||
"chapter": "1.产品基本信息",
|
||
"item": "产品名称",
|
||
"rule": "办法 第十条",
|
||
"status": "完整",
|
||
"risk": "低风险",
|
||
"problem": "-",
|
||
},
|
||
{
|
||
"chapter": "1.产品基本信息",
|
||
"item": "预期用途",
|
||
"rule": "办法 第十条",
|
||
"status": "完整",
|
||
"risk": "低风险",
|
||
"problem": "-",
|
||
},
|
||
{
|
||
"chapter": "2.综述资料",
|
||
"item": "产品描述",
|
||
"rule": "指导原则4.2.1",
|
||
"status": "完整",
|
||
"risk": "低风险",
|
||
"problem": "-",
|
||
},
|
||
{
|
||
"chapter": "2.综述资料",
|
||
"item": "作用原理",
|
||
"rule": "指导原则4.2.2",
|
||
"status": "部分缺失",
|
||
"risk": "中风险",
|
||
"problem": "缺少关键原理图及验证数据说明",
|
||
},
|
||
{
|
||
"chapter": "3.研究资料",
|
||
"item": "分析性能评估",
|
||
"rule": "指导原则5.3.1",
|
||
"status": "部分缺失",
|
||
"risk": "中风险",
|
||
"problem": "线性范围验证数据不完整",
|
||
},
|
||
{
|
||
"chapter": "3.研究资料",
|
||
"item": "阳性判断值",
|
||
"rule": "指导原则5.3.2",
|
||
"status": "缺失",
|
||
"risk": "高风险",
|
||
"problem": "未提供阳性判断值确定依据",
|
||
},
|
||
{
|
||
"chapter": "4.临床评价资料",
|
||
"item": "临床试验方案",
|
||
"rule": "指导原则6.2.1",
|
||
"status": "完整",
|
||
"risk": "低风险",
|
||
"problem": "-",
|
||
},
|
||
{
|
||
"chapter": "4.临床评价资料",
|
||
"item": "临床试验报告",
|
||
"rule": "指导原则6.2.2",
|
||
"status": "部分缺失",
|
||
"risk": "中风险",
|
||
"problem": "有效性结果分析不完整",
|
||
},
|
||
{
|
||
"chapter": "4.临床评价资料",
|
||
"item": "不良事件汇总分析",
|
||
"rule": "指导原则6.2.4",
|
||
"status": "缺失",
|
||
"risk": "高风险",
|
||
"problem": "未提供不良事件汇总分析报告",
|
||
},
|
||
{
|
||
"chapter": "5.生产资料",
|
||
"item": "生产工艺验证",
|
||
"rule": "指导原则7.2.3",
|
||
"status": "完整",
|
||
"risk": "低风险",
|
||
"problem": "-",
|
||
},
|
||
]
|
||
key_risks = [
|
||
{"title": "阳性判断值确定依据缺失", "level": "高风险"},
|
||
{"title": "不良事件汇总分析报告缺失", "level": "高风险"},
|
||
{"title": "临床试验方案偏离未充分说明", "level": "中风险"},
|
||
]
|
||
next_actions = [
|
||
{"title": "退回企业补充资料", "detail": "需企业补充 3 项高风险资料", "state": "待处理", "tone": "danger"},
|
||
{"title": "补充说明或澄清", "detail": "需企业说明 7 项中风险问题", "state": "待处理", "tone": "warning"},
|
||
{"title": "进入核查检验环节(可选)", "detail": "风险可控后进入下一环节", "state": "待处理", "tone": "success"},
|
||
]
|
||
owners = [
|
||
{"role": "审评专家", "name": "张审评员", "status": "当前处理人"},
|
||
{"role": "审核组长", "name": "李组长", "status": "待确认"},
|
||
{"role": "法规专员", "name": "王法规", "status": "协同处理"},
|
||
{"role": "临床专家", "name": "陈专家", "status": "协同处理"},
|
||
]
|
||
operation_logs = [
|
||
{"time": "2025-05-21 10:24", "actor": "张审评员", "action": "发起完整性核查"},
|
||
{"time": "2025-05-21 10:26", "actor": "Agent Core", "action": "命中 62 项检查规则"},
|
||
{"time": "2025-05-21 10:28", "actor": "Agent Core", "action": "生成风险准入结论"},
|
||
]
|
||
knowledge_filters = [
|
||
{"label": "全部", "active": True},
|
||
{"label": "法规依据", "active": False},
|
||
{"label": "模板规则", "active": False},
|
||
{"label": "业务资料", "active": False},
|
||
]
|
||
knowledge_form = {
|
||
"title": "新增 / 编辑知识源",
|
||
"fields": [
|
||
{"label": "知识源名称", "value": "体外诊断试剂注册申报资料要求及说明"},
|
||
{"label": "知识源类型", "value": "法规依据"},
|
||
{"label": "适用流程", "value": "registration"},
|
||
{"label": "状态", "value": "已生效"},
|
||
{"label": "切片策略", "value": "按章条切片,保留条款编号"},
|
||
],
|
||
}
|
||
rule_form = {
|
||
"title": "新增 / 编辑规则项",
|
||
"fields": [
|
||
{"label": "规则编码", "value": "RULE-005"},
|
||
{"label": "所属章节", "value": "CH1 监管信息"},
|
||
{"label": "规则名称", "value": "申请表签章完整性检查"},
|
||
{"label": "模板字段", "value": "签章页 / 申请人签字"},
|
||
{"label": "规则说明", "value": "若申请表缺少签章,则标记为高优先级缺失项"},
|
||
],
|
||
}
|
||
return {
|
||
"batch": batch,
|
||
"metrics": metrics,
|
||
"workflow_overview": workflow_overview,
|
||
"risk_board": risk_board,
|
||
"quick_links": quick_links,
|
||
"knowledge_sources": knowledge_sources,
|
||
"rule_tree": rule_tree,
|
||
"knowledge_stats": knowledge_stats,
|
||
"governance_sections": governance_sections,
|
||
"rag_chunks": rag_chunks,
|
||
"field_schemas": field_schemas,
|
||
"owner_mappings": owner_mappings,
|
||
"feishu_configs": feishu_configs,
|
||
"template_mappings": template_mappings,
|
||
"knowledge_filters": knowledge_filters,
|
||
"knowledge_form": knowledge_form,
|
||
"rule_form": rule_form,
|
||
"mcp_connectors": mcp_connectors,
|
||
"skills": skills,
|
||
"workflow_steps": workflow_steps,
|
||
"command_batch": command_batch,
|
||
"command_metrics": command_metrics,
|
||
"command_flow": command_flow,
|
||
"command_tabs": command_tabs,
|
||
"command_checks": command_checks,
|
||
"key_risks": key_risks,
|
||
"next_actions": next_actions,
|
||
"owners": owners,
|
||
"operation_logs": operation_logs,
|
||
}
|