Files
YG_FT_Platform/web/pages/main.html

1032 lines
49 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>大模型微调平台 - 主页</title>
<!-- Tailwind CSS CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Chart.js CDN -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.8/dist/chart.umd.min.js"></script>
<!-- 自定义Tailwind配置匹配浅色主题 -->
<script>
tailwind.config = {
theme: {
extend: {
colors: {
dashboard: {
bg: '#DBE0F9', // 主背景色与login一致
card: '#FFFFFF', // 卡片背景
primary: '#6065D9', // 主蓝色
secondary: '#764BA2', // 深蓝紫色
accent: '#17D7FA', // 浅蓝高亮
text: '#333333', // 文字色
textLight: '#666666' // 浅文字色
}
},
fontFamily: {
inter: ['Inter', 'sans-serif'],
},
}
}
}
</script>
<style type="text/tailwindcss">
@layer utilities {
.gradient-blue {
background: linear-gradient(135deg, #6065D9 0%, #17D7FA 100%);
}
.card-shadow {
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
}
.progress-bar {
height: 8px;
border-radius: 4px;
overflow: hidden;
}
.radial-progress {
position: relative;
width: 120px;
height: 120px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.radial-progress::before {
content: '';
position: absolute;
width: 90%;
height: 90%;
background-color: #FFFFFF;
border-radius: 50%;
}
}
</style>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<!-- 登录验证脚本 -->
<script>
// 页面加载时检查登录状态
document.addEventListener('DOMContentLoaded', function() {
const isLoggedIn = sessionStorage.getItem('isLoggedIn') === 'true';
if (!isLoggedIn) {
// 如果未登录,重定向到登录页面
window.location.href = 'login.html';
}
});
</script>
</head>
<body class="bg-dashboard-bg text-dashboard-text font-inter min-h-screen">
<div class="flex">
<!-- 侧边栏 -->
<aside class="w-16 md:w-64 bg-white h-screen p-4 flex flex-col shadow-lg">
<div class="flex items-center mb-8">
<div class="w-10 h-10 rounded-lg gradient-blue flex items-center justify-center">
<span class="text-white font-bold">AI</span>
</div>
<span class="ml-2 text-lg font-semibold hidden md:block text-dashboard-primary">大模型平台</span>
</div>
<nav class="flex-1">
<ul class="space-y-4">
<li><a href="#" data-page="dashboard" class="nav-item flex items-center p-2 rounded-lg gradient-blue text-white">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path></svg>
<span class="hidden md:block">仪表盘</span>
</a></li>
<li><a href="#" data-page="preprocess" class="nav-item flex items-center p-2 rounded-lg hover:bg-dashboard-primary/10 text-dashboard-textLight">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4"></path></svg>
<span class="hidden md:block">数据预处理</span>
</a></li>
<li><a href="#" data-page="pretrain" class="nav-item flex items-center p-2 rounded-lg hover:bg-dashboard-primary/10 text-dashboard-textLight">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path></svg>
<span class="hidden md:block">模型预训练</span>
</a></li>
<li><a href="#" data-page="finetune" class="nav-item flex items-center p-2 rounded-lg hover:bg-dashboard-primary/10 text-dashboard-textLight">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z"></path></svg>
<span class="hidden md:block">模型微调</span>
</a></li>
<li><a href="#" data-page="rl" class="nav-item flex items-center p-2 rounded-lg hover:bg-dashboard-primary/10 text-dashboard-textLight">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"></path></svg>
<span class="hidden md:block">强化训练</span>
</a></li>
<li><a href="#" data-page="validate" class="nav-item flex items-center p-2 rounded-lg hover:bg-dashboard-primary/10 text-dashboard-textLight">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
<span class="hidden md:block">模型验证</span>
</a></li>
<li><a href="#" data-page="compare" class="nav-item flex items-center p-2 rounded-lg hover:bg-dashboard-primary/10 text-dashboard-textLight">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path></svg>
<span class="hidden md:block">模型对比</span>
</a></li>
<li><a href="#" data-page="dataset" class="nav-item flex items-center p-2 rounded-lg hover:bg-dashboard-primary/10 text-dashboard-textLight">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"></path></svg>
<span class="hidden md:block">数据集管理</span>
</a></li>
<li><a href="#" data-page="config" class="nav-item flex items-center p-2 rounded-lg hover:bg-dashboard-primary/10 text-dashboard-textLight">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
<span class="hidden md:block">模型配置</span>
</a></li>
<li><a href="#" onclick="logout()" class="flex items-center p-2 rounded-lg hover:bg-red-100 text-dashboard-textLight hover:text-red-600">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1"></path></svg>
<span class="hidden md:block">退出登录</span>
</a></li>
</ul>
</nav>
</aside>
<!-- 主内容区 -->
<main class="flex-1" style="height: calc(100vh - 0px);">
<!-- 仪表盘页面 -->
<div id="dashboard-page" class="page-content hidden" style="padding: 1.5rem; height: 100%; overflow-y: auto;">
<!-- 顶部数据卡片 -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6">
<div class="bg-white rounded-xl p-4 card-shadow">
<p class="text-dashboard-textLight text-sm">活跃模型</p>
<p class="text-2xl font-bold mt-1 text-dashboard-text">12</p>
<div class="flex items-center mt-2 text-green-500 text-sm">
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7"></path></svg>
<span>+3个</span>
</div>
</div>
<div class="bg-white rounded-xl p-4 card-shadow">
<p class="text-dashboard-textLight text-sm">训练中项目</p>
<p class="text-2xl font-bold mt-1 text-dashboard-text">5</p>
<div class="flex items-center mt-2 text-blue-500 text-sm">
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path></svg>
<span>运行中</span>
</div>
</div>
<div class="bg-white rounded-xl p-4 card-shadow">
<p class="text-dashboard-textLight text-sm">完成任务</p>
<p class="text-2xl font-bold mt-1 text-dashboard-text">158</p>
<div class="flex items-center mt-2 text-green-500 text-sm">
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
<span>全部成功</span>
</div>
</div>
</div>
<!-- 中部核心卡片 - 系统监控 -->
<div class="grid grid-cols-1 gap-6 mb-6">
<!-- 系统状态监控 -->
<div class="bg-white rounded-xl p-6 card-shadow">
<div class="flex items-center justify-between mb-6">
<p class="text-lg font-semibold text-dashboard-text">系统监控</p>
<div class="flex items-center">
<div class="w-3 h-3 rounded-full bg-green-500 mr-2 animate-pulse"></div>
<p class="text-dashboard-textLight text-sm">实时监控</p>
</div>
</div>
<!-- 三个实时监控图表 -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<!-- CPU监控 -->
<div class="bg-gray-50 rounded-lg p-4">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center">
<div class="w-3 h-3 rounded-full bg-red-500 mr-2"></div>
<span class="text-sm font-medium text-dashboard-text">CPU</span>
</div>
<span id="cpuPercent" class="text-lg font-bold text-dashboard-text">45%</span>
</div>
<div class="h-24">
<canvas id="cpuChart"></canvas>
</div>
</div>
<!-- GPU监控 -->
<div class="bg-gray-50 rounded-lg p-4">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center">
<div class="w-3 h-3 rounded-full bg-green-500 mr-2"></div>
<span class="text-sm font-medium text-dashboard-text">GPU</span>
</div>
<span id="gpuPercent" class="text-lg font-bold text-dashboard-text">67%</span>
</div>
<div class="h-24">
<canvas id="gpuChart"></canvas>
</div>
</div>
<!-- 内存监控 -->
<div class="bg-gray-50 rounded-lg p-4">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center">
<div class="w-3 h-3 rounded-full bg-blue-500 mr-2"></div>
<span class="text-sm font-medium text-dashboard-text">内存</span>
</div>
<span id="memoryPercent" class="text-lg font-bold text-dashboard-text">52%</span>
</div>
<div class="h-24">
<canvas id="memoryChart"></canvas>
</div>
</div>
</div>
</div>
</div>
<!-- 图表区域 -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<!-- 训练进度折线图 -->
<div class="bg-white rounded-xl p-6 card-shadow">
<p class="text-lg font-semibold mb-4 text-dashboard-text">训练进度</p>
<div class="w-full h-60">
<canvas id="trainingChart"></canvas>
</div>
</div>
<!-- 模型分布柱状图 -->
<div class="bg-white rounded-xl p-6 card-shadow">
<div class="flex justify-between items-center mb-4">
<p class="text-lg font-semibold text-dashboard-text">模型类型分布</p>
<div class="flex space-x-2">
<div class="px-3 py-1 bg-dashboard-primary/10 rounded text-xs text-dashboard-primary">全部</div>
</div>
</div>
<div class="w-full h-40 mb-4">
<canvas id="modelChart"></canvas>
</div>
<div class="grid grid-cols-3 gap-2 text-center">
<div>
<p class="text-lg font-bold text-dashboard-text">GPT</p>
<p class="text-xs text-dashboard-textLight">8个</p>
</div>
<div>
<p class="text-lg font-bold text-dashboard-text">BERT</p>
<p class="text-xs text-dashboard-textLight">5个</p>
</div>
<div>
<p class="text-lg font-bold text-dashboard-text">LLaMA</p>
<p class="text-xs text-dashboard-textLight">3个</p>
</div>
</div>
</div>
</div>
<!-- 底部项目和订单 -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- 当前任务 -->
<div class="bg-white rounded-xl p-6 card-shadow">
<p class="text-lg font-semibold mb-4 text-dashboard-text">当前训练任务</p>
<div class="space-y-4">
<div class="border-b border-dashboard-bg pb-4">
<div class="flex justify-between mb-2">
<p class="font-medium text-dashboard-text">GPT-4微调</p>
<p class="text-dashboard-textLight text-sm">进行中</p>
</div>
<div class="progress-bar bg-dashboard-bg">
<div class="w-[75%] gradient-blue"></div>
</div>
<p class="text-right text-xs text-dashboard-textLight mt-1">75%</p>
</div>
<div class="border-b border-dashboard-bg pb-4">
<div class="flex justify-between mb-2">
<p class="font-medium text-dashboard-text">BERT情感分析</p>
<p class="text-dashboard-textLight text-sm">队列中</p>
</div>
<div class="progress-bar bg-dashboard-bg">
<div class="w-[0%] gradient-blue"></div>
</div>
<p class="text-right text-xs text-dashboard-textLight mt-1">0%</p>
</div>
<div class="border-b border-dashboard-bg pb-4">
<div class="flex justify-between mb-2">
<p class="font-medium text-dashboard-text">LLaMA对话模型</p>
<p class="text-dashboard-textLight text-sm">已完成</p>
</div>
<div class="progress-bar bg-dashboard-bg">
<div class="w-[100%] gradient-blue"></div>
</div>
<p class="text-right text-xs text-dashboard-textLight mt-1">100%</p>
</div>
<div class="border-b border-dashboard-bg pb-4">
<div class="flex justify-between mb-2">
<p class="font-medium text-dashboard-text">图像分类模型</p>
<p class="text-dashboard-textLight text-sm">已完成</p>
</div>
<div class="progress-bar bg-dashboard-bg">
<div class="w-[100%] gradient-blue"></div>
</div>
<p class="text-right text-xs text-dashboard-textLight mt-1">100%</p>
</div>
<div>
<div class="flex justify-between mb-2">
<p class="font-medium text-dashboard-text">推荐系统优化</p>
<p class="text-dashboard-textLight text-sm">已完成</p>
</div>
<div class="progress-bar bg-dashboard-bg">
<div class="w-[100%] gradient-blue"></div>
</div>
<p class="text-right text-xs text-dashboard-textLight mt-1">100%</p>
</div>
</div>
</div>
<!-- 最近活动 -->
<div class="bg-white rounded-xl p-6 card-shadow">
<p class="text-lg font-semibold mb-4 text-dashboard-text">最近活动</p>
<div class="space-y-4">
<div class="border-b border-dashboard-bg pb-4">
<div class="flex justify-between mb-1">
<p class="font-medium text-dashboard-text">模型训练完成</p>
<p class="text-xs bg-green-100 text-green-600 px-2 py-1 rounded">成功</p>
</div>
<p class="text-dashboard-textLight text-sm">GPT-4微调任务已完成</p>
<p class="text-xs text-dashboard-textLight mt-1">2分钟前</p>
</div>
<div class="border-b border-dashboard-bg pb-4">
<div class="flex justify-between mb-1">
<p class="font-medium text-dashboard-text">新任务开始</p>
<p class="text-xs bg-blue-100 text-blue-600 px-2 py-1 rounded">进行中</p>
</div>
<p class="text-dashboard-textLight text-sm">BERT情感分析模型开始训练</p>
<p class="text-xs text-dashboard-textLight mt-1">5分钟前</p>
</div>
<div class="border-b border-dashboard-bg pb-4">
<div class="flex justify-between mb-1">
<p class="font-medium text-dashboard-text">模型部署</p>
<p class="text-xs bg-green-100 text-green-600 px-2 py-1 rounded">成功</p>
</div>
<p class="text-dashboard-textLight text-sm">LLaMA对话模型已部署到云端</p>
<p class="text-xs text-dashboard-textLight mt-1">10分钟前</p>
</div>
<div class="border-b border-dashboard-bg pb-4">
<div class="flex justify-between mb-1">
<p class="font-medium text-dashboard-text">数据集更新</p>
<p class="text-xs bg-purple-100 text-purple-600 px-2 py-1 rounded">已完成</p>
</div>
<p class="text-dashboard-textLight text-sm">训练数据集已更新</p>
<p class="text-xs text-dashboard-textLight mt-1">30分钟前</p>
</div>
</div>
</div>
</div>
</div>
<!-- 数据集管理页面 -->
<div id="dataset-page" class="page-content hidden" style="padding: 1.5rem; height: 100%; overflow-y: auto;">
<div class="bg-white rounded-xl p-6 card-shadow">
<div class="flex justify-between items-center mb-6">
<p class="text-lg font-semibold text-dashboard-text">数据集管理</p>
<button onclick="document.getElementById('fileInput').click()" class="px-4 py-2 gradient-blue text-white rounded-lg hover:opacity-90 transition-opacity">
上传数据集
</button>
<input type="file" id="fileInput" style="display: none" accept=".json,.jsonl" onchange="handleFileUpload(this)">
</div>
<!-- 数据集列表 -->
<div id="datasetList" class="space-y-4">
<!-- 数据集列表将通过 JavaScript 动态加载 -->
</div>
</div>
</div>
<!-- 数据预处理页面 - Easy-Datasets -->
<div id="preprocess-page" class="page-content hidden h-full" style="padding: 0;">
<iframe id="easy-datasets-frame"
src="http://localhost:1717"
style="width: 100%; height: 100%; border: none;"
title="Easy-Datasets">
</iframe>
</div>
<div id="pretrain-page" class="page-content hidden" style="padding: 1.5rem; height: 100%; overflow-y: auto;">
<div class="bg-white rounded-xl p-6 card-shadow">
<p class="text-lg font-semibold text-dashboard-text mb-4">模型预训练</p>
<p class="text-dashboard-textLight">模型预训练功能开发中...</p>
</div>
</div>
<div id="finetune-page" class="page-content hidden" style="padding: 1.5rem; height: 100%; overflow-y: auto;">
<div class="bg-white rounded-xl p-6 card-shadow">
<p class="text-lg font-semibold text-dashboard-text mb-4">模型微调</p>
<p class="text-dashboard-textLight">模型微调功能开发中...</p>
</div>
</div>
<div id="rl-page" class="page-content hidden" style="padding: 1.5rem; height: 100%; overflow-y: auto;">
<div class="bg-white rounded-xl p-6 card-shadow">
<p class="text-lg font-semibold text-dashboard-text mb-4">强化训练</p>
<p class="text-dashboard-textLight">强化训练功能开发中...</p>
</div>
</div>
<div id="validate-page" class="page-content hidden" style="padding: 1.5rem; height: 100%; overflow-y: auto;">
<div class="bg-white rounded-xl p-6 card-shadow">
<p class="text-lg font-semibold text-dashboard-text mb-4">模型验证</p>
<p class="text-dashboard-textLight">模型验证功能开发中...</p>
</div>
</div>
<div id="compare-page" class="page-content hidden" style="padding: 1.5rem; height: 100%; overflow-y: auto;">
<div class="bg-white rounded-xl p-6 card-shadow">
<p class="text-lg font-semibold text-dashboard-text mb-4">模型对比</p>
<p class="text-dashboard-textLight">模型对比功能开发中...</p>
</div>
</div>
<div id="config-page" class="page-content hidden" style="padding: 1.5rem; height: 100%; overflow-y: auto;">
<div class="bg-white rounded-xl p-6 card-shadow">
<p class="text-lg font-semibold text-dashboard-text mb-4">模型配置</p>
<p class="text-dashboard-textLight">模型配置功能开发中...</p>
</div>
</div>
</main>
</div>
<!-- 图表初始化脚本 -->
<script>
// 训练进度折线图
const trainingCtx = document.getElementById('trainingChart').getContext('2d');
new Chart(trainingCtx, {
type: 'line',
data: {
labels: ['第1天', '第2天', '第3天', '第4天', '第5天', '第6天', '第7天'],
datasets: [{
label: '准确率',
data: [65, 72, 78, 85, 88, 92, 95],
borderColor: '#6065D9',
backgroundColor: 'rgba(96, 101, 217, 0.1)',
fill: true,
tension: 0.4,
pointBackgroundColor: '#FFFFFF',
pointBorderColor: '#6065D9'
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
}
},
scales: {
x: {
grid: {
display: false
},
ticks: {
color: '#666666'
}
},
y: {
grid: {
color: 'rgba(0, 0, 0, 0.05)'
},
ticks: {
color: '#666666'
}
}
}
}
});
// 模型类型分布柱状图
const modelCtx = document.getElementById('modelChart').getContext('2d');
new Chart(modelCtx, {
type: 'bar',
data: {
labels: ['GPT', 'BERT', 'LLaMA', 'T5', 'Others'],
datasets: [{
label: '模型数量',
data: [8, 5, 3, 2, 4],
backgroundColor: [
'rgba(96, 101, 217, 0.8)',
'rgba(118, 75, 162, 0.8)',
'rgba(23, 215, 250, 0.8)',
'rgba(96, 101, 217, 0.6)',
'rgba(118, 75, 162, 0.6)'
],
borderRadius: 4
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
}
},
scales: {
x: {
grid: {
display: false
},
ticks: {
color: '#666666'
}
},
y: {
grid: {
color: 'rgba(0, 0, 0, 0.05)'
},
ticks: {
color: '#666666'
}
}
}
}
});
// 系统监控图表配置
const chartConfig = {
type: 'line',
options: {
responsive: true,
maintainAspectRatio: false,
animation: false,
plugins: {
legend: {
display: false
}
},
scales: {
x: {
display: false
},
y: {
display: false,
min: 0,
max: 100
}
},
elements: {
line: {
tension: 0.4,
borderWidth: 2
},
point: {
radius: 0
}
}
}
};
// 数据存储
let cpuHistoryData = [];
let gpuHistoryData = [];
let memoryHistoryData = [];
const maxDataPoints = 20;
// 生成模拟系统数据
function generateMockData() {
const base = 50;
const variation = 30;
return {
cpu: Math.floor(base + (Math.random() - 0.5) * variation),
gpu: Math.floor(base + (Math.random() - 0.5) * variation),
memory: Math.floor(base + (Math.random() - 0.5) * variation)
};
}
// 添加数据到历史记录
function addToHistory(type, value) {
switch(type) {
case 'cpu':
cpuHistoryData.push(value);
if (cpuHistoryData.length > maxDataPoints) cpuHistoryData.shift();
break;
case 'gpu':
gpuHistoryData.push(value);
if (gpuHistoryData.length > maxDataPoints) gpuHistoryData.shift();
break;
case 'memory':
memoryHistoryData.push(value);
if (memoryHistoryData.length > maxDataPoints) memoryHistoryData.shift();
break;
}
}
// 创建CPU图表
const cpuCtx = document.getElementById('cpuChart').getContext('2d');
const cpuChart = new Chart(cpuCtx, {
...chartConfig,
data: {
labels: Array.from({length: maxDataPoints}, (_, i) => i),
datasets: [{
label: 'CPU',
data: new Array(maxDataPoints).fill(0),
borderColor: '#EF4444',
backgroundColor: 'rgba(239, 68, 68, 0.1)',
fill: true
}]
}
});
// 创建GPU图表
const gpuCtx = document.getElementById('gpuChart').getContext('2d');
const gpuChart = new Chart(gpuCtx, {
...chartConfig,
data: {
labels: Array.from({length: maxDataPoints}, (_, i) => i),
datasets: [{
label: 'GPU',
data: new Array(maxDataPoints).fill(0),
borderColor: '#10B981',
backgroundColor: 'rgba(16, 185, 129, 0.1)',
fill: true
}]
}
});
// 创建内存图表
const memoryCtx = document.getElementById('memoryChart').getContext('2d');
const memoryChart = new Chart(memoryCtx, {
...chartConfig,
data: {
labels: Array.from({length: maxDataPoints}, (_, i) => i),
datasets: [{
label: 'Memory',
data: new Array(maxDataPoints).fill(0),
borderColor: '#3B82F6',
backgroundColor: 'rgba(59, 130, 246, 0.1)',
fill: true
}]
}
});
// 更新图表数据
function updateCharts() {
// 确保数据长度一致
while (cpuHistoryData.length < maxDataPoints) {
cpuHistoryData.unshift(0);
gpuHistoryData.unshift(0);
memoryHistoryData.unshift(0);
}
// 更新图表数据
cpuChart.data.datasets[0].data = cpuHistoryData;
gpuChart.data.datasets[0].data = gpuHistoryData;
memoryChart.data.datasets[0].data = memoryHistoryData;
// 刷新图表
cpuChart.update('none');
gpuChart.update('none');
memoryChart.update('none');
}
// 初始化并开始模拟监控
function initSystemMonitoring() {
// 生成初始数据
for (let i = 0; i < maxDataPoints; i++) {
const data = generateMockData();
addToHistory('cpu', data.cpu);
addToHistory('gpu', data.gpu);
addToHistory('memory', data.memory);
}
// 设置定期更新
setInterval(() => {
const data = generateMockData();
// 更新百分比显示
document.getElementById('cpuPercent').textContent = data.cpu + '%';
document.getElementById('gpuPercent').textContent = data.gpu + '%';
document.getElementById('memoryPercent').textContent = data.memory + '%';
// 添加到历史数据
addToHistory('cpu', data.cpu);
addToHistory('gpu', data.gpu);
addToHistory('memory', data.memory);
// 更新图表
updateCharts();
}, 2000); // 每2秒更新一次
}
// 页面加载完成后启动监控
document.addEventListener('DOMContentLoaded', initSystemMonitoring);
</script>
<script>
// 页面导航功能
function switchPage(pageId) {
// 隐藏所有页面
const allPages = document.querySelectorAll('.page-content');
allPages.forEach(page => {
page.classList.add('hidden');
});
// 显示选中的页面
const targetPage = document.getElementById(pageId + '-page');
if (targetPage) {
targetPage.classList.remove('hidden');
}
// 更新侧边栏激活状态
const navItems = document.querySelectorAll('.nav-item');
navItems.forEach(item => {
item.classList.remove('gradient-blue', 'text-white');
item.classList.add('hover:bg-dashboard-primary/10', 'text-dashboard-textLight');
});
// 激活当前页面
const activeItem = document.querySelector(`[data-page="${pageId}"]`);
if (activeItem) {
activeItem.classList.remove('hover:bg-dashboard-primary/10', 'text-dashboard-textLight');
activeItem.classList.add('gradient-blue', 'text-white');
}
}
// 初始化导航
document.addEventListener('DOMContentLoaded', function() {
// 默认显示仪表盘
switchPage('dashboard');
// 为所有导航项添加点击事件
const navItems = document.querySelectorAll('.nav-item');
navItems.forEach(item => {
item.addEventListener('click', function(e) {
e.preventDefault();
const pageId = this.getAttribute('data-page');
switchPage(pageId);
});
});
});
// 修改 switchPage 函数以支持数据集页面加载
const originalSwitchPage = switchPage;
switchPage = function(pageId) {
originalSwitchPage(pageId);
// 如果切换到数据集页面,加载数据集列表
if (pageId === 'dataset') {
loadDatasets();
}
};
// 数据集管理相关功能
const API_BASE = 'http://localhost:3000/api';
// 加载数据集列表
async function loadDatasets() {
try {
const response = await fetch(`${API_BASE}/datasets`);
const result = await response.json();
// 适配StandardResponse格式: {status: 1, response: {...}}
if (result.status === 1 && result.response && result.response.datasets) {
renderDatasetList(result.response.datasets);
} else if (result.status === 0) {
console.error('加载数据集列表失败:', result.response?.error || '未知错误');
}
} catch (error) {
console.error('加载数据集列表失败:', error);
}
}
// 渲染数据集列表
function renderDatasetList(datasets) {
const container = document.getElementById('datasetList');
if (!container) return;
container.innerHTML = '';
datasets.forEach(dataset => {
const statusClass = getStatusClass(dataset.status);
const statusText = dataset.status;
const datasetDiv = document.createElement('div');
datasetDiv.className = 'border border-dashboard-bg rounded-lg p-4 hover:shadow-md transition-shadow';
datasetDiv.innerHTML = `
<div class="flex justify-between items-center">
<div>
<h3 class="font-medium text-dashboard-text">${dataset.name}</h3>
<p class="text-sm text-dashboard-textLight mt-1">${dataset.size_display || dataset.size_mb + ' MB' || '未知大小'}${dataset.description || '无描述'}</p>
</div>
<div class="flex items-center space-x-2">
<span class="px-2 py-1 ${statusClass} text-xs rounded">${statusText}</span>
<button onclick="viewDatasetDetails('${dataset.file_id}')" class="text-dashboard-primary hover:underline text-sm">查看详情</button>
<button onclick="deleteDataset('${dataset.file_id}', '${dataset.name}')" class="text-red-500 hover:text-red-700 text-sm">删除</button>
</div>
</div>
`;
container.appendChild(datasetDiv);
});
}
// 获取状态样式类
function getStatusClass(status) {
switch(status) {
case '已处理':
return 'bg-green-100 text-green-600';
case '处理中':
return 'bg-blue-100 text-blue-600';
case '待处理':
return 'bg-gray-100 text-gray-600';
default:
return 'bg-gray-100 text-gray-600';
}
}
// 查看数据集详情
// 处理文件上传
async function handleFileUpload(input) {
const file = input.files[0];
if (!file) return;
// 检查文件类型
const allowedTypes = ['.json', '.jsonl'];
const fileExtension = '.' + file.name.split('.').pop().toLowerCase();
if (!allowedTypes.includes(fileExtension)) {
alert('只支持 JSON 和 JSONL 格式的文件!');
input.value = '';
return;
}
// 检查文件大小 (100MB)
const maxSize = 100 * 1024 * 1024;
if (file.size > maxSize) {
alert('文件大小不能超过 100MB');
input.value = '';
return;
}
try {
const formData = new FormData();
formData.append('file', file);
formData.append('description', `用户上传的数据集文件: ${file.name}`);
const response = await fetch(`${API_BASE}/datasets/upload`, {
method: 'POST',
body: formData
});
const result = await response.json();
// 适配StandardResponse格式: {status: 1, response: {...}}
if (result.status === 1) {
alert('上传成功!');
// 重新加载数据集列表
loadDatasets();
} else {
const errorMsg = result.response?.error || result.message || '未知错误';
alert('上传失败: ' + errorMsg);
}
} catch (error) {
console.error('上传失败:', error);
alert('上传失败: 网络错误');
}
// 清空文件选择
input.value = '';
}
// 退出登录函数
function logout() {
// 清除登录状态
sessionStorage.removeItem('isLoggedIn');
// 跳转到登录页面
window.location.href = 'login.html';
}
// 查看数据集详情
async function viewDatasetDetails(fileId) {
try {
// 调用API获取文件内容
const response = await fetch(`${API_BASE}/datasets/${fileId}/content?limit=5`);
const result = await response.json();
if (result.status === 1) {
const data = result.response;
let contentHtml = '';
if (Array.isArray(data.preview)) {
// 如果是数组显示前5条记录
contentHtml = '<div style="max-height: 400px; overflow-y: auto;"><pre>' +
JSON.stringify(data.preview, null, 2) +
'</pre></div>';
} else {
// 如果是对象,直接显示
contentHtml = '<div style="max-height: 400px; overflow-y: auto;"><pre>' +
JSON.stringify(data.preview, null, 2) +
'</pre></div>';
}
// 显示模态框
showDatasetModal(data.filename, contentHtml);
} else {
alert('获取文件内容失败: ' + (result.response?.error || '未知错误'));
}
} catch (error) {
console.error('获取文件详情失败:', error);
alert('获取文件详情失败: 网络错误');
}
}
// 显示数据集详情模态框
function showDatasetModal(title, content) {
const modal = document.createElement('div');
modal.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 10000;
`;
const modalContent = document.createElement('div');
modalContent.style.cssText = `
background: white;
padding: 20px;
border-radius: 8px;
max-width: 800px;
max-height: 600px;
overflow: hidden;
display: flex;
flex-direction: column;
`;
const modalHeader = document.createElement('div');
modalHeader.style.cssText = `
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
border-bottom: 1px solid #eee;
padding-bottom: 10px;
`;
const titleElement = document.createElement('h3');
titleElement.textContent = title;
titleElement.style.cssText = 'margin: 0; color: #333;';
const closeButton = document.createElement('button');
closeButton.textContent = '×';
closeButton.style.cssText = `
background: none;
border: none;
font-size: 24px;
cursor: pointer;
color: #666;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
`;
closeButton.onmouseover = () => closeButton.style.background = '#f0f0f0';
closeButton.onmouseout = () => closeButton.style.background = 'none';
const closeModal = () => {
document.body.removeChild(modal);
};
closeButton.onclick = closeModal;
modal.onclick = (e) => {
if (e.target === modal) closeModal();
};
modalHeader.appendChild(titleElement);
modalHeader.appendChild(closeButton);
const contentDiv = document.createElement('div');
contentDiv.innerHTML = content;
modalContent.appendChild(modalHeader);
modalContent.appendChild(contentDiv);
modal.appendChild(modalContent);
document.body.appendChild(modal);
}
// 删除数据集
async function deleteDataset(fileId, filename) {
// 确认删除对话框
const confirmMessage = `确定要删除数据集 "${filename}" 吗?\n\n此操作不可撤销!`;
if (!confirm(confirmMessage)) {
return;
}
try {
const response = await fetch(`${API_BASE}/datasets/${fileId}`, {
method: 'DELETE'
});
const result = await response.json();
if (result.status === 1) {
alert('删除成功!');
// 重新加载数据集列表
loadDatasets();
} else {
alert('删除失败: ' + (result.response?.error || '未知错误'));
}
} catch (error) {
console.error('删除失败:', error);
alert('删除失败: 网络错误');
}
}
</script>
</body>
</html>