添加更详细的信息查询
This commit is contained in:
@@ -60,7 +60,23 @@
|
||||
loginForm: document.getElementById('loginForm'),
|
||||
loginError: document.getElementById('loginError'),
|
||||
footerTime: document.getElementById('footerTime'),
|
||||
legendP95: document.getElementById('legendP95')
|
||||
legendP95: document.getElementById('legendP95'),
|
||||
// Server Details Modal
|
||||
serverDetailModal: document.getElementById('serverDetailModal'),
|
||||
serverDetailClose: document.getElementById('serverDetailClose'),
|
||||
serverDetailTitle: document.getElementById('serverDetailTitle'),
|
||||
detailGrid: document.getElementById('detailGrid'),
|
||||
detailLoading: document.getElementById('detailLoading'),
|
||||
detailCpuBusy: document.getElementById('detailCpuBusy'),
|
||||
detailSysLoad: document.getElementById('detailSysLoad'),
|
||||
detailMemUsedPct: document.getElementById('detailMemUsedPct'),
|
||||
detailSwapUsedPct: document.getElementById('detailSwapUsedPct'),
|
||||
detailRootFsUsedPct: document.getElementById('detailRootFsUsedPct'),
|
||||
detailCpuCores: document.getElementById('detailCpuCores'),
|
||||
detailMemTotal: document.getElementById('detailMemTotal'),
|
||||
detailUptime: document.getElementById('detailUptime'),
|
||||
detailNetRx: document.getElementById('detailNetRx'),
|
||||
detailNetTx: document.getElementById('detailNetTx')
|
||||
};
|
||||
|
||||
// ---- State ----
|
||||
@@ -113,6 +129,26 @@
|
||||
if (e.key === 'Escape') {
|
||||
closeSettings();
|
||||
closeLoginModal();
|
||||
closeServerDetail();
|
||||
}
|
||||
});
|
||||
|
||||
// Server detail modal listeners
|
||||
dom.serverDetailClose.addEventListener('click', closeServerDetail);
|
||||
dom.serverDetailModal.addEventListener('click', (e) => {
|
||||
if (e.target === dom.serverDetailModal) closeServerDetail();
|
||||
});
|
||||
|
||||
// Server table row click delegator
|
||||
dom.serverTableBody.addEventListener('click', (e) => {
|
||||
const row = e.target.closest('tr');
|
||||
if (row && !row.classList.contains('empty-row')) {
|
||||
const instance = row.getAttribute('data-instance');
|
||||
const job = row.getAttribute('data-job');
|
||||
const source = row.getAttribute('data-source');
|
||||
if (instance && job && source) {
|
||||
openServerDetail(instance, job, source);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -354,7 +390,7 @@
|
||||
const diskPct = server.diskTotal > 0 ? (server.diskUsed / server.diskTotal * 100) : 0;
|
||||
|
||||
return `
|
||||
<tr>
|
||||
<tr data-instance="${escapeHtml(server.instance)}" data-job="${escapeHtml(server.job)}" data-source="${escapeHtml(server.source)}" style="cursor: pointer;">
|
||||
<td>
|
||||
<span class="status-dot ${server.up ? 'status-dot-online' : 'status-dot-offline'}"></span>
|
||||
</td>
|
||||
@@ -393,6 +429,54 @@
|
||||
}).join('');
|
||||
}
|
||||
|
||||
// ---- Server Detail ----
|
||||
async function openServerDetail(instance, job, source) {
|
||||
dom.serverDetailTitle.textContent = `${job} - 服务器详情`;
|
||||
dom.serverDetailModal.classList.add('active');
|
||||
|
||||
// Show loading
|
||||
dom.detailGrid.style.opacity = '0.3';
|
||||
dom.detailLoading.style.display = 'block';
|
||||
|
||||
try {
|
||||
const url = `/api/metrics/server-details?instance=${encodeURIComponent(instance)}&job=${encodeURIComponent(job)}&source=${encodeURIComponent(source)}`;
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) throw new Error('Fetch failed');
|
||||
const data = await response.json();
|
||||
|
||||
renderServerDetail(data);
|
||||
} catch (err) {
|
||||
console.error('Error fetching server details:', err);
|
||||
} finally {
|
||||
dom.detailGrid.style.opacity = '1';
|
||||
dom.detailLoading.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function closeServerDetail() {
|
||||
dom.serverDetailModal.classList.remove('active');
|
||||
}
|
||||
|
||||
function renderServerDetail(data) {
|
||||
dom.detailCpuBusy.textContent = formatPercent(data.cpuBusy);
|
||||
dom.detailSysLoad.textContent = data.sysLoad.toFixed(1) + '%';
|
||||
dom.detailMemUsedPct.textContent = formatPercent(data.memUsedPct);
|
||||
dom.detailSwapUsedPct.textContent = formatPercent(data.swapUsedPct);
|
||||
dom.detailRootFsUsedPct.textContent = formatPercent(data.rootFsUsedPct);
|
||||
dom.detailCpuCores.textContent = data.cpuCores + ' 核心';
|
||||
dom.detailMemTotal.textContent = formatBytes(data.memTotal);
|
||||
|
||||
// Uptime formatting
|
||||
const uptimeSec = data.uptime;
|
||||
const days = Math.floor(uptimeSec / 86400);
|
||||
const hours = Math.floor((uptimeSec % 86400) / 3600);
|
||||
const mins = Math.floor((uptimeSec % 3600) / 60);
|
||||
dom.detailUptime.textContent = `${days}天 ${hours}小时 ${mins}分`;
|
||||
|
||||
dom.detailNetRx.textContent = formatBandwidth(data.netRx);
|
||||
dom.detailNetTx.textContent = formatBandwidth(data.netTx);
|
||||
}
|
||||
|
||||
// ---- Network History ----
|
||||
async function fetchNetworkHistory() {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user