站点健康star精选
站点测速,同源请求首页记录响应时间,画成 sparkline,一眼看出站点有没有变慢
image效果截图
点击放大notes详细介绍
自动测速:进概要页自动测一次;后台开着时每 5 分钟再测一次。想去掉等下一次就点左上角闪电(bolt)手动测。
sparkline:最近 30 次记录画成固定 52px 高的曲线;失败点画成底部竖线。
code配置代码
<div class="absh"><div class="absh-top"><div class="absh-head"id="absh-head"></div><div class="absh-tools"><button class="absh-btn is-primary"type="button"id="absh-run"title="立即测速(进后台会自动测)"aria-label="立即测速"><span class="material-icons-round">bolt</span></button><button class="absh-iconbtn"type="button"id="absh-clear"title="清空历史"aria-label="清空历史"><span class="material-icons-round">delete_sweep</span></button></div></div><div class="absh-spark ab-ui-tone-primary"id="absh-spark"></div><div class="absh-stats"id="absh-stats"></div><div class="absh-tip"id="absh-tip"></div></div><style>.absh{--absh-ease:cubic-bezier(.2,0,0,1);display:flex;flex-direction:column;gap:10px}.absh-top{display:flex;align-items:center;gap:8px}.absh-head{flex:1 1 auto;min-width:0}.absh-tools{flex:none;display:flex;align-items:center;gap:2px}.absh-btn{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border:0;border-radius:50%;background:transparent;color:var(--md-on-surface-variant);cursor:pointer;transition:background-color.2s var(--absh-ease),transform.2s var(--absh-ease)}.absh-btn:hover{background:var(--md-surface-container-high)}.absh-btn:active{transform:scale(.94)}.absh-btn.is-primary{background:var(--md-primary-container);color:var(--md-on-primary-container)}.absh-btn.is-primary:hover{background:var(--md-primary-container);filter:brightness(1.04)}.absh-btn.material-icons-round{display:block;font-size:19px;line-height:1}.absh-btn.is-busy.material-icons-round{animation:absh-spin 1s linear infinite}.absh-iconbtn{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border:0;border-radius:50%;background:transparent;color:var(--md-on-surface-variant);cursor:pointer;transition:background-color.2s var(--absh-ease)}.absh-iconbtn:hover{background:var(--md-surface-container-high);color:var(--md-error)}.absh-iconbtn.material-icons-round{display:block;font-size:19px;line-height:1}.absh-btn:focus-visible,.absh-iconbtn:focus-visible{outline:2px solid color-mix(in srgb,var(--md-primary)55%,transparent);outline-offset:2px}.absh-spark{position:relative;box-sizing:border-box;height:52px;padding:6px 8px;border-radius:14px;background:var(--md-surface-container-low);overflow:hidden}.absh-spark-box,.absh-spark-svg{display:block;width:100%;height:100%}.absh-spark-line{fill:none;stroke:var(--ab-ui-icon,var(--md-primary));stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.absh-spark-area{fill:var(--ab-ui-icon,var(--md-primary));opacity:.16;stroke:none}.absh-spark-dot{fill:var(--ab-ui-fg,var(--md-error));stroke:none}.absh-ph{display:flex;align-items:center;justify-content:center;height:100%;font-size:12.5px;color:var(--md-on-surface-variant)}.absh-stats:empty{display:none}.absh-stat-list{display:flex;flex-wrap:wrap;gap:2px 10px;font-size:12px;line-height:1.6;color:var(--md-on-surface-variant)}.absh-stat{display:inline-flex;align-items:baseline;gap:5px;white-space:nowrap}.absh-stat-v{font-size:13px;font-weight:600;color:var(--md-on-surface);font-variant-numeric:tabular-nums}.absh-stat.is-danger.absh-stat-v{color:var(--md-error)}.absh-tip:empty{display:none}@keyframes absh-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.absh-btn,.absh-iconbtn{transition:none}.absh-btn.is-busy.material-icons-round{animation:none}}</style>
(function(){'use strict';if(typeof card.__abshBoot==='function'){card.__abshBoot();return}var KEY='site-health-history';var MAX_POINTS=30;var AUTO_MS=5*60*1000;var SKIP_MS=60*1000;var TIMEOUT=8000;var el=ab.ui.el;var history=[];var headNode=null;var measuring=false;function $(id){return card.querySelector('#'+id)}function say(text,tone){if(ab.notify)ab.notify(text,tone||'info')}function probe(){if(typeof window.fetch!=='function')return Promise.reject(new Error('当前浏览器不支持 fetch'));var url=location.origin+'/?ab-health='+Date.now();var t0=window.performance&&performance.now?performance.now():Date.now();return new Promise(function(resolve,reject){var timer=ab.timeout(function(){reject(new Error('超时(>'+(TIMEOUT/1000)+'s)'))},TIMEOUT);window.fetch(url,{cache:'no-store',credentials:'omit'}).then(function(r){var cost=(window.performance&&performance.now?performance.now():Date.now())-t0;window.clearTimeout(timer);if(!r.ok){reject(new Error('HTTP '+r.status));return}resolve(Math.max(1,Math.round(cost)))}).catch(function(err){window.clearTimeout(timer);reject(err)})})}function pickHistory(raw){var list=Object.prototype.toString.call(raw)==='[object Array]'?raw:[];var out=[];for(var i=0;i<list.length&&out.length<MAX_POINTS;i++){var it=list[i];if(!it||typeof it!=='object')continue;var ms=(it.ms===null||it.ms===undefined)?null:parseInt(it.ms,10);out.push({t:parseInt(it.t,10)||0,ms:(ms===null||isNaN(ms))?null:ms})}return out}function push(ms){history.push({t:Date.now(),ms:ms});if(history.length>MAX_POINTS)history=history.slice(history.length-MAX_POINTS);ab.data.save(KEY,history,{scope:'site'}).catch(function(){})}function stats(){var ok=0,fail=0,sum=0,min=0,max=0;for(var i=0;i<history.length;i++){var ms=history[i].ms;if(ms===null){fail++;continue}ok++;sum+=ms;if(!min||ms<min)min=ms;if(ms>max)max=ms}return{ok:ok,fail:fail,avg:ok?Math.round(sum/ok):0,min:min,max:max,total:history.length}}function toneOf(ms){if(ms===null)return'danger';if(ms<=400)return'success';if(ms<=1200)return'primary';if(ms<=3000)return'warn';return'danger'}function fmtMs(ms){if(ms>=1000)return(ms/1000).toFixed(ms>=10000?0:1)+' s';return ms+' ms'}function renderHead(){var host=$('absh-head');if(!host)return;var last=history.length?history[history.length-1]:null;var opts={icon:last&&last.ms===null?'cloud_off':'speed',label:'站点首页响应',value:last?(last.ms===null?'请求失败':fmtMs(last.ms)):(measuring?'测速中…':'—'),tone:last?toneOf(last.ms):'default'};if(headNode&&headNode.update){headNode.update(opts);return}headNode=ab.ui.row(opts);ab.ui.mount(host,headNode)}function renderStats(){var host=$('absh-stats');if(!host)return;var s=stats();var last=history.length?history[history.length-1]:null;if(!last){ab.ui.mount(host,'');return}var items=[{k:'最近',v:ab.format.relative(last.t)},{k:'平均',v:s.ok?fmtMs(s.avg):'—'},{k:'最慢',v:s.max?fmtMs(s.max):'—'},{k:'失败',v:String(s.fail),danger:s.fail>0}];var wrap=el('div','absh-stat-list',null);for(var i=0;i<items.length;i++){var cell=el('span','absh-stat'+(items[i].danger?' is-danger':''),null);cell.appendChild(el('span','absh-stat-k',items[i].k));cell.appendChild(el('span','absh-stat-v',items[i].v));wrap.appendChild(cell)}ab.ui.mount(host,wrap)}function renderSpark(){var host=$('absh-spark');if(!host)return;if(history.length<2){host.className='absh-spark ab-ui-tone-primary';ab.ui.mount(host,el('div','absh-ph',measuring?'正在自动测速…':(history.length?'再测一次就能画出走势':'暂无数据,进后台会自动测速')));return}var n=history.length,i,max=0;for(i=0;i<n;i++){var v=history[i].ms===null?0:history[i].ms;if(v>max)max=v}if(max<=0)max=1;var W=100,H=30,PAD=3;var pts=[],marks='';for(i=0;i<n;i++){var x=(i/(n-1))*W;var ms=history[i].ms;var y=H-PAD-((ms===null?0:ms)/max)*(H-PAD*2);pts.push(x.toFixed(2)+','+y.toFixed(2));if(ms===null){marks+='<rect class="absh-spark-dot" x="'+(x-0.5).toFixed(2)+'" y="'+y.toFixed(2)+'" width="1" height="'+(H-y).toFixed(2)+'"/>'}}var line=pts.join(' ');host.className='absh-spark ab-ui-tone-'+toneOf(history[n-1].ms);var box=el('div','absh-spark-box',null);box.innerHTML='<svg class="absh-spark-svg" viewBox="0 0 '+W+' '+H+'" preserveAspectRatio="none" aria-hidden="true"><polygon class="absh-spark-area" points="0,'+H+' '+line+' '+W+','+H+'"/><polyline class="absh-spark-line" points="'+line+'" vector-effect="non-scaling-stroke"/>'+marks+'</svg>';ab.ui.mount(host,box)}function renderTip(){var host=$('absh-tip');if(!host)return;var last=history.length?history[history.length-1]:null;if(last&&last.ms===null){ab.ui.mount(host,ab.ui.notice({icon:'error_outline',tone:'danger',text:'最近一次测速失败,已记为一个失败点'}));return}ab.ui.mount(host,'')}function render(){renderHead();renderSpark();renderStats();renderTip()}function measure(manual){var btn=$('absh-run');if(btn)btn.classList.add('is-busy');measuring=true;if(!history.length)render();return probe().then(function(ms){measuring=false;push(ms);render();if(manual)say('测速完成:'+fmtMs(ms),toneOf(ms)==='success'?'success':'info');return ms}).catch(function(err){measuring=false;push(null);render();if(manual)say('测速失败:'+((err&&err.message)||'未知错误'),'danger');return null}).then(function(r){if(btn)btn.classList.remove('is-busy');return r})}function clearHistory(){var run=function(){history=[];headNode=null;ab.data.save(KEY,[],{scope:'site'}).catch(function(){});render();var host=$('absh-head');if(host)host.innerHTML='';renderHead();say('历史已清空','info')};if(typeof ab.ui.confirm==='function'){ab.ui.confirm({title:'清空测速历史?',text:'会删掉全部 '+history.length+' 个历史点(不影响站点数据)。',okText:'清空',tone:'danger'}).then(function(ok){if(ok)run()});return}run()}function bind(){var run=$('absh-run');if(run)run.addEventListener('click',function(){measure(true)});var clear=$('absh-clear');if(clear)clear.addEventListener('click',clearHistory)}function boot(){return ab.data.get(KEY,[],{scope:'site'}).then(function(saved){history=pickHistory(saved);render();var last=history.length?history[history.length-1]:null;if(!last||(Date.now()-last.t)>SKIP_MS){ab.timeout(function(){measure(false)},300)}return null}).catch(function(err){say('读取测速历史失败:'+((err&&err.message)||'未知错误'),'danger');render()})}card.__abshBoot=boot;bind();boot();ab.interval(function(){measure(false)},AUTO_MS)})();
download_for_offline如何导入
Typecho 后台 → 控制台 → 插件 → AB Admin(AdminBeautify)→「概要页卡片设置」
找到 自定义卡片 区域,打开总开关(默认关闭)
点 添加卡片,按下表填写:
| 图标 | monitor_heart |
| 卡片标题 | 站点健康 |
| HTML 内容 | 见上方「HTML 内容」标签页 |
| JavaScript | 见上方「JavaScript」标签页 |
点右下角 保存设置,回到概要页即可看到卡片(顺序可在排序列表里拖动调整)
shield安全信息
error
带告警项(已人工确认)
warning
卡片 JavaScript 会在你的后台页面里执行。本站已做敏感信息、站外请求与越权操作的自动扫描 + 人工审核,但仍请在使用前自行阅读上方代码;发现可疑卡片请到
GitHub 反馈。