Files
AIclinicalresearch/docs/01-平台基础层/06-前端架构/03-架构原型图.html
HaHafeng e3e7e028e8 feat(platform): Complete platform infrastructure implementation and verification
Platform Infrastructure - 8 Core Modules Completed:
- Storage Service (LocalAdapter + OSSAdapter stub)
- Logging System (Winston + JSON format)
- Cache Service (MemoryCache + Redis stub)
- Async Job Queue (MemoryQueue + DatabaseQueue stub)
- Health Check Endpoints (liveness/readiness/detailed)
- Database Connection Pool (with Serverless optimization)
- Environment Configuration Management
- Monitoring Metrics (DB connections/memory/API)

Key Features:
- Adapter Pattern for zero-code environment switching
- Full backward compatibility with legacy modules
- 100% test coverage (all 8 modules verified)
- Complete documentation (11 docs updated)

Technical Improvements:
- Fixed duplicate /health route registration issue
- Fixed TypeScript interface export (export type)
- Installed winston dependency
- Added structured logging with context support
- Implemented graceful shutdown for Serverless
- Added connection pool optimization for SAE

Documentation Updates:
- Platform infrastructure planning (04-骞冲彴鍩虹璁炬柦瑙勫垝.md)
- Implementation report (2025-11-17-骞冲彴鍩虹璁炬柦瀹炴柦瀹屾垚鎶ュ憡.md)
- Verification report (2025-11-17-骞冲彴鍩虹璁炬柦楠岃瘉鎶ュ憡.md)
- Git commit guidelines (06-Git鎻愪氦瑙勮寖.md) - Added commit frequency rules
- Updated 3 core architecture documents

Code Statistics:
- New code: 2,532 lines
- New files: 22
- Updated files: 130+
- Test pass rate: 100% (8/8 modules)

Deployment Readiness:
- Local environment: 鉁?Ready
- Cloud environment: 馃攧 Needs OSS/Redis dependencies

Next Steps:
- Ready to start ASL module development
- Can directly use storage/logger/cache/jobQueue

Tested: Local verification 100% passed
Related: #Platform-Infrastructure
2025-11-18 08:00:41 +08:00

