First Commit

This commit is contained in:
CN-JS-HuiBai
2026-04-04 15:13:32 +08:00
commit e69424dab2
14 changed files with 3927 additions and 0 deletions

310
public/index.html Normal file
View File

@@ -0,0 +1,310 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="多源Prometheus服务器监控展示大屏 - 实时CPU、内存、磁盘、网络统计">
<title>数据可视化展示大屏</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<!-- Animated Background -->
<div class="bg-grid"></div>
<div class="bg-glow bg-glow-1"></div>
<div class="bg-glow bg-glow-2"></div>
<div class="bg-glow bg-glow-3"></div>
<!-- App Container -->
<div id="app">
<!-- Header -->
<header class="header" id="header">
<div class="header-left">
<div class="logo">
<svg class="logo-icon" viewBox="0 0 32 32" fill="none">
<rect x="2" y="2" width="28" height="28" rx="8" stroke="url(#logoGrad)" stroke-width="2.5"/>
<path d="M8 22 L12 14 L16 18 L20 10 L24 16" stroke="url(#logoGrad)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
<circle cx="12" cy="14" r="2" fill="url(#logoGrad)"/>
<circle cx="20" cy="10" r="2" fill="url(#logoGrad)"/>
<defs>
<linearGradient id="logoGrad" x1="0" y1="0" x2="32" y2="32">
<stop offset="0%" stop-color="#6366f1"/>
<stop offset="100%" stop-color="#06b6d4"/>
</linearGradient>
</defs>
</svg>
<h1 class="logo-text">数据可视化展示大屏</h1>
</div>
<div class="header-meta">
<span class="server-count" id="serverCount">
<span class="dot dot-pulse"></span>
<span id="serverCountText">0 台服务器</span>
</span>
<span class="source-count" id="sourceCount">0 个数据源</span>
</div>
</div>
<div class="header-right">
<div class="clock" id="clock"></div>
<button class="btn-settings" id="btnSettings" title="配置管理">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="3"></circle>
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
</svg>
</button>
</div>
</header>
<!-- Main Dashboard -->
<main class="dashboard" id="dashboard">
<!-- Top Stat Cards -->
<section class="stat-cards">
<div class="stat-card stat-card-servers" id="cardServers">
<div class="stat-card-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<rect x="2" y="2" width="20" height="8" rx="2"/>
<rect x="2" y="14" width="20" height="8" rx="2"/>
<circle cx="6" cy="6" r="1" fill="currentColor"/>
<circle cx="6" cy="18" r="1" fill="currentColor"/>
</svg>
</div>
<div class="stat-card-content">
<span class="stat-card-label">服务器总数</span>
<span class="stat-card-value" id="totalServers">0</span>
</div>
</div>
<div class="stat-card stat-card-cpu" id="cardCpu">
<div class="stat-card-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<rect x="4" y="4" width="16" height="16" rx="2"/>
<rect x="9" y="9" width="6" height="6"/>
<line x1="9" y1="2" x2="9" y2="4"/><line x1="15" y1="2" x2="15" y2="4"/>
<line x1="9" y1="20" x2="9" y2="22"/><line x1="15" y1="20" x2="15" y2="22"/>
<line x1="2" y1="9" x2="4" y2="9"/><line x1="2" y1="15" x2="4" y2="15"/>
<line x1="20" y1="9" x2="22" y2="9"/><line x1="20" y1="15" x2="22" y2="15"/>
</svg>
</div>
<div class="stat-card-content">
<span class="stat-card-label">CPU 使用率</span>
<span class="stat-card-value" id="cpuPercent">0%</span>
<span class="stat-card-sub" id="cpuDetail">0 / 0 核心</span>
</div>
</div>
<div class="stat-card stat-card-mem" id="cardMem">
<div class="stat-card-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<rect x="3" y="3" width="18" height="18" rx="2"/>
<path d="M7 7h4v4H7zM13 7h4v4h-4zM7 13h4v4H7zM13 13h4v4h-4z"/>
</svg>
</div>
<div class="stat-card-content">
<span class="stat-card-label">内存使用率</span>
<span class="stat-card-value" id="memPercent">0%</span>
<span class="stat-card-sub" id="memDetail">0 / 0 GB</span>
</div>
</div>
<div class="stat-card stat-card-disk" id="cardDisk">
<div class="stat-card-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<ellipse cx="12" cy="5" rx="9" ry="3"/>
<path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/>
<path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/>
</svg>
</div>
<div class="stat-card-content">
<span class="stat-card-label">磁盘使用率</span>
<span class="stat-card-value" id="diskPercent">0%</span>
<span class="stat-card-sub" id="diskDetail">0 / 0 GB</span>
</div>
</div>
<div class="stat-card stat-card-bandwidth" id="cardBandwidth">
<div class="stat-card-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M22 12h-4l-3 9L9 3l-3 9H2"/>
</svg>
</div>
<div class="stat-card-content">
<span class="stat-card-label">实时总带宽</span>
<span class="stat-card-value" id="totalBandwidth">0 B/s</span>
<span class="stat-card-sub" id="bandwidthDetail">↓ 0 ↑ 0</span>
</div>
</div>
</section>
<!-- Center Charts -->
<section class="charts-section">
<!-- Network Traffic 24h Chart -->
<div class="chart-card chart-card-wide" id="networkChart">
<div class="chart-card-header">
<h2 class="chart-title">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" class="chart-title-icon">
<polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/>
</svg>
网络流量趋势 (24h)
</h2>
<div class="chart-legend">
<span class="legend-item"><span class="legend-dot legend-rx"></span>接收 (RX)</span>
<span class="legend-item"><span class="legend-dot legend-tx"></span>发送 (TX)</span>
</div>
</div>
<div class="chart-body">
<canvas id="networkCanvas"></canvas>
</div>
<div class="chart-footer">
<div class="traffic-stat">
<span class="traffic-label">24h 接收总量</span>
<span class="traffic-value" id="traffic24hRx">0 B</span>
</div>
<div class="traffic-stat">
<span class="traffic-label">24h 发送总量</span>
<span class="traffic-value" id="traffic24hTx">0 B</span>
</div>
<div class="traffic-stat traffic-stat-total">
<span class="traffic-label">24h 总流量</span>
<span class="traffic-value" id="traffic24hTotal">0 B</span>
</div>
</div>
</div>
<!-- Resource Gauges -->
<div class="chart-card chart-card-gauges" id="gaugesCard">
<div class="chart-card-header">
<h2 class="chart-title">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" class="chart-title-icon">
<path d="M12 20V10M18 20V4M6 20v-4"/>
</svg>
资源使用概览
</h2>
</div>
<div class="gauges-container">
<div class="gauge-wrapper">
<div class="gauge" id="gaugeCpu">
<svg viewBox="0 0 120 120">
<circle class="gauge-bg" cx="60" cy="60" r="52"/>
<circle class="gauge-fill gauge-fill-cpu" cx="60" cy="60" r="52" id="gaugeCpuFill"/>
</svg>
<div class="gauge-center">
<span class="gauge-value" id="gaugeCpuValue">0%</span>
<span class="gauge-label">CPU</span>
</div>
</div>
</div>
<div class="gauge-wrapper">
<div class="gauge" id="gaugeRam">
<svg viewBox="0 0 120 120">
<circle class="gauge-bg" cx="60" cy="60" r="52"/>
<circle class="gauge-fill gauge-fill-ram" cx="60" cy="60" r="52" id="gaugeRamFill"/>
</svg>
<div class="gauge-center">
<span class="gauge-value" id="gaugeRamValue">0%</span>
<span class="gauge-label">RAM</span>
</div>
</div>
</div>
<div class="gauge-wrapper">
<div class="gauge" id="gaugeDisk">
<svg viewBox="0 0 120 120">
<circle class="gauge-bg" cx="60" cy="60" r="52"/>
<circle class="gauge-fill gauge-fill-disk" cx="60" cy="60" r="52" id="gaugeDiskFill"/>
</svg>
<div class="gauge-center">
<span class="gauge-value" id="gaugeDiskValue">0%</span>
<span class="gauge-label">DISK</span>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Server List -->
<section class="server-list-section" id="serverListSection">
<div class="chart-card">
<div class="chart-card-header">
<h2 class="chart-title">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" class="chart-title-icon">
<rect x="2" y="2" width="20" height="8" rx="2"/>
<rect x="2" y="14" width="20" height="8" rx="2"/>
<circle cx="6" cy="6" r="1" fill="currentColor"/>
<circle cx="6" cy="18" r="1" fill="currentColor"/>
</svg>
服务器详情
</h2>
</div>
<div class="server-table-wrap">
<table class="server-table" id="serverTable">
<thead>
<tr>
<th>状态</th>
<th>服务器</th>
<th>数据源</th>
<th>CPU</th>
<th>内存</th>
<th>磁盘</th>
<th>网络 ↓</th>
<th>网络 ↑</th>
</tr>
</thead>
<tbody id="serverTableBody">
<tr class="empty-row">
<td colspan="8">暂无数据 - 请先配置 Prometheus 数据源</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
</main>
<!-- Settings Modal -->
<div class="modal-overlay" id="settingsModal">
<div class="modal">
<div class="modal-header">
<h2>Prometheus 数据源管理</h2>
<button class="modal-close" id="modalClose">&times;</button>
</div>
<div class="modal-body">
<!-- Add Source Form -->
<div class="add-source-form" id="addSourceForm">
<h3>添加数据源</h3>
<div class="form-row">
<div class="form-group">
<label for="sourceName">名称</label>
<input type="text" id="sourceName" placeholder="例:生产环境" autocomplete="off">
</div>
<div class="form-group form-group-wide">
<label for="sourceUrl">Prometheus URL</label>
<input type="url" id="sourceUrl" placeholder="http://prometheus.example.com:9090" autocomplete="off">
</div>
</div>
<div class="form-row">
<div class="form-group form-group-wide">
<label for="sourceDesc">描述 (可选)</label>
<input type="text" id="sourceDesc" placeholder="数据源描述" autocomplete="off">
</div>
<div class="form-actions">
<button class="btn btn-test" id="btnTest">测试连接</button>
<button class="btn btn-add" id="btnAdd">添加</button>
</div>
</div>
<div class="form-message" id="formMessage"></div>
</div>
<!-- Source List -->
<div class="source-list" id="sourceList">
<h3>已配置数据源</h3>
<div class="source-items" id="sourceItems">
<div class="source-empty">暂无数据源</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="/js/utils.js"></script>
<script src="/js/chart.js"></script>
<script src="/js/app.js"></script>
</body>
</html>