feat(iit): Initialize IIT Manager Agent MVP - Day 1 complete

- Add iit_schema with 5 tables
- Create module structure and types (223 lines)
- WeChat integration verified (Access Token success)
- Update system docs to v2.4
- Add REDCap source folders to .gitignore
- Day 1/14 complete (11/11 tasks)
This commit is contained in:
2025-12-31 18:35:05 +08:00
parent decff0bb1f
commit 4c5bb3d174
154 changed files with 13759 additions and 8 deletions

View File

@@ -0,0 +1,224 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>IIT Manager Agent - Agent 协作中心</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
body { background-color: #f8fafc; }
.module-container { height: calc(100vh - 64px); }
.inbox-item-active { background-color: #eff6ff; border-left: 4px solid #2563eb; }
.evidence-box { background: #fdfdfd; border: 1px solid #e2e8f0; border-radius: 8px; }
.shadow-data-tag { background: #fff7ed; border: 1px dashed #fb923c; color: #c2410c; }
</style>
</head>
<body class="h-screen flex flex-col overflow-hidden">
<!-- 1. 顶部状态条 -->
<header class="h-14 bg-white border-b border-slate-200 flex items-center justify-between px-6 shrink-0 z-20 shadow-sm">
<div class="flex items-center space-x-4">
<div class="flex items-center space-x-2">
<i class="fa-solid fa-microchip text-blue-600 text-xl"></i>
<span class="font-bold text-slate-800">Agent 协作中心 (Workbench)</span>
</div>
<div class="h-4 w-px bg-slate-300"></div>
<select class="text-sm font-medium border-none bg-transparent focus:ring-0 text-slate-600">
<option>全部受试者项目</option>
<option>北医三院 - 骨质疏松研究</option>
<option>北大肿瘤 - 肺癌研究</option>
</select>
</div>
<div class="flex items-center space-x-6">
<div class="flex space-x-4 text-xs">
<span class="text-slate-500">待复核 QC: <b class="text-slate-800 ml-1">12</b></span>
<span class="text-slate-500">待处理任务: <b class="text-slate-800 ml-1">8</b></span>
<span class="text-slate-500">已回写 REDCap: <b class="text-green-600 ml-1">156</b></span>
</div>
<button class="bg-blue-600 text-white px-3 py-1.5 rounded-lg text-xs font-bold hover:bg-blue-700 transition-all">
<i class="fa-solid fa-upload mr-1"></i>批量导入/OCR
</button>
</div>
</header>
<!-- 2. 主体三栏布局 -->
<main class="flex-1 flex overflow-hidden">
<!-- A 栏:任务分流枢纽 (Action Inbox) -->
<aside class="w-80 bg-white border-r border-slate-200 flex flex-col shrink-0">
<div class="p-4 bg-slate-50 border-b border-slate-200">
<div class="relative">
<i class="fa-solid fa-magnifying-glass absolute left-3 top-2.5 text-slate-400 text-xs"></i>
<input type="text" placeholder="搜索受试者或任务..." class="w-full pl-8 pr-4 py-2 bg-white border border-slate-200 rounded-lg text-xs focus:ring-1 focus:ring-blue-500 outline-none">
</div>
<div class="flex mt-3 space-x-1">
<button class="flex-1 py-1 px-2 bg-blue-600 text-white text-[10px] font-bold rounded">全部</button>
<button class="flex-1 py-1 px-2 bg-slate-100 text-slate-500 text-[10px] rounded hover:bg-slate-200">质控</button>
<button class="flex-1 py-1 px-2 bg-slate-100 text-slate-500 text-[10px] rounded hover:bg-slate-200">采集</button>
<button class="flex-1 py-1 px-2 bg-slate-100 text-slate-500 text-[10px] rounded hover:bg-slate-200">随访</button>
</div>
</div>
<!-- 任务列表滚动区 -->
<div class="flex-1 overflow-y-auto">
<!-- 任务卡片示例 -->
<div class="p-4 border-b border-slate-100 inbox-item-active cursor-pointer">
<div class="flex justify-between items-start mb-1">
<span class="text-[10px] font-bold text-amber-600 bg-amber-50 px-1.5 py-0.5 rounded">QC ERROR</span>
<span class="text-[10px] text-slate-400">09:41</span>
</div>
<h4 class="text-sm font-bold text-slate-800">受试者 P001: 方案偏离预警</h4>
<p class="text-xs text-slate-500 mt-1 line-clamp-2">血红蛋白录入值(85)低于方案排除标准(90),建议发起质疑或确认偏离理由。</p>
</div>
<div class="p-4 border-b border-slate-100 hover:bg-slate-50 cursor-pointer">
<div class="flex justify-between items-start mb-1">
<span class="text-[10px] font-bold text-blue-600 bg-blue-50 px-1.5 py-0.5 rounded">OCR CAPTURE</span>
<span class="text-[10px] text-slate-400">11:20</span>
</div>
<h4 class="text-sm font-bold text-slate-800">化验单提取: 4 个指标待确认</h4>
<p class="text-xs text-slate-500 mt-1">已完成 PDF 报告解析,匹配到 4 个 REDCap 字段。</p>
</div>
<div class="p-4 border-b border-slate-100 hover:bg-slate-50 cursor-pointer">
<div class="flex justify-between items-start mb-1">
<span class="text-[10px] font-bold text-red-600 bg-red-50 px-1.5 py-0.5 rounded">URGENT</span>
<span class="text-[10px] text-slate-400">昨天</span>
</div>
<h4 class="text-sm font-bold text-slate-800">受试者 P055: 访视窗即将关闭</h4>
<p class="text-xs text-slate-500 mt-1">V3 访视应于今日完成,患者暂无反馈。</p>
</div>
</div>
</aside>
<!-- B 栏:沉浸式复核区 (Review Workspace) -->
<section class="flex-1 bg-slate-50 flex flex-col overflow-hidden">
<!-- 上下文摘要条 -->
<div class="h-14 bg-white border-b border-slate-200 flex items-center justify-between px-6 shrink-0">
<div class="flex items-center space-x-4">
<div class="flex flex-col">
<span class="text-[10px] text-slate-400 uppercase font-bold">正在复核</span>
<span class="text-sm font-bold text-slate-800">受试者: P001 (张三) | 筛选期访视 (V1)</span>
</div>
<div class="h-8 w-px bg-slate-200"></div>
<div class="flex space-x-2">
<button class="text-xs text-blue-600 hover:underline">查看 REDCap 原生数据</button>
<button class="text-xs text-blue-600 hover:underline">查看审计日志</button>
</div>
</div>
<div class="flex space-x-2">
<button class="px-4 py-2 bg-slate-100 text-slate-600 rounded-lg text-xs font-bold hover:bg-slate-200">驳回 AI 建议</button>
<button class="px-4 py-2 bg-blue-600 text-white rounded-lg text-xs font-bold hover:bg-blue-700 shadow-lg">确认并同步到 REDCap</button>
</div>
</div>
<!-- 核心对比工作台 -->
<div class="flex-1 overflow-hidden p-6 flex space-x-6">
<!-- 模块:影子建议表单 (Shadow Form) -->
<div class="flex-1 flex flex-col space-y-4">
<div class="bg-white rounded-2xl p-6 border border-slate-200 shadow-sm flex-1">
<h5 class="text-xs font-bold text-slate-400 uppercase tracking-widest mb-4">待处理的影子动作 (Shadow Actions)</h5>
<div class="space-y-6">
<!-- 对比单元 1 -->
<div class="p-4 rounded-xl border-l-4 border-amber-400 bg-amber-50/30">
<p class="text-xs font-bold text-slate-800 mb-2">字段: 血红蛋白 (HGB)</p>
<div class="grid grid-cols-2 gap-4">
<div class="p-3 bg-white rounded-lg border border-slate-200">
<p class="text-[10px] text-slate-400">REDCap 原生值</p>
<p class="text-lg font-bold text-slate-400 italic">尚未录入</p>
</div>
<div class="p-3 shadow-data-tag rounded-lg">
<p class="text-[10px]">AI 提取建议值</p>
<p class="text-lg font-bold">85 <span class="text-xs font-normal">g/L</span></p>
</div>
</div>
<div class="mt-3 flex items-start space-x-2 text-xs text-amber-700">
<i class="fa-solid fa-circle-info mt-0.5"></i>
<p>AI 推理: 从“2025-12-28 检验单”中提取。注意: 该值低于方案规定的 90g/L 入组门限。</p>
</div>
</div>
<!-- 对比单元 2 -->
<div class="p-4 rounded-xl border-l-4 border-blue-400 bg-blue-50/30">
<p class="text-xs font-bold text-slate-800 mb-2">字段: 知情同意签署日期</p>
<div class="grid grid-cols-2 gap-4">
<div class="p-3 bg-white rounded-lg border border-slate-200">
<p class="text-[10px] text-slate-400">REDCap 原生值</p>
<p class="text-lg font-bold">2025-12-30</p>
</div>
<div class="p-3 bg-white rounded-lg border border-blue-200">
<p class="text-[10px] text-blue-500 font-bold">AI 映射确认</p>
<p class="text-lg font-bold text-blue-700">一致 <i class="fa-solid fa-check-circle ml-1"></i></p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 模块:证据浏览器 (Evidence Browser) -->
<div class="w-1/3 flex flex-col space-y-4">
<div class="bg-slate-800 rounded-2xl flex-1 flex flex-col overflow-hidden shadow-2xl">
<div class="h-10 bg-slate-900 flex items-center justify-between px-4">
<span class="text-[10px] text-slate-400 font-bold uppercase">源证据: PDF 原始附件</span>
<div class="flex space-x-2 text-slate-400">
<i class="fa-solid fa-magnifying-glass-plus cursor-pointer"></i>
<i class="fa-solid fa-expand cursor-pointer"></i>
</div>
</div>
<div class="flex-1 relative flex items-center justify-center p-6">
<!-- 模拟高亮证据 -->
<div class="w-full bg-white p-6 shadow-inner text-[8px] text-slate-300 relative">
<p class="text-slate-900 font-bold text-[10px] mb-4 text-center border-b pb-2">XXX 医院检验报告单</p>
<div class="grid grid-cols-2 gap-2 mb-4">
<p>姓名: 张三</p>
<p>日期: 2025-12-28</p>
</div>
<div class="space-y-1">
<p>白细胞 (WBC) ...... 6.2</p>
<!-- 高亮区域 -->
<div class="relative">
<p class="text-slate-900 font-bold bg-amber-200/50 border border-amber-300 px-1">血红蛋白 (HGB) ... 85</p>
<div class="absolute -right-4 -top-2 w-4 h-4 bg-amber-500 rounded-full flex items-center justify-center text-white text-[8px] animate-pulse">!</div>
</div>
<p>血小板 (PLT) ...... 210</p>
</div>
</div>
</div>
</div>
<!-- 快速 AI 追问 -->
<div class="bg-white rounded-xl p-4 border border-slate-200">
<p class="text-[10px] font-bold text-slate-400 mb-2 uppercase">AI Copilot 追问</p>
<div class="relative">
<input type="text" placeholder="问 AI: 为什么这个值有风险?" class="w-full text-xs p-2 bg-slate-50 border border-slate-100 rounded focus:ring-1 focus:ring-blue-500 outline-none">
<i class="fa-solid fa-paper-plane absolute right-2 top-2.5 text-blue-400 text-xs cursor-pointer"></i>
</div>
</div>
</div>
</div>
</section>
<!-- C 栏:系统反馈与审计 (History/Audit) -->
<aside class="w-16 bg-white border-l border-slate-200 flex flex-col items-center py-6 space-y-6">
<div class="p-2 text-blue-600 cursor-pointer hover:bg-slate-50 rounded" title="操作历史">
<i class="fa-solid fa-clock-rotate-left"></i>
</div>
<div class="p-2 text-slate-400 cursor-pointer hover:bg-slate-50 rounded" title="质疑列表">
<i class="fa-solid fa-clipboard-question"></i>
</div>
<div class="p-2 text-slate-400 cursor-pointer hover:bg-slate-50 rounded" title="邮件/微信通知">
<i class="fa-solid fa-paper-plane"></i>
</div>
<div class="flex-1"></div>
<div class="p-2 text-slate-400 cursor-pointer hover:bg-slate-50 rounded" title="设置">
<i class="fa-solid fa-cog"></i>
</div>
</aside>
</main>
</body>
</html>

View File

@@ -0,0 +1,200 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>IIT Manager Agent - 管理后台</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
body { background-color: #f1f5f9; }
.sidebar-item-active { background-color: #e2e8f0; color: #1e40af; border-right: 3px solid #1e40af; }
.step-active { color: #1e40af; border-bottom: 2px solid #1e40af; }
.card-hover:hover { transform: translateY(-2px); box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); }
</style>
</head>
<body class="h-screen flex overflow-hidden">
<!-- 1. 左侧全局导航 (Sider) -->
<aside class="w-64 bg-slate-900 text-slate-300 flex flex-col shrink-0">
<div class="p-6 flex items-center space-x-3">
<div class="w-8 h-8 bg-blue-500 rounded-lg flex items-center justify-center text-white font-bold">I</div>
<span class="text-white font-bold tracking-tight">IIT Manager Admin</span>
</div>
<nav class="flex-1 px-4 space-y-1 mt-4">
<a href="#" class="flex items-center space-x-3 p-3 rounded-lg hover:bg-slate-800 transition-all text-sm sidebar-item-active">
<i class="fa-solid fa-house"></i> <span>项目全景</span>
</a>
<a href="#" class="flex items-center space-x-3 p-3 rounded-lg hover:bg-slate-800 transition-all text-sm">
<i class="fa-solid fa-wand-magic-sparkles"></i> <span>向导式初始化</span>
</a>
<a href="#" class="flex items-center space-x-3 p-3 rounded-lg hover:bg-slate-800 transition-all text-sm">
<i class="fa-solid fa-database"></i> <span>EDC 适配管理</span>
</a>
<a href="#" class="flex items-center space-x-3 p-3 rounded-lg hover:bg-slate-800 transition-all text-sm">
<i class="fa-solid fa-robot"></i> <span>Agent 策略中心</span>
</a>
<div class="pt-4 pb-2 text-[10px] font-bold text-slate-500 uppercase tracking-widest">组织管理</div>
<a href="#" class="flex items-center space-x-3 p-3 rounded-lg hover:bg-slate-800 transition-all text-sm">
<i class="fa-solid fa-hospital"></i> <span>医院/中心映射</span>
</a>
<a href="#" class="flex items-center space-x-3 p-3 rounded-lg hover:bg-slate-800 transition-all text-sm">
<i class="fa-solid fa-user-shield"></i> <span>角色与权限</span>
</a>
</nav>
<div class="p-4 border-t border-slate-800">
<div class="flex items-center space-x-3 px-2">
<div class="w-8 h-8 bg-slate-700 rounded-full flex items-center justify-center text-xs">AD</div>
<div class="text-xs">
<p class="text-slate-100 font-bold">Admin@yizx.ai</p>
<p class="text-slate-500">壹证循系统管理员</p>
</div>
</div>
</div>
</aside>
<!-- 2. 主内容区 -->
<main class="flex-1 flex flex-col overflow-hidden">
<!-- 顶部条 -->
<header class="h-16 bg-white border-b border-slate-200 flex items-center justify-between px-8 shrink-0">
<div class="flex items-center">
<h2 class="text-lg font-bold text-slate-800">新建项目初始化向导</h2>
</div>
<div class="flex items-center space-x-4">
<button class="text-slate-500 hover:text-slate-800"><i class="fa-solid fa-bell"></i></button>
<button class="bg-blue-600 text-white px-4 py-2 rounded-lg text-sm font-medium hover:bg-blue-700 shadow-sm transition-all">
<i class="fa-solid fa-plus mr-2"></i>创建新项目
</button>
</div>
</header>
<!-- 内容滚动区 -->
<div class="flex-1 overflow-y-auto p-8">
<!-- 初始化向导步骤条 (Wizard Steps) -->
<div class="max-w-4xl mx-auto mb-10">
<div class="flex items-center justify-between text-sm font-medium text-slate-400">
<div class="flex flex-col items-center space-y-2 step-active pb-2">
<span class="w-8 h-8 rounded-full border-2 border-blue-600 flex items-center justify-center text-blue-600">1</span>
<span>方案数字化注入</span>
</div>
<div class="h-px bg-slate-200 flex-1 mx-4 -mt-6"></div>
<div class="flex flex-col items-center space-y-2">
<span class="w-8 h-8 rounded-full border-2 border-slate-200 flex items-center justify-center">2</span>
<span>EDC 联通与映射</span>
</div>
<div class="h-px bg-slate-200 flex-1 mx-4 -mt-6"></div>
<div class="flex flex-col items-center space-y-2">
<span class="w-8 h-8 rounded-full border-2 border-slate-200 flex items-center justify-center">3</span>
<span>AI 策略与知识库</span>
</div>
<div class="h-px bg-slate-200 flex-1 mx-4 -mt-6"></div>
<div class="flex flex-col items-center space-y-2">
<span class="w-8 h-8 rounded-full border-2 border-slate-200 flex items-center justify-center">4</span>
<span>发布与激活</span>
</div>
</div>
</div>
<!-- 当前步骤内容Step 1 -->
<div class="max-w-5xl mx-auto space-y-6">
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<!-- 左侧:方案上传区 -->
<div class="md:col-span-1 bg-white p-6 rounded-2xl border border-slate-200 shadow-sm">
<h3 class="font-bold text-slate-800 mb-4">第一步:上传研究方案</h3>
<p class="text-xs text-slate-500 mb-6">请上传 PDF 格式的临床研究方案AI 将自动解析访视计划和入排标准。</p>
<div class="border-2 border-dashed border-slate-200 rounded-xl p-8 text-center hover:border-blue-400 transition-all cursor-pointer bg-slate-50">
<i class="fa-solid fa-cloud-arrow-up text-3xl text-slate-300 mb-2"></i>
<p class="text-xs font-medium text-slate-600">点击或拖拽文件上传</p>
<p class="text-[10px] text-slate-400 mt-1">支持 PDF/Word, 最大 50MB</p>
</div>
<div class="mt-6 space-y-3">
<div class="flex items-center justify-between text-xs p-3 bg-blue-50 border border-blue-100 rounded-lg">
<div class="flex items-center space-x-2 overflow-hidden">
<i class="fa-solid fa-file-pdf text-red-500"></i>
<span class="truncate font-medium text-blue-800">Protocol_V2.1.pdf</span>
</div>
<i class="fa-solid fa-circle-check text-green-500"></i>
</div>
</div>
</div>
<!-- 右侧AI 解析结果展示与确认 -->
<div class="md:col-span-2 bg-white p-6 rounded-2xl border border-slate-200 shadow-sm flex flex-col">
<div class="flex justify-between items-center mb-6">
<h3 class="font-bold text-slate-800">AI 解析结果预览 (数字化日历)</h3>
<button class="text-xs text-blue-600 hover:underline"><i class="fa-solid fa-pen-to-square mr-1"></i>手动修正</button>
</div>
<!-- 解析出的访视日历列表 -->
<div class="space-y-4 flex-1">
<div class="flex items-start space-x-4 p-4 border border-slate-100 rounded-xl bg-slate-50 relative">
<div class="w-12 h-12 bg-white rounded-lg border border-slate-200 flex flex-col items-center justify-center text-slate-400">
<span class="text-[10px] uppercase font-bold">Day</span>
<span class="text-lg font-bold text-slate-800">0</span>
</div>
<div>
<h4 class="text-sm font-bold text-slate-800">V1 (筛选期/基线访视)</h4>
<p class="text-xs text-slate-500 mt-1">关键动作: 签署知情同意书, 入排标准核对, 随机化分配。</p>
<div class="flex mt-2 space-x-2">
<span class="module-tag">知情同意书</span><span class="module-tag">血常规</span><span class="module-tag">心电图</span>
</div>
</div>
<span class="absolute top-4 right-4 text-[10px] bg-green-100 text-green-700 px-2 py-0.5 rounded-full font-bold">置信度: 98%</span>
</div>
<div class="flex items-start space-x-4 p-4 border border-slate-100 rounded-xl bg-white relative">
<div class="w-12 h-12 bg-white rounded-lg border border-slate-200 flex flex-col items-center justify-center text-slate-400">
<span class="text-[10px] uppercase font-bold">Day</span>
<span class="text-lg font-bold text-slate-800">28</span>
</div>
<div>
<h4 class="text-sm font-bold text-slate-800">V2 (给药后第一次访视)</h4>
<p class="text-xs text-slate-500 mt-1">访视窗: ±3天。 关键动作: 药物依从性检查, 安全性评估 (AE)。</p>
<div class="flex mt-2 space-x-2">
<span class="module-tag">生存质量量表</span><span class="module-tag">不良事件上报</span>
</div>
</div>
<span class="absolute top-4 right-4 text-[10px] bg-blue-100 text-blue-700 px-2 py-0.5 rounded-full font-bold">置信度: 92%</span>
</div>
<div class="p-8 text-center border border-dashed border-slate-200 rounded-xl">
<p class="text-xs text-slate-400">向下滚动查看后续 12 个访视点...</p>
</div>
</div>
<div class="mt-8 flex justify-end">
<button class="bg-blue-600 text-white px-8 py-2.5 rounded-xl font-bold hover:bg-blue-700 shadow-lg transition-all">确认解析并进入下一步</button>
</div>
</div>
</div>
<!-- 底部:提示与状态说明 -->
<div class="bg-blue-900 rounded-2xl p-6 text-white flex items-center justify-between">
<div class="flex items-center space-x-4">
<div class="w-12 h-12 bg-white/10 rounded-full flex items-center justify-center text-xl">
<i class="fa-solid fa-lightbulb text-amber-400"></i>
</div>
<div>
<p class="font-bold">设计提示: 数字化访视日历是 Agent 的执行基准</p>
<p class="text-xs text-blue-200 mt-1">一旦在此确认,任务引擎将自动为 100+ 受试者排程,请务必仔细核对 Day 偏移量和访视窗。</p>
</div>
</div>
<button class="bg-white/10 hover:bg-white/20 px-4 py-2 rounded-lg text-sm transition-all">查看详细解析报告</button>
</div>
</div>
</div>
</main>
<script>
// 简单的步骤模拟逻辑
console.log("Admin Portal Prototype Loaded");
</script>
</body>
</html>

View File

@@ -0,0 +1,235 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>PI 决策舱 - 微信端原型</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
body {
background-color: #f3f4f6;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
.wechat-card {
box-shadow: 0 1px 2px rgba(0,0,0,0.05);
}
.mini-program-nav {
background: linear-gradient(135deg, #1e40af 0%, #1e3a8a 100%);
}
.glass-card {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
}
.safe-area-bottom {
padding-bottom: env(safe-area-inset-bottom);
}
@keyframes pulse-soft {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.02); }
}
.urgent-pulse {
animation: pulse-soft 2s infinite;
}
</style>
</head>
<body class="flex flex-col items-center min-h-screen">
<!-- 模拟手机外壳 -->
<div class="w-full max-w-md bg-white min-h-screen shadow-2xl overflow-hidden flex flex-col relative">
<!-- 场景 1企业微信消息列表 (模拟) -->
<div id="scene-notification" class="flex-1 flex flex-col bg-slate-100">
<!-- 微信顶部状态栏 -->
<div class="h-10 bg-slate-100 flex items-center justify-between px-6">
<span class="text-xs font-bold">18:30</span>
<div class="flex space-x-1">
<i class="fa-solid fa-signal text-[10px]"></i>
<i class="fa-solid fa-wifi text-[10px]"></i>
<i class="fa-solid fa-battery-three-quarters text-[10px]"></i>
</div>
</div>
<!-- 微信导航栏 -->
<div class="h-12 border-b border-slate-200 flex items-center px-4 space-x-4 bg-slate-100">
<i class="fa-solid fa-chevron-left"></i>
<span class="font-bold">企业微信 (1)</span>
</div>
<!-- 消息内容 -->
<div class="p-4 space-y-6">
<div class="text-center">
<span class="bg-slate-200 text-white text-[10px] px-2 py-0.5 rounded">18:31</span>
</div>
<!-- 智能提醒卡片 -->
<div onclick="openApplet()" class="wechat-card bg-white rounded-lg overflow-hidden cursor-pointer active:bg-slate-50 transition-colors">
<div class="p-4 border-b border-slate-100 flex items-center space-x-3">
<div class="w-10 h-10 bg-blue-600 rounded flex items-center justify-center text-white text-xl">
<i class="fa-solid fa-robot"></i>
</div>
<div>
<p class="font-bold text-slate-800">临床研究助理</p>
<p class="text-xs text-slate-400">来自: 北医三院项目组</p>
</div>
</div>
<div class="p-4">
<h4 class="font-bold text-slate-800 mb-2">⚠️ 严重方案偏离提醒 (PD)</h4>
<div class="space-y-1 text-sm text-slate-600">
<p>受试者: <span class="font-medium text-slate-900">P001</span></p>
<p>异常类型: <span class="text-red-600 font-bold">入排标准违背</span></p>
<p>详情: 年龄录入为 76 岁,超出方案限制。</p>
</div>
<div class="mt-4 pt-4 border-t border-slate-100 text-blue-600 text-sm font-medium flex justify-between items-center">
<span>点击进入决策中心查看证据</span>
<i class="fa-solid fa-chevron-right text-xs"></i>
</div>
</div>
</div>
</div>
</div>
<!-- 场景 2微信小程序 (决策中心) -->
<div id="scene-applet" class="hidden absolute inset-0 z-50 bg-slate-50 flex flex-col">
<!-- 小程序胶囊按钮 (模拟) -->
<div class="mini-program-nav h-24 pt-10 px-4 flex items-center justify-between text-white shrink-0">
<div class="flex items-center space-x-2">
<i class="fa-solid fa-hospital text-sm opacity-80"></i>
<span class="text-sm font-bold truncate max-w-[200px]">北医三院骨科项目组</span>
</div>
<div class="flex items-center space-x-3 bg-black/20 rounded-full px-3 py-1 border border-white/20">
<i class="fa-solid fa-ellipsis text-sm"></i>
<div class="w-px h-3 bg-white/20"></div>
<i onclick="closeApplet()" class="fa-solid fa-circle-stop text-sm cursor-pointer"></i>
</div>
</div>
<!-- 主题切换与项目卡片 -->
<div class="flex-1 overflow-y-auto no-scrollbar">
<!-- 影子决策详情 -->
<div class="p-4">
<div class="bg-white rounded-2xl shadow-sm border border-slate-200 overflow-hidden">
<div class="bg-amber-50 p-4 border-b border-amber-100 flex items-center justify-between">
<span class="text-xs font-bold text-amber-800 uppercase tracking-widest">待复核质疑</span>
<span class="text-[10px] bg-amber-200 text-amber-800 px-2 py-0.5 rounded-full">高风险</span>
</div>
<div class="p-4">
<div class="flex items-center justify-between mb-4">
<div>
<p class="text-[10px] text-slate-400 font-bold">受试者编号</p>
<p class="text-lg font-bold text-slate-800">P001</p>
</div>
<div class="text-right">
<p class="text-[10px] text-slate-400 font-bold">提交时间</p>
<p class="text-sm text-slate-600">18:31</p>
</div>
</div>
<!-- 证据展示区 -->
<div class="bg-slate-50 rounded-xl p-4 mb-4">
<p class="text-xs text-slate-500 mb-2">AI 推理建议:</p>
<p class="text-sm font-medium text-slate-800 leading-relaxed">
检测到年龄录入值为 <span class="bg-amber-200 px-1 font-bold">76</span>。检索研究方案第 14 页入选标准第 1.1 条,明确要求年龄上限为 <span class="underline decoration-blue-500">75 岁</span>
</p>
</div>
<!-- 移动端证据预览 -->
<div class="relative h-40 bg-slate-800 rounded-xl overflow-hidden mb-4 border border-slate-200">
<div class="absolute inset-0 p-4 text-[8px] text-slate-400 bg-white">
<p class="text-[10px] font-bold text-slate-900 border-b pb-1 mb-2">方案原文节选</p>
<p>1. 受试者入选标准:</p>
<p class="bg-amber-100 text-slate-800 font-bold px-1 mt-1">1.1 年龄 18 岁(含)至 75 岁(含),性别不限;</p>
<p>1.2 经组织学或细胞学确诊的局部晚期...</p>
</div>
<div class="absolute bottom-2 right-2 px-2 py-1 bg-blue-600 text-white text-[8px] rounded-full shadow-lg">
<i class="fa-solid fa-magnifying-glass mr-1"></i> 点击查看全文
</div>
</div>
<!-- 决策按钮 -->
<div class="flex space-x-3">
<button class="flex-1 py-3 bg-slate-100 text-slate-600 rounded-xl font-bold text-sm" onclick="rejectAction()">暂缓处理</button>
<button class="flex-1 py-3 bg-blue-600 text-white rounded-xl font-bold text-sm shadow-lg shadow-blue-200" onclick="approveAction()">批准并生成质疑</button>
</div>
</div>
</div>
</div>
<!-- 快捷统计看板 -->
<div class="px-4 pb-10">
<h5 class="text-sm font-bold text-slate-800 mb-4">今日项目动态</h5>
<div class="grid grid-cols-2 gap-3">
<div class="bg-white p-4 rounded-2xl border border-slate-100 shadow-sm">
<p class="text-[10px] text-slate-400 font-bold uppercase">入组进度</p>
<p class="text-xl font-bold text-slate-800 mt-1">85<span class="text-xs text-slate-400 font-normal"> / 100</span></p>
</div>
<div class="bg-white p-4 rounded-2xl border border-slate-100 shadow-sm">
<p class="text-[10px] text-slate-400 font-bold uppercase">待审 PD</p>
<p class="text-xl font-bold text-amber-500 mt-1">3</p>
</div>
</div>
</div>
</div>
<!-- 底部导航 (小程序 TabBar) -->
<div class="h-16 border-t border-slate-100 bg-white flex items-center justify-around safe-area-bottom">
<div class="flex flex-col items-center text-blue-600">
<i class="fa-solid fa-house text-sm"></i>
<span class="text-[10px] mt-1">首页</span>
</div>
<div class="flex flex-col items-center text-slate-400">
<i class="fa-solid fa-chart-pie text-sm"></i>
<span class="text-[10px] mt-1">报表中心</span>
</div>
<div class="flex flex-col items-center text-slate-400">
<i class="fa-solid fa-robot text-sm"></i>
<span class="text-[10px] mt-1">AI 咨询</span>
</div>
<div class="flex flex-col items-center text-slate-400">
<i class="fa-solid fa-user text-sm"></i>
<span class="text-[10px] mt-1">我的</span>
</div>
</div>
</div>
<!-- 成功/反馈轻提示 -->
<div id="toast" class="fixed bottom-24 left-1/2 -translate-x-1/2 bg-slate-800/90 text-white px-6 py-3 rounded-full text-xs font-bold transform translate-y-20 opacity-0 transition-all z-[100]">
已批准REDcap 质疑已自动生成
</div>
</div>
<script>
function openApplet() {
document.getElementById('scene-notification').classList.add('hidden');
document.getElementById('scene-applet').classList.remove('hidden');
}
function closeApplet() {
document.getElementById('scene-notification').classList.remove('hidden');
document.getElementById('scene-applet').classList.add('hidden');
}
function approveAction() {
const toast = document.getElementById('toast');
toast.innerText = "✅ 影子决策已转正REDcap 质疑已生成";
toast.classList.remove('translate-y-20', 'opacity-0');
setTimeout(() => {
toast.classList.add('translate-y-20', 'opacity-0');
}, 2000);
}
function rejectAction() {
const toast = document.getElementById('toast');
toast.innerText = "已记录意见,待 CRC 进一步核实";
toast.classList.remove('translate-y-20', 'opacity-0');
setTimeout(() => {
toast.classList.add('translate-y-20', 'opacity-0');
}, 2000);
}
</script>
</body>
</html>

View File

@@ -0,0 +1,280 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>患者随访端 - 壹证循</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
body {
background-color: #ededed;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
overflow-x: hidden;
}
.chat-bubble-left {
position: relative;
background: white;
border-radius: 8px;
padding: 10px 12px;
margin-left: 10px;
max-width: 75%;
font-size: 15px;
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
}
.chat-bubble-left::after {
content: '';
position: absolute;
left: -6px;
top: 14px;
border-width: 6px 6px 6px 0;
border-style: solid;
border-color: transparent white transparent transparent;
}
.chat-bubble-right {
position: relative;
background: #95ec69;
border-radius: 8px;
padding: 10px 12px;
margin-right: 10px;
max-width: 75%;
font-size: 15px;
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
}
.chat-bubble-right::after {
content: '';
position: absolute;
right: -6px;
top: 14px;
border-width: 6px 0 6px 6px;
border-style: solid;
border-color: transparent transparent transparent #95ec69;
}
.tab-active { color: #07c160; }
.bottom-nav { border-top: 1px solid #d1d1d1; background: #f7f7f7; }
.task-done { text-decoration: line-through; color: #a0a0a0; }
</style>
</head>
<body class="flex justify-center">
<!-- 模拟手机容器 -->
<div class="w-full max-w-md bg-[#ededed] min-h-screen flex flex-col relative shadow-2xl">
<!-- 场景 1: 对话互动界面 (Chat) -->
<div id="tab-chat-content" class="flex-1 flex flex-col overflow-hidden">
<!-- 顶部导航 -->
<div class="h-12 bg-[#ededed] border-b border-[#d1d1d1] flex items-center justify-between px-4 shrink-0">
<i class="fa-solid fa-chevron-left text-slate-600"></i>
<span class="font-bold text-[17px]">北医三院项目组-王老师</span>
<i class="fa-solid fa-ellipsis text-slate-600"></i>
</div>
<!-- 聊天滚动区 -->
<div class="flex-1 overflow-y-auto p-4 space-y-6">
<!-- 时间戳 -->
<div class="text-center"><span class="text-[12px] text-slate-400">10:05</span></div>
<!-- AI CRC 发送的消息 -->
<div class="flex items-start">
<div class="w-10 h-10 bg-blue-500 rounded flex items-center justify-center text-white shrink-0">
<i class="fa-solid fa-user-doctor"></i>
</div>
<div class="chat-bubble-left">
王先生您好我是研究组的数字助理。明天12月31日是您的第 3 次访视时间,请记得早晨 <span class="text-red-500 font-bold">空腹</span> 到骨科门诊找林医生。
</div>
</div>
<!-- 任务卡片消息 -->
<div class="flex items-start">
<div class="w-10 h-10 bg-blue-500 rounded flex items-center justify-center text-white shrink-0 opacity-0"></div>
<div class="bg-white rounded-xl overflow-hidden shadow-sm border border-slate-200 ml-2 w-full max-w-[240px]">
<div class="p-3 bg-blue-50 border-b border-blue-100 flex items-center space-x-2">
<i class="fa-solid fa-clipboard-check text-blue-600 text-xs"></i>
<span class="text-[12px] font-bold text-blue-800 uppercase">访视前准备</span>
</div>
<div class="p-3 space-y-2">
<div class="flex items-center text-xs text-slate-600">
<i class="fa-regular fa-square mr-2"></i> <span>空腹 8 小时以上</span>
</div>
<div class="flex items-center text-xs text-slate-600">
<i class="fa-regular fa-square mr-2"></i> <span>带齐过往检验单据</span>
</div>
<div class="mt-3 pt-2 border-t border-slate-50 text-center">
<span class="text-blue-600 text-[12px] font-bold">确认已收到提醒</span>
</div>
</div>
</div>
</div>
<!-- 患者回复 -->
<div class="flex items-start justify-end">
<div class="chat-bubble-right">
好的,王老师。请问我现在可以喝咖啡吗?
</div>
<div class="w-10 h-10 bg-slate-400 rounded flex items-center justify-center text-white shrink-0 overflow-hidden">
<img src="https://api.dicebear.com/7.x/avataaars/svg?seed=King" alt="avatar">
</div>
</div>
<!-- AI 基于 RAG 自动回复 -->
<div class="flex items-start">
<div class="w-10 h-10 bg-blue-500 rounded flex items-center justify-center text-white shrink-0">
<i class="fa-solid fa-user-doctor"></i>
</div>
<div class="chat-bubble-left">
<p class="mb-2">根据研究方案规定:</p>
<p class="text-slate-700">访视前 8 小时禁食,禁饮(水除外)。<span class="font-bold">咖啡可能会影响血液指标检查,建议您明天检查完后再饮用。</span></p>
<div class="mt-3 pt-2 border-t border-slate-100 flex items-center text-[11px] text-slate-400">
<i class="fa-solid fa-robot mr-1"></i> AI 助理回复,已提醒 CRC 复核
</div>
</div>
</div>
</div>
<!-- 底部输入框 -->
<div class="h-14 bg-[#f7f7f7] border-t border-[#d1d1d1] flex items-center px-3 space-x-3 shrink-0">
<i class="fa-solid fa-microphone text-xl text-slate-600"></i>
<input type="text" placeholder="咨询或上报症状..." class="flex-1 h-9 bg-white border border-[#d1d1d1] rounded-md px-3 text-sm focus:outline-none">
<i class="fa-regular fa-face-smile text-xl text-slate-600"></i>
<i class="fa-solid fa-circle-plus text-xl text-slate-600"></i>
</div>
</div>
<!-- 场景 2: 任务进度与资料中心 (小程序) -->
<div id="tab-tasks-content" class="hidden flex-1 flex flex-col bg-slate-50 overflow-y-auto no-scrollbar">
<!-- 品牌顶部 -->
<div class="bg-blue-600 p-6 text-white shrink-0">
<div class="flex items-center space-x-2 mb-4">
<div class="w-8 h-8 bg-white/20 rounded-full flex items-center justify-center">
<i class="fa-solid fa-dna text-xs"></i>
</div>
<span class="text-sm font-bold">北医三院骨质疏松研究项目</span>
</div>
<h2 class="text-xl font-bold mb-1">您好, 王先生</h2>
<p class="text-blue-100 text-xs italic">您的健康是科研最有价值的数据</p>
</div>
<!-- 项目进度条 -->
<div class="p-4 -mt-6">
<div class="bg-white rounded-2xl shadow-sm p-4 border border-slate-100">
<div class="flex justify-between items-center mb-4">
<span class="text-xs font-bold text-slate-400 uppercase">研究阶段进度</span>
<span class="text-xs font-bold text-blue-600">访视 3 / 5</span>
</div>
<div class="flex items-center justify-between relative px-2">
<div class="absolute h-1 bg-slate-100 left-8 right-8 top-3 z-0"></div>
<div class="absolute h-1 bg-blue-500 left-8 w-1/2 top-3 z-0"></div>
<div class="z-10 flex flex-col items-center">
<div class="w-6 h-6 rounded-full bg-blue-500 flex items-center justify-center text-white text-[10px] shadow-lg shadow-blue-200"><i class="fa-solid fa-check"></i></div>
<span class="text-[9px] mt-2 text-slate-400">V1 基线</span>
</div>
<div class="z-10 flex flex-col items-center">
<div class="w-6 h-6 rounded-full bg-blue-500 flex items-center justify-center text-white text-[10px] shadow-lg shadow-blue-200"><i class="fa-solid fa-check"></i></div>
<span class="text-[9px] mt-2 text-slate-400">V2 随机</span>
</div>
<div class="z-10 flex flex-col items-center">
<div class="w-6 h-6 rounded-full bg-white border-2 border-blue-500 flex items-center justify-center text-blue-500 text-[10px] font-bold animate-pulse">3</div>
<span class="text-[9px] mt-2 text-blue-600 font-bold">V3 给药</span>
</div>
<div class="z-10 flex flex-col items-center opacity-30">
<div class="w-6 h-6 rounded-full bg-slate-200 flex items-center justify-center text-slate-400 text-[10px] font-bold">4</div>
<span class="text-[9px] mt-2 text-slate-400">V4 随访</span>
</div>
<div class="z-10 flex flex-col items-center opacity-30">
<div class="w-6 h-6 rounded-full bg-slate-200 flex items-center justify-center text-slate-400 text-[10px] font-bold">5</div>
<span class="text-[9px] mt-2 text-slate-400">V5 结束</span>
</div>
</div>
</div>
</div>
<!-- 待办任务 -->
<div class="px-4 space-y-3 mb-6">
<h3 class="text-sm font-bold text-slate-800 px-1">待办任务</h3>
<div class="bg-white rounded-xl p-4 flex items-center justify-between shadow-sm">
<div class="flex items-center space-x-3">
<div class="w-10 h-10 bg-amber-100 rounded-lg flex items-center justify-center text-amber-600">
<i class="fa-solid fa-capsules text-lg"></i>
</div>
<div>
<p class="text-sm font-bold text-slate-800">今日服药打卡</p>
<p class="text-[10px] text-slate-400">请在早餐后 30 分钟内服用</p>
</div>
</div>
<button class="bg-blue-600 text-white text-xs px-4 py-1.5 rounded-full font-bold">去打卡</button>
</div>
<div class="bg-white rounded-xl p-4 flex items-center justify-between shadow-sm opacity-60">
<div class="flex items-center space-x-3">
<div class="w-10 h-10 bg-slate-100 rounded-lg flex items-center justify-center text-slate-400">
<i class="fa-solid fa-file-signature text-lg"></i>
</div>
<div>
<p class="text-sm font-bold text-slate-800 task-done">知情同意书签署</p>
<p class="text-[10px] text-slate-400">已于 2025-12-01 完成</p>
</div>
</div>
<i class="fa-solid fa-circle-check text-green-500"></i>
</div>
</div>
<!-- 资料与指南 -->
<div class="px-4 pb-10 space-y-3">
<h3 class="text-sm font-bold text-slate-800 px-1">项目资料</h3>
<div class="grid grid-cols-2 gap-3">
<div class="bg-white p-4 rounded-xl shadow-sm border border-slate-100 flex flex-col items-center text-center">
<i class="fa-solid fa-book-open text-blue-500 mb-2"></i>
<span class="text-[11px] font-medium">受试者手册</span>
</div>
<div class="bg-white p-4 rounded-xl shadow-sm border border-slate-100 flex flex-col items-center text-center">
<i class="fa-solid fa-phone-volume text-emerald-500 mb-2"></i>
<span class="text-[11px] font-medium">紧急联系人</span>
</div>
</div>
</div>
</div>
<!-- 底部 Tab 导航 -->
<div class="bottom-nav h-14 flex items-center justify-around shrink-0 pb-safe">
<div onclick="switchTab('chat')" id="tab-chat-btn" class="flex flex-col items-center tab-active cursor-pointer">
<i class="fa-solid fa-message text-sm"></i>
<span class="text-[10px] mt-1">对话</span>
</div>
<div onclick="switchTab('tasks')" id="tab-tasks-btn" class="flex flex-col items-center text-slate-400 cursor-pointer">
<i class="fa-solid fa-calendar-check text-sm"></i>
<span class="text-[10px] mt-1">任务</span>
</div>
<div class="flex flex-col items-center text-slate-400">
<i class="fa-solid fa-compass text-sm"></i>
<span class="text-[10px] mt-1">发现</span>
</div>
<div class="flex flex-col items-center text-slate-400">
<i class="fa-solid fa-user text-sm"></i>
<span class="text-[10px] mt-1">我的</span>
</div>
</div>
</div>
<script>
function switchTab(tab) {
const chatContent = document.getElementById('tab-chat-content');
const tasksContent = document.getElementById('tab-tasks-content');
const chatBtn = document.getElementById('tab-chat-btn');
const tasksBtn = document.getElementById('tab-tasks-btn');
if (tab === 'chat') {
chatContent.classList.remove('hidden');
tasksContent.classList.add('hidden');
chatBtn.classList.add('tab-active');
tasksBtn.classList.remove('tab-active');
} else {
chatContent.classList.add('hidden');
tasksContent.classList.remove('hidden');
chatBtn.classList.remove('tab-active');
tasksBtn.classList.add('tab-active');
}
}
</script>
</body>
</html>