import { runtimeStatus } from "/assets/js/ui-semantics.js"; import { monitorHealth, summaryStatus, dataIsCurrent } from "/assets/js/overview-health.js"; import { state as appState } from "/assets/js/state.js"; import { storageCards } from "./storage.js"; import { esc } from "/assets/js/shared.js"; import { tr } from "/assets/js/i18n.js"; import { bytes, formatUptime, meter } from "/assets/js/overview.js"; import { fanMetric } from "./hardware.js"; import { ownerName, rgbName } from "./schema.js"; export function agentHostCard(entry) { const h = entry.host; if (!entry.online) return `

${esc(h.name || h.id)}

ID ${esc(h.id)}${esc(h.url || tr("本机"))}
${tr("离线")}
${esc(entry.error || tr("连接失败"))}
`; const s = entry.status, y = s.system || {}, n = s.network || {}, d = s.display || {}, v = s.device || {}, m = s.machine || h, signal = n.signal_percent, memUsed = y.memory_used_bytes, memTotal = y.memory_total_bytes, diskUsed = y.disk_used_bytes, diskTotal = y.disk_total_bytes; const hardware = Object.values(s.plugins || {}).filter(p => p.capabilities?.display || p.capabilities?.rgb); const current = dataIsCurrent(entry); const ready = p => current && p.online === true && p.status?.available !== false; const oled = hardware.find(p => p.capabilities?.display && ready(p) && p.status?.oled_page); const rgb = hardware.find(p => p.capabilities?.rgb && ready(p) && p.status?.rgb_mode); const displayText = [oled ? `OLED ${ownerName(oled.status.oled_page)}` : ownerName(d.owner), rgb ? `RGB ${rgbName(rgb.status.rgb_mode)}` : ""].filter(Boolean).join(" · "); const hardwareState = !hardware.length ? "unlinked" : !current ? "unknown" : hardware.some(p => p.online === false) ? "offline" : hardware.every(ready) ? "online" : "unknown"; const hardwareLabel = { online: tr("正常"), offline: tr("离线"), unknown: appState.LANG === "zh" ? "未确认" : "Unconfirmed", unlinked: appState.LANG === "zh" ? "未接入" : "Not connected" }[hardwareState]; const hardwareNames = hardware.map(p => p.name).filter(Boolean).join(" · "); const percent = n => Number.isFinite(n) ? `${n.toFixed(1)}%` : "--"; const progress = n => Number.isFinite(n) ? meter(n) : ""; return `

${esc(m.name || h.name || m.id)}

${esc(formatUptime(s.uptime_seconds))}
ID ${esc(m.id || h.id)}${appState.LANG === "zh" ? "主机名" : "Hostname"} ${esc(m.hostname || v.hostname || "--")}${esc(v.manufacturer || "")} ${esc(v.model || "--")}${appState.LANG === "zh" ? "序列号" : "Serial"} ${esc(v.serial || "--")}${appState.LANG === "zh" ? "硬件版本" : "Revision"} ${esc(v.revision || "--")}${esc(v.os || "--")}${appState.LANG === "zh" ? "内核" : "Kernel"} ${esc(v.kernel || "--")}${esc(v.architecture || "--")} · CPU ${esc(v.cpu_count || "--")}${appState.LANG === "zh" ? "程序版本" : "Agent"} ${esc(s.version || "--")}
${tr("在线")}
${tr("处理器负载")}
${percent(y.cpu_percent)}
${progress(y.cpu_percent)}
${appState.LANG === "zh" ? "频率" : "Frequency"} ${esc(y.cpu_freq_mhz)} MHz · ${esc(y.temperature_c)}°C${fanMetric(s.plugins || {})}
${tr("内存占用")}
${percent(y.memory_percent)}
${progress(y.memory_percent)}
${bytes(memUsed)} / ${bytes(memTotal)} · ${appState.LANG === "zh" ? "可用" : "Available"} ${bytes(y.memory_available_bytes)}
${tr("主网络")}
↓ ${bytes(n.rx_bytes_per_second)}/s · ↑ ${bytes(n.tx_bytes_per_second)}/s
${esc(n.interface || "--")} · ${n.kind === "WIF" ? `${esc(n.metric)} dBm · ` : n.link_speed_mbps ? `${esc(n.link_speed_mbps)} Mbps · ` : ""}${esc(n.ip_label)} ${esc(n.ip)} · ${n.link === true ? (appState.LANG === "zh" ? "已连接" : "Connected") : n.link === false ? (appState.LANG === "zh" ? "已断开" : "Disconnected") : (appState.LANG === "zh" ? "状态未确认" : "Unconfirmed")}
${Array.isArray(y.storage_inventory) ? storageCards(y,entry.snapshot?.resources) : `
${tr("磁盘占用")}
${percent(y.disk_percent)}
${progress(y.disk_percent)}
${bytes(diskUsed)} / ${bytes(diskTotal)} · ${appState.LANG === "zh" ? "剩余" : "Free"} ${bytes(y.disk_free_bytes)}
`}
${appState.LANG === "zh" ? "主要告警" : "Primary alert"}${esc(hardwareLabel)}
${esc(displayText)}
${hardwareNames ? `
${esc(hardwareNames)}
` : ""}
${(d.alerts || []).length || !dataIsCurrent(entry) || !Array.isArray(d.alerts) ? `
${tr("当前告警")}
${(d.alerts || []).length}
${(d.alerts || []).map((a) => esc(ownerName(a.id))).join(" · ") || tr("无告警")}
` : ""}
${tr("服务与进程监控")}${summaryStatus(monitorHealth(s.watches, dataIsCurrent(entry)), appState.LANG)}
${(s.watches || []).map((w) => `
${esc(w.name)} · ${esc(w.target)}${runtimeStatus(w.up, appState.LANG)}
`).join("") || `
${tr("暂无数据")}
`}
`; }