Files
AIclinicalresearch/docs/03-业务模块/DC-数据清洗整理/03-UI设计/智能数据清洗工作台V2.html
HaHafeng d4d33528c7 feat(dc): Complete Phase 1 - Portal workbench page development
Summary:
- Implement DC module Portal page with 3 tool cards
- Create ToolCard component with decorative background and hover animations
- Implement TaskList component with table layout and progress bars
- Implement AssetLibrary component with tab switching and file cards
- Complete database verification (4 tables confirmed)
- Complete backend API verification (6 endpoints ready)
- Optimize UI to match prototype design (V2.html)

Frontend Components (~715 lines):
- components/ToolCard.tsx - Tool cards with animations
- components/TaskList.tsx - Recent tasks table view
- components/AssetLibrary.tsx - Data asset library with tabs
- hooks/useRecentTasks.ts - Task state management
- hooks/useAssets.ts - Asset state management
- pages/Portal.tsx - Main portal page
- types/portal.ts - TypeScript type definitions

Backend Verification:
- Backend API: 1495 lines code verified
- Database: dc_schema with 4 tables verified
- API endpoints: 6 endpoints tested (templates API works)

Documentation:
- Database verification report
- Backend API test report
- Phase 1 completion summary
- UI optimization report
- Development task checklist
- Development plan for Tool B

Status: Phase 1 completed (100%), ready for browser testing
Next: Phase 2 - Tool B Step 1 and 2 development
2025-12-02 21:53:24 +08:00

