72 lines
3.0 KiB
JavaScript
72 lines
3.0 KiB
JavaScript
|
|
async function jget(u){const r=await fetch(u);return r.json();}
|
|
async function post(u){const r=await fetch(u,{method:'POST'});return r.json();}
|
|
|
|
async function refresh(){
|
|
try{
|
|
const s=await jget('/api/stats');
|
|
el('m-total').textContent=s.total.toLocaleString('ru');
|
|
el('m-today').textContent=s.today.toLocaleString('ru');
|
|
const alive=Object.values(s.engines).filter(e=>e.alive).length;
|
|
el('m-eng').textContent=alive+' / '+Object.keys(s.engines).length;
|
|
el('m-ts').textContent=s.ts;
|
|
// движки
|
|
const box=el('eng');box.innerHTML='';
|
|
for(const [id,e] of Object.entries(s.engines)){
|
|
const c=document.createElement('div');c.className='card';
|
|
c.innerHTML=`<div><span class="dot ${e.alive?'on':'off'}"></span><b>${id}</b><div style="color:var(--dim);font-size:12px">${e.desc}${e.auto?' · auto':''}</div></div>`;
|
|
const btn=document.createElement('button');
|
|
btn.textContent=e.alive?'стоп':'старт';
|
|
if(e.alive)btn.className='stop';
|
|
btn.onclick=async()=>{e.alive?await post('/api/engine/'+id+'/stop'):await post('/api/engine/'+id+'/start');refresh();};
|
|
c.appendChild(btn);box.appendChild(c);
|
|
}
|
|
// статусы
|
|
const st=el('t-status');st.innerHTML='';
|
|
const mx=Math.max(...s.by_status.map(x=>x.n),1);
|
|
for(const r of s.by_status){
|
|
const tr=document.createElement('tr');
|
|
tr.innerHTML=`<td><span class="badge b-${r.status}">${r.status}</span></td><td>${r.n.toLocaleString('ru')}</td>
|
|
<td style="width:40%"><div class="bar"><i style="width:${(100*r.n/mx).toFixed(0)}%"></i></div></td>`;
|
|
st.appendChild(tr);
|
|
}
|
|
// провайдеры
|
|
const pv=el('t-prov');pv.innerHTML='';
|
|
for(const r of s.by_prov){
|
|
const tr=document.createElement('tr');
|
|
tr.innerHTML=`<td>${r.prov}</td><td>${r.n.toLocaleString('ru')}</td>`;
|
|
tr.style.cursor='pointer';
|
|
tr.onclick=()=>{el('f-prov').value=r.prov;loadKeys();};
|
|
pv.appendChild(tr);
|
|
}
|
|
loadKeys();
|
|
loadLog();
|
|
}catch(e){console.error(e);}
|
|
}
|
|
|
|
async function loadKeys(){
|
|
const st=el('f-status').value,pv=el('f-prov').value,lim=el('f-limit').value||50;
|
|
const d=await jget(`/api/keys?status=${st}&prov=${pv}&limit=${lim}`);
|
|
const t=el('t-keys');t.innerHTML='';
|
|
for(const r of d.rows){
|
|
const tr=document.createElement('tr');
|
|
tr.innerHTML=`<td><span class="badge b-${r.status}">${r.status}</span></td><td>${r.prov}</td>
|
|
<td title="${r.val}">${r.val}</td><td title="${r.repo||''}">${r.repo||''}</td><td>${r.found||''}</td>`;
|
|
t.appendChild(tr);
|
|
}
|
|
el('k-count').textContent=d.rows.length+' показано';
|
|
}
|
|
|
|
async function loadLog(){
|
|
const r=await fetch('/api/log?engine='+el('f-log').value);
|
|
el('log').textContent=await r.text();
|
|
el('log').scrollTop=el('log').scrollHeight;
|
|
}
|
|
|
|
function el(id){return document.getElementById(id);}
|
|
function exportKeys(){const st=el('f-status').value,pv=el('f-prov').value;
|
|
window.open(`/api/export?status=${st}&prov=${pv}`,'_blank');}
|
|
|
|
refresh();
|
|
setInterval(refresh,5000);
|