V3.0 Plan: - Finalize CRA Agent V3.0 development plan (replace CRA positioning) - Add unified CRA QC platform PRD - Add HTML UI prototype (dashboard, AI stream, eQuery, reports) - Architecture: report-driven + LLM Tool Use + 4 semantic tools Module Status Update: - Update architecture from dual-brain V2.9.1 to V3.0 Tool Use - Update DB schema inventory (5 tables -> 18 tables) - Update code stats (577 lines -> 15,000+ lines / 61 files) - Update next steps to V3.0 P0 roadmap - Archive old phase plans (ReAct engine, IntentService) - Add V3.0 document references (plan, PRD, prototype) Co-authored-by: Cursor <cursoragent@cursor.com>
743 lines
50 KiB
HTML
743 lines
50 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>统一数字 CRA 质控平台 - 终极版</title>
|
||
<script src="https://cdn.tailwindcss.com"></script>
|
||
<script src="https://unpkg.com/@phosphor-icons/web"></script>
|
||
<style>
|
||
.no-scrollbar::-webkit-scrollbar { display: none; }
|
||
.no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
|
||
.dash-border { background-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' rx='8' ry='8' stroke='%2394A3B8FF' stroke-width='2' stroke-dasharray='8%2c 8' stroke-dashoffset='0' stroke-linecap='square'/%3e%3c/svg%3e"); border-radius: 8px; }
|
||
.dash-border:hover { background-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' rx='8' ry='8' stroke='%233B82F6FF' stroke-width='2' stroke-dasharray='8%2c 8' stroke-dashoffset='0' stroke-linecap='square'/%3e%3c/svg%3e"); }
|
||
/* Timeline line styling */
|
||
.timeline-line::before {
|
||
content: ''; position: absolute; top: 24px; bottom: -24px; left: 15px; width: 2px; background-color: #e2e8f0; z-index: 0;
|
||
}
|
||
.timeline-item:last-child .timeline-line::before { display: none; }
|
||
</style>
|
||
</head>
|
||
<body class="flex h-screen w-full bg-slate-50 text-slate-800 font-sans overflow-hidden">
|
||
|
||
<!-- 1. 统一左侧导航栏 -->
|
||
<aside class="w-64 bg-slate-900 text-slate-300 flex flex-col transition-all duration-300 shrink-0">
|
||
<div class="h-16 flex items-center px-6 border-b border-slate-800 bg-slate-950">
|
||
<i class="ph-fill ph-robot text-2xl text-blue-500 mr-2"></i>
|
||
<span class="font-bold text-lg text-white tracking-wide">AI 监查系统</span>
|
||
</div>
|
||
|
||
<div class="p-4">
|
||
<p class="text-[10px] font-bold text-slate-500 uppercase tracking-widest mb-2">当前监控项目</p>
|
||
<div class="bg-slate-800 rounded-lg p-3 border border-slate-700 shadow-inner">
|
||
<h3 class="text-sm font-bold text-white mb-1 leading-tight">IIT-2026-001</h3>
|
||
<p class="text-xs text-slate-400 leading-tight">非小细胞肺癌真实世界研究</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 统一视角的导航菜单 -->
|
||
<nav class="flex-1 px-3 py-4 space-y-1 overflow-y-auto">
|
||
<p class="text-[10px] font-bold text-slate-500 uppercase tracking-widest px-3 mb-2">全局与宏观概览</p>
|
||
<a href="#" onclick="switchView('dashboard')" id="nav-dashboard" class="flex items-center px-3 py-2.5 rounded-md group transition-colors bg-blue-600/20 text-blue-400">
|
||
<i class="ph ph-presentation-chart text-xl mr-3 opacity-70 group-hover:opacity-100"></i>
|
||
<span class="font-medium text-sm">项目健康度大盘</span>
|
||
</a>
|
||
<a href="#" onclick="switchView('reports')" id="nav-reports" class="flex items-center px-3 py-2.5 rounded-md text-slate-400 group hover:bg-slate-800 hover:text-white transition-colors">
|
||
<i class="ph ph-files text-xl mr-3 opacity-70 group-hover:opacity-100"></i>
|
||
<span class="font-medium text-sm">定期报告与关键事件</span>
|
||
</a>
|
||
|
||
<p class="text-[10px] font-bold text-slate-500 uppercase tracking-widest px-3 mb-2 mt-6">AI 监查过程与细节</p>
|
||
<a href="#" onclick="switchView('ai-stream')" id="nav-ai-stream" class="flex items-center px-3 py-2.5 rounded-md text-slate-400 group hover:bg-slate-800 hover:text-white transition-colors">
|
||
<i class="ph ph-activity text-xl mr-3 opacity-70 group-hover:opacity-100"></i>
|
||
<span class="font-medium text-sm">AI 实时工作流水</span>
|
||
<span class="ml-auto flex h-2 w-2 relative">
|
||
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
|
||
<span class="relative inline-flex rounded-full h-2 w-2 bg-emerald-500"></span>
|
||
</span>
|
||
</a>
|
||
|
||
<p class="text-[10px] font-bold text-slate-500 uppercase tracking-widest px-3 mb-2 mt-6">人工介入与协作</p>
|
||
<a href="#" onclick="switchView('equery')" id="nav-equery" class="flex items-center px-3 py-2.5 rounded-md text-slate-400 group hover:bg-slate-800 hover:text-white transition-colors">
|
||
<i class="ph ph-list-checks text-xl mr-3 opacity-70 group-hover:opacity-100"></i>
|
||
<span class="font-medium text-sm">待处理电子质疑 (eQuery)</span>
|
||
<span class="ml-auto bg-red-500 text-white py-0.5 px-2 rounded-full text-[10px] font-bold shadow-sm">3</span>
|
||
</a>
|
||
</nav>
|
||
|
||
<div class="p-4 border-t border-slate-800 text-xs text-slate-500 flex items-center">
|
||
<i class="ph-fill ph-check-circle text-emerald-500 mr-2"></i> 系统统一视图,全员可见
|
||
</div>
|
||
</aside>
|
||
|
||
<!-- 2. 主内容区域 -->
|
||
<main class="flex-1 flex flex-col min-w-0 overflow-hidden relative">
|
||
<!-- 顶部 Header -->
|
||
<header class="h-16 bg-white border-b border-slate-200 flex items-center justify-between px-6 shrink-0 z-10">
|
||
<div class="flex items-center">
|
||
<button id="btn-back" onclick="switchView('equery')" class="hidden mr-4 p-1.5 rounded-md hover:bg-slate-100 text-slate-500 transition-colors">
|
||
<i class="ph ph-arrow-left text-xl"></i>
|
||
</button>
|
||
<h1 id="header-title" class="text-xl font-bold text-slate-800">项目健康度大盘</h1>
|
||
</div>
|
||
|
||
<div class="flex items-center space-x-4">
|
||
<div class="flex items-center px-3 py-1.5 bg-slate-50 border border-slate-200 rounded-full">
|
||
<i class="ph-fill ph-plugs-connected text-emerald-500 mr-2"></i>
|
||
<span class="text-xs font-medium text-slate-600">EDC 实时直连中</span>
|
||
</div>
|
||
<button onclick="toggleCopilot()" id="btn-copilot-toggle" class="p-2 rounded-md transition-colors bg-blue-50 text-blue-600 hover:bg-blue-100" title="呼叫 AI 助理">
|
||
<i class="ph-fill ph-sparkle text-xl"></i>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- ================= 视图 A:全局大盘 (Dashboard) ================= -->
|
||
<div id="view-dashboard" class="flex-1 overflow-y-auto p-6 bg-slate-50/50 block">
|
||
<div class="mb-6 flex justify-between items-end">
|
||
<div>
|
||
<h2 class="text-2xl font-bold text-slate-800">全局监查态势</h2>
|
||
<p class="text-sm text-slate-500 mt-1">从宏观趋势到底层患者明细,掌握项目全维度数据质量</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 1. 宏观数据卡片 -->
|
||
<div class="grid grid-cols-4 gap-4 mb-8">
|
||
<div class="bg-white rounded-xl border border-slate-200 p-5 shadow-sm relative overflow-hidden">
|
||
<div class="absolute top-0 right-0 w-24 h-24 bg-emerald-100 rounded-full -mr-8 -mt-8 opacity-50"></div>
|
||
<div class="flex items-center text-slate-500 mb-2 relative z-10">
|
||
<span class="text-sm font-bold">整体数据合规率</span>
|
||
</div>
|
||
<div class="text-3xl font-black text-emerald-600 relative z-10">96.8%</div>
|
||
<div class="text-xs text-emerald-600 mt-2 font-medium">↑ 较上周提升 1.2%</div>
|
||
</div>
|
||
<div class="bg-white rounded-xl border border-slate-200 p-5 shadow-sm cursor-pointer hover:border-blue-400 transition-colors" onclick="switchView('equery')">
|
||
<div class="flex items-center text-slate-500 mb-2">
|
||
<span class="text-sm font-bold">待处理违规 (eQuery)</span>
|
||
<i class="ph-bold ph-arrow-up-right ml-auto text-blue-500"></i>
|
||
</div>
|
||
<div class="text-3xl font-black text-red-600">3</div>
|
||
<div class="text-xs text-red-500 mt-2 font-medium">包含 1 项重大时序冲突</div>
|
||
</div>
|
||
<div class="bg-white rounded-xl border border-slate-200 p-5 shadow-sm cursor-pointer hover:border-blue-400 transition-colors" onclick="switchView('ai-stream')">
|
||
<div class="flex items-center text-slate-500 mb-2">
|
||
<span class="text-sm font-bold">AI 今日审查表单数</span>
|
||
<i class="ph-bold ph-arrow-up-right ml-auto text-blue-500"></i>
|
||
</div>
|
||
<div class="text-3xl font-black text-slate-800">142</div>
|
||
<div class="text-xs text-slate-500 mt-2">100% 自动化,无需人工参与</div>
|
||
</div>
|
||
<div class="bg-gradient-to-br from-slate-800 to-slate-900 rounded-xl border border-slate-700 p-5 shadow-sm text-white cursor-pointer hover:from-slate-700 hover:to-slate-800 transition-colors" onclick="switchView('reports')">
|
||
<div class="flex items-center text-slate-300 mb-2">
|
||
<span class="text-sm font-bold">累计关键事件 (AE/PD)</span>
|
||
<i class="ph-bold ph-arrow-up-right ml-auto text-blue-300"></i>
|
||
</div>
|
||
<div class="text-3xl font-black text-white">12 <span class="text-sm text-slate-400 font-normal">项</span></div>
|
||
<div class="text-xs text-blue-300 mt-2">已沉淀至定期质控报告</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 2. 微观状态底座:项目风险热力图 (引入患者维度真实质控情况) -->
|
||
<div class="bg-white rounded-xl border border-slate-200 shadow-sm mb-8 relative overflow-hidden">
|
||
<div class="px-6 py-4 border-b border-slate-200 flex justify-between items-center bg-slate-50/50">
|
||
<h2 class="text-base font-bold text-slate-800 flex items-center">
|
||
<i class="ph-fill ph-squares-four text-blue-500 mr-2 text-lg"></i>
|
||
当前入组患者最新质控状态 (受试者 × 表单矩阵)
|
||
</h2>
|
||
<div class="flex items-center text-xs text-slate-500 space-x-4">
|
||
<span class="flex items-center"><div class="w-3 h-3 rounded-sm bg-red-500 border border-red-600 mr-1"></div>异常/质疑中</span>
|
||
<span class="flex items-center"><div class="w-3 h-3 rounded-sm bg-yellow-400 border border-yellow-500 mr-1"></div>逻辑存疑</span>
|
||
<span class="flex items-center"><div class="w-3 h-3 rounded-sm bg-emerald-50 border border-emerald-200 mr-1"></div>AI 质控通过</span>
|
||
</div>
|
||
</div>
|
||
<div class="p-6 overflow-x-auto">
|
||
<table class="w-full text-sm text-left">
|
||
<thead>
|
||
<tr>
|
||
<th class="pb-3 pr-4 font-bold text-slate-500 w-32 border-b border-slate-200">受试者编号</th>
|
||
<th class="pb-3 px-2 font-bold text-slate-500 text-center border-b border-slate-200">知情同意</th>
|
||
<th class="pb-3 px-2 font-bold text-slate-500 text-center border-b border-slate-200">入选标准</th>
|
||
<th class="pb-3 px-2 font-bold text-slate-500 text-center border-b border-slate-200">实验室检查</th>
|
||
<th class="pb-3 px-2 font-bold text-slate-500 text-center border-b border-slate-200">不良事件 (AE)</th>
|
||
<th class="pb-3 px-2 font-bold text-slate-500 text-center border-b border-slate-200">随访记录</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="heatmap-body">
|
||
<!-- JS 动态渲染热力图 -->
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div class="px-6 py-3 border-t border-slate-100 bg-slate-50 text-xs text-slate-500 flex justify-between items-center">
|
||
<span>* 矩阵实时反映 REDCap 最新录入与 AI 验证结果。点击红色高亮色块可直接进入 eQuery 处理中心。</span>
|
||
<button class="text-blue-600 font-bold hover:underline">查看全部 45 名患者</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 3. 近期概览 (事件预警 & 质量评级) -->
|
||
<div class="grid grid-cols-2 gap-6">
|
||
<!-- 近期高亮事件 -->
|
||
<div class="bg-white rounded-xl border border-slate-200 shadow-sm">
|
||
<div class="px-6 py-4 border-b border-slate-200 flex justify-between items-center">
|
||
<h2 class="text-base font-bold text-slate-800 flex items-center">
|
||
<i class="ph-fill ph-warning-circle text-yellow-500 mr-2 text-lg"></i>
|
||
近期关键事件预警 (AE/PD)
|
||
</h2>
|
||
</div>
|
||
<div class="p-0">
|
||
<div class="divide-y divide-slate-100">
|
||
<div class="p-4 px-6 hover:bg-slate-50">
|
||
<div class="flex items-center justify-between mb-1">
|
||
<span class="text-xs font-bold px-2 py-0.5 rounded bg-red-100 text-red-700">严重不良事件 (SAE)</span>
|
||
<span class="text-xs text-slate-400">昨天 14:30</span>
|
||
</div>
|
||
<p class="text-sm font-bold text-slate-800">P005 - 谷丙转氨酶(ALT)达到 150U/L</p>
|
||
<p class="text-xs text-slate-500 mt-1">由 AI 从实验室检查表抓取,已触发强制 SDV。</p>
|
||
</div>
|
||
<div class="p-4 px-6 hover:bg-slate-50">
|
||
<div class="flex items-center justify-between mb-1">
|
||
<span class="text-xs font-bold px-2 py-0.5 rounded bg-orange-100 text-orange-700">方案偏离 (PD)</span>
|
||
<span class="text-xs text-slate-400">3天前</span>
|
||
</div>
|
||
<p class="text-sm font-bold text-slate-800">P002 - 随访 2 严重超窗</p>
|
||
<p class="text-xs text-slate-500 mt-1">实际随访日期偏离方案要求窗口期超过 7 天。</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 质量评级 -->
|
||
<div class="bg-white rounded-xl border border-slate-200 shadow-sm">
|
||
<div class="px-6 py-4 border-b border-slate-200">
|
||
<h2 class="text-base font-bold text-slate-800 flex items-center">
|
||
<i class="ph-fill ph-users-three text-slate-400 mr-2 text-lg"></i>
|
||
数据响应质量一览
|
||
</h2>
|
||
</div>
|
||
<div class="p-6">
|
||
<p class="text-sm text-slate-600 mb-4">通过 AI 发起质疑的响应速度,评估各中心的数据录入质量与配合度。</p>
|
||
<div class="space-y-4">
|
||
<div>
|
||
<div class="flex justify-between text-sm mb-1">
|
||
<span class="font-medium text-slate-800">北京协和中心 (李明)</span>
|
||
<span class="text-emerald-600 font-bold">平均响应 4.5h</span>
|
||
</div>
|
||
<div class="w-full bg-slate-100 h-2 rounded-full overflow-hidden">
|
||
<div class="bg-emerald-500 h-full w-[90%] rounded-full"></div>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<div class="flex justify-between text-sm mb-1">
|
||
<span class="font-medium text-slate-800">上海中山中心 (赵小丽)</span>
|
||
<span class="text-yellow-600 font-bold">平均响应 12.2h</span>
|
||
</div>
|
||
<div class="w-full bg-slate-100 h-2 rounded-full overflow-hidden">
|
||
<div class="bg-yellow-400 h-full w-[60%] rounded-full"></div>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<div class="flex justify-between text-sm mb-1">
|
||
<span class="font-medium text-slate-800">广州南方中心 (王强)</span>
|
||
<span class="text-red-500 font-bold">平均响应 48.2h</span>
|
||
</div>
|
||
<div class="w-full bg-slate-100 h-2 rounded-full overflow-hidden">
|
||
<div class="bg-red-500 h-full w-[25%] rounded-full"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ================= 视图 B:AI 工作流水 (AI Stream) ================= -->
|
||
<div id="view-ai-stream" class="flex-1 overflow-y-auto p-6 bg-slate-50/50 hidden">
|
||
<div class="max-w-4xl mx-auto">
|
||
<div class="mb-8">
|
||
<h2 class="text-2xl font-bold text-slate-800 flex items-center">
|
||
AI 实时工作流水
|
||
<span class="ml-4 flex items-center text-xs font-normal px-2.5 py-1 rounded-full bg-emerald-100 text-emerald-700">
|
||
<i class="ph-fill ph-radio mr-1"></i> Webhook 实时监听中
|
||
</span>
|
||
</h2>
|
||
<p class="text-sm text-slate-500 mt-1">完全透明展示 AI 的每一次审查、推理和结果,建立 100% 的信任。</p>
|
||
</div>
|
||
|
||
<div class="bg-white rounded-xl border border-slate-200 shadow-sm p-6 relative">
|
||
<div class="absolute top-6 left-12 bottom-6 w-px bg-slate-200"></div> <!-- 贯穿的垂直线 -->
|
||
|
||
<div class="space-y-6">
|
||
<!-- 流水记录 1 -->
|
||
<div class="relative flex items-start gap-4">
|
||
<div class="w-16 shrink-0 text-right pt-1">
|
||
<span class="text-xs font-bold text-blue-600">刚才</span>
|
||
</div>
|
||
<div class="w-8 h-8 rounded-full bg-blue-100 border-2 border-white flex items-center justify-center relative z-10 shrink-0 shadow-sm">
|
||
<i class="ph-bold ph-eye text-blue-600"></i>
|
||
</div>
|
||
<div class="flex-1 bg-slate-50 rounded-lg p-4 border border-slate-100">
|
||
<p class="text-sm font-bold text-slate-800">监听 EDC 保存事件,扫描 <span class="text-blue-600">P008 随访记录表</span></p>
|
||
<p class="text-xs text-slate-500 mt-1">调用 12 条硬逻辑规则,比对完成。耗时 0.2 秒。</p>
|
||
<div class="mt-2 inline-flex items-center text-xs font-bold text-emerald-600 bg-emerald-50 px-2 py-1 rounded">
|
||
<i class="ph-fill ph-check-circle mr-1"></i> 未发现异常,放行。
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 流水记录 2 (发现问题并派发) -->
|
||
<div class="relative flex items-start gap-4">
|
||
<div class="w-16 shrink-0 text-right pt-1">
|
||
<span class="text-xs font-medium text-slate-400">10:24</span>
|
||
</div>
|
||
<div class="w-8 h-8 rounded-full bg-red-100 border-2 border-white flex items-center justify-center relative z-10 shrink-0 shadow-sm">
|
||
<i class="ph-bold ph-warning text-red-600"></i>
|
||
</div>
|
||
<div class="flex-1 bg-red-50/50 rounded-lg p-4 border border-red-100">
|
||
<p class="text-sm font-bold text-slate-800">扫描 <span class="text-blue-600">P005 实验室检查表</span> 时拦截异常</p>
|
||
<p class="text-xs text-slate-600 mt-1 leading-relaxed">
|
||
<strong class="text-slate-800">AI 推理链路:</strong>提取到 ALT=150U/L -> 检索方案知识库发现超 SAE 阈值 -> 交叉查询患者不良事件表 -> <span class="text-red-600 font-bold">发现记录缺失。</span>
|
||
</p>
|
||
<div class="mt-3 bg-white border border-red-200 rounded p-3 text-sm flex justify-between items-center">
|
||
<div>
|
||
<span class="font-mono text-xs text-red-500 font-bold block mb-1">执行动作:</span>
|
||
已自动生成电子质疑 <strong>eQuery-1029</strong>,并推送到 CRC 任务列表。
|
||
</div>
|
||
<button onclick="switchView('equery')" class="px-3 py-1.5 bg-red-100 text-red-700 text-xs font-bold rounded hover:bg-red-200 transition-colors">
|
||
查看该质疑
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 流水记录 3 (自动复核闭环) -->
|
||
<div class="relative flex items-start gap-4">
|
||
<div class="w-16 shrink-0 text-right pt-1">
|
||
<span class="text-xs font-medium text-slate-400">09:15</span>
|
||
</div>
|
||
<div class="w-8 h-8 rounded-full bg-purple-100 border-2 border-white flex items-center justify-center relative z-10 shrink-0 shadow-sm">
|
||
<i class="ph-bold ph-arrows-clockwise text-purple-600"></i>
|
||
</div>
|
||
<div class="flex-1 bg-slate-50 rounded-lg p-4 border border-slate-100">
|
||
<p class="text-sm font-bold text-slate-800">执行二次自动复核 (P003 体格检查表)</p>
|
||
<p class="text-xs text-slate-500 mt-1">接收到 CRC 数据修正信号。重新验证身高体重计算的 BMI 逻辑关系。</p>
|
||
<div class="mt-2 inline-flex items-center text-xs font-bold text-purple-600 bg-purple-50 px-2 py-1 rounded">
|
||
<i class="ph-fill ph-check-circle mr-1"></i> 数据一致性验证通过,已自动关闭 eQuery-1015。
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 凌晨跑批 -->
|
||
<div class="relative flex items-start gap-4">
|
||
<div class="w-16 shrink-0 text-right pt-1">
|
||
<span class="text-xs font-medium text-slate-400">02:00</span>
|
||
</div>
|
||
<div class="w-8 h-8 rounded-full bg-slate-200 border-2 border-white flex items-center justify-center relative z-10 shrink-0 shadow-sm">
|
||
<i class="ph-bold ph-moon-stars text-slate-600"></i>
|
||
</div>
|
||
<div class="flex-1 bg-slate-50 rounded-lg p-4 border border-slate-100">
|
||
<p class="text-sm font-bold text-slate-800">执行每日凌晨全量交叉核对跑批 (Cron Job)</p>
|
||
<p class="text-xs text-slate-500 mt-1">扫描全库 1204 份表单,进行跨表单逻辑验证。耗时 4.2 秒。未发现全局性新问题。</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ================= 视图 C:待处理质疑 (eQuery) ================= -->
|
||
<div id="view-equery" class="flex-1 overflow-y-auto p-6 bg-slate-50/50 hidden">
|
||
<div class="max-w-5xl mx-auto">
|
||
<div class="mb-6 flex justify-between items-end">
|
||
<div>
|
||
<h2 class="text-2xl font-bold text-slate-800">待处理质疑 (eQuery) 列表</h2>
|
||
<p class="text-sm text-slate-500 mt-1">AI 发现的数据缺陷,需人工 (CRC) 响应修复或上传 SDV 凭证。</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="bg-white rounded-xl border border-slate-200 shadow-sm overflow-hidden mb-6">
|
||
<div class="divide-y divide-slate-100">
|
||
<!-- 质疑项 1 -->
|
||
<div class="p-6 hover:bg-slate-50 transition-colors flex gap-6">
|
||
<div class="mt-1">
|
||
<i class="ph-fill ph-warning text-3xl text-red-500"></i>
|
||
</div>
|
||
<div class="flex-1">
|
||
<div class="flex justify-between items-start mb-2">
|
||
<div class="flex items-center gap-3">
|
||
<span class="px-2.5 py-1 rounded bg-slate-100 text-sm font-bold text-slate-700">P005</span>
|
||
<span class="text-base font-bold text-slate-800">实验室检查异常:漏报 AE</span>
|
||
<span class="text-xs font-bold px-2 py-0.5 bg-red-100 text-red-700 rounded border border-red-200">强制 SDV</span>
|
||
</div>
|
||
<span class="text-xs font-bold text-slate-500 font-mono bg-slate-100 px-2 py-1 rounded">eQuery-1029</span>
|
||
</div>
|
||
<p class="text-sm text-slate-700 leading-relaxed mb-4 p-3 bg-red-50/50 rounded border border-red-100">
|
||
<strong>AI 监查意见:</strong>检测到 ALT 异常升高 (150U/L),已达到方案规定的 SAE 标准。但该患者无对应的 AE 记录。为了排除数据录入错误,此项已触发强制 SDV。请上传该次访视的原始化验单照片供 AI 核对。
|
||
</p>
|
||
<div class="flex items-center justify-between mt-2 pt-4 border-t border-slate-100">
|
||
<div class="text-xs text-slate-500">
|
||
<i class="ph-fill ph-clock mr-1"></i> AI 派发时间: 今天 10:24
|
||
</div>
|
||
<button onclick="switchView('sdv-response')" class="px-6 py-2 text-sm font-bold text-white bg-blue-600 rounded-lg shadow-sm hover:bg-blue-700 transition-colors flex items-center">
|
||
去响应并上传凭证 <i class="ph-bold ph-arrow-right ml-2"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 质疑项 2 -->
|
||
<div class="p-6 hover:bg-slate-50 transition-colors flex gap-6">
|
||
<div class="mt-1">
|
||
<i class="ph-fill ph-info text-3xl text-yellow-500"></i>
|
||
</div>
|
||
<div class="flex-1">
|
||
<div class="flex justify-between items-start mb-2">
|
||
<div class="flex items-center gap-3">
|
||
<span class="px-2.5 py-1 rounded bg-slate-100 text-sm font-bold text-slate-700">P002</span>
|
||
<span class="text-base font-bold text-slate-800">知情同意书:逻辑时序冲突</span>
|
||
</div>
|
||
<span class="text-xs font-bold text-slate-500 font-mono bg-slate-100 px-2 py-1 rounded">eQuery-1028</span>
|
||
</div>
|
||
<p class="text-sm text-slate-700 leading-relaxed mb-4 p-3 bg-yellow-50/50 rounded border border-yellow-100">
|
||
<strong>AI 监查意见:</strong>签署知情同意书的日期 (2026-02-25) 晚于心电图检查日期 (2026-02-24),涉嫌违规操作。请核实 REDCap 录入日期是否错误。
|
||
</p>
|
||
<div class="flex items-center justify-end gap-3 mt-2 pt-4 border-t border-slate-100">
|
||
<button class="px-4 py-2 bg-white border border-slate-300 hover:bg-slate-50 text-slate-700 text-sm font-medium rounded-lg transition-colors">
|
||
声明此为真实数据 (填写理由)
|
||
</button>
|
||
<button class="px-4 py-2 bg-slate-800 hover:bg-slate-900 text-white text-sm font-medium rounded-lg transition-colors flex items-center">
|
||
<i class="ph-bold ph-arrows-clockwise mr-2"></i> 我已在 EDC 修正,通知 AI 重查
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ================= 视图 D:定期报告与事件沉淀 (Reports) ================= -->
|
||
<div id="view-reports" class="flex-1 overflow-y-auto p-6 bg-slate-50/50 hidden">
|
||
<div class="max-w-5xl mx-auto">
|
||
<div class="mb-8">
|
||
<h2 class="text-2xl font-bold text-slate-800">定期报告与关键事件库</h2>
|
||
<p class="text-sm text-slate-500 mt-1">临床研究的长期资产。AI 自动生成的阶段性报告与全生命周期重大事件追踪。</p>
|
||
</div>
|
||
|
||
<div class="grid grid-cols-3 gap-6">
|
||
<!-- 左侧:定期质控报告 -->
|
||
<div class="col-span-2">
|
||
<h3 class="text-base font-bold text-slate-800 mb-4 flex items-center">
|
||
<i class="ph-fill ph-files text-blue-500 mr-2"></i> AI 自动生成定期报告
|
||
</h3>
|
||
<div class="grid grid-cols-2 gap-4">
|
||
<!-- Report Card -->
|
||
<div class="bg-white rounded-xl border border-slate-200 p-5 shadow-sm hover:border-blue-400 cursor-pointer transition-colors group">
|
||
<div class="flex justify-between items-start mb-3">
|
||
<div class="w-10 h-10 rounded bg-blue-50 flex items-center justify-center text-blue-600">
|
||
<i class="ph-bold ph-file-pdf text-xl"></i>
|
||
</div>
|
||
<span class="text-xs font-bold text-slate-400">本周</span>
|
||
</div>
|
||
<h4 class="font-bold text-slate-800 group-hover:text-blue-600 transition-colors">2026年2月第3周 质控周报</h4>
|
||
<p class="text-xs text-slate-500 mt-2 mb-4 leading-relaxed">共审查 842 份表单,拦截并闭环 12 项逻辑错误,项目合规率提升 0.5%。</p>
|
||
<div class="text-xs font-medium text-blue-600 flex items-center border-t border-slate-100 pt-3">
|
||
点击预览详细报告 <i class="ph-bold ph-arrow-right ml-1"></i>
|
||
</div>
|
||
</div>
|
||
<!-- Report Card -->
|
||
<div class="bg-white rounded-xl border border-slate-200 p-5 shadow-sm hover:border-blue-400 cursor-pointer transition-colors group">
|
||
<div class="flex justify-between items-start mb-3">
|
||
<div class="w-10 h-10 rounded bg-slate-100 flex items-center justify-center text-slate-500">
|
||
<i class="ph-bold ph-file-pdf text-xl"></i>
|
||
</div>
|
||
<span class="text-xs font-bold text-slate-400">上周</span>
|
||
</div>
|
||
<h4 class="font-bold text-slate-800 group-hover:text-blue-600 transition-colors">2026年2月第2周 质控周报</h4>
|
||
<p class="text-xs text-slate-500 mt-2 mb-4 leading-relaxed">共审查 750 份表单,包含 1 项 PD (方案偏离) 专题汇总分析。</p>
|
||
<div class="text-xs font-medium text-slate-500 flex items-center border-t border-slate-100 pt-3">
|
||
点击预览详细报告 <i class="ph-bold ph-arrow-right ml-1"></i>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 右侧:重大事件记录库 -->
|
||
<div class="col-span-1">
|
||
<h3 class="text-base font-bold text-slate-800 mb-4 flex items-center">
|
||
<i class="ph-fill ph-archive text-slate-500 mr-2"></i> 重大事件沉淀库
|
||
</h3>
|
||
<div class="bg-white rounded-xl border border-slate-200 shadow-sm overflow-hidden">
|
||
<div class="divide-y divide-slate-100">
|
||
<div class="p-4 hover:bg-slate-50 cursor-pointer">
|
||
<div class="flex items-center justify-between mb-1">
|
||
<span class="text-xs font-bold text-red-600">严重不良事件 (SAE) 归档</span>
|
||
</div>
|
||
<p class="text-sm font-bold text-slate-800">P012 肺炎住院</p>
|
||
<p class="text-xs text-slate-500 mt-1">2026-01-15 发生,已完成与申办方的上报流程并闭环。</p>
|
||
</div>
|
||
<div class="p-4 hover:bg-slate-50 cursor-pointer">
|
||
<div class="flex items-center justify-between mb-1">
|
||
<span class="text-xs font-bold text-orange-600">方案偏离 (PD) 归档</span>
|
||
</div>
|
||
<p class="text-sm font-bold text-slate-800">P003 服药依从性极低</p>
|
||
<p class="text-xs text-slate-500 mt-1">记录于 2026-01-10,AI 评估为重大偏离,剔除分析集。</p>
|
||
</div>
|
||
<div class="p-3 text-center bg-slate-50 border-t border-slate-100">
|
||
<button class="text-xs font-bold text-blue-600 hover:underline">查看全部 12 项历史事件</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ================= 视图 E:SDV 响应界面 ================= -->
|
||
<div id="view-sdv" class="flex-1 flex flex-col h-full bg-slate-100 p-6 overflow-hidden hidden">
|
||
<div class="flex flex-col h-full bg-white rounded-xl border border-slate-200 shadow-sm overflow-hidden">
|
||
<div class="px-6 py-4 border-b border-slate-200 bg-slate-50 flex justify-between items-center shrink-0">
|
||
<div>
|
||
<h2 class="text-lg font-bold text-slate-800">响应 eQuery-1029:上传 SDV 原始凭证</h2>
|
||
<p class="text-xs text-slate-500 mt-1">受试者 P005 / 实验室检查 / ALT 异常漏报</p>
|
||
</div>
|
||
<span class="px-3 py-1 bg-red-100 text-red-700 font-bold text-xs rounded-full flex items-center">
|
||
<i class="ph-bold ph-warning-circle mr-1"></i> AI 强制核查项
|
||
</span>
|
||
</div>
|
||
|
||
<div class="flex-1 flex overflow-hidden">
|
||
<div class="w-1/3 bg-slate-50 border-r border-slate-200 p-6 overflow-y-auto">
|
||
<div class="flex items-center text-blue-600 font-bold mb-4">
|
||
<i class="ph-fill ph-robot text-xl mr-2"></i> AI 监查员判定依据
|
||
</div>
|
||
<div class="space-y-6">
|
||
<div>
|
||
<h4 class="text-xs font-bold text-slate-400 uppercase mb-2">当前 REDCap 数据</h4>
|
||
<div class="bg-white border border-slate-200 rounded p-3 text-sm">
|
||
<span class="text-slate-500">lab_alt:</span> <span class="font-bold text-slate-800 ml-2">150 U/L</span>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<h4 class="text-xs font-bold text-slate-400 uppercase mb-2">AI 要求指令</h4>
|
||
<div class="bg-red-50 border border-red-100 rounded p-3 text-sm text-red-800">
|
||
在 REDCap 的《不良事件表》中未查找到对应记录。请在右侧上传该检验报告的原件照片,AI 将重新提取化验单数值以确认是否为您的键盘录入错误。
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex-1 p-8 flex flex-col justify-center items-center bg-white relative">
|
||
<div id="drop-zone" class="w-full max-w-lg p-10 dash-border bg-slate-50 text-center hover:bg-blue-50 transition-colors cursor-pointer group">
|
||
<div class="w-16 h-16 rounded-full bg-blue-100 text-blue-600 flex items-center justify-center mx-auto mb-4 group-hover:scale-110 transition-transform">
|
||
<i class="ph-fill ph-cloud-arrow-up text-3xl"></i>
|
||
</div>
|
||
<h3 class="text-lg font-bold text-slate-800 mb-2">点击或将凭证照片拖拽至此处</h3>
|
||
<p class="text-sm text-slate-500 mb-6">支持 JPG, PNG, PDF 格式。请确保图片清晰,包含患者脱敏 ID。</p>
|
||
<button class="px-6 py-2.5 bg-white border border-slate-300 shadow-sm text-slate-700 font-medium rounded-lg hover:bg-slate-50 transition-colors">
|
||
浏览本地文件
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</main>
|
||
|
||
<!-- 3. 全局统一 AI Copilot -->
|
||
<aside id="sidebar-copilot" class="w-80 bg-white border-l border-slate-200 flex flex-col transition-all duration-300 ease-in-out shrink-0 z-20 shadow-xl">
|
||
<div class="h-16 border-b border-slate-100 flex items-center justify-between px-4 shrink-0 bg-blue-50/50">
|
||
<div class="flex items-center">
|
||
<div class="w-6 h-6 rounded bg-gradient-to-br from-blue-500 to-indigo-600 flex items-center justify-center mr-2 shadow-sm">
|
||
<i class="ph-fill ph-sparkle text-white text-xs"></i>
|
||
</div>
|
||
<span class="font-bold text-slate-800 text-sm">项目大模型助理</span>
|
||
</div>
|
||
<button onclick="toggleCopilot()" class="text-slate-400 hover:text-slate-600">
|
||
<i class="ph-fill ph-x-circle text-xl"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<div id="chat-container" class="flex-1 overflow-y-auto p-4 space-y-4">
|
||
<div class="flex justify-start">
|
||
<div class="max-w-[85%] rounded-2xl px-4 py-3 text-sm leading-relaxed bg-slate-100 text-slate-800 rounded-bl-sm border border-slate-200">
|
||
<span class="font-bold block mb-1">您好!</span>
|
||
我是本项目的统一数字监查大脑。无论您是研究者还是协调员,都可以随时向我提问关于项目进度、数据质量或具体违规记录的细节。
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="p-3 border-t border-slate-100 bg-white shrink-0">
|
||
<form id="chat-form" class="relative">
|
||
<input
|
||
type="text"
|
||
id="chat-input"
|
||
placeholder="例如: 总结本周重大事件..."
|
||
class="w-full bg-slate-50 border border-slate-200 rounded-full pl-4 pr-10 py-2.5 text-sm focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500"
|
||
autocomplete="off"
|
||
/>
|
||
<button type="submit" class="absolute right-2 top-1/2 -translate-y-1/2 p-1.5 bg-blue-600 text-white rounded-full hover:bg-blue-700 transition-colors flex items-center justify-center">
|
||
<i class="ph-bold ph-paper-plane-right text-sm"></i>
|
||
</button>
|
||
</form>
|
||
<div class="mt-2 flex gap-2 overflow-x-auto pb-1 no-scrollbar">
|
||
<span onclick="sendPrompt('总结本周最容易犯的错误')" class="whitespace-nowrap bg-slate-50 border border-slate-200 text-slate-500 text-[10px] px-2 py-1 rounded-full cursor-pointer hover:bg-slate-100">总结本周错误趋势</span>
|
||
<span onclick="sendPrompt('解释为什么 P005 需要SDV')" class="whitespace-nowrap bg-slate-50 border border-slate-200 text-slate-500 text-[10px] px-2 py-1 rounded-full cursor-pointer hover:bg-slate-100">解释 P005 问题</span>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
|
||
<script>
|
||
// === Heatmap 渲染逻辑整合 ===
|
||
const MOCK_HEATMAP = [
|
||
{ id: 'P001', forms: ['green', 'green', 'green', 'green', 'yellow'] },
|
||
{ id: 'P002', forms: ['green', 'red', 'green', 'green', 'green'] },
|
||
{ id: 'P003', forms: ['green', 'green', 'yellow', 'green', 'green'] },
|
||
{ id: 'P004', forms: ['green', 'green', 'green', 'green', 'green'] },
|
||
{ id: 'P005', forms: ['green', 'green', 'red', 'red', 'yellow'] },
|
||
];
|
||
|
||
function renderHeatmap() {
|
||
const tbody = document.getElementById('heatmap-body');
|
||
if(!tbody) return;
|
||
let html = '';
|
||
MOCK_HEATMAP.forEach(row => {
|
||
let rowHtml = `<tr class="border-t border-slate-100 hover:bg-slate-50 transition-colors"><td class="py-3 pr-4 font-bold text-slate-700">${row.id}</td>`;
|
||
row.forms.forEach(status => {
|
||
let colorClass = status === 'red' ? 'bg-red-500 border-red-600 text-white shadow-sm hover:opacity-80' :
|
||
status === 'yellow' ? 'bg-yellow-400 border-yellow-500 text-yellow-900 shadow-sm hover:opacity-80' :
|
||
'bg-emerald-50 border-emerald-100 opacity-60 hover:opacity-100';
|
||
let iconHtml = status === 'red' ? `<i class="ph-bold ph-warning"></i>` : '';
|
||
let action = (status === 'red' || status === 'yellow') ? `onclick="switchView('equery')"` : '';
|
||
|
||
rowHtml += `<td class="p-1">
|
||
<div ${action} class="h-10 rounded flex items-center justify-center border transition-all cursor-pointer ${colorClass}">
|
||
${iconHtml}
|
||
</div>
|
||
</td>`;
|
||
});
|
||
rowHtml += '</tr>';
|
||
html += rowHtml;
|
||
});
|
||
tbody.innerHTML = html;
|
||
}
|
||
|
||
// === 视图路由映射表 ===
|
||
const views = {
|
||
'dashboard': { el: 'view-dashboard', title: '项目健康度大盘', nav: 'nav-dashboard', showBack: false },
|
||
'reports': { el: 'view-reports', title: '定期报告与关键事件', nav: 'nav-reports', showBack: false },
|
||
'ai-stream': { el: 'view-ai-stream', title: 'AI 工作流水', nav: 'nav-ai-stream', showBack: false },
|
||
'equery': { el: 'view-equery', title: '待处理质疑 (eQuery)', nav: 'nav-equery', showBack: false },
|
||
'sdv-response': { el: 'view-sdv', title: 'SDV 凭证上传与验证', nav: 'nav-equery', showBack: true }
|
||
};
|
||
|
||
function switchView(targetViewId) {
|
||
// 隐藏所有视图
|
||
Object.values(views).forEach(v => {
|
||
document.getElementById(v.el).classList.add('hidden');
|
||
document.getElementById(v.el).classList.remove('block', 'flex');
|
||
});
|
||
// 重置所有导航高亮
|
||
['nav-dashboard', 'nav-reports', 'nav-ai-stream', 'nav-equery'].forEach(id => {
|
||
const el = document.getElementById(id);
|
||
el.classList.remove('bg-blue-600/20', 'text-blue-400');
|
||
el.classList.add('text-slate-400');
|
||
});
|
||
|
||
// 显示目标视图
|
||
const target = views[targetViewId];
|
||
const el = document.getElementById(target.el);
|
||
// 某些视图需要 flex (如 sdv),其他用 block
|
||
if(targetViewId === 'sdv-response') {
|
||
el.classList.remove('hidden'); el.classList.add('flex');
|
||
} else {
|
||
el.classList.remove('hidden'); el.classList.add('block');
|
||
}
|
||
|
||
// 更新 Header 与返回按钮
|
||
document.getElementById('header-title').innerText = target.title;
|
||
const btnBack = document.getElementById('btn-back');
|
||
if(target.showBack) {
|
||
btnBack.classList.remove('hidden');
|
||
} else {
|
||
btnBack.classList.add('hidden');
|
||
}
|
||
|
||
// 更新导航高亮
|
||
const navEl = document.getElementById(target.nav);
|
||
navEl.classList.add('bg-blue-600/20', 'text-blue-400');
|
||
navEl.classList.remove('text-slate-400');
|
||
}
|
||
|
||
// Copilot 逻辑
|
||
let copilotOpen = true;
|
||
function toggleCopilot() {
|
||
const sidebar = document.getElementById('sidebar-copilot');
|
||
const btnToggle = document.getElementById('btn-copilot-toggle');
|
||
copilotOpen = !copilotOpen;
|
||
|
||
if (copilotOpen) {
|
||
sidebar.classList.remove('w-0', 'border-none');
|
||
sidebar.classList.add('w-80');
|
||
btnToggle.classList.replace('text-slate-400', 'text-blue-600');
|
||
btnToggle.classList.replace('hover:bg-slate-100', 'bg-blue-50');
|
||
} else {
|
||
sidebar.classList.remove('w-80');
|
||
sidebar.classList.add('w-0', 'border-none');
|
||
btnToggle.classList.replace('text-blue-600', 'text-slate-400');
|
||
btnToggle.classList.replace('bg-blue-50', 'hover:bg-slate-100');
|
||
}
|
||
}
|
||
|
||
let chatMessages = [
|
||
{ role: 'system', content: '您好!我是本项目的统一数字监查大脑。无论您是研究者还是协调员,都可以随时向我提问关于项目进度、数据质量或具体违规记录的细节。' }
|
||
];
|
||
|
||
function renderChat() {
|
||
const container = document.getElementById('chat-container');
|
||
let html = '';
|
||
chatMessages.forEach(msg => {
|
||
let alignment = msg.role === 'user' ? 'justify-end' : 'justify-start';
|
||
let styling = msg.role === 'user' ? 'bg-blue-600 text-white rounded-br-sm' :
|
||
msg.role === 'system' ? 'bg-slate-100 text-slate-500 text-xs text-center w-full rounded-lg' :
|
||
'bg-slate-100 text-slate-800 rounded-bl-sm border border-slate-200';
|
||
|
||
html += `
|
||
<div class="flex ${alignment}">
|
||
<div class="max-w-[85%] rounded-2xl px-4 py-2.5 text-sm leading-relaxed ${styling}">
|
||
${msg.content}
|
||
</div>
|
||
</div>`;
|
||
});
|
||
container.innerHTML = html;
|
||
container.scrollTop = container.scrollHeight;
|
||
}
|
||
|
||
function sendPrompt(text) {
|
||
document.getElementById('chat-input').value = text;
|
||
document.getElementById('chat-form').dispatchEvent(new Event('submit'));
|
||
}
|
||
|
||
document.getElementById('chat-form').addEventListener('submit', function(e) {
|
||
e.preventDefault();
|
||
const input = document.getElementById('chat-input');
|
||
const text = input.value.trim();
|
||
if (!text) return;
|
||
|
||
chatMessages.push({ role: 'user', content: text });
|
||
input.value = '';
|
||
renderChat();
|
||
|
||
setTimeout(() => {
|
||
chatMessages.push({ role: 'ai', content: '收到您的指令。我已将底层数据检索报告推送到您的界面,请查看左侧的模块视图。' });
|
||
renderChat();
|
||
}, 800);
|
||
});
|
||
|
||
// 初始化
|
||
window.onload = function() {
|
||
renderHeatmap(); // 渲染热力图
|
||
switchView('dashboard'); // 默认进入大盘视图
|
||
};
|
||
|
||
</script>
|
||
</body>
|
||
</html> |