- 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>
598 lines
39 KiB
HTML
598 lines
39 KiB
HTML
<!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"><task></p>
|
||
<p class="pl-4">基于上传的 Protocol,核查患者是否符合 I-03 标准。</p>
|
||
<p class="text-purple-400"></task></p>
|
||
<br>
|
||
<p class="text-purple-400"><criteria></p>
|
||
<p class="pl-4">标准值:ALT < 2.5 * ULN (100 U/L)</p>
|
||
<p class="text-purple-400"></criteria></p>
|
||
<br>
|
||
<p class="text-purple-400"><data_requirement></p>
|
||
<p class="pl-4 text-green-400">Tag: #lab, #safety</p>
|
||
<p class="text-purple-400"></data_requirement></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"><task></span>核查该患者是否符合研究入排标准<span class="xml-tag"></task></span></div>
|
||
<br>
|
||
<div><span class="xml-tag"><protocol_criteria></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"></protocol_criteria></span></div>
|
||
<br>
|
||
<div><span class="xml-tag"><patient_slice</span> <span class="xml-attr">tag</span>=<span class="xml-val">"#lab"</span><span class="xml-tag">></span></div>
|
||
<div class="pl-4 text-gray-400"><!-- Layer 1 Filtered Data --></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"></patient_slice></span></div>
|
||
<br>
|
||
<div><span class="xml-tag"><instruction></span></div>
|
||
<div class="pl-4 text-[#ce9178]">请一步步推理,对比患者数据与标准。重点关注肝功能指标。</div>
|
||
<div><span class="xml-tag"></instruction></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> |