From 80db7a482a820438440086040474be2a6e04d283 Mon Sep 17 00:00:00 2001 From: kory Date: Mon, 28 Sep 2026 09:42:46 +0800 Subject: [PATCH] fix(web): exclude local hub from device list and align 6-grid profile metrics --- internal/web/static/app.css | 15 +++++++-------- internal/web/static/app.js | 21 +++++++++++---------- web/static/app.css | 15 +++++++-------- web/static/app.js | 21 +++++++++++---------- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/internal/web/static/app.css b/internal/web/static/app.css index 1489c95..577876a 100644 --- a/internal/web/static/app.css +++ b/internal/web/static/app.css @@ -31,11 +31,10 @@ header strong{font-size:18px}header span{margin-left:12px;color:var(--text-muted .device-meta{font-size:12px;color:var(--text-muted);display:flex;align-items:center;gap:6px;flex-wrap:wrap} /* 资源画像 2列紧凑栅格 */ -.profile-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;padding:10px;background:var(--bg-card);border:1px solid var(--border);border-radius:8px;font-size:12px} -.p-item{display:flex;justify-content:space-between;align-items:center;gap:6px} -.p-label{color:var(--text-muted)} -.p-val{font-family:ui-monospace,monospace;font-weight:600;color:var(--text-main)} -.p-docker{grid-column:1/-1;display:flex;justify-content:flex-end} -.badge-docker{font-size:11px;padding:2px 8px;border-radius:4px;font-weight:600} -.badge-docker.yes{background:rgba(34,197,94,.15);color:var(--dot-online);border:1px solid rgba(34,197,94,.3)} -.badge-docker.no{background:rgba(148,163,184,.15);color:var(--text-muted);border:1px solid var(--border)} +.profile-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px 12px;padding:10px 12px;background:var(--bg-card);border:1px solid var(--border);border-radius:8px;font-size:12px} +.p-item{display:flex;justify-content:space-between;align-items:center;gap:6px;min-height:20px} +.p-label{color:var(--text-muted);font-weight:500} +.p-val{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-weight:600;color:var(--text-main);white-space:nowrap} +.badge-docker-text{padding:1px 6px;border-radius:4px;font-size:11px;font-weight:700} +.badge-docker-text.yes{background:rgba(34,197,94,.15);color:var(--dot-online);border:1px solid rgba(34,197,94,.3)} +.badge-docker-text.no{background:rgba(148,163,184,.15);color:var(--text-muted);border:1px solid var(--border)} diff --git a/internal/web/static/app.js b/internal/web/static/app.js index 9e55cc8..76ed1ba 100644 --- a/internal/web/static/app.js +++ b/internal/web/static/app.js @@ -32,17 +32,19 @@ async function removeDevice(name){ } async function loadDevices(){ - let ds=await api("/devices"); + let all=await api("/devices"); + let ds=all.filter(d=>!d.is_local); $("#devices").innerHTML=ds.map(d=>{ const p = d.profile || {}; - const role = p.role || (d.is_local ? "CONTROL" : "APPLICATION"); + const role = p.role || "APPLICATION"; const isOnline = d.status === "online"; const cpuStr = p.cpu_cores ? `${p.cpu_cores}C · ${p.cpu_usage_percent ?? 0}%` : '-'; const memStr = p.mem_percent !== undefined ? `${p.mem_percent}%` + (p.mem_available ? ` (${p.mem_available})` : '') : '-'; - const swapStr = p.swap_percent !== undefined ? `${p.swap_percent}%` : '-'; + const swapStr = (p.swap_percent !== undefined && p.swap_percent !== null) ? `${p.swap_percent}%` : '-'; const diskStr = p.disk_percent !== undefined ? `${p.disk_percent}%` : '-'; const psiStr = p.io_psi !== undefined ? p.io_psi.toFixed(2) : '-'; - const dockerBadge = p.docker ? 'Docker YES' : 'Docker NO'; + const dockerVal = p.docker ? 'YES' : 'NO'; + const dockerClass = p.docker ? 'yes' : 'no'; return `
@@ -52,20 +54,19 @@ async function loadDevices(){ ${esc(d.name)} ${esc(role)}
- ${d.is_local ? '' : ``} +
${esc(d.status)} · - ${d.is_local ? "local" : "remote"} · ${esc(d.arch||"")}/${esc(d.os||"")}
CPU${cpuStr}
-
Mem${memStr}
-
Swap${swapStr}
-
Disk${diskStr}
+
MEM${memStr}
+
DISK${diskStr}
+
SWAP${swapStr}
IO PSI${psiStr}
-
${dockerBadge}
+
DOCKER${dockerVal}
`; diff --git a/web/static/app.css b/web/static/app.css index 1489c95..577876a 100644 --- a/web/static/app.css +++ b/web/static/app.css @@ -31,11 +31,10 @@ header strong{font-size:18px}header span{margin-left:12px;color:var(--text-muted .device-meta{font-size:12px;color:var(--text-muted);display:flex;align-items:center;gap:6px;flex-wrap:wrap} /* 资源画像 2列紧凑栅格 */ -.profile-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;padding:10px;background:var(--bg-card);border:1px solid var(--border);border-radius:8px;font-size:12px} -.p-item{display:flex;justify-content:space-between;align-items:center;gap:6px} -.p-label{color:var(--text-muted)} -.p-val{font-family:ui-monospace,monospace;font-weight:600;color:var(--text-main)} -.p-docker{grid-column:1/-1;display:flex;justify-content:flex-end} -.badge-docker{font-size:11px;padding:2px 8px;border-radius:4px;font-weight:600} -.badge-docker.yes{background:rgba(34,197,94,.15);color:var(--dot-online);border:1px solid rgba(34,197,94,.3)} -.badge-docker.no{background:rgba(148,163,184,.15);color:var(--text-muted);border:1px solid var(--border)} +.profile-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px 12px;padding:10px 12px;background:var(--bg-card);border:1px solid var(--border);border-radius:8px;font-size:12px} +.p-item{display:flex;justify-content:space-between;align-items:center;gap:6px;min-height:20px} +.p-label{color:var(--text-muted);font-weight:500} +.p-val{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-weight:600;color:var(--text-main);white-space:nowrap} +.badge-docker-text{padding:1px 6px;border-radius:4px;font-size:11px;font-weight:700} +.badge-docker-text.yes{background:rgba(34,197,94,.15);color:var(--dot-online);border:1px solid rgba(34,197,94,.3)} +.badge-docker-text.no{background:rgba(148,163,184,.15);color:var(--text-muted);border:1px solid var(--border)} diff --git a/web/static/app.js b/web/static/app.js index 9e55cc8..76ed1ba 100644 --- a/web/static/app.js +++ b/web/static/app.js @@ -32,17 +32,19 @@ async function removeDevice(name){ } async function loadDevices(){ - let ds=await api("/devices"); + let all=await api("/devices"); + let ds=all.filter(d=>!d.is_local); $("#devices").innerHTML=ds.map(d=>{ const p = d.profile || {}; - const role = p.role || (d.is_local ? "CONTROL" : "APPLICATION"); + const role = p.role || "APPLICATION"; const isOnline = d.status === "online"; const cpuStr = p.cpu_cores ? `${p.cpu_cores}C · ${p.cpu_usage_percent ?? 0}%` : '-'; const memStr = p.mem_percent !== undefined ? `${p.mem_percent}%` + (p.mem_available ? ` (${p.mem_available})` : '') : '-'; - const swapStr = p.swap_percent !== undefined ? `${p.swap_percent}%` : '-'; + const swapStr = (p.swap_percent !== undefined && p.swap_percent !== null) ? `${p.swap_percent}%` : '-'; const diskStr = p.disk_percent !== undefined ? `${p.disk_percent}%` : '-'; const psiStr = p.io_psi !== undefined ? p.io_psi.toFixed(2) : '-'; - const dockerBadge = p.docker ? 'Docker YES' : 'Docker NO'; + const dockerVal = p.docker ? 'YES' : 'NO'; + const dockerClass = p.docker ? 'yes' : 'no'; return `
@@ -52,20 +54,19 @@ async function loadDevices(){ ${esc(d.name)} ${esc(role)}
- ${d.is_local ? '' : ``} +
${esc(d.status)} · - ${d.is_local ? "local" : "remote"} · ${esc(d.arch||"")}/${esc(d.os||"")}
CPU${cpuStr}
-
Mem${memStr}
-
Swap${swapStr}
-
Disk${diskStr}
+
MEM${memStr}
+
DISK${diskStr}
+
SWAP${swapStr}
IO PSI${psiStr}
-
${dockerBadge}
+
DOCKER${dockerVal}
`;