From 3da774e5374576aedbce233256fab0ed06e8626f Mon Sep 17 00:00:00 2001 From: bruce Date: Wed, 3 Jun 2026 23:00:22 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=8E=9F=E5=9E=8B=E8=AE=BE=E8=AE=A1):=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=9F=A5=E8=AF=86=E5=BA=93=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E4=B8=8E=E6=B5=81=E7=A8=8B=E7=8A=B6=E6=80=81=E5=8D=A1=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../原型设计/registration-prototype-demo.html | 486 ++++++++++++++++-- 1 file changed, 442 insertions(+), 44 deletions(-) diff --git a/docs/原型设计/registration-prototype-demo.html b/docs/原型设计/registration-prototype-demo.html index 4440f66..b669f82 100644 --- a/docs/原型设计/registration-prototype-demo.html +++ b/docs/原型设计/registration-prototype-demo.html @@ -355,6 +355,21 @@ font-size: 12px; } + .task-status-line { + display: flex; + justify-content: space-between; + align-items: center; + gap: 10px; + margin-bottom: 10px; + } + + .task-note { + color: var(--muted); + font-size: 12px; + line-height: 1.6; + min-height: 40px; + } + .task-meta { display: flex; justify-content: space-between; @@ -488,6 +503,155 @@ gap: 14px; } + .phase-board { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 12px; + } + + .phase-card { + padding: 14px; + border-radius: var(--radius-lg); + background: #f8fafb; + border: 1px solid #dbe4eb; + min-height: 142px; + display: grid; + gap: 10px; + align-content: start; + } + + .phase-card.running { + background: #eef4fb; + border-color: #bfd2e3; + box-shadow: inset 0 0 0 1px rgba(32, 74, 112, 0.06); + } + + .phase-card.completed { + background: #eff8f2; + border-color: #c8dfcf; + } + + .phase-card.blocked { + background: #fff3ef; + border-color: #efc7bc; + } + + .phase-card.pending { + background: #f8fafb; + border-color: #dbe4eb; + } + + .phase-head { + display: flex; + justify-content: space-between; + align-items: flex-start; + gap: 10px; + } + + .phase-card strong { + font-size: 15px; + line-height: 1.4; + } + + .phase-state { + font-size: 12px; + font-weight: 700; + color: var(--muted); + line-height: 1.4; + } + + .phase-note { + color: var(--muted); + font-size: 12px; + line-height: 1.7; + } + + .phase-card.running .phase-state { + color: var(--navy); + } + + .phase-card.completed .phase-state { + color: var(--success); + } + + .phase-card.blocked .phase-state { + color: var(--danger); + } + + .knowledge-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 14px; + } + + .knowledge-card { + padding: 16px; + border-radius: var(--radius-lg); + background: var(--panel-strong); + border: 1px solid var(--line); + display: grid; + gap: 12px; + } + + .knowledge-card p { + margin: 0; + color: var(--muted); + line-height: 1.7; + font-size: 13px; + } + + .knowledge-stat { + font-size: 28px; + font-weight: 800; + color: var(--navy-strong); + line-height: 1; + } + + .knowledge-actions { + display: flex; + flex-wrap: wrap; + gap: 8px; + } + + .upload-zone { + border: 1px dashed #a7bacb; + background: linear-gradient(180deg, #f9fbfc 0%, #f3f7fa 100%); + border-radius: var(--radius-lg); + padding: 20px; + display: grid; + gap: 12px; + } + + .upload-zone strong { + font-size: 16px; + } + + .upload-list { + display: grid; + gap: 10px; + } + + .upload-item { + padding: 12px 14px; + border-radius: var(--radius-md); + border: 1px solid #dbe4eb; + background: #f8fafb; + display: grid; + grid-template-columns: 1fr auto; + gap: 12px; + align-items: center; + } + + .upload-item strong { + display: block; + margin-bottom: 6px; + } + + .upload-item .muted { + color: #5f7285; + line-height: 1.6; + } + .alert { padding: 14px 16px; border-radius: var(--radius-md); @@ -848,7 +1012,9 @@ .metric-grid, .task-grid, - .copy-grid { + .copy-grid, + .phase-board, + .knowledge-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } } @@ -865,7 +1031,9 @@ .metric-grid, .task-grid, - .copy-grid { + .copy-grid, + .phase-board, + .knowledge-grid { grid-template-columns: 1fr; } @@ -959,6 +1127,56 @@ { id: "risk", name: "风险预警", status: "已完成", metric: "高风险", detail: "综合结论不通过,建议先整改" }, { id: "word", name: "Word 回填导出", status: "已阻断", metric: "仅草稿可导出", detail: "正式版被高风险与冲突字段拦截" }, ], + taskStatusMap: { + pending: "待执行", + running: "执行中", + completed: "已完成", + blocked: "已阻断" + }, + processFlows: { + import: [ + { key: "upload", title: "资料上传", state: "completed", stateText: "上传完成", note: "18 份文件和 1 个压缩包已建立批次。" }, + { key: "parse", title: "文档解析", state: "running", stateText: "解析中", note: "正在提取目录结构、页数与文档元数据。" }, + { key: "recognize", title: "章节点识别", state: "pending", stateText: "待执行", note: "待文档解析完成后自动识别 CH 章节节点。" }, + { key: "summary", title: "目录汇总", state: "pending", stateText: "待执行", note: "将生成 registration_overview_report 并写入工作台。" } + ], + completeness: [ + { key: "load-rules", title: "加载规则包", state: "completed", stateText: "已完成", note: "已装载 NMPA IVD 注册资料规则包。" }, + { key: "compare-items", title: "必交项比对", state: "running", stateText: "核查中", note: "对照 CH1 资料要求检查缺失项与错放项。" }, + { key: "evidence", title: "法规证据关联", state: "pending", stateText: "待执行", note: "待生成命中法规条款与证据摘要。" }, + { key: "risk-tag", title: "完整性风险判定", state: "pending", stateText: "待执行", note: "将输出完整性风险等级和责任角色。" } + ], + fields: [ + { key: "ocr", title: "文本准备", state: "completed", stateText: "已完成", note: "OCR / 文本抽取结果已就绪。" }, + { key: "extract", title: "字段抽取", state: "running", stateText: "抽取中", note: "按字段 Schema 从说明书与申请表中抽取字段。" }, + { key: "pool", title: "字段池写入", state: "pending", stateText: "待执行", note: "将沉淀字段值、来源、置信度与回填标记。" }, + { key: "review", title: "待复核标记", state: "pending", stateText: "待执行", note: "对低置信度字段追加人工复核状态。" } + ], + consistency: [ + { key: "load-pool", title: "加载字段池", state: "completed", stateText: "已完成", note: "已读取统一字段池和强一致字段定义。" }, + { key: "compare", title: "来源对比", state: "running", stateText: "核查中", note: "正在比较说明书、申请表和章节文档取值。" }, + { key: "mix-risk", title: "混档风险分析", state: "pending", stateText: "待执行", note: "将输出疑似混档与来源偏差解释。" }, + { key: "conflict", title: "冲突结论生成", state: "pending", stateText: "待执行", note: "生成冲突字段列表和建议采用值。" } + ], + risk: [ + { key: "collect", title: "风险汇总", state: "completed", stateText: "已完成", note: "已汇总完整性、一致性和待复核结论。" }, + { key: "grade", title: "风险评级", state: "running", stateText: "判定中", note: "按高 / 中 / 低规则综合判定当前批次。" }, + { key: "rectify", title: "整改建议生成", state: "pending", stateText: "待执行", note: "将结合责任角色输出整改动作。" }, + { key: "gate", title: "导出闸门决策", state: "pending", stateText: "待执行", note: "将决定是否允许正式版回填导出。" } + ], + word: [ + { key: "mapping", title: "模板映射加载", state: "completed", stateText: "已完成", note: "已读取 Word 模板占位符和字段映射。" }, + { key: "fill", title: "字段回填", state: "running", stateText: "回填中", note: "正在把可回填字段写入草稿模板。" }, + { key: "block", title: "拦截校验", state: "blocked", stateText: "已阻断", note: "正式版被高风险和冲突字段命中拦截。" }, + { key: "download", title: "导出结果生成", state: "pending", stateText: "待执行", note: "仅草稿下载入口会在拦截后继续保留。" } + ], + notification: [ + { key: "compose", title: "消息编排", state: "completed", stateText: "已完成", note: "已生成飞书交互卡片内容。" }, + { key: "mention", title: "责任人映射", state: "running", stateText: "匹配中", note: "正在匹配章节责任人与风险责任人账号。" }, + { key: "link", title: "Web 详情链接", state: "pending", stateText: "待执行", note: "待拼装批次详情跳转链接。" }, + { key: "send", title: "发送回执", state: "pending", stateText: "待执行", note: "发送后将写入 message_id 和 sent_at。" } + ] + }, importTimeline: [ { step: "创建批次", status: "已完成", detail: "创建 SUB-20260603-001,来源角色为 submission。" }, { step: "文件校验", status: "已完成", detail: "18 份文件通过校验,1 份 DOC 标记待复核。" }, @@ -973,6 +1191,28 @@ { path: "第1章 监管信息/CH1.9 产品申报前沟通的说明.doc", type: "DOC", pages: "待复核", confidence: "低", chapter: "CH1.9", name: "沟通说明", status: "待复核", hit: "是" }, { path: "说明书/目标产品说明书.docx", type: "DOCX", pages: "18", confidence: "精确", chapter: "CH3", name: "产品说明书", status: "已汇总", hit: "是" }, ], + knowledgeBase: { + summary: [ + { label: "知识库资料数", value: "27", note: "法规、模板、示例资料统一管理" }, + { label: "待入库任务", value: "3", note: "含 1 个法规包更新和 2 个业务资料" }, + { label: "有效切片数", value: "486", note: "支持 RAG 召回与规则辅助解释" }, + { label: "启用规则包", value: "4", note: "注册审核与一致性规则均已启用" } + ], + uploadQueue: [ + { name: "体外诊断试剂注册申报资料要求及说明_2026修订版.docx", type: "法规资料", owner: "法规管理员", state: "文档解析中", detail: "已上传,正在提取章节标题与法规条款。" }, + { name: "说明书模板映射补充包.zip", type: "模板资料", owner: "数据治理专员", state: "解析完成", detail: "已识别 12 个占位符映射,待进入数据处理。" }, + { name: "注册申报常见问题汇编.docx", type: "业务知识", owner: "注册经理", state: "数据处理中", detail: "正在生成切片、关键词和召回标签。" }, + { name: "临床评价参考示例.pdf", type: "示例资料", owner: "医学专员", state: "处理完成", detail: "已入知识库并开放检索使用。" } + ], + cards: [ + { title: "法规规则包", value: "4", desc: "维护完整性检查、一致性判断和风险等级规则。", actions: ["新增规则包", "上传新版", "停用旧版"] }, + { title: "RAG 文档源", value: "27", desc: "手动上传法规原文、模板文档、示例资料和内部 SOP。", actions: ["上传文档", "编辑标签", "重新入库"] }, + { title: "切片与召回", value: "486", desc: "查看切片状态、命中场景、阈值和是否可召回。", actions: ["新增切片", "拆分切片", "重建向量"] }, + { title: "字段 Schema", value: "38", desc: "统一字段标准、是否可回填、强一致约束和来源优先级。", actions: ["新增字段", "编辑字段", "复制版本"] }, + { title: "模板与映射", value: "9", desc: "维护 Word 模板、占位符映射和导出阻断约束。", actions: ["上传模板", "编辑映射", "预览模板"] }, + { title: "通知与责任人", value: "12", desc: "维护责任角色映射、飞书群聊、机器人和消息模板。", actions: ["新增映射", "发送测试", "查看回执"] } + ] + }, completeness: { summary: [ { label: "必交项", value: "8" }, @@ -1263,6 +1503,7 @@ const navConfig = [ { id: "workspace", name: "审核任务工作台", subtitle: "7 个流程任务卡片和执行状态" }, + { id: "knowledge", name: "知识库管理页", subtitle: "手动上传资料、入库状态、治理动作" }, { id: "import", name: "资料包导入页", subtitle: "上传、目录、页数、章节点" }, { id: "completeness", name: "法规完整性检查页", subtitle: "缺失项、错放项、法规依据" }, { id: "fields", name: "字段抽取与字段池页", subtitle: "字段表、来源、置信度、待复核" }, @@ -1279,6 +1520,7 @@ const pageTitle = document.getElementById("pageTitle"); const governanceDrawer = document.getElementById("governanceDrawer"); const overlay = document.getElementById("overlay"); + let activePageId = "workspace"; function metricCards(items) { return `
${items.map(item => ` @@ -1373,7 +1615,76 @@ `; } + function renderProcessFlow(flowKey) { + const items = data.processFlows[flowKey] || []; + return ` +
+ ${items.map(item => ` +
+
+ ${item.title} + ${item.stateText} +
+ + ${data.taskStatusMap[item.state] || item.stateText} + +
${item.note}
+
+ `).join("")} +
+ `; + } + + function buildLiveTasks(currentPageId) { + return data.tasks.map(task => { + const flow = data.processFlows[task.id]; + if (!flow) { + return task; + } + + const blocked = flow.find(item => item.state === "blocked"); + const running = currentPageId === task.id ? flow.find(item => item.state === "running") : null; + const pendingCount = flow.filter(item => item.state === "pending").length; + const completedCount = flow.filter(item => item.state === "completed").length; + + if (blocked) { + return { + ...task, + status: "已阻断", + metric: blocked.stateText, + detail: blocked.note + }; + } + + if (running) { + return { + ...task, + status: running.stateText, + metric: `${completedCount}/${flow.length} 已完成`, + detail: running.note + }; + } + + if (pendingCount === 0) { + return { + ...task, + status: "已完成", + metric: `${flow.length}/${flow.length} 已完成`, + detail: task.detail + }; + } + + return { + ...task, + status: "待执行", + metric: `${completedCount}/${flow.length} 已完成`, + detail: task.detail + }; + }); + } + function renderWorkspacePage() { + const liveTasks = buildLiveTasks(activePageId); return `
@@ -1413,17 +1724,20 @@

七个流程任务卡片

-

点击卡片可以直接切换到对应页面。

+

点击卡片切换流程页面后,状态会实时更新为当前动作。

- ${data.tasks.map(task => ` -
- ${task.status} + ${liveTasks.map(task => ` +
+
+ ${task.status} + ${task.metric} +

${task.name}

-

${task.detail}

+
${task.detail}
- ${task.metric} + 进入流程 查看详情
@@ -1521,6 +1835,98 @@ `; } + function renderKnowledgePage() { + return ` +
+ ${metricCards(data.knowledgeBase.summary)} +
+
+
+
+

知识库管理

+

手动上传法规、模板、示例资料和内部业务知识,统一进入 Agent 可用知识库。

+
+ +
+
+ 手动上传知识库资料 +
支持批量上传 pdf / docx / doc / zip,并按“法规资料 / 模板资料 / 示例资料 / 内部 SOP”进行分类。
+
+ + + +
+
+
+
+
+
+

入库处理状态

+

通过卡片实时展示每份资料的处理动作。

+
+
+
+ ${data.knowledgeBase.uploadQueue.map(item => ` +
+
+ ${item.name} +
${item.type} · 责任人:${item.owner}
${item.detail}
+
+ ${item.state} +
+ `).join("")} +
+
+
+
+
+
+

知识库能力卡片

+

原有治理内容收拢为卡片式入口,适合演示 Agent 依赖的知识管理能力。

+
+
+
+ ${data.knowledgeBase.cards.map(card => ` +
+
${card.title}
+
${card.value}
+

${card.desc}

+
+ ${card.actions.map(action => ``).join("")} +
+
+ `).join("")} +
+
+
+
+
+
+

入库动作流

+

模拟上传后的后台流水线动作。

+
+
+ ${renderProcessFlow("import")} +
+
+
+
+

Agent 如何使用知识库

+

上传并入库后,后续页面会自动引用这些知识进行解释和核查。

+
+
+
+
法规资料进入 RAG 文档源,用于完整性检查时的法规依据解释。
+
模板资料进入模板映射中心,用于 Word 回填与导出拦截。
+
业务示例进入示例知识库,用于字段抽取提示和冲突解释增强。
+
责任人和通知配置会驱动飞书通知中的 @ 与 Web 详情链接。
+
+
+
+
+ `; + } + function renderImportPage() { return `
@@ -1553,21 +1959,10 @@

处理流水线

-

展示导入后每个环节的处理状态。

+

进入本流程后,状态卡片会切换到当前执行动作。

-
- ${data.importTimeline.map((item, idx) => ` -
-
${idx + 1}
-
- ${item.step} -
${item.detail}
-
- ${item.status} -
- `).join("")} -
+ ${renderProcessFlow("import")}
@@ -2142,6 +2537,7 @@ const pageTemplates = { workspace: renderWorkspacePage, + knowledge: renderKnowledgePage, import: renderImportPage, completeness: renderCompletenessPage, fields: renderFieldsPage, @@ -2206,6 +2602,8 @@ } function setActivePage(pageId) { + activePageId = pageId; + renderPages(); document.querySelectorAll(".page").forEach(page => { page.classList.toggle("active", page.dataset.page === pageId); }); @@ -2275,34 +2673,34 @@ panel.classList.toggle("active", panel.dataset.governancePanel === id); }); } + + if (event.target.closest("#draftBtn")) { + document.getElementById("downloadBox").innerHTML = ` +
+ 注册申报表格_回填草稿_v2.docx +
状态:草稿已重新生成 · 版式校验:通过 · 时间:2026-06-03 10:42
+
+ + `; + } + + if (event.target.closest("#formalBtn")) { + alert("正式导出已被阻断:当前批次存在高风险和冲突字段,请先完成整改。"); + } + + if (event.target.closest("#sendBtn")) { + document.getElementById("receiptBox").className = "alert success"; + document.getElementById("receiptBox").innerHTML = ` + 已发送至飞书群聊 oc_demo_chat
+ message_id:${data.notification.receipt.id}
+ sent_at:${data.notification.receipt.time} + `; + } }); document.getElementById("openDrawerBtn").addEventListener("click", () => openGovernance("rules")); document.getElementById("closeDrawerBtn").addEventListener("click", closeGovernance); overlay.addEventListener("click", closeGovernance); - - document.getElementById("draftBtn")?.addEventListener("click", () => { - document.getElementById("downloadBox").innerHTML = ` -
- 注册申报表格_回填草稿_v2.docx -
状态:草稿已重新生成 · 版式校验:通过 · 时间:2026-06-03 10:42
-
- - `; - }); - - document.getElementById("formalBtn")?.addEventListener("click", () => { - alert("正式导出已被阻断:当前批次存在高风险和冲突字段,请先完成整改。"); - }); - - document.getElementById("sendBtn")?.addEventListener("click", () => { - document.getElementById("receiptBox").className = "alert success"; - document.getElementById("receiptBox").innerHTML = ` - 已发送至飞书群聊 oc_demo_chat
- message_id:${data.notification.receipt.id}
- sent_at:${data.notification.receipt.time} - `; - });