修改web服务器指标卡片
This commit is contained in:
@@ -203,6 +203,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<p class="text-sm text-gray-500 font-medium mb-1">CPU 使用率</p>
|
<p class="text-sm text-gray-500 font-medium mb-1">CPU 使用率</p>
|
||||||
<h3 id="cpuValue" class="text-3xl font-bold text-gray-900 metric-value">0.0%</h3>
|
<h3 id="cpuValue" class="text-3xl font-bold text-gray-900 metric-value">0.0%</h3>
|
||||||
|
<p id="cpuDetails" class="text-xs text-gray-500 mt-1">0.00 GHz | 负载: 0.00</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-blue-100 p-3 rounded-full">
|
<div class="bg-blue-100 p-3 rounded-full">
|
||||||
<i class="fa fa-microchip text-blue-600 text-xl"></i>
|
<i class="fa fa-microchip text-blue-600 text-xl"></i>
|
||||||
@@ -216,6 +217,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<p class="text-sm text-gray-500 font-medium mb-1">内存使用率</p>
|
<p class="text-sm text-gray-500 font-medium mb-1">内存使用率</p>
|
||||||
<h3 id="memoryValue" class="text-3xl font-bold text-gray-900 metric-value">0.0%</h3>
|
<h3 id="memoryValue" class="text-3xl font-bold text-gray-900 metric-value">0.0%</h3>
|
||||||
|
<p id="memoryDetails" class="text-xs text-gray-500 mt-1">0 MB / 0 MB</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-green-100 p-3 rounded-full">
|
<div class="bg-green-100 p-3 rounded-full">
|
||||||
<i class="fa fa-memory text-green-600 text-xl"></i>
|
<i class="fa fa-memory text-green-600 text-xl"></i>
|
||||||
@@ -229,6 +231,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<p class="text-sm text-gray-500 font-medium mb-1">磁盘使用率</p>
|
<p class="text-sm text-gray-500 font-medium mb-1">磁盘使用率</p>
|
||||||
<h3 id="diskValue" class="text-3xl font-bold text-gray-900 metric-value">0.0%</h3>
|
<h3 id="diskValue" class="text-3xl font-bold text-gray-900 metric-value">0.0%</h3>
|
||||||
|
<p id="diskDetails" class="text-xs text-gray-500 mt-1">0 MB / 0 MB</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-yellow-100 p-3 rounded-full">
|
<div class="bg-yellow-100 p-3 rounded-full">
|
||||||
<i class="fa fa-hdd text-yellow-600 text-xl"></i>
|
<i class="fa fa-hdd text-yellow-600 text-xl"></i>
|
||||||
@@ -241,7 +244,8 @@
|
|||||||
<div class="flex justify-between items-start">
|
<div class="flex justify-between items-start">
|
||||||
<div>
|
<div>
|
||||||
<p class="text-sm text-gray-500 font-medium mb-1">网络流量</p>
|
<p class="text-sm text-gray-500 font-medium mb-1">网络流量</p>
|
||||||
<h3 id="networkValue" class="text-3xl font-bold text-gray-900 metric-value">0.0 MB/s</h3>
|
<h3 id="networkValue" class="text-3xl font-bold text-gray-900 metric-value">0.0</h3>
|
||||||
|
<p id="networkDetails" class="text-xs text-gray-500 mt-1">接收: 0 MB/s | 发送: 0 MB/s<br>总量: 接收 0 MB | 发送 0 MB</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-purple-100 p-3 rounded-full">
|
<div class="bg-purple-100 p-3 rounded-full">
|
||||||
<i class="fa fa-exchange-alt text-purple-600 text-xl"></i>
|
<i class="fa fa-exchange-alt text-purple-600 text-xl"></i>
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ let state = {
|
|||||||
currentTimeRange: '1h', // 与UI默认值保持一致
|
currentTimeRange: '1h', // 与UI默认值保持一致
|
||||||
customStartTime: '',
|
customStartTime: '',
|
||||||
customEndTime: '',
|
customEndTime: '',
|
||||||
currentInterval: '10m' // 固定10分钟区间
|
currentInterval: '10m', // 固定10分钟区间
|
||||||
|
historyMetrics: {} // 存储历史指标数据
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebSocket连接
|
// WebSocket连接
|
||||||
@@ -1200,133 +1201,196 @@ function handleMetricsUpdate(message) {
|
|||||||
|
|
||||||
// 更新状态卡片
|
// 更新状态卡片
|
||||||
function updateStatusCards(metrics) {
|
function updateStatusCards(metrics) {
|
||||||
|
// 更新历史指标数据
|
||||||
|
updateHistoryMetrics(metrics);
|
||||||
|
|
||||||
|
// 使用历史数据或当前数据
|
||||||
|
const displayMetrics = {
|
||||||
|
cpu: metrics.cpu || state.historyMetrics.cpu,
|
||||||
|
memory: metrics.memory || state.historyMetrics.memory,
|
||||||
|
disk: metrics.disk || state.historyMetrics.disk,
|
||||||
|
network: metrics.network || state.historyMetrics.network
|
||||||
|
};
|
||||||
|
|
||||||
// 更新CPU状态卡片
|
// 更新CPU状态卡片
|
||||||
if (metrics.cpu) {
|
if (displayMetrics.cpu) {
|
||||||
if (Array.isArray(metrics.cpu) && metrics.cpu.length > 0) {
|
let cpuUsage = 0;
|
||||||
const latestCPU = metrics.cpu[metrics.cpu.length - 1].value;
|
let cpuGhz = 0;
|
||||||
const cpuElement = document.getElementById('cpuValue');
|
let cpuLoad = 0;
|
||||||
if (cpuElement) {
|
|
||||||
cpuElement.textContent = `${latestCPU.toFixed(1)}%`;
|
// 解析CPU数据
|
||||||
|
if (Array.isArray(displayMetrics.cpu) && displayMetrics.cpu.length > 0) {
|
||||||
|
cpuUsage = displayMetrics.cpu[displayMetrics.cpu.length - 1].value;
|
||||||
|
} else if (typeof displayMetrics.cpu === 'number') {
|
||||||
|
cpuUsage = displayMetrics.cpu;
|
||||||
|
} else if (typeof displayMetrics.cpu === 'object' && displayMetrics.cpu.usage) {
|
||||||
|
cpuUsage = displayMetrics.cpu.usage;
|
||||||
|
cpuGhz = displayMetrics.cpu.frequency || 0;
|
||||||
|
cpuLoad = displayMetrics.cpu.load || 0;
|
||||||
}
|
}
|
||||||
} else if (typeof metrics.cpu === 'number') {
|
|
||||||
|
// 更新显示
|
||||||
const cpuElement = document.getElementById('cpuValue');
|
const cpuElement = document.getElementById('cpuValue');
|
||||||
|
const cpuDetailsElement = document.getElementById('cpuDetails');
|
||||||
if (cpuElement) {
|
if (cpuElement) {
|
||||||
cpuElement.textContent = `${metrics.cpu.toFixed(1)}%`;
|
cpuElement.textContent = `${cpuUsage.toFixed(1)}%`;
|
||||||
|
// 设置红色显示如果达到顶峰
|
||||||
|
cpuElement.className = cpuUsage > 90 ? 'text-red-500' : '';
|
||||||
}
|
}
|
||||||
|
if (cpuDetailsElement) {
|
||||||
|
cpuDetailsElement.textContent = `${cpuGhz.toFixed(2)} GHz | 负载: ${cpuLoad.toFixed(2)}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新内存状态卡片
|
// 更新内存状态卡片
|
||||||
if (metrics.memory) {
|
if (displayMetrics.memory) {
|
||||||
if (Array.isArray(metrics.memory) && metrics.memory.length > 0) {
|
let memoryUsage = 0;
|
||||||
const latestMemory = metrics.memory[metrics.memory.length - 1].value;
|
let memoryUsed = 0;
|
||||||
const memoryElement = document.getElementById('memoryValue');
|
let memoryTotal = 0;
|
||||||
if (memoryElement) {
|
|
||||||
memoryElement.textContent = `${latestMemory.toFixed(1)}%`;
|
// 解析内存数据
|
||||||
|
if (Array.isArray(displayMetrics.memory) && displayMetrics.memory.length > 0) {
|
||||||
|
memoryUsage = displayMetrics.memory[displayMetrics.memory.length - 1].value;
|
||||||
|
} else if (typeof displayMetrics.memory === 'number') {
|
||||||
|
memoryUsage = displayMetrics.memory;
|
||||||
|
} else if (typeof displayMetrics.memory === 'object') {
|
||||||
|
memoryUsage = displayMetrics.memory.usage || 0;
|
||||||
|
memoryUsed = displayMetrics.memory.used || 0;
|
||||||
|
memoryTotal = displayMetrics.memory.total || 0;
|
||||||
}
|
}
|
||||||
} else if (typeof metrics.memory === 'number') {
|
|
||||||
|
// 更新显示
|
||||||
const memoryElement = document.getElementById('memoryValue');
|
const memoryElement = document.getElementById('memoryValue');
|
||||||
|
const memoryDetailsElement = document.getElementById('memoryDetails');
|
||||||
if (memoryElement) {
|
if (memoryElement) {
|
||||||
memoryElement.textContent = `${metrics.memory.toFixed(1)}%`;
|
memoryElement.textContent = `${memoryUsage.toFixed(1)}%`;
|
||||||
|
// 设置红色显示如果达到顶峰
|
||||||
|
memoryElement.className = memoryUsage > 90 ? 'text-red-500' : '';
|
||||||
}
|
}
|
||||||
|
if (memoryDetailsElement) {
|
||||||
|
memoryDetailsElement.textContent = `${formatBytes(memoryUsed)} / ${formatBytes(memoryTotal)}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新磁盘状态卡片
|
// 更新磁盘状态卡片
|
||||||
if (metrics.disk) {
|
if (displayMetrics.disk) {
|
||||||
|
let totalUsed = 0;
|
||||||
|
let totalSize = 0;
|
||||||
|
let usagePercent = 0;
|
||||||
|
|
||||||
|
// 过滤掉不需要的挂载点
|
||||||
|
const excludedMountpoints = ['/usr', '/boot', '/boot/efi'];
|
||||||
|
|
||||||
|
// 解析磁盘数据
|
||||||
|
if (typeof displayMetrics.disk === 'object' && displayMetrics.disk !== null && !Array.isArray(displayMetrics.disk)) {
|
||||||
|
// 按挂载点分组的数据
|
||||||
|
for (const mountpoint in displayMetrics.disk) {
|
||||||
|
// 跳过排除的挂载点
|
||||||
|
if (excludedMountpoints.includes(mountpoint)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = displayMetrics.disk[mountpoint];
|
||||||
|
if (data && typeof data === 'object' && data.used !== undefined && data.total !== undefined) {
|
||||||
|
totalUsed += data.used;
|
||||||
|
totalSize += data.total;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (typeof displayMetrics.disk === 'object' && displayMetrics.disk.used !== undefined && displayMetrics.disk.total !== undefined) {
|
||||||
|
// 单磁盘数据
|
||||||
|
totalUsed = displayMetrics.disk.used;
|
||||||
|
totalSize = displayMetrics.disk.total;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算使用率
|
||||||
|
if (totalSize > 0) {
|
||||||
|
usagePercent = (totalUsed / totalSize) * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新显示
|
||||||
const diskElement = document.getElementById('diskValue');
|
const diskElement = document.getElementById('diskValue');
|
||||||
|
const diskDetailsElement = document.getElementById('diskDetails');
|
||||||
if (diskElement) {
|
if (diskElement) {
|
||||||
if (typeof metrics.disk === 'object' && metrics.disk !== null && !Array.isArray(metrics.disk)) {
|
diskElement.textContent = `${usagePercent.toFixed(1)}%`;
|
||||||
// 计算所有挂载点的平均使用率
|
// 设置红色显示如果达到顶峰
|
||||||
let totalUsage = 0;
|
diskElement.className = usagePercent > 90 ? 'text-red-500' : '';
|
||||||
let mountpointCount = 0;
|
|
||||||
|
|
||||||
for (const mountpoint in metrics.disk) {
|
|
||||||
const data = metrics.disk[mountpoint];
|
|
||||||
if (data && Array.isArray(data) && data.length > 0) {
|
|
||||||
const latestValue = data[data.length - 1].value;
|
|
||||||
totalUsage += latestValue;
|
|
||||||
mountpointCount++;
|
|
||||||
} else if (typeof data === 'number') {
|
|
||||||
totalUsage += data;
|
|
||||||
mountpointCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mountpointCount > 0) {
|
|
||||||
const averageUsage = totalUsage / mountpointCount;
|
|
||||||
diskElement.textContent = `${averageUsage.toFixed(1)}%`;
|
|
||||||
}
|
|
||||||
} else if (Array.isArray(metrics.disk) && metrics.disk.length > 0) {
|
|
||||||
const latestDisk = metrics.disk[metrics.disk.length - 1].value;
|
|
||||||
diskElement.textContent = `${latestDisk.toFixed(1)}%`;
|
|
||||||
} else if (typeof metrics.disk === 'number') {
|
|
||||||
diskElement.textContent = `${metrics.disk.toFixed(1)}%`;
|
|
||||||
}
|
}
|
||||||
|
if (diskDetailsElement) {
|
||||||
|
diskDetailsElement.textContent = `${formatBytes(totalUsed)} / ${formatBytes(totalSize)}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新网络状态卡片
|
// 更新网络状态卡片
|
||||||
if (metrics.network) {
|
if (displayMetrics.network) {
|
||||||
const networkValueElement = document.getElementById('networkValue');
|
let sentRate = 0;
|
||||||
const networkSentElement = document.getElementById('networkSent');
|
let receivedRate = 0;
|
||||||
const networkReceivedElement = document.getElementById('networkReceived');
|
let sentTotal = 0;
|
||||||
|
let receivedTotal = 0;
|
||||||
|
|
||||||
// 处理不同格式的网络数据
|
// 解析网络数据
|
||||||
if (metrics.network.sent && metrics.network.received) {
|
if (displayMetrics.network.sent && displayMetrics.network.received) {
|
||||||
// 处理数组格式的数据
|
// 处理数组格式的数据
|
||||||
if (Array.isArray(metrics.network.sent) && metrics.network.sent.length > 0 &&
|
if (Array.isArray(displayMetrics.network.sent) && displayMetrics.network.sent.length > 0 &&
|
||||||
Array.isArray(metrics.network.received) && metrics.network.received.length > 0) {
|
Array.isArray(displayMetrics.network.received) && displayMetrics.network.received.length > 0) {
|
||||||
|
|
||||||
const latestSent = metrics.network.sent[metrics.network.sent.length - 1].value;
|
sentRate = displayMetrics.network.sent[displayMetrics.network.sent.length - 1].value;
|
||||||
const latestReceived = metrics.network.received[metrics.network.received.length - 1].value;
|
receivedRate = displayMetrics.network.received[displayMetrics.network.received.length - 1].value;
|
||||||
|
// 计算总量(假设数组中的值是累积的)
|
||||||
if (networkValueElement) {
|
sentTotal = displayMetrics.network.sent.reduce((sum, item) => sum + item.value, 0);
|
||||||
// 显示较大的值
|
receivedTotal = displayMetrics.network.received.reduce((sum, item) => sum + item.value, 0);
|
||||||
const maxValue = Math.max(latestSent, latestReceived);
|
|
||||||
networkValueElement.textContent = formatBytes(maxValue, 2, true); // 显示速率
|
|
||||||
}
|
|
||||||
|
|
||||||
if (networkSentElement) {
|
|
||||||
networkSentElement.textContent = formatBytes(latestSent, 2, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (networkReceivedElement) {
|
|
||||||
networkReceivedElement.textContent = formatBytes(latestReceived, 2, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// 处理数值格式的数据
|
// 处理数值格式的数据
|
||||||
else if (typeof metrics.network.sent === 'number' && typeof metrics.network.received === 'number') {
|
else if (typeof displayMetrics.network.sent === 'number' && typeof displayMetrics.network.received === 'number') {
|
||||||
if (networkValueElement) {
|
sentRate = displayMetrics.network.sent;
|
||||||
const maxValue = Math.max(metrics.network.sent, metrics.network.received);
|
receivedRate = displayMetrics.network.received;
|
||||||
networkValueElement.textContent = formatBytes(maxValue, 2, true);
|
sentTotal = displayMetrics.network.sent_total || sentRate;
|
||||||
|
receivedTotal = displayMetrics.network.received_total || receivedRate;
|
||||||
}
|
}
|
||||||
|
} else if (typeof displayMetrics.network === 'object' &&
|
||||||
if (networkSentElement) {
|
displayMetrics.network.bytes_sent !== undefined &&
|
||||||
networkSentElement.textContent = formatBytes(metrics.network.sent, 2, true);
|
displayMetrics.network.bytes_received !== undefined) {
|
||||||
}
|
|
||||||
|
|
||||||
if (networkReceivedElement) {
|
|
||||||
networkReceivedElement.textContent = formatBytes(metrics.network.received, 2, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (typeof metrics.network === 'object' &&
|
|
||||||
metrics.network.bytes_sent !== undefined &&
|
|
||||||
metrics.network.bytes_received !== undefined) {
|
|
||||||
// WebSocket消息格式
|
// WebSocket消息格式
|
||||||
|
sentRate = displayMetrics.network.bytes_sent;
|
||||||
|
receivedRate = displayMetrics.network.bytes_received;
|
||||||
|
sentTotal = displayMetrics.network.bytes_sent_total || sentRate;
|
||||||
|
receivedTotal = displayMetrics.network.bytes_received_total || receivedRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算比率
|
||||||
|
let ratioText = '0.0';
|
||||||
|
if (sentRate > 0) {
|
||||||
|
ratioText = (receivedRate / sentRate).toFixed(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新显示
|
||||||
|
const networkValueElement = document.getElementById('networkValue');
|
||||||
|
const networkDetailsElement = document.getElementById('networkDetails');
|
||||||
if (networkValueElement) {
|
if (networkValueElement) {
|
||||||
const maxValue = Math.max(metrics.network.bytes_sent, metrics.network.bytes_received);
|
networkValueElement.innerHTML = `${ratioText} <span style="color: green;">↓</span> / <span style="color: red;">↑</span>`;
|
||||||
networkValueElement.textContent = formatBytes(maxValue, 2, true);
|
|
||||||
}
|
}
|
||||||
|
if (networkDetailsElement) {
|
||||||
|
networkDetailsElement.innerHTML =
|
||||||
|
`接收: <span style="color: green;">${formatBytes(receivedRate, 2, true)}</span> | ` +
|
||||||
|
`发送: <span style="color: red;">${formatBytes(sentRate, 2, true)}</span><br>` +
|
||||||
|
`总量: 接收 ${formatBytes(receivedTotal)} | 发送 ${formatBytes(sentTotal)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (networkSentElement) {
|
// 更新历史指标数据
|
||||||
networkSentElement.textContent = formatBytes(metrics.network.bytes_sent, 2, true);
|
function updateHistoryMetrics(metrics) {
|
||||||
|
// 只更新有有效数据的指标
|
||||||
|
if (metrics.cpu) {
|
||||||
|
state.historyMetrics.cpu = metrics.cpu;
|
||||||
}
|
}
|
||||||
|
if (metrics.memory) {
|
||||||
if (networkReceivedElement) {
|
state.historyMetrics.memory = metrics.memory;
|
||||||
networkReceivedElement.textContent = formatBytes(metrics.network.bytes_received, 2, true);
|
|
||||||
}
|
}
|
||||||
|
if (metrics.disk) {
|
||||||
|
state.historyMetrics.disk = metrics.disk;
|
||||||
}
|
}
|
||||||
|
if (metrics.network) {
|
||||||
|
state.historyMetrics.network = metrics.network;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user