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,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>