diff --git a/web/css/app.css b/web/css/app.css index 73f54d2..0480d0b 100644 --- a/web/css/app.css +++ b/web/css/app.css @@ -152,12 +152,7 @@ body.light .gauge-half .needle{background:linear-gradient(var(--text),var(--text .bucket span{display:block;width:100%;background:var(--accent);border-radius:4px 4px 6px 6px;height:var(--h);align-self:flex-end;transition:height .8s cubic-bezier(.4,0,.2,1),background .3s} .bucket[data-lv=warn] span{background:var(--warn)} .bucket[data-lv=bad] span{background:var(--danger)} -.bucket label{position:absolute;left:0;right:0;bottom:2px;text-align:center;pointer-events:none; - /* 统一为与仪表盘数值相同的风格 */ - font-family:ui-monospace,SFMono-Regular,Menlo,monospace; - font-size:12px;font-weight:600;letter-spacing:.25px; - font-variant-numeric:tabular-nums;color:var(--text); -} +.bucket label{position:absolute;left:0;right:0;bottom:2px;font-size:10px;text-align:center;color:var(--text-dim);pointer-events:none} .bucket:hover label{color:var(--text)} /* 居中联通电信移动列 */ diff --git a/web/js/app.js b/web/js/app.js index 4b419f2..104544a 100644 --- a/web/js/app.js +++ b/web/js/app.js @@ -33,17 +33,21 @@ async function fetchData(){ if(!r.ok) throw new Error(r.status); const j = await r.json(); if(j.reload) location.reload(); - S.updated = j.updated; S.servers = j.servers||[]; S.ssl = j.sslcerts||[]; S.error=false; - // 更新延迟历史 (按节点名聚合) - S.servers.forEach(s=>{ - const key = s.name || s.location || 'node'; + S.updated = j.updated; S.servers = j.servers||[]; S.ssl = j.sslcerts||[]; S.error=false; + // 为每个服务器生成唯一 key(基于 name|location|type + 顺序号),避免同名节点写入同一历史 + const keyCount = Object.create(null); + S.servers.forEach((s, idx)=>{ + const base = [s.name||'-', s.location||'-', s.type||'-'].join('|'); + const seq = (keyCount[base]||0) + 1; keyCount[base] = seq; + const key = `${base}#${seq}`; + s._key = key; // 挂到对象上,后续查找/弹窗均用它 if(!S.hist[key]) S.hist[key] = {cu:[],ct:[],cm:[]}; const H = S.hist[key]; // 使用 time_ 字段 (ms) 若不存在则跳过 if(typeof s.time_10010 === 'number') H.cu.push(s.time_10010); if(typeof s.time_189 === 'number') H.ct.push(s.time_189); if(typeof s.time_10086 === 'number') H.cm.push(s.time_10086); - const MAX=256; // 保留最多 256 条 + const MAX=120; // 保留最多 120 条 ['cu','ct','cm'].forEach(k=>{ if(H[k].length>MAX) H[k].splice(0,H[k].length-MAX); }); // 指标历史 (仅在线时记录) if(!S.metricHist[key]) S.metricHist[key] = {cpu:[],mem:[],hdd:[]}; @@ -59,7 +63,7 @@ async function fetchData(){ // 负载历史 (记录 load_1 / load_5 / load_15) if(!S.loadHist[key]) S.loadHist[key] = {l1:[],l5:[],l15:[]}; const LH = S.loadHist[key]; - const pushLoad = (arr,val)=>{ if(typeof val === 'number' && val >= 0){ arr.push(val); if(arr.length>256) arr.splice(0,arr.length-256); } }; + const pushLoad = (arr,val)=>{ if(typeof val === 'number' && val >= 0){ arr.push(val); if(arr.length>120) arr.splice(0,arr.length-120); } }; pushLoad(LH.l1, s.load_1); pushLoad(LH.l5, s.load_5); pushLoad(LH.l15, s.load_15); @@ -99,7 +103,7 @@ function renderServers(){ const p1 = (s.ping_10010||0); const p2 = (s.ping_189||0); const p3 = (s.ping_10086||0); function bucket(p){ const v = Math.max(0, Math.min(100, p)); const level = v>=20?'bad':(v>=10?'warn':'ok'); return `