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
309 lines
20 KiB
HTML
309 lines
20 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>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>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|