From 99db3acc207190c0613e82b91a2c3c5b06334b56 Mon Sep 17 00:00:00 2001 From: Hyoseong Jo Date: Sun, 28 Dec 2025 18:09:04 +0900 Subject: [PATCH] =?UTF-8?q?=EC=86=8C=EC=8A=A4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/components/ServerPortlet.vue | 37 +++++++++++++++++---------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/frontend/components/ServerPortlet.vue b/frontend/components/ServerPortlet.vue index 66b49cf..888e498 100644 --- a/frontend/components/ServerPortlet.vue +++ b/frontend/components/ServerPortlet.vue @@ -99,7 +99,7 @@
- {{ container.cpu_percent?.toFixed(0) || '-' }}% + {{ formatCpuPercent(container.cpu_percent) }}
@@ -301,6 +301,15 @@ function getMemPercent(c: ContainerStatus): number { return (Number(c.memory_usage) / Number(c.memory_limit)) * 100 } +function formatCpuPercent(value: number | null): string { + if (value === null || value === undefined) return '-' + // 10% 이상이면 정수로, 미만이면 소수점 1자리 + if (value >= 10) return `${value.toFixed(0)}%` + if (value >= 1) return `${value.toFixed(1)}%` + if (value >= 0.1) return `${value.toFixed(1)}%` + return `${value.toFixed(2)}%` +} + function formatMemoryShort(bytes: number | null): string { if (bytes === null || bytes === undefined) return '-' const numBytes = Number(bytes) @@ -379,9 +388,9 @@ function formatTimeAgo(datetime: string | null): string { .offline-text { font-size: 18px; margin-bottom: 8px; } .offline-time { font-size: 15px; opacity: 0.7; } -.container-area { display: flex; flex-wrap: wrap; gap: 12px; padding: 14px; align-content: flex-start; min-width: 140px; } +.container-area { display: flex; flex-wrap: wrap; gap: 10px; padding: 12px; align-content: flex-start; min-width: 140px; } -.container-card { width: 260px; padding: 14px; border-radius: 10px; border: 1px solid var(--border-color); background: var(--bg-secondary); cursor: pointer; transition: all 0.15s; overflow: hidden; } +.container-card { width: 200px; padding: 10px; border-radius: 8px; border: 1px solid var(--border-color); background: var(--bg-secondary); cursor: pointer; transition: all 0.15s; overflow: hidden; } .container-card:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.1); } .container-card.normal { background: var(--container-normal-bg, #f0fdf4); border-color: var(--container-normal-border, #86efac); } .container-card.warning { background: var(--container-warning-bg, #fefce8); border-color: var(--container-warning-border, #fde047); } @@ -389,22 +398,22 @@ function formatTimeAgo(datetime: string | null): string { .container-card.danger { background: var(--container-danger-bg, #fef2f2); border-color: var(--container-danger-border, #fca5a5); } .container-card.stopped { background: var(--container-danger-bg, #fef2f2); border-color: var(--container-danger-border, #fca5a5); } -.card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; overflow: hidden; } -.card-name { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; overflow: hidden; } -.card-name .card-level { font-size: 14px; flex-shrink: 0; } -.card-name .name { font-size: 17px; font-weight: 700; color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } -.card-uptime { font-size: 14px; color: var(--text-muted); flex-shrink: 0; margin-left: 12px; white-space: nowrap; } +.card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; overflow: hidden; } +.card-name { display: flex; align-items: center; gap: 6px; flex: 1; min-width: 0; overflow: hidden; } +.card-name .card-level { font-size: 12px; flex-shrink: 0; } +.card-name .name { font-size: 15px; font-weight: 700; color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.card-uptime { font-size: 12px; color: var(--text-muted); flex-shrink: 0; margin-left: 8px; white-space: nowrap; } -.card-metrics { display: flex; flex-wrap: wrap; gap: 8px 12px; } -.card-metric { display: flex; align-items: center; gap: 8px; width: calc(50% - 6px); overflow: hidden; } -.card-metric .label { font-size: 13px; color: var(--text-muted); width: 28px; flex-shrink: 0; font-weight: 500; } -.mini-bar { flex: 1; height: 8px; background: rgba(0,0,0,0.1); border-radius: 4px; overflow: hidden; min-width: 28px; } -.mini-fill { height: 100%; border-radius: 4px; } +.card-metrics { display: flex; flex-wrap: wrap; gap: 5px 8px; } +.card-metric { display: flex; align-items: center; gap: 4px; width: calc(50% - 4px); overflow: hidden; } +.card-metric .label { font-size: 11px; color: var(--text-muted); width: 22px; flex-shrink: 0; font-weight: 500; } +.mini-bar { flex: 1; height: 6px; background: rgba(0,0,0,0.1); border-radius: 3px; overflow: hidden; min-width: 20px; } +.mini-fill { height: 100%; border-radius: 3px; } .mini-fill.normal { background: #22c55e; } .mini-fill.warning { background: #eab308; } .mini-fill.critical { background: #f97316; } .mini-fill.danger { background: #ef4444; } -.card-metric .value { font-size: 15px; font-weight: 700; color: var(--text-secondary); width: 50px; text-align: right; flex-shrink: 0; overflow: hidden; text-overflow: ellipsis; transition: all 0.3s; padding: 2px 4px; border-radius: 4px; } +.card-metric .value { font-size: 13px; font-weight: 700; color: var(--text-secondary); min-width: 38px; text-align: right; flex-shrink: 0; transition: all 0.3s; padding: 1px 2px; border-radius: 3px; } .card-metric .value.mem-highlight { color: #dc2626; font-weight: 800; } .card-metric .value.net { color: var(--text-muted); font-weight: 600; }