abuse: схлопывание перепечаток (sig в индексе, uniq в API), кэш выдачи 60с; scan 13с -> 1.5с
This commit is contained in:
@@ -503,7 +503,7 @@ V.abuse=async ctx=>{
|
||||
ctx.mount(`<div class="card"><div class="card-header"><nav class="nav nav-tabs card-header-tabs" aria-label="Виды находок"><a class="nav-link ${S.tab==="signals"?"active":""}" href="#/abuse" data-ab-tab="signals" ${S.tab==="signals"?'aria-current="page"':""}>Находки в публикациях</a><a class="nav-link ${S.tab==="panels"?"active":""}" href="#/abuse?tab=panels" data-ab-tab="panels" ${S.tab==="panels"?'aria-current="page"':""}>Бесплатные API-панели</a></nav></div><div id="ab-content">${loading("Загрузка находок…",5)}</div><div id="pn-box" ${S.tab!=="panels"?"hidden":""}></div></div><div id="sum-box" class="mt-4" aria-live="polite"></div>`);
|
||||
if(S.tab==="panels"){$("#ab-content").hidden=true;await loadPanels(ctx);return}
|
||||
const d=await api("/api/abuse?limit=120"+(S.tag?"&tag="+encodeURIComponent(S.tag):""),{signal:ctx.signal});if(!ctx.valid())return;S.abuse=d.items||[];const tags=Object.entries(d.labels||{});
|
||||
$("#ab-content").innerHTML=`<div class="card-body border-bottom"><div class="row g-3 align-items-end"><div class="col-sm-5"><label class="form-label" for="ab-tag">Что искать в публикациях</label><select class="form-select" id="ab-tag"><option value="">Все находки</option>${tags.map(([tag,label])=>`<option value="${esc(tag)}" ${S.tag===tag?"selected":""}>${text(label)}</option>`).join("")}</select></div><div class="col text-secondary">Показано ${num(S.abuse.length)} из ${num(d.total)} находок</div></div><p class="text-secondary small mt-3 mb-0">Это признаки в публикациях, а не подтверждённые предложения. Проверяйте условия в оригинале. Значения API-ключей не отображаются.</p></div><div id="ab-list" class="list-group list-group-flush">${S.abuse.map(it=>itemRow(it)).join("")||empty("Находок пока нет","Выберите другой признак или соберите свежие записи источников.",'<button class="btn" data-tag="" type="button">Все находки</button>')}</div>`;
|
||||
$("#ab-content").innerHTML=`<div class="card-body border-bottom"><div class="row g-3 align-items-end"><div class="col-sm-5"><label class="form-label" for="ab-tag">Что искать в публикациях</label><select class="form-select" id="ab-tag"><option value="">Все находки</option>${tags.map(([tag,label])=>`<option value="${esc(tag)}" ${S.tag===tag?"selected":""}>${text(label)}</option>`).join("")}</select></div><div class="col text-secondary">Показано ${num(S.abuse.length)} из ${num(d.total)} находок${d.uniq&&d.uniq!==d.total?` · ${num(d.uniq)} уникальных`:"\u00a0"}</div></div><p class="text-secondary small mt-3 mb-0">Это признаки в публикациях, а не подтверждённые предложения. Проверяйте условия в оригинале. Значения API-ключей не отображаются.</p></div><div id="ab-list" class="list-group list-group-flush">${S.abuse.map(it=>itemRow(it)).join("")||empty("Находок пока нет","Выберите другой признак или соберите свежие записи источников.",'<button class="btn" data-tag="" type="button">Все находки</button>')}</div>`;
|
||||
};
|
||||
async function loadPanels(ctx=activeContext){const scope=requestScope("panels",ctx),box=$("#pn-box");if(!box)return;box.innerHTML=loading("Загрузка API-панелей…");try{const d=await api("/api/panels",{signal:scope.signal});if(!scope.valid())return;const all=(d.panels||[]).filter(p=>Number(p.free_count||p.free||0)>0),rows=all.slice(0,40);box.innerHTML=`<div class="card-body border-bottom"><h2 class="card-title">Панели с бесплатными моделями</h2><p class="text-secondary mb-0">${num(all.length)} с бесплатными моделями из ${num(d.total)} в реестре · показано ${num(rows.length)}. Доступность и условия проверяйте на сайте панели. Учётные данные здесь не запрашиваются.</p></div>${rows.length?`<div class="table-responsive"><table class="table table-vcenter mb-0" id="panels-table"><thead><tr><th scope="col">Панель</th><th scope="col">Бесплатных моделей</th><th scope="col">Всего моделей</th><th scope="col">Действие</th></tr></thead><tbody>${rows.map(p=>{const raw=String(p.host||p.url||""),url=safeUrl(/^https?:\/\//i.test(raw)?raw:"https://"+raw),host=url?new URL(url).hostname:"Адрес недоступен",models=Array.isArray(p.models)?p.models.length:(p.models||p.model_count||0);return `<tr><td class="fw-medium text-break">${esc(host)}</td><td>${num(p.free_count||p.free||0)}</td><td>${num(models)}</td><td>${external(url,"Открыть панель","btn btn-sm")}</td></tr>`}).join("")}</tbody></table></div>`:empty("Бесплатных панелей пока нет","В текущем реестре нет панелей с бесплатными моделями. Обновите список позже.",'<button class="btn" data-act="panels-retry" type="button">Обновить список</button>')}`}
|
||||
catch(error){if(scope.valid()&&error.name!=="AbortError")box.innerHTML=`<div class="p-3">${failure(error,()=>loadPanels(ctx))}</div>`}}
|
||||
|
||||
Reference in New Issue
Block a user