docs(iit): Add QC system UI and LLM format optimization plan

- Add development plan: 07-QC system UI and LLM format optimization

- Phase 1: PromptBuilder + XML clinical slice format (~5.5h)

- Phase 2: QC cockpit + stat cards + risk heatmap (~9.5h)

- Phase 3: Variable tagging system (~5h)

- Add CRA Agent design document and prototype

- Update module status: design 100%, code 45%

- Update system status: real-time QC complete + plan ready

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-08 09:59:44 +08:00
parent 5db4a7064c
commit 45c7b32dbb
6 changed files with 1234 additions and 15 deletions

View File

@@ -0,0 +1,598 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>IIT Manager - CRA 智能监查驾驶舱</title>
<!-- 引入 Tailwind CSS 进行快速样式构建 -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- 引入 FontAwesome 图标 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<!-- 引入 Google Fonts (Inter) -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
body { font-family: 'Inter', sans-serif; }
/* 自定义滚动条 */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: #f1f1f1; }
::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: #94a3b8; }
/* 模拟代码高亮 */
.xml-tag { color: #2563eb; }
.xml-attr { color: #9333ea; }
.xml-val { color: #16a34a; }
.xml-content { color: #374151; }
/* 动画 */
.slide-in-right {
animation: slideIn 0.3s ease-out forwards;
}
@keyframes slideIn {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
</style>
</head>
<body class="bg-gray-50 text-gray-800 h-screen flex overflow-hidden">
<!-- 左侧导航栏 -->
<aside class="w-64 bg-slate-900 text-white flex-shrink-0 flex flex-col transition-all duration-300">
<div class="h-16 flex items-center px-6 border-b border-slate-800">
<div class="flex items-center gap-2">
<div class="w-8 h-8 bg-blue-500 rounded-lg flex items-center justify-center">
<i class="fas fa-robot text-white text-sm"></i>
</div>
<span class="font-bold text-lg tracking-tight">IIT Manager</span>
</div>
</div>
<nav class="flex-1 py-6 px-3 space-y-1">
<a href="#" onclick="switchTab('overview')" class="nav-item flex items-center gap-3 px-3 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800 hover:text-white transition-colors">
<i class="fas fa-chart-pie w-5 text-center"></i>
<span>项目概览</span>
</a>
<!-- 激活状态 -->
<a href="#" onclick="switchTab('cockpit')" class="nav-item active flex items-center gap-3 px-3 py-2.5 rounded-lg bg-blue-600 text-white shadow-lg shadow-blue-900/20 transition-colors">
<i class="fas fa-table-cells w-5 text-center"></i>
<span>智能监查驾驶舱</span>
</a>
<a href="#" onclick="switchTab('rules')" class="nav-item flex items-center gap-3 px-3 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800 hover:text-white transition-colors">
<i class="fas fa-sliders w-5 text-center"></i>
<span>规则配置中心</span>
</a>
<div class="pt-4 mt-4 border-t border-slate-800">
<p class="px-3 text-xs font-semibold text-slate-500 uppercase tracking-wider mb-2">数据管理</p>
<a href="#" class="flex items-center gap-3 px-3 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800 hover:text-white transition-colors">
<i class="fas fa-users w-5 text-center"></i>
<span>受试者管理</span>
</a>
<a href="#" class="flex items-center gap-3 px-3 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800 hover:text-white transition-colors">
<i class="fas fa-database w-5 text-center"></i>
<span>REDCap 同步</span>
</a>
</div>
</nav>
<div class="p-4 border-t border-slate-800">
<div class="flex items-center gap-3">
<img src="https://ui-avatars.com/api/?name=Admin&background=random" class="w-8 h-8 rounded-full">
<div>
<p class="text-sm font-medium">Dr. Admin</p>
<p class="text-xs text-slate-500">项目管理员</p>
</div>
</div>
</div>
</aside>
<!-- 主内容区 -->
<main class="flex-1 flex flex-col min-w-0 overflow-hidden relative">
<!-- 顶部栏 -->
<header class="h-16 bg-white border-b border-gray-200 flex items-center justify-between px-8 flex-shrink-0 z-10">
<div>
<h1 class="text-xl font-bold text-gray-800" id="page-title">CRA 智能监查驾驶舱</h1>
<p class="text-xs text-gray-500 mt-0.5">项目: 肺癌靶向治疗研究 (PID: 16) | 最后同步: 10分钟前</p>
</div>
<div class="flex items-center gap-4">
<button class="px-4 py-2 bg-white border border-gray-300 text-gray-700 rounded-lg text-sm font-medium hover:bg-gray-50 flex items-center gap-2">
<i class="fas fa-sync-alt"></i> 全量质控
</button>
<button class="px-4 py-2 bg-blue-600 text-white rounded-lg text-sm font-medium hover:bg-blue-700 shadow-sm flex items-center gap-2">
<i class="fas fa-file-export"></i> 导出监查报告
</button>
</div>
</header>
<!-- 视图容器 -->
<div id="content-area" class="flex-1 overflow-auto p-8 bg-gray-50 relative">
<!-- VIEW 1: 智能监查驾驶舱 (Risk Heatmap) -->
<div id="view-cockpit" class="view-section space-y-6">
<!-- 统计卡片 -->
<div class="grid grid-cols-1 md:grid-cols-4 gap-6">
<div class="bg-white p-5 rounded-xl border border-gray-200 shadow-sm">
<div class="flex justify-between items-start">
<div>
<p class="text-sm text-gray-500 font-medium">总体数据质量分</p>
<h3 class="text-3xl font-bold text-gray-800 mt-2">92 <span class="text-sm font-normal text-gray-400">/100</span></h3>
</div>
<span class="p-2 bg-green-100 text-green-600 rounded-lg"><i class="fas fa-heartbeat"></i></span>
</div>
<div class="mt-4 w-full bg-gray-100 rounded-full h-1.5">
<div class="bg-green-500 h-1.5 rounded-full" style="width: 92%"></div>
</div>
</div>
<div class="bg-white p-5 rounded-xl border border-gray-200 shadow-sm border-l-4 border-l-red-500">
<div class="flex justify-between items-start">
<div>
<p class="text-sm text-gray-500 font-medium">严重违规 (Critical)</p>
<h3 class="text-3xl font-bold text-red-600 mt-2">3 <span class="text-sm font-normal text-gray-500"></span></h3>
</div>
<span class="p-2 bg-red-100 text-red-600 rounded-lg"><i class="fas fa-exclamation-triangle"></i></span>
</div>
<p class="text-xs text-red-500 mt-3 font-medium">需立即处理:入排标准违背 (2)</p>
</div>
<div class="bg-white p-5 rounded-xl border border-gray-200 shadow-sm border-l-4 border-l-yellow-400">
<div class="flex justify-between items-start">
<div>
<p class="text-sm text-gray-500 font-medium">待确认 Query (Major)</p>
<h3 class="text-3xl font-bold text-yellow-600 mt-2">12 <span class="text-sm font-normal text-gray-500"></span></h3>
</div>
<span class="p-2 bg-yellow-100 text-yellow-600 rounded-lg"><i class="fas fa-question-circle"></i></span>
</div>
<p class="text-xs text-yellow-600 mt-3">主要是实验室数据异常</p>
</div>
<div class="bg-white p-5 rounded-xl border border-gray-200 shadow-sm">
<div class="flex justify-between items-start">
<div>
<p class="text-sm text-gray-500 font-medium">方案偏离 (PD)</p>
<h3 class="text-3xl font-bold text-gray-800 mt-2">5 <span class="text-sm font-normal text-gray-500"></span></h3>
</div>
<span class="p-2 bg-purple-100 text-purple-600 rounded-lg"><i class="fas fa-clock"></i></span>
</div>
<p class="text-xs text-gray-500 mt-3">大多为访视超窗</p>
</div>
</div>
<!-- 风险热力图 (The Matrix) -->
<div class="bg-white rounded-xl border border-gray-200 shadow-sm overflow-hidden">
<div class="px-6 py-4 border-b border-gray-200 flex justify-between items-center bg-gray-50">
<h3 class="font-bold text-gray-800">受试者风险全景图 (Risk Heatmap)</h3>
<div class="flex items-center gap-4 text-xs text-gray-500">
<span class="flex items-center gap-1"><span class="w-3 h-3 rounded-full bg-green-500"></span> 无异常</span>
<span class="flex items-center gap-1"><span class="w-3 h-3 rounded-full bg-yellow-400"></span> 疑问 (Query)</span>
<span class="flex items-center gap-1"><span class="w-3 h-3 rounded-full bg-red-500"></span> 严重违规</span>
<span class="flex items-center gap-1"><span class="w-3 h-3 rounded-full bg-gray-200"></span> 未开始</span>
</div>
</div>
<div class="overflow-x-auto">
<table class="w-full text-sm text-left">
<thead class="text-xs text-gray-500 uppercase bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-6 py-3 font-medium">受试者 ID</th>
<th class="px-6 py-3 font-medium">入组状态</th>
<th class="px-4 py-3 text-center">Screening<br>(筛查期)</th>
<th class="px-4 py-3 text-center">Baseline<br>(基线期)</th>
<th class="px-4 py-3 text-center">Visit 1<br>(第1周)</th>
<th class="px-4 py-3 text-center">Visit 2<br>(第4周)</th>
<th class="px-4 py-3 text-center">AE Log<br>(不良事件)</th>
<th class="px-4 py-3 text-center">CM Log<br>(合并用药)</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
<!-- 行 1: 有严重问题 -->
<tr class="hover:bg-gray-50 transition-colors">
<td class="px-6 py-4 font-medium text-gray-900">SUB-001</td>
<td class="px-6 py-4"><span class="px-2 py-1 bg-green-100 text-green-700 text-xs rounded-full">已入组</span></td>
<!-- 红色单元格:可点击 -->
<td class="px-4 py-4 text-center cursor-pointer hover:bg-red-50" onclick="openDrawer('SUB-001', 'Screening')">
<div class="w-8 h-8 rounded-lg bg-red-500 text-white flex items-center justify-center mx-auto shadow-sm shadow-red-200 transition-transform hover:scale-110">
<i class="fas fa-times"></i>
</div>
</td>
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-gray-200 mx-auto"></div></td>
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
</tr>
<!-- 行 2: 有警告 -->
<tr class="hover:bg-gray-50 transition-colors">
<td class="px-6 py-4 font-medium text-gray-900">SUB-002</td>
<td class="px-6 py-4"><span class="px-2 py-1 bg-green-100 text-green-700 text-xs rounded-full">已入组</span></td>
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
<td class="px-4 py-4 text-center cursor-pointer hover:bg-yellow-50">
<div class="w-8 h-8 rounded-lg bg-yellow-400 text-white flex items-center justify-center mx-auto shadow-sm shadow-yellow-200 transition-transform hover:scale-110">
<i class="fas fa-exclamation"></i>
</div>
</td>
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
</tr>
<!-- 更多行... -->
<tr class="hover:bg-gray-50 transition-colors">
<td class="px-6 py-4 font-medium text-gray-900">SUB-003</td>
<td class="px-6 py-4"><span class="px-2 py-1 bg-blue-100 text-blue-700 text-xs rounded-full">筛查中</span></td>
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-green-500 mx-auto"></div></td>
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-gray-200 mx-auto"></div></td>
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-gray-200 mx-auto"></div></td>
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-gray-200 mx-auto"></div></td>
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-gray-200 mx-auto"></div></td>
<td class="px-4 py-4 text-center"><div class="w-3 h-3 rounded-full bg-gray-200 mx-auto"></div></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- VIEW 2: 规则配置中心 (Rule Studio) -->
<div id="view-rules" class="view-section hidden space-y-6">
<!-- Layer 3: AI 配置 -->
<div class="bg-white rounded-xl border border-gray-200 shadow-sm p-6">
<div class="flex justify-between items-center mb-6">
<div>
<h3 class="text-lg font-bold text-gray-800 flex items-center gap-2">
<span class="bg-purple-100 text-purple-600 px-2 py-1 rounded text-xs">Layer 3</span>
AI 监查员配置 (AI Setup)
</h3>
<p class="text-sm text-gray-500 mt-1">负责复杂医学逻辑如入排标准、AE判定的智能化配置</p>
</div>
<button class="px-4 py-2 bg-purple-600 text-white rounded-lg text-sm hover:bg-purple-700">
<i class="fas fa-file-pdf mr-2"></i>重新解析 Protocol
</button>
</div>
<div class="grid grid-cols-2 gap-8">
<!-- 左侧Protocol 提取 -->
<div class="bg-gray-50 p-4 rounded-lg border border-gray-200">
<h4 class="text-sm font-bold text-gray-700 mb-3">AI 提取的入排标准 (Top 3)</h4>
<div class="space-y-3">
<div class="p-3 bg-white border border-gray-200 rounded shadow-sm">
<div class="flex justify-between">
<span class="text-xs font-bold text-gray-500">I-03 (入选)</span>
<span class="text-xs text-green-600 bg-green-50 px-1 rounded">已确认</span>
</div>
<p class="text-sm mt-1">肝肾功能正常,定义为 ALT/AST < 2.5倍 ULN</p>
<div class="mt-2 flex gap-2">
<span class="px-2 py-0.5 bg-blue-50 text-blue-600 text-xs rounded border border-blue-100">Tag: #lab</span>
<span class="px-2 py-0.5 bg-blue-50 text-blue-600 text-xs rounded border border-blue-100">Tag: #safety</span>
</div>
</div>
<div class="p-3 bg-white border border-gray-200 rounded shadow-sm">
<div class="flex justify-between">
<span class="text-xs font-bold text-gray-500">E-02 (排除)</span>
<span class="text-xs text-green-600 bg-green-50 px-1 rounded">已确认</span>
</div>
<p class="text-sm mt-1">既往 5 年内有其他恶性肿瘤病史。</p>
<div class="mt-2 flex gap-2">
<span class="px-2 py-0.5 bg-blue-50 text-blue-600 text-xs rounded border border-blue-100">Tag: #history</span>
</div>
</div>
</div>
</div>
<!-- 右侧Prompt 预览 -->
<div class="bg-slate-900 text-slate-300 p-4 rounded-lg font-mono text-xs overflow-auto h-64">
<div class="text-slate-500 mb-2">// 系统自动生成的 Layer 2 检查 Prompt</div>
<p class="text-purple-400">&lt;task&gt;</p>
<p class="pl-4">基于上传的 Protocol核查患者是否符合 I-03 标准。</p>
<p class="text-purple-400">&lt;/task&gt;</p>
<br>
<p class="text-purple-400">&lt;criteria&gt;</p>
<p class="pl-4">标准值ALT < 2.5 * ULN (100 U/L)</p>
<p class="text-purple-400">&lt;/criteria&gt;</p>
<br>
<p class="text-purple-400">&lt;data_requirement&gt;</p>
<p class="pl-4 text-green-400">Tag: #lab, #safety</p>
<p class="text-purple-400">&lt;/data_requirement&gt;</p>
</div>
</div>
</div>
<!-- Layer 1: 字段映射 -->
<div class="bg-white rounded-xl border border-gray-200 shadow-sm p-6">
<h3 class="text-lg font-bold text-gray-800 mb-4 flex items-center gap-2">
<span class="bg-blue-100 text-blue-600 px-2 py-1 rounded text-xs">Layer 1</span>
字段自动映射 (Auto Mapping)
</h3>
<div class="overflow-x-auto">
<table class="w-full text-sm text-left">
<thead class="bg-gray-50 text-gray-500">
<tr>
<th class="px-4 py-2">REDCap 字段</th>
<th class="px-4 py-2">所属表单</th>
<th class="px-4 py-2">自动规则 (Hard Rules)</th>
<th class="px-4 py-2">语义标签 (Tags)</th>
<th class="px-4 py-2">操作</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
<tr>
<td class="px-4 py-3 font-mono">dob</td>
<td class="px-4 py-3">Demographics</td>
<td class="px-4 py-3"><span class="bg-gray-100 px-2 py-1 rounded text-xs">Required</span> <span class="bg-gray-100 px-2 py-1 rounded text-xs">Date</span></td>
<td class="px-4 py-3">
<span class="bg-blue-50 text-blue-600 border border-blue-200 px-2 py-0.5 rounded text-xs">#demographics</span>
</td>
<td class="px-4 py-3 text-blue-600 cursor-pointer">编辑</td>
</tr>
<tr>
<td class="px-4 py-3 font-mono">lab_alt</td>
<td class="px-4 py-3">Lab Test</td>
<td class="px-4 py-3"><span class="bg-gray-100 px-2 py-1 rounded text-xs">Min: 0</span> <span class="bg-gray-100 px-2 py-1 rounded text-xs">Max: 1000</span></td>
<td class="px-4 py-3">
<span class="bg-blue-50 text-blue-600 border border-blue-200 px-2 py-0.5 rounded text-xs">#lab</span>
<span class="bg-red-50 text-red-600 border border-red-200 px-2 py-0.5 rounded text-xs">#safety</span>
</td>
<td class="px-4 py-3 text-blue-600 cursor-pointer">编辑</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- 侧滑抽屉:智能诊断详情 (Subject 360) -->
<div id="drawer-overlay" class="fixed inset-0 bg-black/50 z-40 hidden transition-opacity opacity-0" onclick="closeDrawer()"></div>
<div id="drawer-panel" class="fixed inset-y-0 right-0 w-[1000px] bg-white shadow-2xl z-50 transform translate-x-full transition-transform duration-300 flex flex-col">
<!-- 抽屉头部 -->
<div class="h-16 px-6 border-b border-gray-200 flex items-center justify-between bg-gray-50">
<div class="flex items-center gap-4">
<div class="w-10 h-10 rounded-full bg-blue-100 text-blue-600 flex items-center justify-center font-bold">
01
</div>
<div>
<h2 class="text-lg font-bold text-gray-800">受试者 SUB-001</h2>
<p class="text-xs text-gray-500">访视阶段: Screening | 录入时间: 2026-02-07 14:30</p>
</div>
</div>
<div class="flex items-center gap-2">
<button class="px-3 py-1.5 bg-white border border-gray-300 text-gray-600 rounded text-sm hover:bg-gray-50">
<i class="fas fa-external-link-alt mr-1"></i> REDCap
</button>
<button onclick="closeDrawer()" class="p-2 text-gray-400 hover:text-gray-600 rounded-full hover:bg-gray-100">
<i class="fas fa-times text-xl"></i>
</button>
</div>
</div>
<!-- 抽屉内容:左右分栏 -->
<div class="flex-1 flex overflow-hidden">
<!-- 左栏:真实数据 (Source of Truth) -->
<div class="w-1/2 border-r border-gray-200 flex flex-col bg-white">
<div class="p-4 bg-gray-50 border-b border-gray-200 flex justify-between items-center">
<h3 class="font-bold text-gray-700"><i class="fas fa-database mr-2"></i>真实数据 (Screening Form)</h3>
<span class="text-xs bg-gray-200 text-gray-600 px-2 py-0.5 rounded">Read Only</span>
</div>
<div class="flex-1 overflow-y-auto p-6 space-y-6">
<!-- 表单字段 -->
<div class="space-y-4">
<div>
<label class="block text-xs font-medium text-gray-500 uppercase">Screening Date</label>
<div class="mt-1 p-2 bg-gray-50 border border-gray-200 rounded text-gray-800">2026-01-15</div>
</div>
<!-- 异常字段高亮 -->
<div class="relative group">
<div class="absolute -left-4 top-2 text-red-500"><i class="fas fa-arrow-right"></i></div>
<label class="block text-xs font-medium text-gray-500 uppercase">Lab Test: ALT (U/L)</label>
<div class="mt-1 p-2 bg-red-50 border border-red-300 rounded text-red-700 font-bold flex justify-between items-center">
<span>150</span>
<i class="fas fa-exclamation-circle"></i>
</div>
<p class="text-xs text-red-500 mt-1">Ref Range: 0-40</p>
</div>
<div>
<label class="block text-xs font-medium text-gray-500 uppercase">Lab Test: AST (U/L)</label>
<div class="mt-1 p-2 bg-gray-50 border border-gray-200 rounded text-gray-800">45</div>
</div>
<div>
<label class="block text-xs font-medium text-gray-500 uppercase">Inclusion Criteria Checklist</label>
<div class="mt-1 p-2 bg-gray-50 border border-gray-200 rounded text-gray-800">Complete</div>
</div>
</div>
</div>
</div>
<!-- 右栏AI 监查报告 + LLM Trace -->
<div class="w-1/2 flex flex-col bg-slate-50">
<div class="border-b border-gray-200 bg-white">
<nav class="flex -mb-px">
<button onclick="switchDrawerTab('report')" id="tab-report" class="w-1/2 py-4 px-1 text-center border-b-2 border-blue-500 font-medium text-sm text-blue-600">
<i class="fas fa-robot mr-2"></i>智能诊断报告
</button>
<button onclick="switchDrawerTab('trace')" id="tab-trace" class="w-1/2 py-4 px-1 text-center border-b-2 border-transparent font-medium text-sm text-gray-500 hover:text-gray-700 hover:border-gray-300">
<i class="fas fa-code mr-2"></i>LLM Trace (透视)
</button>
</nav>
</div>
<!-- Tab 1: 报告 -->
<div id="drawer-content-report" class="flex-1 overflow-y-auto p-6 space-y-4">
<!-- 严重报警卡片 -->
<div class="bg-white rounded-lg shadow-sm border border-red-200 overflow-hidden">
<div class="bg-red-50 px-4 py-3 border-b border-red-100 flex justify-between items-center">
<h4 class="text-red-700 font-bold flex items-center gap-2">
<i class="fas fa-times-circle"></i> 违反入排标准 (Critical)
</h4>
<span class="text-xs bg-white text-red-600 px-2 py-1 rounded border border-red-200">置信度: High</span>
</div>
<div class="p-4">
<div class="mb-4">
<p class="text-xs font-bold text-gray-500 uppercase mb-1">AI 观点</p>
<p class="text-sm text-gray-800">
根据 Protocol 标准 I-03受试者肝功能需正常ALT < 2.5倍 ULN < 100
<br>检测到该患者当前 <strong>ALT 为 150</strong>,显著超出允许范围,建议剔除。
</p>
</div>
<div class="mb-4 bg-gray-50 p-3 rounded border border-gray-200 text-xs text-gray-600">
<p class="font-bold mb-1">原始证据链 (Evidence Chain):</p>
<ul class="list-disc pl-4 space-y-1">
<li>Variable: <code>lab_alt</code> = 150</li>
<li>Standard: <code>limit_max</code> = 100</li>
<li>Form: Screening Form</li>
</ul>
</div>
<div class="flex gap-2 pt-2 border-t border-gray-100">
<button class="flex-1 bg-red-600 text-white text-sm py-2 rounded hover:bg-red-700">确认违规 (PD)</button>
<button class="flex-1 bg-white border border-gray-300 text-gray-700 text-sm py-2 rounded hover:bg-gray-50">发送 Query</button>
<button class="px-3 bg-white border border-gray-300 text-gray-400 rounded hover:text-gray-600" title="忽略"><i class="fas fa-trash-alt"></i></button>
</div>
</div>
</div>
<!-- 警告卡片 -->
<div class="bg-white rounded-lg shadow-sm border border-yellow-200 overflow-hidden opacity-75">
<div class="bg-yellow-50 px-4 py-3 border-b border-yellow-100 flex justify-between items-center">
<h4 class="text-yellow-700 font-bold flex items-center gap-2">
<i class="fas fa-exclamation-triangle"></i> 数据完整性警告
</h4>
<span class="text-xs bg-white text-yellow-600 px-2 py-1 rounded border border-yellow-200">置信度: Medium</span>
</div>
<div class="p-4">
<p class="text-sm text-gray-800">AST 字段有值 (45),但未填写单位。虽然数值在正常范围内,建议确认单位是否为 U/L。</p>
</div>
</div>
</div>
<!-- Tab 2: LLM Trace (XML View) -->
<div id="drawer-content-trace" class="hidden flex-1 overflow-y-auto p-0 bg-[#1e1e1e] text-gray-300 font-mono text-xs">
<div class="p-4 border-b border-gray-700 bg-[#252526] text-gray-400 flex justify-between">
<span>Prompt Context (Sent to DeepSeek-V3)</span>
<span class="text-blue-400">XML Protocol</span>
</div>
<div class="p-6 space-y-1">
<div><span class="xml-tag">&lt;task&gt;</span>核查该患者是否符合研究入排标准<span class="xml-tag">&lt;/task&gt;</span></div>
<br>
<div><span class="xml-tag">&lt;protocol_criteria&gt;</span></div>
<div class="pl-4 text-[#ce9178]">1. 年龄 18-75 岁。</div>
<div class="pl-4 text-[#ce9178]">2. 病理确诊为非小细胞肺癌。</div>
<div class="pl-4 text-[#ce9178]">3. 肝肾功能正常 (ALT/AST < 2.5 ULN)</div>
<div><span class="xml-tag">&lt;/protocol_criteria&gt;</span></div>
<br>
<div><span class="xml-tag">&lt;patient_slice</span> <span class="xml-attr">tag</span>=<span class="xml-val">"#lab"</span><span class="xml-tag">&gt;</span></div>
<div class="pl-4 text-gray-400">&lt;!-- Layer 1 Filtered Data --&gt;</div>
<div class="pl-4 text-[#9cdcfe]">- 实验室检查日期: 2026-01-15</div>
<div class="pl-4 text-[#9cdcfe]">- ALT: <span class="bg-red-900 text-white px-1">150</span> U/L</div>
<div class="pl-4 text-[#9cdcfe]">- AST: 45 U/L</div>
<div><span class="xml-tag">&lt;/patient_slice&gt;</span></div>
<br>
<div><span class="xml-tag">&lt;instruction&gt;</span></div>
<div class="pl-4 text-[#ce9178]">请一步步推理,对比患者数据与标准。重点关注肝功能指标。</div>
<div><span class="xml-tag">&lt;/instruction&gt;</span></div>
<div class="mt-8 pt-4 border-t border-gray-700">
<div class="text-green-400 mb-2">// LLM Output (Chain of Thought)</div>
<div class="text-gray-400 italic">
> Thinking: 标准要求 ALT 小于 100 (2.5 * 40)。<br>
> 检查 patient_slice 数据...<br>
> 发现 ALT = 150。<br>
> 150 > 100判定违规。<br>
> 生成 Critical 级别报警。
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<script>
// 简单的 Tab 切换逻辑
function switchTab(tabId) {
// 隐藏所有视图
document.querySelectorAll('.view-section').forEach(el => el.classList.add('hidden'));
document.querySelectorAll('.nav-item').forEach(el => {
el.classList.remove('bg-blue-600', 'text-white', 'shadow-lg');
el.classList.add('text-slate-400', 'hover:bg-slate-800');
});
// 显示选中视图
document.getElementById('view-' + tabId).classList.remove('hidden');
// 这里的 active 样式逻辑简化处理,实际开发可用 Vue/React 控制 class
const activeLink = document.querySelector(`a[onclick="switchTab('${tabId}')"]`);
activeLink.classList.remove('text-slate-400', 'hover:bg-slate-800');
activeLink.classList.add('bg-blue-600', 'text-white', 'shadow-lg');
// 更新标题
const titles = {
'overview': '项目概览 Dashboard',
'cockpit': 'CRA 智能监查驾驶舱',
'rules': '规则配置中心 (Rule Studio)'
};
document.getElementById('page-title').innerText = titles[tabId];
}
// 抽屉控制
function openDrawer(subjectId, visit) {
const drawerPanel = document.getElementById('drawer-panel');
const drawerOverlay = document.getElementById('drawer-overlay');
drawerOverlay.classList.remove('hidden');
// 强制重绘以触发 transition
setTimeout(() => {
drawerOverlay.classList.remove('opacity-0');
drawerPanel.classList.remove('translate-x-full');
}, 10);
}
function closeDrawer() {
const drawerPanel = document.getElementById('drawer-panel');
const drawerOverlay = document.getElementById('drawer-overlay');
drawerPanel.classList.add('translate-x-full');
drawerOverlay.classList.add('opacity-0');
setTimeout(() => {
drawerOverlay.classList.add('hidden');
}, 300);
}
// 抽屉内 Tab 切换
function switchDrawerTab(tabName) {
const reportContent = document.getElementById('drawer-content-report');
const traceContent = document.getElementById('drawer-content-trace');
const tabReport = document.getElementById('tab-report');
const tabTrace = document.getElementById('tab-trace');
if (tabName === 'report') {
reportContent.classList.remove('hidden');
traceContent.classList.add('hidden');
tabReport.classList.add('border-blue-500', 'text-blue-600');
tabReport.classList.remove('border-transparent', 'text-gray-500');
tabTrace.classList.remove('border-blue-500', 'text-blue-600');
tabTrace.classList.add('border-transparent', 'text-gray-500');
} else {
reportContent.classList.add('hidden');
traceContent.classList.remove('hidden');
tabTrace.classList.add('border-blue-500', 'text-blue-600');
tabTrace.classList.remove('border-transparent', 'text-gray-500');
tabReport.classList.remove('border-blue-500', 'text-blue-600');
tabReport.classList.add('border-transparent', 'text-gray-500');
}
}
</script>
</body>
</html>