|
|
|
@@ -164,27 +164,41 @@
|
|
|
|
|
var oldMem = parseFloat((body.getAttribute('data-mem')||memVal));
|
|
|
|
|
body.setAttribute('data-cpu', cpuVal);
|
|
|
|
|
body.setAttribute('data-mem', memVal);
|
|
|
|
|
body.innerHTML =
|
|
|
|
|
'<div class="metric-row">'+
|
|
|
|
|
'<div class="metric"><div class="metric-label">CPU</div><div class="metric-value cpu-val">'+oldCpu.toFixed(1)+'%</div><div class="metric-bar"><div class="metric-bar-fill '+cpuBarCls+'" style="width:'+oldCpu+'%"></div></div></div>'+
|
|
|
|
|
'<div class="metric"><div class="metric-label">MEM</div><div class="metric-value mem-val">'+oldMem.toFixed(1)+'%</div><div class="metric-bar"><div class="metric-bar-fill '+memBarCls+'" style="width:'+oldMem+'%"></div></div></div>'+
|
|
|
|
|
'</div>'+
|
|
|
|
|
'<div class="metric-row">'+
|
|
|
|
|
'<div class="metric"><div class="metric-label">NET ↓</div><div class="metric-value" style="font-size:.9rem">'+fmtSpeed(net.rx_bytes_sec||0)+'</div></div>'+
|
|
|
|
|
'<div class="metric"><div class="metric-label">NET ↑</div><div class="metric-value" style="font-size:.9rem">'+fmtSpeed(net.tx_bytes_sec||0)+'</div></div>'+
|
|
|
|
|
'</div>'+
|
|
|
|
|
'<div style="font-size:.7rem;color:var(--text-dim);margin-top:8px">内存 '+(mem.used_gb||0).toFixed(1)+'/'+(mem.total_gb||0).toFixed(1)+' GB</div>';
|
|
|
|
|
// 动画计数
|
|
|
|
|
var cpuEl = body.querySelector('.cpu-val');
|
|
|
|
|
var memEl = body.querySelector('.mem-val');
|
|
|
|
|
animateValue(cpuEl, oldCpu, cpuVal, 1, '%');
|
|
|
|
|
animateValue(memEl, oldMem, memVal, 1, '%');
|
|
|
|
|
// 进度条平滑过渡 (CSS transition 自动处理)
|
|
|
|
|
requestAnimationFrame(function(){
|
|
|
|
|
var fills = body.querySelectorAll('.metric-bar-fill');
|
|
|
|
|
if (fills[0]) { fills[0].style.width = cpuVal+'%'; fills[0].className = 'metric-bar-fill '+cpuBarCls; }
|
|
|
|
|
if (fills[1]) { fills[1].style.width = memVal+'%'; fills[1].className = 'metric-bar-fill '+memBarCls; }
|
|
|
|
|
});
|
|
|
|
|
var isNew = !body.querySelector('.cpu-val');
|
|
|
|
|
if (isNew) {
|
|
|
|
|
body.innerHTML =
|
|
|
|
|
'<div class="metric-row">'+
|
|
|
|
|
'<div class="metric"><div class="metric-label">CPU</div><div class="metric-value cpu-val">0%</div><div class="metric-bar"><div class="metric-bar-fill" style="width:0%"></div></div></div>'+
|
|
|
|
|
'<div class="metric"><div class="metric-label">MEM</div><div class="metric-value mem-val">0%</div><div class="metric-bar"><div class="metric-bar-fill" style="width:0%"></div></div></div>'+
|
|
|
|
|
'</div>'+
|
|
|
|
|
'<div class="metric-row">'+
|
|
|
|
|
'<div class="metric"><div class="metric-label">NET ↓</div><div class="metric-value net-down" style="font-size:.9rem"></div></div>'+
|
|
|
|
|
'<div class="metric"><div class="metric-label">NET ↑</div><div class="metric-value net-up" style="font-size:.9rem"></div></div>'+
|
|
|
|
|
'</div>'+
|
|
|
|
|
'<div class="mem-detail"></div>';
|
|
|
|
|
}
|
|
|
|
|
// 更新 NET
|
|
|
|
|
body.querySelector('.net-down').textContent = fmtSpeed(net.rx_bytes_sec||0);
|
|
|
|
|
body.querySelector('.net-up').textContent = fmtSpeed(net.tx_bytes_sec||0);
|
|
|
|
|
body.querySelector('.mem-detail').innerHTML = '<div style="font-size:.7rem;color:var(--text-dim);margin-top:8px">内存 '+(mem.used_gb||0).toFixed(1)+'/'+(mem.total_gb||0).toFixed(1)+' GB</div>';
|
|
|
|
|
// 进度条: 先设旧值 → force reflow → 设新值
|
|
|
|
|
var barCpu = body.querySelectorAll('.metric-bar-fill')[0];
|
|
|
|
|
var barMem = body.querySelectorAll('.metric-bar-fill')[1];
|
|
|
|
|
barCpu.style.transition = 'none';
|
|
|
|
|
barMem.style.transition = 'none';
|
|
|
|
|
barCpu.style.width = oldCpu+'%';
|
|
|
|
|
barMem.style.width = oldMem+'%';
|
|
|
|
|
barCpu.className = 'metric-bar-fill '+cpuBarCls;
|
|
|
|
|
barMem.className = 'metric-bar-fill '+memBarCls;
|
|
|
|
|
barCpu.offsetWidth; // force reflow
|
|
|
|
|
barMem.offsetWidth;
|
|
|
|
|
barCpu.style.transition = '';
|
|
|
|
|
barMem.style.transition = '';
|
|
|
|
|
barCpu.style.width = cpuVal+'%';
|
|
|
|
|
barMem.style.width = memVal+'%';
|
|
|
|
|
// 数字跳动
|
|
|
|
|
animateValue(body.querySelector('.cpu-val'), oldCpu, cpuVal, 1, '%');
|
|
|
|
|
animateValue(body.querySelector('.mem-val'), oldMem, memVal, 1, '%');
|
|
|
|
|
} else {
|
|
|
|
|
body.innerHTML = '<div style="color:var(--error);font-size:.85rem">'+(n.error||'离线')+'</div>';
|
|
|
|
|
}
|
|
|
|
|