Files
HaHafeng 45c7b32dbb 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>
2026-02-08 09:59:44 +08:00

598 lines
39 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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>