v1.0.175: виртуальные группы + classify_raw + stepper
This commit is contained in:
@@ -29,6 +29,26 @@ function syncDB() {
|
||||
body: JSON.stringify({keep_ids: keepIds})
|
||||
}).catch(function(){});
|
||||
}
|
||||
// ── Pipeline stepper ─────────────────────────────────────────
|
||||
function stepDone(id) {
|
||||
var el = document.getElementById(id);
|
||||
if (el) { el.innerHTML = el.innerHTML.replace('○','✓'); el.style.color = 'var(--green)'; }
|
||||
}
|
||||
function stepActive(id) {
|
||||
var el = document.getElementById(id);
|
||||
if (el) { el.innerHTML = el.innerHTML.replace('○','⏳').replace('✓','⏳'); el.style.color = 'var(--brand-primary)'; }
|
||||
}
|
||||
function resetStepper(fromId) {
|
||||
var steps = ['stepUpload','stepClassify','stepGroups','stepCompare'];
|
||||
var reset = false;
|
||||
steps.forEach(function(id) {
|
||||
if (id === fromId) reset = true;
|
||||
if (reset) {
|
||||
var el = document.getElementById(id);
|
||||
if (el) { el.innerHTML = el.innerHTML.replace('✓','○').replace('⏳','○'); el.style.color = 'var(--muted)'; }
|
||||
}
|
||||
});
|
||||
}
|
||||
// Утилиты (formatSize, formatDate, moveUp, moveDown, escHtml, fmtDate) —
|
||||
// вынесены в app_utils.js для облегчения анализа и отладки.
|
||||
|
||||
@@ -67,6 +87,8 @@ fileInput.addEventListener('change', async function() {
|
||||
renderTable();
|
||||
// Разблокировать кнопку классификации — состав файлов изменился
|
||||
showClassifyBtn();
|
||||
// Сбросить прогресс пайплайна
|
||||
resetStepper('stepUpload');
|
||||
|
||||
for (var i = 0; i < newFiles.length; i++) {
|
||||
var f = newFiles[i];
|
||||
@@ -186,6 +208,8 @@ fileInput.addEventListener('change', async function() {
|
||||
}
|
||||
|
||||
await refreshSupps();
|
||||
stepDone('stepUpload');
|
||||
stepActive('stepClassify');
|
||||
|
||||
// Синхронизировать БД с таблицей — удалить всё, чего нет в fileQueue
|
||||
syncDB();
|
||||
@@ -220,6 +244,7 @@ async function runClassify() {
|
||||
var btn = document.getElementById('classifyBtn');
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<span class="spinner"></span> Классификация... 0с';
|
||||
stepActive('stepClassify');
|
||||
|
||||
var start = Date.now();
|
||||
var timer = setInterval(function() {
|
||||
@@ -253,6 +278,8 @@ async function runClassify() {
|
||||
clearInterval(pollTimer);
|
||||
if (data.ok) {
|
||||
btn.innerHTML = '✓ ' + data.done + '/' + data.total + ' классифицировано (' + Math.round((Date.now() - start) / 1000) + 'с)';
|
||||
stepDone('stepClassify');
|
||||
stepActive('stepGroups');
|
||||
loadGroups();
|
||||
} else {
|
||||
btn.innerHTML = '✗ ' + (data.error || 'ошибка');
|
||||
@@ -277,6 +304,7 @@ async function loadGroups() {
|
||||
var realGroups = data.groups.filter(function(g) { return g.contract_number !== '__unresolved__'; });
|
||||
var unresolvedGroup = data.groups.find(function(g) { return g.contract_number === '__unresolved__'; });
|
||||
diffBody.innerHTML = '<div style="font-weight:600;margin-bottom:8px;">📋 Найдено групп: ' + realGroups.length + (unresolvedGroup ? ' | ⚠ ' + unresolvedGroup.documents.length + ' файлов не распознано' : '') + '</div>';
|
||||
stepDone('stepGroups');
|
||||
|
||||
// Сохраняем группы для compare
|
||||
window._groupsData = data.groups;
|
||||
@@ -346,6 +374,7 @@ window.runCompareForGroup = async function(gi) {
|
||||
|
||||
var cid = ad.contract_ids[0];
|
||||
btn.innerHTML = '<span class="spinner"></span> Сравнение...';
|
||||
stepActive('stepCompare');
|
||||
|
||||
var diffCard = document.getElementById('diffCard');
|
||||
var diffBody = document.getElementById('diffBody');
|
||||
@@ -539,6 +568,7 @@ document.getElementById('llmBtn').addEventListener('click', function() {
|
||||
es.close();
|
||||
diffStatus.textContent = '✓ ' + d.total_time_s + 'с';
|
||||
btn.innerHTML = '<i data-lucide="check" style="width:16px;height:16px;"></i> ✓ Готово';
|
||||
stepDone('stepCompare');
|
||||
if (d.total_unresolved > 0) {
|
||||
diffBody.innerHTML += '<div style="margin-top:8px;color:#eab308;">⚠ ' + d.total_unresolved + ' неразрешённых строк — <a href="/resolve.cfm?contract_id=' + contractId + '">разобрать</a></div>';
|
||||
}
|
||||
@@ -688,6 +718,22 @@ async function showText(i) {
|
||||
if (f.supp_id) {
|
||||
rightHtml += '<div class="kv"><span class="k">Тип ДС</span><span class="v">' + (f.supp_type || '—') + '</span></div>';
|
||||
}
|
||||
|
||||
// ── Результаты классификации ──────────────────────────
|
||||
if (qData.classify_status === 'classified' || qData.classify_raw) {
|
||||
rightHtml += '<div style="margin-top:12px;font-weight:600;font-size:12px;border-top:1px solid var(--brand-gray);padding-top:8px;">🏷️ Классификация LLM</div>';
|
||||
if (qData.doc_type) rightHtml += '<div class="kv"><span class="k">Тип</span><span class="v">' + qData.doc_type + '</span></div>';
|
||||
if (qData.own_number) rightHtml += '<div class="kv"><span class="k">Номер</span><span class="v">' + qData.own_number + '</span></div>';
|
||||
if (qData.parent_number) rightHtml += '<div class="kv"><span class="k">Родительский</span><span class="v">' + qData.parent_number + '</span></div>';
|
||||
if (qData.doc_date) rightHtml += '<div class="kv"><span class="k">Дата</span><span class="v">' + qData.doc_date + '</span></div>';
|
||||
if (qData.counterparty) rightHtml += '<div class="kv"><span class="k">Контрагент</span><span class="v">' + qData.counterparty + '</span></div>';
|
||||
if (qData.classify_raw) {
|
||||
var rawId = 'raw_' + docId.replace(/-/g,'');
|
||||
rightHtml += '<details style="margin-top:8px;"><summary style="cursor:pointer;font-size:11px;color:var(--brand-primary);">Сырой ответ LLM</summary>';
|
||||
rightHtml += '<pre style="font-size:10px;max-height:200px;overflow:auto;background:var(--brand-grey-light);padding:6px;border-radius:4px;margin-top:4px;">' + escHtml(qData.classify_raw) + '</pre>';
|
||||
rightHtml += '</details>';
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
leftHtml = '<span style="color:var(--destructive);">Ошибка</span>';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user