213 lines
17 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>智能数据清洗工作台 V2 - 数据资产库升级版</title>
<!-- 引入 Tailwind CSS (CDN) -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- 引入 Lucide Icons (CDN) -->
<script src="https://unpkg.com/lucide@latest"></script>
<!-- 引入 Alpine.js 用于简单的交互逻辑 (Tab切换) -->
<script src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<style>
.fade-in { animation: fadeIn 0.3s ease-in-out; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: translateY(0); } }
</style>
</head>
<body class="min-h-screen bg-slate-50 font-sans text-slate-800">
<!-- 1. 顶部一级导航 -->
<header class="bg-white border-b border-slate-200 sticky top-0 z-50">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<div class="flex items-center">
<div class="flex-shrink-0 flex items-center gap-2">
<div class="w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center">
<i data-lucide="database" class="text-white w-5 h-5"></i>
</div>
<span class="font-bold text-xl text-slate-900">MedData AI</span>
</div>
<nav class="hidden md:ml-10 md:flex md:space-x-8">
<a href="#" class="text-slate-500 hover:text-slate-900 px-1 pt-1 border-b-2 border-transparent text-sm font-medium">AI问答</a>
<a href="#" class="text-slate-500 hover:text-slate-900 px-1 pt-1 border-b-2 border-transparent text-sm font-medium">智能数据分析</a>
<a href="#" class="text-slate-500 hover:text-slate-900 px-1 pt-1 border-b-2 border-transparent text-sm font-medium">知识库</a>
<a href="#" class="border-blue-500 text-slate-900 px-1 pt-1 border-b-2 text-sm font-medium">智能数据清洗</a>
</nav>
</div>
<div class="flex items-center gap-4">
<div class="text-sm text-slate-500">张医生 (主治医师)</div>
<div class="w-8 h-8 bg-slate-200 rounded-full flex items-center justify-center text-slate-500 text-sm font-bold">ZH</div>
</div>
</div>
</div>
</header>
<!-- 2. 主内容区 -->
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 fade-in">
<div class="mb-8">
<h1 class="text-2xl font-bold text-slate-900">数据清洗工作台</h1>
<p class="text-slate-500 mt-1">从原始 Excel 到科研级数据集,只需三步。</p>
</div>
<!-- 3. 功能启动区 -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-10">
<!-- 卡片 A -->
<div class="bg-white rounded-xl shadow-sm border border-slate-200 p-6 hover:shadow-md transition-shadow cursor-pointer group relative overflow-hidden">
<div class="absolute top-0 right-0 w-24 h-24 bg-blue-50 rounded-bl-full -mr-4 -mt-4 transition-transform group-hover:scale-110"></div>
<div class="relative">
<div class="w-12 h-12 bg-blue-100 rounded-lg flex items-center justify-center mb-4 text-blue-600"><i data-lucide="file-spreadsheet" class="w-7 h-7"></i></div>
<h3 class="text-lg font-bold text-slate-900 mb-2 group-hover:text-blue-600 transition-colors">超级合并器</h3>
<p class="text-sm text-slate-500 mb-4 h-10">解决多源数据时间轴对齐难题。支持 HIS 导出数据按病人 ID 自动合并。</p>
<div class="flex items-center text-sm font-medium text-blue-600">开始合并 <i data-lucide="arrow-right" class="w-4 h-4 ml-1 group-hover:translate-x-1 transition-transform"></i></div>
</div>
</div>
<!-- 卡片 B -->
<div class="bg-white rounded-xl shadow-sm border border-slate-200 p-6 hover:shadow-md transition-shadow cursor-pointer group relative overflow-hidden">
<div class="absolute top-0 right-0 w-24 h-24 bg-purple-50 rounded-bl-full -mr-4 -mt-4 transition-transform group-hover:scale-110"></div>
<div class="relative">
<div class="w-12 h-12 bg-purple-100 rounded-lg flex items-center justify-center mb-4 text-purple-600"><i data-lucide="bot" class="w-7 h-7"></i></div>
<h3 class="text-lg font-bold text-slate-900 mb-2 group-hover:text-purple-600 transition-colors">病历结构化机器人</h3>
<p class="text-sm text-slate-500 mb-4 h-10">利用大模型提取非结构化文本。支持自动脱敏、批量处理与抽检。</p>
<div class="flex items-center text-sm font-medium text-purple-600">新建提取任务 <i data-lucide="arrow-right" class="w-4 h-4 ml-1 group-hover:translate-x-1 transition-transform"></i></div>
</div>
</div>
<!-- 卡片 C -->
<div class="bg-white rounded-xl shadow-sm border border-slate-200 p-6 hover:shadow-md transition-shadow cursor-pointer group relative overflow-hidden">
<div class="absolute top-0 right-0 w-24 h-24 bg-emerald-50 rounded-bl-full -mr-4 -mt-4 transition-transform group-hover:scale-110"></div>
<div class="relative">
<div class="w-12 h-12 bg-emerald-100 rounded-lg flex items-center justify-center mb-4 text-emerald-600"><i data-lucide="table-2" class="w-7 h-7"></i></div>
<h3 class="text-lg font-bold text-slate-900 mb-2 group-hover:text-emerald-600 transition-colors">科研数据编辑器</h3>
<p class="text-sm text-slate-500 mb-4 h-10">Excel 风格的在线清洗工具。支持缺失值填补、值替换与分析集导出。</p>
<div class="flex items-center text-sm font-medium text-emerald-600">打开编辑器 <i data-lucide="arrow-right" class="w-4 h-4 ml-1 group-hover:translate-x-1 transition-transform"></i></div>
</div>
</div>
</div>
<!-- 4. 任务与资产中心 -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<!-- 左侧:最近任务 (不变) -->
<div class="lg:col-span-2">
<div class="flex items-center justify-between mb-4">
<h2 class="text-lg font-bold text-slate-900 flex items-center gap-2"><i data-lucide="history" class="w-5 h-5 text-slate-500"></i> 最近处理任务</h2>
<button class="text-sm text-blue-600 hover:underline">查看全部</button>
</div>
<div class="bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden min-h-[400px]">
<table class="min-w-full divide-y divide-slate-200">
<thead class="bg-slate-50">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-slate-500 uppercase tracking-wider">任务名称</th>
<th class="px-6 py-3 text-left text-xs font-medium text-slate-500 uppercase tracking-wider">工具</th>
<th class="px-6 py-3 text-left text-xs font-medium text-slate-500 uppercase tracking-wider">状态</th>
<th class="px-6 py-3 text-right text-xs font-medium text-slate-500 uppercase tracking-wider">操作</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-slate-200">
<tr class="hover:bg-slate-50 transition-colors">
<td class="px-6 py-4 whitespace-nowrap"><div class="flex flex-col"><span class="text-sm font-medium text-slate-900">肺癌门诊数据_2023合并任务</span><span class="text-xs text-slate-500">10分钟前</span></div></td>
<td class="px-6 py-4 whitespace-nowrap"><span class="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-700"><i data-lucide="database" class="w-3 h-3"></i> 超级合并器</span></td>
<td class="px-6 py-4 whitespace-nowrap"><span class="inline-flex items-center text-xs text-emerald-600 font-medium"><i data-lucide="check-circle-2" class="w-4 h-4 mr-1.5"></i> 完成 (12,450 行)</span></td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"><div class="flex justify-end gap-3"><button class="text-slate-500 hover:text-slate-900"><i data-lucide="download" class="w-4 h-4"></i></button><button class="text-purple-600 hover:text-purple-800 flex items-center gap-1">去 AI 提取 <i data-lucide="arrow-right" class="w-4 h-4"></i></button></div></td>
</tr>
<tr class="hover:bg-slate-50 transition-colors">
<td class="px-6 py-4 whitespace-nowrap"><div class="flex flex-col"><span class="text-sm font-medium text-slate-900">Q3出院小结_批量提取</span><span class="text-xs text-slate-500">正在运行</span></div></td>
<td class="px-6 py-4 whitespace-nowrap"><span class="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium bg-purple-100 text-purple-700"><i data-lucide="bot" class="w-3 h-3"></i> AI 结构化</span></td>
<td class="px-6 py-4 whitespace-nowrap"><div class="w-32"><div class="flex justify-between text-xs mb-1"><span class="text-blue-600 font-medium">处理中</span><span class="text-slate-500">45%</span></div><div class="w-full bg-slate-200 rounded-full h-1.5"><div class="bg-blue-600 h-1.5 rounded-full" style="width: 45%"></div></div></div></td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"><span class="text-slate-400 text-xs">等待完成...</span></td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- 右侧:数据资产库 (V2 核心修改) -->
<div class="lg:col-span-1 flex flex-col h-full" x-data="{ activeTab: 'all' }">
<div class="flex items-center justify-between mb-4">
<h2 class="text-lg font-bold text-slate-900 flex items-center gap-2">
<i data-lucide="database" class="w-5 h-5 text-slate-500"></i> 数据资产库
</h2>
<div class="flex gap-1">
<button class="p-1 hover:bg-slate-100 rounded-full"><i data-lucide="search" class="w-4 h-4 text-slate-400"></i></button>
</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-slate-200 flex flex-col flex-1 min-h-[400px]">
<!-- Tabs -->
<div class="flex border-b border-slate-200">
<button @click="activeTab = 'all'" :class="{ 'border-blue-500 text-blue-600': activeTab === 'all', 'border-transparent text-slate-500 hover:text-slate-700': activeTab !== 'all' }" class="flex-1 py-3 text-xs font-medium text-center border-b-2 transition-colors">全部</button>
<button @click="activeTab = 'output'" :class="{ 'border-emerald-500 text-emerald-600': activeTab === 'output', 'border-transparent text-slate-500 hover:text-slate-700': activeTab !== 'output' }" class="flex-1 py-3 text-xs font-medium text-center border-b-2 transition-colors">处理结果</button>
<button @click="activeTab = 'input'" :class="{ 'border-slate-400 text-slate-600': activeTab === 'input', 'border-transparent text-slate-500 hover:text-slate-700': activeTab !== 'input' }" class="flex-1 py-3 text-xs font-medium text-center border-b-2 transition-colors">原始上传</button>
</div>
<!-- 列表内容 -->
<div class="p-4 space-y-3 flex-1 overflow-y-auto">
<!-- 结果文件 1 -->
<div x-show="activeTab === 'all' || activeTab === 'output'" class="group p-3 rounded-lg border border-slate-100 hover:border-blue-200 hover:bg-blue-50 transition-all cursor-pointer">
<div class="flex justify-between items-start mb-2">
<div class="flex items-center gap-2">
<i data-lucide="file-spreadsheet" class="w-4 h-4 text-emerald-600"></i>
<h4 class="text-sm font-bold text-slate-800 group-hover:text-blue-700 truncate max-w-[150px]">2024_肺癌分析最终版.csv</h4>
</div>
<button class="text-slate-400 hover:text-slate-600"><i data-lucide="more-horizontal" class="w-4 h-4"></i></button>
</div>
<div class="flex items-center gap-2 mb-3">
<span class="px-1.5 py-0.5 bg-emerald-50 text-emerald-600 border border-emerald-100 text-[10px] rounded">已清洗</span>
<span class="px-1.5 py-0.5 bg-emerald-50 text-emerald-600 border border-emerald-100 text-[10px] rounded">已脱敏</span>
</div>
<div class="flex items-center justify-between text-xs text-slate-500"><span>12,405 行</span><span>2023-10-24</span></div>
</div>
<!-- 原始文件 2 -->
<div x-show="activeTab === 'all' || activeTab === 'input'" class="group p-3 rounded-lg border border-slate-100 hover:border-blue-200 hover:bg-blue-50 transition-all cursor-pointer">
<div class="flex justify-between items-start mb-2">
<div class="flex items-center gap-2">
<i data-lucide="file-input" class="w-4 h-4 text-slate-400"></i>
<h4 class="text-sm font-bold text-slate-800 group-hover:text-blue-700 truncate max-w-[150px]">心血管回顾性研究_raw.xlsx</h4>
</div>
<button class="text-slate-400 hover:text-slate-600"><i data-lucide="more-horizontal" class="w-4 h-4"></i></button>
</div>
<div class="flex items-center gap-2 mb-3">
<span class="px-1.5 py-0.5 bg-slate-100 text-slate-500 border border-slate-200 text-[10px] rounded">原始底表</span>
<span class="px-1.5 py-0.5 bg-slate-100 text-slate-500 border border-slate-200 text-[10px] rounded">未处理</span>
</div>
<div class="flex items-center justify-between text-xs text-slate-500"><span>45,200 行</span><span>2023-10-22</span></div>
</div>
<!-- 结果文件 3 -->
<div x-show="activeTab === 'all' || activeTab === 'output'" class="group p-3 rounded-lg border border-slate-100 hover:border-blue-200 hover:bg-blue-50 transition-all cursor-pointer">
<div class="flex justify-between items-start mb-2">
<div class="flex items-center gap-2">
<i data-lucide="file-spreadsheet" class="w-4 h-4 text-emerald-600"></i>
<h4 class="text-sm font-bold text-slate-800 group-hover:text-blue-700 truncate max-w-[150px]">药物临床试验组_提取结果.csv</h4>
</div>
<button class="text-slate-400 hover:text-slate-600"><i data-lucide="more-horizontal" class="w-4 h-4"></i></button>
</div>
<div class="flex items-center gap-2 mb-3">
<span class="px-1.5 py-0.5 bg-emerald-50 text-emerald-600 border border-emerald-100 text-[10px] rounded">AI提取</span>
</div>
<div class="flex items-center justify-between text-xs text-slate-500"><span>800 行</span><span>2023-10-20</span></div>
</div>
</div>
<!-- 底部上传 -->
<div class="p-4 border-t border-slate-100 bg-slate-50 rounded-b-xl">
<button class="w-full py-2 text-sm text-slate-600 border border-dashed border-slate-300 bg-white rounded-lg hover:border-blue-400 hover:text-blue-600 hover:bg-blue-50 transition-colors flex items-center justify-center gap-2">
<i data-lucide="upload-cloud" class="w-4 h-4"></i> + 上传原始文件到库
</button>
</div>
</div>
</div>
</div>
</main>
<!-- 初始化 Icons -->
<script>
lucide.createIcons();
</script>
</body>
</html>