Yolov/templates/demo/monitoring.html

812 lines
34 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>系统监控 - 多任务YOLO检测系统</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
<link href="css/style.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<!-- 导航栏 -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="index.html">
<i class="bi bi-cpu-fill me-2"></i>多任务YOLO检测系统
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="index.html">
<i class="bi bi-house-door me-1"></i>首页
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="task-management.html">
<i class="bi bi-list-task me-1"></i>任务管理
</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="monitoring.html">
<i class="bi bi-graph-up me-1"></i>系统监控
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="video-player.html">
<i class="bi bi-camera-video me-1"></i>视频播放
</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- 主内容区 -->
<div class="container-fluid mt-4">
<div class="row">
<div class="col-md-12">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2><i class="bi bi-graph-up text-primary me-2"></i>系统监控</h2>
<div>
<button class="btn btn-outline-primary me-2" id="refreshCharts">
<i class="bi bi-arrow-clockwise me-1"></i>刷新数据
</button>
<div class="btn-group">
<button class="btn btn-outline-secondary" id="autoRefreshToggle">
<i class="bi bi-play-circle me-1"></i>自动刷新
</button>
</div>
</div>
</div>
<!-- 系统资源卡片 -->
<div class="row mb-4">
<div class="col-md-3 mb-3">
<div class="card border-0 shadow-sm h-100">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-2">CPU使用率</h6>
<h2 id="cpuPercent">42%</h2>
</div>
<div class="icon-circle bg-danger">
<i class="bi bi-cpu text-white"></i>
</div>
</div>
<div class="progress mt-2" style="height: 6px;">
<div class="progress-bar bg-danger" id="cpuBar" style="width: 42%"></div>
</div>
<p class="text-muted small mt-2 mb-0">总核心: 8, 使用中: 3</p>
</div>
</div>
</div>
<div class="col-md-3 mb-3">
<div class="card border-0 shadow-sm h-100">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-2">内存使用</h6>
<h2 id="memoryPercent">68%</h2>
</div>
<div class="icon-circle bg-info">
<i class="bi bi-memory text-white"></i>
</div>
</div>
<div class="progress mt-2" style="height: 6px;">
<div class="progress-bar bg-info" id="memoryBar" style="width: 68%"></div>
</div>
<p class="text-muted small mt-2 mb-0">已用: 10.2GB / 总: 16GB</p>
</div>
</div>
</div>
<div class="col-md-3 mb-3">
<div class="card border-0 shadow-sm h-100">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-2">GPU使用率</h6>
<h2 id="gpuPercent">78%</h2>
</div>
<div class="icon-circle bg-warning">
<i class="bi bi-gpu-card text-white"></i>
</div>
</div>
<div class="progress mt-2" style="height: 6px;">
<div class="progress-bar bg-warning" id="gpuBar" style="width: 78%"></div>
</div>
<p class="text-muted small mt-2 mb-0">显存: 6.4GB / 总: 8GB</p>
</div>
</div>
</div>
<div class="col-md-3 mb-3">
<div class="card border-0 shadow-sm h-100">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-2">磁盘使用</h6>
<h2 id="diskPercent">34%</h2>
</div>
<div class="icon-circle bg-success">
<i class="bi bi-hdd text-white"></i>
</div>
</div>
<div class="progress mt-2" style="height: 6px;">
<div class="progress-bar bg-success" id="diskBar" style="width: 34%"></div>
</div>
<p class="text-muted small mt-2 mb-0">可用: 256GB / 总: 512GB</p>
</div>
</div>
</div>
</div>
<!-- 图表区域 -->
<div class="row mb-4">
<div class="col-md-6 mb-4">
<div class="card border-0 shadow-sm h-100">
<div class="card-header bg-white">
<h5 class="mb-0">CPU使用率趋势</h5>
</div>
<div class="card-body">
<canvas id="cpuChart" height="250"></canvas>
</div>
</div>
</div>
<div class="col-md-6 mb-4">
<div class="card border-0 shadow-sm h-100">
<div class="card-header bg-white">
<h5 class="mb-0">内存使用趋势</h5>
</div>
<div class="card-body">
<canvas id="memoryChart" height="250"></canvas>
</div>
</div>
</div>
</div>
<div class="row mb-4">
<div class="col-md-6 mb-4">
<div class="card border-0 shadow-sm h-100">
<div class="card-header bg-white">
<h5 class="mb-0">任务FPS分布</h5>
</div>
<div class="card-body">
<canvas id="fpsChart" height="250"></canvas>
</div>
</div>
</div>
<div class="col-md-6 mb-4">
<div class="card border-0 shadow-sm h-100">
<div class="card-header bg-white">
<h5 class="mb-0">模型使用统计</h5>
</div>
<div class="card-body">
<canvas id="modelChart" height="250"></canvas>
</div>
</div>
</div>
</div>
<!-- 任务性能表 -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-header bg-white">
<h5 class="mb-0">任务性能监控</h5>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead class="table-light">
<tr>
<th>任务名称</th>
<th>状态</th>
<th>FPS</th>
<th>处理时间</th>
<th>检测数</th>
<th>模型数</th>
<th>GPU显存</th>
<th>运行时长</th>
</tr>
</thead>
<tbody id="performanceTable">
<!-- 性能数据将通过JavaScript动态生成 -->
</tbody>
</table>
</div>
</div>
</div>
<!-- 系统信息 -->
<div class="row">
<div class="col-md-6 mb-4">
<div class="card border-0 shadow-sm h-100">
<div class="card-header bg-white">
<h5 class="mb-0">系统信息</h5>
</div>
<div class="card-body">
<table class="table table-sm">
<tr>
<td><strong>操作系统</strong></td>
<td>Ubuntu 20.04 LTS</td>
</tr>
<tr>
<td><strong>Python版本</strong></td>
<td>3.8.10</td>
</tr>
<tr>
<td><strong>PyTorch版本</strong></td>
<td>2.0.1+cu118</td>
</tr>
<tr>
<td><strong>CUDA版本</strong></td>
<td>11.8</td>
</tr>
<tr>
<td><strong>Ultralytics版本</strong></td>
<td>8.0.0</td>
</tr>
<tr>
<td><strong>OpenCV版本</strong></td>
<td>4.8.0</td>
</tr>
<tr>
<td><strong>FFmpeg版本</strong></td>
<td>4.4.2</td>
</tr>
<tr>
<td><strong>启动时间</strong></td>
<td id="systemUptime">2天 5小时 30分钟</td>
</tr>
</table>
</div>
</div>
</div>
<div class="col-md-6 mb-4">
<div class="card border-0 shadow-sm h-100">
<div class="card-header bg-white">
<h5 class="mb-0">硬件信息</h5>
</div>
<div class="card-body">
<table class="table table-sm">
<tr>
<td><strong>CPU型号</strong></td>
<td>Intel Core i9-13900K</td>
</tr>
<tr>
<td><strong>CPU核心数</strong></td>
<td>24核心 (8P+16E)</td>
</tr>
<tr>
<td><strong>GPU型号</strong></td>
<td>NVIDIA RTX 4090</td>
</tr>
<tr>
<td><strong>GPU显存</strong></td>
<td>24GB GDDR6X</td>
</tr>
<tr>
<td><strong>系统内存</strong></td>
<td>32GB DDR5 5600MHz</td>
</tr>
<tr>
<td><strong>磁盘型号</strong></td>
<td>Samsung 980 Pro 1TB NVMe</td>
</tr>
<tr>
<td><strong>网络接口</strong></td>
<td>2.5Gbps Ethernet</td>
</tr>
<tr>
<td><strong>系统温度</strong></td>
<td id="systemTemp">42°C</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 页脚 -->
<footer class="bg-dark text-white mt-5 py-4">
<div class="container-fluid">
<div class="row">
<div class="col-md-6">
<h5>系统监控</h5>
<p class="text-light">多任务YOLO检测系统的实时监控界面</p>
</div>
<div class="col-md-6 text-md-end">
<p class="mb-0">© 2023 多任务YOLO检测系统 | 演示版本 v1.0.0</p>
<p class="text-light small">此页面为演示版本,使用模拟数据</p>
</div>
</div>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
// 图表实例
let cpuChart, memoryChart, fpsChart, modelChart;
let autoRefreshInterval = null;
let isAutoRefreshing = false;
// 模拟性能数据
const mockPerformanceData = [
{ name: "交通监控-路口A", status: "running", fps: 24.5, processTime: "45ms", detections: 156, models: 3, gpuMem: "2.4GB", uptime: "5h 30m" },
{ name: "安全监控-入口", status: "running", fps: 28.1, processTime: "38ms", detections: 89, models: 2, gpuMem: "1.8GB", uptime: "4h 15m" },
{ name: "停车场监控", status: "stopped", fps: 0, processTime: "0ms", detections: 0, models: 1, gpuMem: "0GB", uptime: "0m" },
{ name: "生产线检测", status: "error", fps: 15.3, processTime: "62ms", detections: 0, models: 2, gpuMem: "1.2GB", uptime: "2h 45m" },
{ name: "测试任务", status: "creating", fps: 0, processTime: "0ms", detections: 0, models: 1, gpuMem: "0GB", uptime: "5m" }
];
// 模拟图表数据
let timeLabels = [];
let cpuData = [];
let memoryData = [];
let gpuData = [];
// 初始化时间标签
function initTimeLabels() {
timeLabels = [];
const now = new Date();
for (let i = 9; i >= 0; i--) {
const time = new Date(now.getTime() - i * 60000);
timeLabels.push(time.getHours().toString().padStart(2, '0') + ':' + time.getMinutes().toString().padStart(2, '0'));
}
}
// 初始化数据
function initChartData() {
cpuData = [];
memoryData = [];
gpuData = [];
for (let i = 0; i < 10; i++) {
cpuData.push(Math.floor(Math.random() * 30) + 30);
memoryData.push(Math.floor(Math.random() * 20) + 50);
gpuData.push(Math.floor(Math.random() * 30) + 50);
}
}
// 初始化CPU图表
function initCpuChart() {
const ctx = document.getElementById('cpuChart').getContext('2d');
if (cpuChart) {
cpuChart.destroy();
}
cpuChart = new Chart(ctx, {
type: 'line',
data: {
labels: timeLabels,
datasets: [{
label: 'CPU使用率 (%)',
data: cpuData,
borderColor: '#dc3545',
backgroundColor: 'rgba(220, 53, 69, 0.1)',
borderWidth: 2,
fill: true,
tension: 0.4
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: true,
position: 'top'
}
},
scales: {
y: {
beginAtZero: true,
max: 100,
ticks: {
callback: function(value) {
return value + '%';
}
}
}
}
}
});
}
// 初始化内存图表
function initMemoryChart() {
const ctx = document.getElementById('memoryChart').getContext('2d');
if (memoryChart) {
memoryChart.destroy();
}
memoryChart = new Chart(ctx, {
type: 'line',
data: {
labels: timeLabels,
datasets: [{
label: '内存使用率 (%)',
data: memoryData,
borderColor: '#0dcaf0',
backgroundColor: 'rgba(13, 202, 240, 0.1)',
borderWidth: 2,
fill: true,
tension: 0.4
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: true,
position: 'top'
}
},
scales: {
y: {
beginAtZero: true,
max: 100,
ticks: {
callback: function(value) {
return value + '%';
}
}
}
}
}
});
}
// 初始化FPS图表
function initFpsChart() {
const ctx = document.getElementById('fpsChart').getContext('2d');
if (fpsChart) {
fpsChart.destroy();
}
// 获取运行中任务的FPS数据
const runningTasks = mockPerformanceData.filter(task => task.status === 'running');
const taskNames = runningTasks.map(task => task.name);
const taskFps = runningTasks.map(task => task.fps);
fpsChart = new Chart(ctx, {
type: 'bar',
data: {
labels: taskNames,
datasets: [{
label: 'FPS',
data: taskFps,
backgroundColor: [
'rgba(255, 99, 132, 0.7)',
'rgba(54, 162, 235, 0.7)',
'rgba(255, 206, 86, 0.7)',
'rgba(75, 192, 192, 0.7)',
'rgba(153, 102, 255, 0.7)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)'
],
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
}
},
scales: {
y: {
beginAtZero: true,
title: {
display: true,
text: 'FPS'
}
}
}
}
});
}
// 初始化模型图表
function initModelChart() {
const ctx = document.getElementById('modelChart').getContext('2d');
if (modelChart) {
modelChart.destroy();
}
// 模拟模型使用数据
const modelNames = ['yolov8n.pt', 'yolov8s.pt', 'yolov8m.pt', 'custom.pt', 'yolov5s.pt'];
const modelUsage = [45, 30, 15, 7, 3];
modelChart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: modelNames,
datasets: [{
data: modelUsage,
backgroundColor: [
'rgba(255, 99, 132, 0.7)',
'rgba(54, 162, 235, 0.7)',
'rgba(255, 206, 86, 0.7)',
'rgba(75, 192, 192, 0.7)',
'rgba(153, 102, 255, 0.7)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)'
],
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'right'
}
}
}
});
}
// 渲染性能表格
function renderPerformanceTable() {
const tbody = document.getElementById('performanceTable');
tbody.innerHTML = '';
mockPerformanceData.forEach(task => {
const row = document.createElement('tr');
// 状态颜色
let statusColor = 'secondary';
let statusText = task.status;
if (task.status === 'running') {
statusColor = 'success';
statusText = '运行中';
} else if (task.status === 'error') {
statusColor = 'danger';
statusText = '错误';
} else if (task.status === 'creating') {
statusColor = 'info';
statusText = '创建中';
} else if (task.status === 'stopped') {
statusColor = 'secondary';
statusText = '已停止';
}
row.innerHTML = `
<td><strong>${task.name}</strong></td>
<td><span class="badge bg-${statusColor}">${statusText}</span></td>
<td>${task.fps > 0 ? task.fps.toFixed(1) : '0'}</td>
<td>${task.processTime}</td>
<td>${task.detections}</td>
<td>${task.models}</td>
<td>${task.gpuMem}</td>
<td>${task.uptime}</td>
`;
tbody.appendChild(row);
});
}
// 更新系统资源数据
function updateResourceData() {
// 更新资源百分比
const cpuPercent = Math.floor(Math.random() * 30) + 30;
const memoryPercent = Math.floor(Math.random() * 20) + 50;
const gpuPercent = Math.floor(Math.random() * 30) + 50;
const diskPercent = Math.floor(Math.random() * 20) + 30;
document.getElementById('cpuPercent').textContent = cpuPercent + '%';
document.getElementById('cpuBar').style.width = cpuPercent + '%';
document.getElementById('memoryPercent').textContent = memoryPercent + '%';
document.getElementById('memoryBar').style.width = memoryPercent + '%';
document.getElementById('gpuPercent').textContent = gpuPercent + '%';
document.getElementById('gpuBar').style.width = gpuPercent + '%';
document.getElementById('diskPercent').textContent = diskPercent + '%';
document.getElementById('diskBar').style.width = diskPercent + '%';
// 更新系统温度和运行时间
const temp = Math.floor(Math.random() * 10) + 38;
document.getElementById('systemTemp').textContent = temp + '°C';
// 更新图表数据
updateChartData();
// 更新性能数据
updatePerformanceData();
// 更新运行时间
updateUptime();
}
// 更新图表数据
function updateChartData() {
// 移除第一个数据点,添加新的数据点
cpuData.shift();
memoryData.shift();
gpuData.shift();
// 添加新的数据点
cpuData.push(Math.floor(Math.random() * 30) + 30);
memoryData.push(Math.floor(Math.random() * 20) + 50);
gpuData.push(Math.floor(Math.random() * 30) + 50);
// 更新时间标签
const now = new Date();
const timeStr = now.getHours().toString().padStart(2, '0') + ':' + now.getMinutes().toString().padStart(2, '0');
timeLabels.shift();
timeLabels.push(timeStr);
// 更新图表
cpuChart.update();
memoryChart.update();
fpsChart.update();
}
// 更新性能数据
function updatePerformanceData() {
mockPerformanceData.forEach(task => {
if (task.status === 'running') {
// 随机更新FPS
task.fps = (Math.random() * 10 + 20).toFixed(1);
// 增加检测数量
task.detections += Math.floor(Math.random() * 10);
// 更新运行时间
if (task.uptime.includes('h')) {
const hours = parseInt(task.uptime.split('h')[0]);
const minutes = parseInt(task.uptime.split('h')[1].split('m')[0]);
let newMinutes = minutes + 1;
let newHours = hours;
if (newMinutes >= 60) {
newHours++;
newMinutes = 0;
}
task.uptime = newHours + 'h ' + newMinutes + 'm';
} else if (task.uptime.includes('m')) {
const minutes = parseInt(task.uptime.split('m')[0]);
if (minutes >= 60) {
task.uptime = '1h ' + (minutes - 60) + 'm';
} else {
task.uptime = (minutes + 1) + 'm';
}
}
}
});
renderPerformanceTable();
initFpsChart(); // 重新初始化FPS图表以更新数据
}
// 更新运行时间
function updateUptime() {
const uptimeElement = document.getElementById('systemUptime');
let text = uptimeElement.textContent;
if (text.includes('天')) {
const days = parseInt(text.split('天')[0]);
const hours = parseInt(text.split('天')[1].split('小时')[0]);
const minutes = parseInt(text.split('小时')[1].split('分钟')[0]);
let newMinutes = minutes + 1;
let newHours = hours;
let newDays = days;
if (newMinutes >= 60) {
newHours++;
newMinutes = 0;
}
if (newHours >= 24) {
newDays++;
newHours = 0;
}
uptimeElement.textContent = newDays + '天 ' + newHours + '小时 ' + newMinutes + '分钟';
}
}
// 切换自动刷新
function toggleAutoRefresh() {
const button = document.getElementById('autoRefreshToggle');
const icon = button.querySelector('i');
if (isAutoRefreshing) {
// 停止自动刷新
clearInterval(autoRefreshInterval);
autoRefreshInterval = null;
button.innerHTML = '<i class="bi bi-play-circle me-1"></i>自动刷新';
button.classList.remove('btn-primary');
button.classList.add('btn-outline-secondary');
isAutoRefreshing = false;
showNotification('自动刷新已停止', '系统将不再自动更新数据', 'info');
} else {
// 开始自动刷新
autoRefreshInterval = setInterval(updateResourceData, 5000);
button.innerHTML = '<i class="bi bi-pause-circle me-1"></i>停止自动刷新';
button.classList.remove('btn-outline-secondary');
button.classList.add('btn-primary');
isAutoRefreshing = true;
showNotification('自动刷新已启动', '系统将每5秒自动更新数据', 'success');
}
}
// 显示通知
function showNotification(title, message, type) {
// 创建通知元素
const notification = document.createElement('div');
notification.className = `alert alert-${type} alert-dismissible fade show position-fixed`;
notification.style.cssText = 'top: 20px; right: 20px; z-index: 1050; min-width: 300px;';
notification.innerHTML = `
<strong>${title}</strong> ${message}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
`;
document.body.appendChild(notification);
// 3秒后自动移除
setTimeout(() => {
if (notification.parentNode) {
notification.remove();
}
}, 3000);
}
// 初始化
document.addEventListener('DOMContentLoaded', function() {
// 初始化数据
initTimeLabels();
initChartData();
// 初始化图表
initCpuChart();
initMemoryChart();
initFpsChart();
initModelChart();
// 渲染性能表格
renderPerformanceTable();
// 更新资源数据
updateResourceData();
// 绑定事件
document.getElementById('refreshCharts').addEventListener('click', updateResourceData);
document.getElementById('autoRefreshToggle').addEventListener('click', toggleAutoRefresh);
// 显示欢迎消息
setTimeout(() => {
showNotification('监控系统已就绪', '系统监控数据已加载完成', 'success');
}, 1000);
});
</script>
</body>
</html>