feat(верификация): рабочая очередь с пагинацией + /skip

- автодогрузка порций + кнопка «Загрузить ещё»; разбор сверху по уверенности
- POST /skip фиксирует пропуск (таблица skipped_item), очередь его исключает

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-27 10:58:10 +05:00
parent 1ff5d93cd8
commit 89928511ba
2 changed files with 29 additions and 4 deletions
+15 -3
View File
@@ -57,6 +57,7 @@
</div>
<p class="text-sm text-tg mt-1">Система предлагает кандидата из справочника — подтвердите, выберите другой или пропустите. Подтверждение обучает систему.</p>
<div id="queue" class="mt-3 space-y-2"></div>
<button id="loadmore" onclick="loadQueue()" class="mt-3 text-sm text-nomad hover:underline hidden">Загрузить ещё →</button>
</section>
</main>
@@ -145,11 +146,17 @@ async function loadAdmin() {
}
async function loadQueue() {
const items = await fetch(`${API}/unmatched?limit=40`).then(r => r.json());
const items = await fetch(`${API}/unmatched?limit=25`).then(r => r.json());
$('queue').innerHTML = items.map(renderCard).join('') || '<div class="text-tg p-4">Очередь пуста 🎉</div>';
$('loadmore').classList.toggle('hidden', items.length === 0);
loadCounts();
}
function maybeRefill() {
// Рабочая очередь: когда необработанных карточек мало — подгружаем следующую порцию.
if ($('queue').querySelectorAll('[id^="card-"]').length < 6) loadQueue();
}
async function loadCounts() {
const c = await fetch(`${API}/unmatched/count`).then(r => r.json());
$('vprogress').innerHTML = `осталось <b>${c.remaining}</b> · обучено синонимов <b class="text-nomad">${c.learned_synonyms}</b>`;
@@ -189,11 +196,16 @@ async function doMatch(itemId, serviceId, btn) {
if (btn) btn.disabled = true;
await fetch(`${API}/match?item_id=${itemId}&service_id=${encodeURIComponent(serviceId)}`, { method: 'POST' });
const card = $(`card-${itemId}`); if (card) card.remove();
loadCounts();
loadCounts(); maybeRefill();
}
function togglePick(id) { $(`pick-${id}`).classList.toggle('hidden'); }
function skipCard(id) { const c = $(`card-${id}`); if (c) c.remove(); }
async function skipCard(id) {
await fetch(`${API}/skip?item_id=${id}`, { method: 'POST' });
const c = $(`card-${id}`); if (c) c.remove();
loadCounts(); maybeRefill();
}
let dictTimer;
function searchDict(itemId, q) {