From 9cd86ccaa32dbbea5889031cf39fbe4d63ed6641 Mon Sep 17 00:00:00 2001 From: cppla Date: Fri, 29 Aug 2025 17:34:12 +0800 Subject: [PATCH] update --- web/css/app.css | 7 +------ web/js/app.js | 28 ++++++++++++++++------------ 2 files changed, 17 insertions(+), 18 deletions(-) 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 `
`; } const pingBuckets = `
${bucket(p1)}${bucket(p2)}${bucket(p3)}
`; - const key = s.name || s.location || 'node'; + // 唯一 key 已附加为 s._key(如需使用) const rowCursor = online? 'pointer':'default'; const highLoad = online && ( (s.cpu||0)>=90 || (memPct)>=90 || (hddPct)>=90 ); html += ` @@ -170,7 +174,7 @@ function renderServersCards(){ 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 `
`; } const buckets = `
${bucket(p1)}${bucket(p2)}${bucket(p3)}
`; - const key = s.name || s.location || 'node'; + // 唯一 key 已附加为 s._key(如需使用) const highLoad = online && ( (s.cpu||0)>=90 || (memPct)>=90 || (hddPct)>=90 ); html += `
\n \n
\n
${s.name||'-'} ${s.location||'-'}
\n ${pill}\n
\n
\n
负载${s.load_1==-1?'–':s.load_1?.toFixed(2)}
\n
在线${s.uptime||'-'}
\n
月流量${monthIn}${monthOut}
\n
网络${netNow}
\n
总流量${netTotal}
\n
CPU${s.cpu||0}%
\n
内存${memPct.toFixed(0)}%
\n
硬盘${hddPct.toFixed(0)}%
\n
\n ${buckets}\n
\n
${online?'点击卡片可查看详情':'离线,不可查看详情'}
\n
\n
`; }); @@ -316,7 +320,7 @@ function openDetail(i){ const procLine = `${num(s.tcp_count)} / ${num(s.udp_count)} / ${num(s.process_count)} / ${num(s.thread_count)}`; // 保留延迟数据用于图表,但不再展示当前延迟文字行 const latText = offline ? '离线' : `CU/CT/CM: ${num(s.time_10010)}ms (${(s.ping_10010||0).toFixed(0)}%) / ${num(s.time_189)}ms (${(s.ping_189||0).toFixed(0)}%) / ${num(s.time_10086)}ms (${(s.ping_10086||0).toFixed(0)}%)`; - const key = s.name || s.location || 'node'; + const key = s._key || [s.name||'-', s.location||'-', s.type||'-'].join('|')+'#1'; let latencyBlock = ''; if(!offline){ @@ -372,7 +376,7 @@ function openDetail(i){ ● load1 (${s.load_1==-1?'–':Math.max(0,(s.load_1||0)).toFixed(2)}) ● load5 (${s.load_5==-1?'–':Math.max(0,(s.load_5||0)).toFixed(2)}) ● load15 (${s.load_15==-1?'–':Math.max(0,(s.load_15||0)).toFixed(2)}) - (~${(S.loadHist[key]?Math.max(S.loadHist[key].l1.length, S.loadHist[key].l5.length, S.loadHist[key].l15.length):0)} 条) + (~${(S.loadHist[key]?Math.max(S.loadHist[key].l1.length, S.loadHist[key].l5.length, S.loadHist[key].l15.length):0)} 条) @@ -383,7 +387,7 @@ function openDetail(i){ if(!offline){ drawLatencyChart(key); drawLoadChart(key); - S._openDetailKey = key; // 记录当前弹窗对应节点 + S._openDetailKey = key; // 记录当前弹窗对应节点(唯一 key) startDetailAutoUpdate(); } else { S._openDetailKey = null; @@ -496,7 +500,7 @@ function drawLoadChart(key){ //# sourceMappingURL=app.js.map // ====== 详情动态刷新 ====== -function findServerByKey(key){ return S.servers.find(x=> (x.name||x.location||'node')===key); } +function findServerByKey(key){ return S.servers.find(x=> (x._key)===key); } function updateDetailMetrics(key){ const s = findServerByKey(key); if(!s) return; if(!(s.online4||s.online6)) return; // 离线不更新 const procLine = `${num(s.tcp_count)} / ${num(s.udp_count)} / ${num(s.process_count)} / ${num(s.thread_count)}`;