소스 수정
This commit is contained in:
@@ -40,22 +40,28 @@
|
||||
</div>
|
||||
|
||||
<template v-if="server.level !== 'offline'">
|
||||
<!-- 업타임 -->
|
||||
<div class="extra-row">
|
||||
<span class="extra-icon">⏱</span>
|
||||
<span class="extra-value">{{ server.uptime_str || '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="metric-row">
|
||||
<span class="metric-label">CPU</span>
|
||||
<div class="progress-bar">
|
||||
<div :class="['progress-fill', server.cpu_level]" :style="{ width: (server.cpu_percent || 0) + '%' }"></div>
|
||||
</div>
|
||||
<span :class="['metric-value', server.cpu_level, { 'value-changed': isChanged(server.target_id, 'cpu') }]">
|
||||
{{ server.cpu_percent?.toFixed(0) || '-' }}
|
||||
{{ server.cpu_percent?.toFixed(0) || '-' }}%
|
||||
</span>
|
||||
</div>
|
||||
<div class="metric-row">
|
||||
<span class="metric-label">MEM</span>
|
||||
<div class="progress-bar">
|
||||
<div :class="['progress-fill', server.memory_level]" :style="{ width: (server.memory_percent || 0) + '%' }"></div>
|
||||
<div :class="['progress-fill', server.memory_level]" :style="{ width: calcMemPercent(server) + '%' }"></div>
|
||||
</div>
|
||||
<span :class="['metric-value', server.memory_level, { 'value-changed': isChanged(server.target_id, 'mem') }]">
|
||||
{{ server.memory_percent?.toFixed(0) || '-' }}
|
||||
{{ calcMemPercent(server).toFixed(0) }}%
|
||||
</span>
|
||||
</div>
|
||||
<div class="metric-row">
|
||||
@@ -64,9 +70,27 @@
|
||||
<div :class="['progress-fill', server.disk_level]" :style="{ width: (server.disk_percent || 0) + '%' }"></div>
|
||||
</div>
|
||||
<span :class="['metric-value', server.disk_level, { 'value-changed': isChanged(server.target_id, 'disk') }]">
|
||||
{{ server.disk_percent?.toFixed(0) || '-' }}
|
||||
{{ server.disk_percent?.toFixed(0) || '-' }}%
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- 추가 정보: 온도, Load, 메모리용량, 디스크용량 -->
|
||||
<div class="extra-row">
|
||||
<span class="extra-icon">🌡</span>
|
||||
<span class="extra-value">{{ server.cpu_temp ? server.cpu_temp + '°C' : '-' }}</span>
|
||||
</div>
|
||||
<div class="extra-row">
|
||||
<span class="extra-icon">⚡</span>
|
||||
<span class="extra-value">{{ server.load_percent ? server.load_percent.toFixed(1) + '%' : '-' }}</span>
|
||||
</div>
|
||||
<div class="extra-row">
|
||||
<span class="extra-icon">🔲</span>
|
||||
<span class="extra-value">{{ formatServerMem(server) }}</span>
|
||||
</div>
|
||||
<div class="extra-row">
|
||||
<span class="extra-icon">📀</span>
|
||||
<span class="extra-value">{{ formatServerDisk(server) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
@@ -162,8 +186,16 @@ interface ServerStatus {
|
||||
cpu_level: string
|
||||
memory_percent: number | null
|
||||
memory_level: string
|
||||
memory_total: number | null
|
||||
memory_free: number | null
|
||||
memory_used: number | null
|
||||
disk_percent: number | null
|
||||
disk_level: string
|
||||
disk_used: number | null
|
||||
disk_total: number | null
|
||||
cpu_temp: number | null
|
||||
load_percent: number | null
|
||||
uptime_str: string | null
|
||||
last_collected: string | null
|
||||
containers: ContainerStatus[]
|
||||
container_summary: { total: number; normal: number; warning: number; critical: number; stopped: number }
|
||||
@@ -265,6 +297,35 @@ function isContainerChanged(serverId: number, containerName: string, metric: str
|
||||
return changedKeys.value.has(`container-${serverId}-${containerName}-${metric}`)
|
||||
}
|
||||
|
||||
// 서버 메모리 퍼센트 계산: (total - free) / total * 100
|
||||
function calcMemPercent(server: ServerStatus): number {
|
||||
const total = Number(server.memory_total) || 0
|
||||
const free = Number(server.memory_free) || 0
|
||||
if (total === 0) return 0
|
||||
return ((total - free) / total) * 100
|
||||
}
|
||||
|
||||
// 서버 메모리 용량 포맷: used/total GB
|
||||
function formatServerMem(server: ServerStatus): string {
|
||||
const total = Number(server.memory_total) || 0
|
||||
const free = Number(server.memory_free) || 0
|
||||
if (total === 0) return '-'
|
||||
const used = total - free
|
||||
const usedGB = (used / (1024 * 1024 * 1024)).toFixed(1)
|
||||
const totalGB = (total / (1024 * 1024 * 1024)).toFixed(1)
|
||||
return `${usedGB}/${totalGB}G`
|
||||
}
|
||||
|
||||
// 서버 디스크 용량 포맷: used/total GB
|
||||
function formatServerDisk(server: ServerStatus): string {
|
||||
const used = Number(server.disk_used) || 0
|
||||
const total = Number(server.disk_total) || 0
|
||||
if (total === 0) return '-'
|
||||
const usedGB = (used / (1024 * 1024 * 1024)).toFixed(0)
|
||||
const totalGB = (total / (1024 * 1024 * 1024)).toFixed(0)
|
||||
return `${usedGB}/${totalGB}G`
|
||||
}
|
||||
|
||||
function sortContainers(containers: ContainerStatus[]) {
|
||||
return [...containers].sort((a, b) => a.name.localeCompare(b.name))
|
||||
}
|
||||
@@ -378,12 +439,16 @@ function formatTimeAgo(datetime: string | null): string {
|
||||
.progress-fill.warning { background: #eab308; }
|
||||
.progress-fill.critical { background: #f97316; }
|
||||
.progress-fill.danger { background: #ef4444; }
|
||||
.metric-value { font-size: 17px; font-weight: 700; width: 36px; text-align: right; transition: all 0.3s; padding: 2px 4px; border-radius: 4px; }
|
||||
.metric-value { font-size: 17px; font-weight: 700; width: 44px; text-align: right; transition: all 0.3s; padding: 2px 4px; border-radius: 4px; }
|
||||
.metric-value.normal { color: #16a34a; }
|
||||
.metric-value.warning { color: #ca8a04; }
|
||||
.metric-value.critical { color: #ea580c; }
|
||||
.metric-value.danger { color: #dc2626; }
|
||||
|
||||
.extra-row { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; }
|
||||
.extra-icon { font-size: 12px; width: 16px; text-align: center; }
|
||||
.extra-value { font-size: 12px; font-weight: 600; color: var(--text-secondary); font-family: monospace; }
|
||||
|
||||
.offline-info { text-align: center; padding: 24px 0; color: var(--text-muted); }
|
||||
.offline-text { font-size: 18px; margin-bottom: 8px; }
|
||||
.offline-time { font-size: 15px; opacity: 0.7; }
|
||||
|
||||
Reference in New Issue
Block a user