Yolov/templates/demo/任务管理.html

1167 lines
38 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>无人机智能分析监控平台</title>
<!-- 引入ECharts -->
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
<!-- 引入ECharts主题 -->
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/extension/dataTool.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Microsoft YaHei', 'Segoe UI', Arial, sans-serif;
}
:root {
--primary-color: #1890ff;
--primary-light: #40a9ff;
--primary-lighter: #69c0ff;
--primary-lightest: #91d5ff;
--bg-color: #f0f8ff;
--text-dark: #1d3557;
--text-medium: #457b9d;
--success-color: #52c41a;
--warning-color: #faad14;
--error-color: #ff4d4f;
--card-bg: #ffffff;
--shadow-color: rgba(24, 144, 255, 0.1);
--border-color: #e6f7ff;
}
body {
background-color: var(--bg-color);
color: var(--text-dark);
min-height: 100vh;
}
/* 顶部导航栏 */
.header {
background: linear-gradient(135deg, var(--primary-color), var(--primary-light));
color: white;
padding: 0 30px;
height: 70px;
display: flex;
align-items: center;
justify-content: space-between;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1000;
}
.logo {
display: flex;
align-items: center;
font-size: 24px;
font-weight: bold;
}
.logo-icon {
font-size: 32px;
margin-right: 12px;
}
.system-status {
display: flex;
align-items: center;
}
.status-indicator {
width: 12px;
height: 12px;
border-radius: 50%;
background-color: var(--success-color);
margin-right: 8px;
box-shadow: 0 0 8px var(--success-color);
}
/* 主体布局 */
.main-container {
display: flex;
margin-top: 70px;
min-height: calc(100vh - 70px);
}
/* 侧边导航栏 */
.sidebar {
width: 220px;
background-color: var(--card-bg);
border-right: 1px solid var(--border-color);
padding: 20px 0;
box-shadow: 2px 0 8px var(--shadow-color);
position: fixed;
top: 70px;
bottom: 0;
left: 0;
z-index: 999;
}
.nav-item {
padding: 16px 30px;
display: flex;
align-items: center;
cursor: pointer;
transition: all 0.3s;
color: var(--text-medium);
border-left: 4px solid transparent;
}
.nav-item:hover {
background-color: var(--primary-lightest);
color: var(--primary-color);
}
.nav-item.active {
background-color: #e6f7ff;
color: var(--primary-color);
border-left-color: var(--primary-color);
font-weight: bold;
}
.nav-icon {
margin-right: 12px;
font-size: 20px;
}
/* 主内容区 */
.content {
flex: 1;
padding: 25px 30px 30px 250px;
min-width: 0;
}
/* 统计卡片 */
.stats-container {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
margin-bottom: 25px;
}
.stat-card {
background: linear-gradient(135deg, var(--primary-color), var(--primary-light));
color: white;
border-radius: 12px;
padding: 20px;
box-shadow: 0 6px 16px var(--shadow-color);
display: flex;
align-items: center;
transition: transform 0.3s, box-shadow 0.3s;
position: relative;
overflow: hidden;
}
.stat-card:hover {
transform: translateY(-5px);
box-shadow: 0 12px 24px rgba(24, 144, 255, 0.3);
}
.stat-card::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 80px;
height: 80px;
background: rgba(255, 255, 255, 0.1);
border-radius: 50%;
transform: translate(20px, -20px);
}
.stat-icon {
font-size: 36px;
margin-right: 20px;
opacity: 0.9;
}
.stat-info {
flex: 1;
}
.stat-title {
font-size: 14px;
opacity: 0.9;
margin-bottom: 5px;
}
.stat-value {
font-size: 28px;
font-weight: bold;
}
.stat-change {
font-size: 12px;
opacity: 0.9;
display: flex;
align-items: center;
margin-top: 5px;
}
/* 图表卡片 */
.chart-container {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
margin-bottom: 25px;
}
.chart-card {
background-color: var(--card-bg);
border-radius: 12px;
padding: 20px;
box-shadow: 0 4px 12px var(--shadow-color);
transition: transform 0.3s;
}
.chart-card:hover {
transform: translateY(-3px);
}
.chart-card.full-width {
grid-column: span 2;
}
.chart-title {
font-size: 18px;
font-weight: bold;
margin-bottom: 20px;
color: var(--text-dark);
display: flex;
align-items: center;
justify-content: space-between;
}
.chart-title-icon {
color: var(--primary-color);
font-size: 20px;
}
.chart-wrapper {
height: 300px;
width: 100%;
}
/* 任务列表 */
.tasks-container {
background-color: var(--card-bg);
border-radius: 12px;
padding: 20px;
box-shadow: 0 4px 12px var(--shadow-color);
margin-bottom: 25px;
}
.table-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.task-table {
width: 100%;
border-collapse: collapse;
}
.task-table th {
text-align: left;
padding: 12px 15px;
border-bottom: 2px solid var(--border-color);
color: var(--text-medium);
font-weight: 600;
}
.task-table td {
padding: 15px;
border-bottom: 1px solid var(--border-color);
}
.task-table tr:hover {
background-color: #f9fdff;
}
/* 状态标签 */
.status-badge {
padding: 4px 12px;
border-radius: 20px;
font-size: 12px;
font-weight: 500;
}
.status-running {
background-color: rgba(82, 196, 26, 0.1);
color: var(--success-color);
}
.status-paused {
background-color: rgba(250, 173, 20, 0.1);
color: var(--warning-color);
}
.status-error {
background-color: rgba(255, 77, 79, 0.1);
color: var(--error-color);
}
.status-stopped {
background-color: rgba(0, 0, 0, 0.05);
color: #666;
}
/* 操作按钮 */
.action-buttons {
display: flex;
gap: 8px;
}
.btn {
padding: 6px 12px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 12px;
font-weight: 500;
transition: all 0.3s;
}
.btn-primary {
background-color: var(--primary-color);
color: white;
}
.btn-primary:hover {
background-color: var(--primary-light);
}
.btn-warning {
background-color: var(--warning-color);
color: white;
}
.btn-warning:hover {
background-color: #ffc53d;
}
.btn-danger {
background-color: var(--error-color);
color: white;
}
.btn-danger:hover {
background-color: #ff7875;
}
/* 资源监控卡片 */
.resource-cards {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
margin-bottom: 25px;
}
.resource-card {
background-color: var(--card-bg);
border-radius: 12px;
padding: 20px;
box-shadow: 0 4px 12px var(--shadow-color);
transition: transform 0.3s;
}
.resource-card:hover {
transform: translateY(-3px);
}
.resource-title {
font-size: 16px;
font-weight: 600;
margin-bottom: 15px;
color: var(--text-dark);
display: flex;
align-items: center;
justify-content: space-between;
}
.resource-value {
font-size: 24px;
font-weight: bold;
margin-bottom: 10px;
}
.progress-bar {
height: 8px;
background-color: #f0f0f0;
border-radius: 4px;
overflow: hidden;
margin-top: 15px;
}
.progress-fill {
height: 100%;
border-radius: 4px;
transition: width 0.5s;
}
.progress-cpu {
background: linear-gradient(90deg, #52c41a, #a0d911);
}
.progress-memory {
background: linear-gradient(90deg, #1890ff, #40a9ff);
}
.progress-gpu {
background: linear-gradient(90deg, #722ed1, #eb2f96);
}
.progress-network {
background: linear-gradient(90deg, #fa8c16, #faad14);
}
/* 响应式设计 */
@media (max-width: 1200px) {
.stats-container, .resource-cards {
grid-template-columns: repeat(2, 1fr);
}
.chart-container {
grid-template-columns: 1fr;
}
.chart-card.full-width {
grid-column: span 1;
}
}
@media (max-width: 768px) {
.sidebar {
width: 60px;
padding: 20px 0;
}
.nav-text {
display: none;
}
.nav-icon {
margin-right: 0;
font-size: 24px;
}
.content {
padding-left: 80px;
}
.stats-container, .resource-cards {
grid-template-columns: 1fr;
}
.chart-card {
padding: 15px;
}
.chart-wrapper {
height: 250px;
}
}
/* 动画效果 */
@keyframes pulse {
0% { opacity: 0.8; }
50% { opacity: 1; }
100% { opacity: 0.8; }
}
.pulse {
animation: pulse 2s infinite;
}
/* 滚动条美化 */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 4px;
}
::-webkit-scrollbar-thumb {
background: var(--primary-light);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--primary-color);
}
</style>
</head>
<body>
<!-- 顶部导航栏 -->
<div class="header">
<div class="logo">
<span class="logo-icon">✈️</span>
<span>无人机智能分析监控平台</span>
</div>
<div class="system-status">
<span class="status-indicator pulse"></span>
<span>系统运行正常 | 最后更新: <span id="last-update">刚刚</span></span>
</div>
</div>
<div class="main-container">
<!-- 侧边导航栏 -->
<div class="sidebar">
<div class="nav-item active">
<span class="nav-icon">📊</span>
<span class="nav-text">监控仪表盘</span>
</div>
<div class="nav-item">
<span class="nav-icon">🚀</span>
<span class="nav-text">任务管理</span>
</div>
<div class="nav-item">
<span class="nav-icon">🧠</span>
<span class="nav-text">算法管理</span>
</div>
<div class="nav-item">
<span class="nav-icon">📈</span>
<span class="nav-text">性能分析</span>
</div>
<div class="nav-item">
<span class="nav-icon">⚙️</span>
<span class="nav-text">系统设置</span>
</div>
</div>
<!-- 主内容区 -->
<div class="content">
<!-- 统计卡片 -->
<div class="stats-container">
<div class="stat-card">
<span class="stat-icon">🚀</span>
<div class="stat-info">
<div class="stat-title">运行任务</div>
<div class="stat-value" id="running-tasks">12</div>
<div class="stat-change">↑ 较昨日增加2个</div>
</div>
</div>
<div class="stat-card">
<span class="stat-icon">🧠</span>
<div class="stat-info">
<div class="stat-title">算法实例</div>
<div class="stat-value" id="algorithm-instances">8</div>
<div class="stat-change">→ 与昨日持平</div>
</div>
</div>
<div class="stat-card">
<span class="stat-icon">✈️</span>
<div class="stat-info">
<div class="stat-title">在线无人机</div>
<div class="stat-value" id="online-drones">5</div>
<div class="stat-change">↑ 1架刚刚上线</div>
</div>
</div>
<div class="stat-card">
<span class="stat-icon">📊</span>
<div class="stat-info">
<div class="stat-title">系统资源占用</div>
<div class="stat-value" id="system-resource">76%</div>
<div class="stat-change">↓ 较昨日降低4%</div>
</div>
</div>
</div>
<!-- 图表区域 -->
<div class="chart-container">
<div class="chart-card">
<div class="chart-title">
<span>任务性能监控</span>
<span class="chart-title-icon">📈</span>
</div>
<div class="chart-wrapper" id="performance-chart"></div>
</div>
<div class="chart-card">
<div class="chart-title">
<span>资源使用情况</span>
<span class="chart-title-icon">💻</span>
</div>
<div class="chart-wrapper" id="resource-chart"></div>
</div>
<div class="chart-card full-width">
<div class="chart-title">
<span>任务状态分布</span>
<span class="chart-title-icon">📊</span>
</div>
<div class="chart-wrapper" id="status-chart"></div>
</div>
</div>
<!-- 资源监控卡片 -->
<div class="resource-cards">
<div class="resource-card">
<div class="resource-title">
<span>CPU使用率</span>
<span>🔧</span>
</div>
<div class="resource-value" id="cpu-usage">68%</div>
<div class="progress-bar">
<div class="progress-fill progress-cpu" id="cpu-progress" style="width: 68%"></div>
</div>
</div>
<div class="resource-card">
<div class="resource-title">
<span>内存使用率</span>
<span>💾</span>
</div>
<div class="resource-value" id="memory-usage">76%</div>
<div class="progress-bar">
<div class="progress-fill progress-memory" id="memory-progress" style="width: 76%"></div>
</div>
</div>
<div class="resource-card">
<div class="resource-title">
<span>GPU使用率</span>
<span>🎮</span>
</div>
<div class="resource-value" id="gpu-usage">82%</div>
<div class="progress-bar">
<div class="progress-fill progress-gpu" id="gpu-progress" style="width: 82%"></div>
</div>
</div>
<div class="resource-card">
<div class="resource-title">
<span>网络带宽</span>
<span>🌐</span>
</div>
<div class="resource-value" id="network-usage">45%</div>
<div class="progress-bar">
<div class="progress-fill progress-network" id="network-progress" style="width: 45%"></div>
</div>
</div>
</div>
<!-- 任务列表 -->
<div class="tasks-container">
<div class="table-header">
<h3>当前运行任务</h3>
<div>
<button class="btn btn-primary" onclick="refreshTasks()">刷新</button>
<button class="btn btn-primary" onclick="createTask()">新建任务</button>
</div>
</div>
<table class="task-table">
<thead>
<tr>
<th>任务ID</th>
<th>任务名称</th>
<th>无人机编号</th>
<th>算法实例</th>
<th>状态</th>
<th>FPS</th>
<th>延迟(ms)</th>
<th>操作</th>
</tr>
</thead>
<tbody id="task-table-body">
<!-- 任务数据将通过JavaScript动态生成 -->
</tbody>
</table>
</div>
</div>
</div>
<script>
// 模拟任务数据
const tasks = [
{ id: 'TASK-001', name: '城市安防巡逻', drone: 'Drone-01', algorithm: 'YOLOv8-安防模型', status: 'running', fps: 24, latency: 120 },
{ id: 'TASK-002', name: '农田监测', drone: 'Drone-02', algorithm: 'YOLOv5-农业模型', status: 'running', fps: 20, latency: 150 },
{ id: 'TASK-003', name: '电力线路巡检', drone: 'Drone-03', algorithm: 'YOLOv7-电力模型', status: 'paused', fps: 0, latency: 0 },
{ id: 'TASK-004', name: '交通流量监控', drone: 'Drone-04', algorithm: 'YOLOv8-交通模型', status: 'running', fps: 30, latency: 90 },
{ id: 'TASK-005', name: '森林防火监测', drone: 'Drone-05', algorithm: 'YOLOv6-火灾模型', status: 'error', fps: 5, latency: 500 },
{ id: 'TASK-006', name: '建筑工地监控', drone: 'Drone-06', algorithm: 'YOLOv5-工地模型', status: 'stopped', fps: 0, latency: 0 },
{ id: 'TASK-007', name: '水域污染检测', drone: 'Drone-01', algorithm: 'YOLOv7-环保模型', status: 'running', fps: 18, latency: 180 },
{ id: 'TASK-008', name: '应急响应侦察', drone: 'Drone-03', algorithm: 'YOLOv8-应急模型', status: 'running', fps: 25, latency: 110 }
];
// 状态映射
const statusMap = {
'running': { text: '运行中', class: 'status-running' },
'paused': { text: '已暂停', class: 'status-paused' },
'error': { text: '错误', class: 'status-error' },
'stopped': { text: '已停止', class: 'status-stopped' }
};
// 初始化函数
function init() {
updateLastUpdateTime();
renderTaskTable();
initPerformanceChart();
initResourceChart();
initStatusChart();
startDataRefresh();
}
// 更新最后更新时间
function updateLastUpdateTime() {
const now = new Date();
const timeString = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`;
document.getElementById('last-update').textContent = timeString;
}
// 渲染任务表格
function renderTaskTable() {
const tableBody = document.getElementById('task-table-body');
tableBody.innerHTML = '';
tasks.forEach(task => {
const statusInfo = statusMap[task.status];
const row = document.createElement('tr');
row.innerHTML = `
<td>${task.id}</td>
<td>${task.name}</td>
<td>${task.drone}</td>
<td>${task.algorithm}</td>
<td><span class="status-badge ${statusInfo.class}">${statusInfo.text}</span></td>
<td>${task.fps}</td>
<td>${task.latency}</td>
<td>
<div class="action-buttons">
${task.status === 'running' ? '<button class="btn btn-warning" onclick="pauseTask(\'' + task.id + '\')">暂停</button>' : ''}
${task.status === 'paused' ? '<button class="btn btn-primary" onclick="resumeTask(\'' + task.id + '\')">恢复</button>' : ''}
${task.status !== 'stopped' ? '<button class="btn btn-danger" onclick="stopTask(\'' + task.id + '\')">停止</button>' : ''}
<button class="btn btn-primary" onclick="restartTask(\'' + task.id + '\')">重启</button>
</div>
</td>
`;
tableBody.appendChild(row);
});
}
// 初始化性能监控图表
function initPerformanceChart() {
const chartDom = document.getElementById('performance-chart');
const chart = echarts.init(chartDom);
// 模拟时间数据
const timeData = [];
const now = new Date();
for (let i = 9; i >= 0; i--) {
const time = new Date(now.getTime() - i * 60000);
timeData.push(`${time.getHours().toString().padStart(2, '0')}:${time.getMinutes().toString().padStart(2, '0')}`);
}
// 模拟FPS和延迟数据
const fpsData = [];
const latencyData = [];
for (let i = 0; i < 10; i++) {
fpsData.push(Math.floor(Math.random() * 10) + 20); // 20-30 FPS
latencyData.push(Math.floor(Math.random() * 100) + 80); // 80-180ms
}
const option = {
color: ['#1890ff', '#52c41a'],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
},
legend: {
data: ['FPS', '延迟(ms)'],
textStyle: {
color: '#1d3557'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
top: '15%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
data: timeData,
axisLine: {
lineStyle: {
color: '#d9d9d9'
}
}
},
yAxis: [
{
type: 'value',
name: 'FPS',
min: 0,
max: 35,
axisLine: {
show: true,
lineStyle: {
color: '#1890ff'
}
}
},
{
type: 'value',
name: '延迟(ms)',
min: 0,
max: 300,
axisLine: {
show: true,
lineStyle: {
color: '#52c41a'
}
}
}
],
series: [
{
name: 'FPS',
type: 'line',
smooth: true,
lineStyle: {
width: 3
},
symbol: 'circle',
symbolSize: 8,
data: fpsData,
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(24, 144, 255, 0.3)' },
{ offset: 1, color: 'rgba(24, 144, 255, 0.05)' }
])
}
},
{
name: '延迟(ms)',
type: 'line',
smooth: true,
yAxisIndex: 1,
lineStyle: {
width: 3
},
symbol: 'circle',
symbolSize: 8,
data: latencyData,
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(82, 196, 26, 0.3)' },
{ offset: 1, color: 'rgba(82, 196, 26, 0.05)' }
])
}
}
]
};
chart.setOption(option);
// 响应式调整
window.addEventListener('resize', function() {
chart.resize();
});
}
// 初始化资源监控图表
function initResourceChart() {
const chartDom = document.getElementById('resource-chart');
const chart = echarts.init(chartDom);
const option = {
color: ['#1890ff', '#52c41a', '#722ed1', '#fa8c16'],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: ['CPU', '内存', 'GPU', '网络'],
textStyle: {
color: '#1d3557'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
top: '15%',
containLabel: true
},
xAxis: {
type: 'category',
data: ['10:00', '10:05', '10:10', '10:15', '10:20', '10:25', '10:30'],
axisLine: {
lineStyle: {
color: '#d9d9d9'
}
}
},
yAxis: {
type: 'value',
name: '使用率(%)',
min: 0,
max: 100,
axisLine: {
lineStyle: {
color: '#d9d9d9'
}
}
},
series: [
{
name: 'CPU',
type: 'bar',
barWidth: '20%',
data: [65, 68, 70, 72, 68, 65, 68]
},
{
name: '内存',
type: 'bar',
barWidth: '20%',
data: [70, 72, 75, 78, 76, 74, 76]
},
{
name: 'GPU',
type: 'bar',
barWidth: '20%',
data: [80, 82, 85, 83, 82, 80, 82]
},
{
name: '网络',
type: 'bar',
barWidth: '20%',
data: [40, 42, 45, 48, 45, 42, 45]
}
]
};
chart.setOption(option);
// 响应式调整
window.addEventListener('resize', function() {
chart.resize();
});
}
// 初始化任务状态分布图表
function initStatusChart() {
const chartDom = document.getElementById('status-chart');
const chart = echarts.init(chartDom);
// 统计任务状态
const statusCount = {
'运行中': 0,
'已暂停': 0,
'错误': 0,
'已停止': 0
};
tasks.forEach(task => {
statusCount[statusMap[task.status].text]++;
});
const option = {
color: ['#52c41a', '#faad14', '#ff4d4f', '#8c8c8c'],
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
legend: {
orient: 'vertical',
right: 10,
top: 'center',
textStyle: {
color: '#1d3557'
},
data: ['运行中', '已暂停', '错误', '已停止']
},
series: [
{
name: '任务状态',
type: 'pie',
radius: ['40%', '70%'],
center: ['35%', '50%'],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 10,
borderColor: '#fff',
borderWidth: 2
},
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: '18',
fontWeight: 'bold'
}
},
labelLine: {
show: false
},
data: [
{ value: statusCount['运行中'], name: '运行中' },
{ value: statusCount['已暂停'], name: '已暂停' },
{ value: statusCount['错误'], name: '错误' },
{ value: statusCount['已停止'], name: '已停止' }
]
}
]
};
chart.setOption(option);
// 响应式调整
window.addEventListener('resize', function() {
chart.resize();
});
}
// 开始数据刷新
function startDataRefresh() {
// 每5秒更新一次数据
setInterval(() => {
updateLastUpdateTime();
updateResourceValues();
updateTaskMetrics();
}, 5000);
}
// 更新资源值
function updateResourceValues() {
// 模拟资源数据变化
const cpu = Math.floor(Math.random() * 20) + 60; // 60-80%
const memory = Math.floor(Math.random() * 15) + 70; // 70-85%
const gpu = Math.floor(Math.random() * 20) + 75; // 75-95%
const network = Math.floor(Math.random() * 30) + 40; // 40-70%
document.getElementById('cpu-usage').textContent = cpu + '%';
document.getElementById('cpu-progress').style.width = cpu + '%';
document.getElementById('memory-usage').textContent = memory + '%';
document.getElementById('memory-progress').style.width = memory + '%';
document.getElementById('gpu-usage').textContent = gpu + '%';
document.getElementById('gpu-progress').style.width = gpu + '%';
document.getElementById('network-usage').textContent = network + '%';
document.getElementById('network-progress').style.width = network + '%';
// 更新系统资源占用
const systemResource = Math.round((cpu + memory + gpu) / 3);
document.getElementById('system-resource').textContent = systemResource + '%';
}
// 更新任务指标
function updateTaskMetrics() {
// 模拟任务数据变化
tasks.forEach(task => {
if (task.status === 'running') {
task.fps = Math.floor(Math.random() * 5) + 20; // 20-25 FPS
task.latency = Math.floor(Math.random() * 50) + 100; // 100-150ms
}
});
// 随机改变一个任务状态(模拟真实环境)
if (Math.random() > 0.7) {
const randomIndex = Math.floor(Math.random() * tasks.length);
const statuses = ['running', 'paused', 'error', 'stopped'];
const currentStatus = tasks[randomIndex].status;
let newStatus;
do {
newStatus = statuses[Math.floor(Math.random() * statuses.length)];
} while (newStatus === currentStatus);
tasks[randomIndex].status = newStatus;
// 如果状态变为运行中设置FPS和延迟
if (newStatus === 'running') {
tasks[randomIndex].fps = Math.floor(Math.random() * 10) + 20;
tasks[randomIndex].latency = Math.floor(Math.random() * 100) + 80;
} else {
tasks[randomIndex].fps = 0;
tasks[randomIndex].latency = 0;
}
renderTaskTable();
initStatusChart(); // 重新渲染状态图表
}
}
// 任务操作函数
function pauseTask(taskId) {
const task = tasks.find(t => t.id === taskId);
if (task) {
task.status = 'paused';
task.fps = 0;
task.latency = 0;
renderTaskTable();
initStatusChart();
alert(`任务 ${taskId} 已暂停`);
}
}
function resumeTask(taskId) {
const task = tasks.find(t => t.id === taskId);
if (task) {
task.status = 'running';
task.fps = Math.floor(Math.random() * 10) + 20;
task.latency = Math.floor(Math.random() * 100) + 80;
renderTaskTable();
initStatusChart();
alert(`任务 ${taskId} 已恢复`);
}
}
function stopTask(taskId) {
const task = tasks.find(t => t.id === taskId);
if (task) {
task.status = 'stopped';
task.fps = 0;
task.latency = 0;
renderTaskTable();
initStatusChart();
alert(`任务 ${taskId} 已停止`);
}
}
function restartTask(taskId) {
const task = tasks.find(t => t.id === taskId);
if (task) {
task.status = 'running';
task.fps = Math.floor(Math.random() * 10) + 20;
task.latency = Math.floor(Math.random() * 100) + 80;
renderTaskTable();
initStatusChart();
alert(`任务 ${taskId} 正在重启...`);
}
}
function refreshTasks() {
// 模拟刷新任务数据
updateTaskMetrics();
alert('任务列表已刷新');
}
function createTask() {
alert('打开新建任务对话框...');
// 这里实际开发中会打开一个模态框来创建新任务
}
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', init);
</script>
</body>
</html>