309 lines
20 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI科研平台-整体架构原型 V3</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/heroicons/2.1.3/24/outline/css/heroicons.min.css" rel="stylesheet">
<style>
body { font-family: 'Inter', sans-serif; background-color: #f3f4f6; }
.top-nav-link { padding: 1rem 1.25rem; color: #4b5563; font-weight: 500; border-bottom: 2px solid transparent; transition: all 0.2s ease; white-space: nowrap;}
.top-nav-link:hover { color: #0ea5e9; }
.top-nav-link.active { color: #0ea5e9; border-bottom-color: #0ea5e9; font-weight: 600; }
.module-view { display: none; }
.module-view.active { display: block; animation: fadeIn 0.3s ease-in-out; }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
.sub-sidebar { background-color: #eef2ff; width: 200px; }
.sub-sidebar-link { display: block; padding: 0.75rem 1.5rem; color: #4338ca; font-size: 0.875rem; border-left: 3px solid transparent; }
.sub-sidebar-link:hover { background-color: #e0e7ff; }
.sub-sidebar-link.active { font-weight: 600; border-left-color: #4f46e5; background-color: #e0e7ff; }
.sub-tabs button { padding: 0.75rem 1.5rem; color: #6b7280; border-bottom: 2px solid transparent; }
.sub-tabs button.active { color: #0ea5e9; border-bottom-color: #0ea5e9; font-weight: 500; }
/* V3 Styles */
.user-menu { position: relative; }
.user-menu-dropdown { display: none; position: absolute; right: 0; top: 100%; margin-top: 0.5rem; background-color: white; border-radius: 0.375rem; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); z-index: 50; width: 10rem; }
.user-menu:hover .user-menu-dropdown { display: block; }
.dropdown-link { display: block; padding: 0.5rem 1rem; color: #374151; font-size: 0.875rem; }
.dropdown-link:hover { background-color: #f3f4f6; }
</style>
</head>
<body class="text-gray-800">
<!-- Header with Top Navigation -->
<header class="bg-white shadow-md sticky top-0 z-20">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between items-center h-16">
<!-- Logo/Brand -->
<div class="flex-shrink-0 flex items-center">
<span class="font-bold text-xl text-sky-600">临床研究平台</span>
</div>
<!-- Top Navigation (V3 Updated) -->
<nav id="top-navigation" class="flex space-x-2">
<a href="#" class="top-nav-link active" onclick="showModule('research')">研究管理</a>
<a href="#" class="top-nav-link" onclick="showModule('stats-tools')">统计分析工具</a>
<a href="#" class="top-nav-link" onclick="showModule('ai-qa')">AI 问答</a> <!-- Renamed back -->
<a href="#" class="top-nav-link" onclick="showModule('knowledge-base')">个人知识库</a>
<a href="#" class="top-nav-link" onclick="showModule('literature-platform')">AI文献平台</a>
<!-- Personal Center removed from top nav -->
</nav>
<!-- User Menu (V3 Updated) -->
<div class="flex items-center space-x-4">
<span class="text-sm text-gray-500">186****8738</span>
<div class="user-menu">
<button class="text-gray-400 hover:text-gray-600 focus:outline-none">
<i class="hi-outline hi-user-circle h-7 w-7"></i>
</button>
<div class="user-menu-dropdown">
<a href="#" class="dropdown-link" onclick="showModule('personal-center'); event.preventDefault();">个人中心</a>
<a href="#" class="dropdown-link" onclick="showModule('personal-center'); event.preventDefault();">历史记录</a> <!-- Direct link example -->
<hr class="my-1">
<a href="#" class="dropdown-link">退出账号</a>
</div>
</div>
</div>
</div>
</div>
</header>
<!-- Main Content Area -->
<main id="main-content" class="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
<!-- Module View: 研究管理 (Research Management) -->
<div id="research-view" class="module-view active">
<!-- Content from V2, unchanged -->
<div class="flex bg-white rounded-lg shadow overflow-hidden min-h-[calc(100vh-10rem)]"><aside class="sub-sidebar p-4 flex-shrink-0"><h2 class="font-semibold text-indigo-700 mb-4 px-2">研究管理</h2><nav class="space-y-1"><a href="#" class="sub-sidebar-link active">首页</a><a href="#" class="sub-sidebar-link">研究项目列表</a><a href="#" class="sub-sidebar-link">PICO</a><a href="#" class="sub-sidebar-link">上传数据</a><a href="#" class="sub-sidebar-link">统计分析</a><a href="#" class="sub-sidebar-link">分析报告</a></nav></aside><div class="flex-grow p-6"><h1 class="text-2xl font-bold mb-4">研究管理 - 首页 (占位内容)</h1><p>这里将展示最近的研究项目卡片...</p><div class="grid grid-cols-3 gap-4 mt-6"><div class="border rounded-lg p-4 bg-gray-50 text-center">新建研究项目</div><div class="border rounded-lg p-4 bg-gray-50">项目A</div><div class="border rounded-lg p-4 bg-gray-50">项目B</div></div></div></div>
</div>
<!-- Module View: 统计分析工具 (Stats Tools) -->
<div id="stats-tools-view" class="module-view">
<!-- Content from V2, unchanged -->
<div class="bg-white rounded-lg shadow overflow-hidden min-h-[calc(100vh-10rem)] p-6"><h1 class="text-2xl font-bold mb-4">统计分析工具</h1><nav class="sub-tabs border-b border-gray-200 mb-6"><button class="active">统计分析</button><button>预测模型建立与验证</button><button>随机分组</button><button>样本量</button></nav><div><h2 class="text-xl font-semibold mb-3">统计分析 (占位内容)</h2><p>这里将展示各种统计分析方法的分类和入口...</p><div class="space-y-4 mt-4 text-sm"><div class="border rounded p-3 bg-gray-50">单组</div><div class="border rounded p-3 bg-gray-50">两组</div><div class="border rounded p-3 bg-gray-50">多组</div></div></div></div>
</div>
<!-- Module View: AI 问答 (AI Q&A - V3 Reverted to Card Layout) -->
<div id="ai-qa-view" class="module-view">
<div class="bg-white rounded-lg shadow overflow-hidden min-h-[calc(100vh-10rem)] p-6">
<div class="text-center mb-8">
<h1 class="text-2xl font-bold text-blue-600 mb-2">医学研究专属大模型 (已接入DeepSeek)</h1>
<input type="text" placeholder="向AI提问或选择下方任务卡片..." class="w-1/2 p-3 border rounded-full shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500">
<button class="ml-2 bg-blue-600 text-white font-bold py-3 px-6 rounded-full hover:bg-blue-700">提问</button>
</div>
<!-- Content for AI Q&A - Card layout similar to screenshot -->
<h2 class="text-xl font-semibold mb-4 text-center text-gray-600">或选择一个智能体开始:</h2>
<div class="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-6">
<div class="border rounded-lg p-6 bg-gray-50 text-center hover:shadow-lg transition-shadow cursor-pointer">
<h3 class="font-bold text-lg mb-2">选题评价</h3>
<p class="text-sm text-gray-600">评估您的研究选题的创新性、价值和可行性。</p>
</div>
<div class="border rounded-lg p-6 bg-gray-50 text-center hover:shadow-lg transition-shadow cursor-pointer">
<h3 class="font-bold text-lg mb-2">科学问题梳理</h3>
<p class="text-sm text-gray-600">将您的研究想法转化为清晰、可研究的科学问题。</p>
</div>
<div class="border rounded-lg p-6 bg-gray-50 text-center hover:shadow-lg transition-shadow cursor-pointer">
<h3 class="font-bold text-lg mb-2">PICO 梳理</h3>
<p class="text-sm text-gray-600">辅助您定义严谨的PICO要素。</p>
</div>
<div class="border rounded-lg p-6 bg-gray-50 text-center hover:shadow-lg transition-shadow cursor-pointer">
<h3 class="font-bold text-lg mb-2">研究方案撰写</h3>
<p class="text-sm text-gray-600">基于PICO信息生成初步的研究方案草稿。</p>
</div>
<div class="border rounded-lg p-6 bg-gray-50 text-center hover:shadow-lg transition-shadow cursor-pointer">
<h3 class="font-bold text-lg mb-2">样本量计算</h3>
<p class="text-sm text-gray-600">根据您的研究设计和预期效果,估算所需样本量。</p>
</div>
<div class="border rounded-lg p-6 bg-gray-50 text-center hover:shadow-lg transition-shadow cursor-pointer">
<h3 class="font-bold text-lg mb-2">文章润色</h3>
<p class="text-sm text-gray-600">对您的论文草稿进行语言润色和风格优化。</p>
</div>
<div class="border rounded-lg p-6 bg-gray-50 text-center hover:shadow-lg transition-shadow cursor-pointer">
<h3 class="font-bold text-lg mb-2">文章翻译</h3>
<p class="text-sm text-gray-600">提供中英文本互译功能。</p>
</div>
<!-- Add other cards -->
</div>
</div>
</div>
<!-- Module View: 个人知识库 (Knowledge Base - V3 Updated) -->
<div id="knowledge-base-view" class="module-view">
<div class="flex bg-white rounded-lg shadow overflow-hidden min-h-[calc(100vh-10rem)]">
<!-- Sub Sidebar for KB -->
<aside class="sub-sidebar p-4 flex-shrink-0 bg-blue-50">
<h2 class="font-semibold text-blue-700 mb-4 px-2">个人知识库</h2>
<nav class="space-y-1">
<a href="#" class="sub-sidebar-link active">知识库 A (心血管)</a>
<a href="#" class="sub-sidebar-link">知识库 B (肿瘤免疫)</a>
<a href="#" class="sub-sidebar-link">知识库 C (未分类)</a>
<a href="#" class="sub-sidebar-link text-blue-500 mt-4">+ 新建知识库</a>
</nav>
</aside>
<!-- Content for KB -->
<div class="flex-grow p-6">
<div class="flex justify-between items-center mb-6">
<h1 class="text-2xl font-bold">知识库 A (35/50篇文献)</h1>
<button class="bg-blue-600 text-white font-semibold py-2 px-4 rounded-lg text-sm">+ 添加文献</button>
</div>
<!-- V3: Contextual QA Input within KB -->
<div class="mb-6 bg-blue-50 p-4 rounded-lg border border-blue-200">
<label class="block text-sm font-medium text-blue-700 mb-2">在此知识库中提问:</label>
<div class="flex space-x-2">
<input type="text" placeholder="例如SGLT2对心衰的影响" class="flex-grow border rounded-md p-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500">
<button onclick="askInKbContext()" class="bg-blue-600 text-white font-semibold px-4 py-2 rounded-md hover:bg-blue-700 text-sm">提问</button>
</div>
</div>
<h2 class="text-xl font-semibold mb-3">文献列表:</h2>
<div class="space-y-3">
<div class="border rounded p-3 bg-white text-sm flex justify-between items-center">
<span>文献1: EMPA-REG...</span>
<button class="text-xs text-red-500 hover:text-red-700">移除</button>
</div>
<div class="border rounded p-3 bg-white text-sm flex justify-between items-center">
<span>文献2: DECLARE-TIMI...</span>
<button class="text-xs text-red-500 hover:text-red-700">移除</button>
</div>
<div class="border rounded p-3 bg-white text-sm flex justify-between items-center">
<span>文献3: CANVAS...</span>
<button class="text-xs text-red-500 hover:text-red-700">移除</button>
</div>
<p class="text-gray-500 text-sm">...</p>
</div>
</div>
</div>
</div>
<!-- Module View: AI文献平台 (AI Literature Platform - V3 Updated) -->
<div id="literature-platform-view" class="module-view">
<div class="flex bg-white rounded-lg shadow overflow-hidden min-h-[calc(100vh-10rem)]">
<!-- Sub Sidebar for Literature Platform -->
<aside class="sub-sidebar p-4 flex-shrink-0 bg-sky-50">
<h2 class="font-semibold text-sky-700 mb-4 px-2">AI文献平台</h2>
<nav class="space-y-1">
<a href="#" class="sub-sidebar-link active">1. 研究方案生成</a>
<a href="#" class="sub-sidebar-link">2. 智能文献检索</a>
<!-- V3: Added Literature Management -->
<a href="#" class="sub-sidebar-link">3. 文献管理</a>
<a href="#" class="sub-sidebar-link">4. 标题摘要初筛</a>
<a href="#" class="sub-sidebar-link">5. 全文复筛</a>
<a href="#" class="sub-sidebar-link">6. 全文解析与数据提取</a>
<a href="#" class="sub-sidebar-link">7. 数据综合分析与报告</a>
</nav>
</aside>
<!-- Content for Literature Platform -->
<div class="flex-grow p-6">
<h1 class="text-2xl font-bold mb-4">研究方案生成 (占位内容)</h1>
<p>这里将是研究方案生成的向导式界面...</p>
<div class="mt-6 border rounded p-3 bg-gray-50 flex justify-between items-center text-sm">
<span>(下方为示意:项目文献管理入口在左侧导航栏)</span>
<button class="text-xs bg-blue-100 text-blue-700 font-semibold py-1 px-2 rounded hover:bg-blue-200" onclick="alert('将此文献添加到个人知识库...')">添加到个人知识库</button>
</div>
</div>
</div>
</div>
<!-- Module View: 个人中心 (Personal Center - V3 Updated) -->
<div id="personal-center-view" class="module-view">
<div class="bg-white rounded-lg shadow p-6 min-h-[calc(100vh-10rem)]">
<h1 class="text-2xl font-bold mb-6">个人中心</h1>
<nav class="flex space-x-8 border-b mb-6">
<button class="pb-2 border-b-2 border-sky-500 text-sky-600 font-semibold">账户信息</button>
<button class="pb-2 border-b-2 border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700">偏好设置</button>
<button class="pb-2 border-b-2 border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700">历史记录</button>
</nav>
<!-- Placeholder Content -->
<div id="personal-center-content">
<h2 class="font-semibold text-lg mb-4">账户信息</h2>
<p class="text-sm text-gray-600">用户名: 186****8738</p>
<button class="text-sm text-sky-600 mt-4 hover:underline">修改密码</button>
<hr class="my-6">
<h2 class="font-semibold text-lg mb-4">完整的历史记录 (占位)</h2>
<p class="text-sm text-gray-600">这里将按模块分类展示您所有的操作历史...</p>
</div>
</div>
</div>
</main>
<script>
// --- STATE MANAGEMENT ---
let currentModule = 'research'; // Default module
// Removed currentQaSource as QA Center design changed
// --- DOM ELEMENTS ---
const topNavLinks = document.querySelectorAll('#top-navigation .top-nav-link');
const moduleViews = document.querySelectorAll('.module-view');
// Removed QA Center specific elements no longer needed
// --- FUNCTIONS ---
function showModule(moduleId) {
currentModule = moduleId;
topNavLinks.forEach(link => {
link.classList.remove('active');
// Adjust condition to handle user menu clicks potentially having different onclick structure
const onclickAttr = link.getAttribute('onclick');
if (onclickAttr && onclickAttr.includes(`'${moduleId}'`)) {
link.classList.add('active');
}
});
// Special handling for personal center activated via user menu
if (moduleId === 'personal-center' && document.querySelector('#top-navigation a.active')) {
document.querySelector('#top-navigation a.active').classList.remove('active');
}
moduleViews.forEach(view => view.classList.remove('active'));
const activeView = document.getElementById(`${moduleId}-view`);
if (activeView) {
activeView.classList.add('active');
} else {
console.error("Module view not found:", moduleId);
document.getElementById('research-view')?.classList.add('active'); // Fallback
}
window.scrollTo(0, 0);
// Close user menu dropdown if open (simple simulation)
const dropdown = document.querySelector('.user-menu-dropdown');
if (dropdown) dropdown.style.display = 'none';
// Re-enable after a short delay for hover effect
setTimeout(() => { if (dropdown) dropdown.style.display = ''; }, 200);
}
// V3: Simplified Ask in KB Context - shows alert
function askInKbContext() {
const question = document.querySelector(`#knowledge-base-view input[placeholder*='在此知识库中提问']`).value;
if (!question.trim()) {
alert("请输入您的问题。");
return;
}
alert(`模拟在当前知识库中提问: "${question}"\n(实际应用中将在后台统一处理)`);
// In a real app, this would send the question and current KB context to the backend QA service.
// The response could potentially be displayed here or link to the QA center history.
}
// --- INITIALIZATION ---
document.addEventListener('DOMContentLoaded', () => {
showModule(currentModule); // Show default module on load
});
</script>
</body>
</html>