diff --git a/deploy/app.js b/deploy/app.js index 5d60219..86b5e0d 100644 --- a/deploy/app.js +++ b/deploy/app.js @@ -11,6 +11,7 @@ var fileInput = document.getElementById('fileInput'); var fileTable = document.getElementById('fileTable'); var fileQueue = []; var contractId = null; +var batchId = crypto.randomUUID(); // классификация: привязка всех файлов сессии function formatSize(bytes) { if (!bytes || bytes === 0) return '—'; @@ -207,13 +208,94 @@ fileInput.addEventListener('change', async function() { fileInput.value = ''; fileInput.disabled = false; - // Показать кнопки LLM после авто-парсинга + // Показать кнопки после авто-парсинга var llmBtn = document.getElementById('llmBtn'); llmBtn.style.display = 'flex'; llmBtn.disabled = false; + showClassifyBtn(); lucide.createIcons(); }); +// ── Классификация ────────────────────────────────────────── +function showClassifyBtn() { + var btn = document.getElementById('classifyBtn'); + if (!btn) { + btn = document.createElement('button'); + btn.id = 'classifyBtn'; + btn.className = 'btn btn-primary'; + btn.style.cssText = 'width:100%;justify-content:center;margin-top:8px;background:var(--brand-primary);border-color:var(--brand-primary);'; + btn.innerHTML = ' Классифицировать'; + btn.addEventListener('click', runClassify); + document.getElementById('llmBtn').parentNode.insertBefore(btn, document.getElementById('llmBtn')); + } + btn.style.display = 'flex'; + btn.disabled = false; +} + +async function runClassify() { + var btn = document.getElementById('classifyBtn'); + btn.disabled = true; + btn.innerHTML = ' Классификация...'; + + try { + var resp = await fetch(VM_API + '/api/classify-batch', { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({batch_id: batchId}) + }); + var data = await resp.json(); + if (data.ok) { + btn.innerHTML = '✓ ' + data.done + '/' + data.total + ' классифицировано'; + loadGroups(); + } else { + btn.innerHTML = '✗ ' + (data.error || 'ошибка'); + btn.disabled = false; + } + } catch(e) { + btn.innerHTML = '✗ ' + e.message; + btn.disabled = false; + } +} + +async function loadGroups() { + var resp = await fetch(VM_API + '/api/groups?batch=' + batchId); + var data = await resp.json(); + if (!data.ok || !data.groups) return; + + var diffBody = document.getElementById('diffBody'); + var diffCard = document.getElementById('diffCard'); + diffCard.style.display = 'block'; + diffBody.innerHTML = '
📋 Найдено групп: ' + data.groups.length + '
'; + + data.groups.forEach(function(g, gi) { + var isUnresolved = g.contract_number === '__unresolved__'; + var card = document.createElement('div'); + card.style.cssText = 'border:1px solid ' + (isUnresolved ? 'var(--destructive)' : 'var(--brand-gray)') + ';border-radius:6px;padding:10px;margin-bottom:8px;'; + card.innerHTML = '
' + + (isUnresolved ? '❓ Не распознано' : '📄 ' + (g.contract_number || 'Без номера') + ' — ' + (g.counterparty || 'контрагент не определён')) + + '
' + + '
' + + g.documents.map(function(d) { + return '
' + + '[' + (d.doc_type || '?') + '] ' + + d.filename + + (d.doc_date ? ' ' + d.doc_date + '' : '') + + '
'; + }).join('') + + '
'; + if (!isUnresolved) { + card.innerHTML += ''; + } + diffBody.appendChild(card); + }); + lucide.createIcons(); +} + +window.runCompareForGroup = function(gi) { + // TODO: run /process-v2 for the specific contract + alert('Сравнение для группы ' + gi + ' — в разработке'); +}; + function uploadFile(file, onProgress) { return new Promise(function(resolve, reject) { // .doc → конвертация в docx @@ -226,6 +308,7 @@ function uploadFile(file, onProgress) { var fd = new FormData(); fd.append('files', uploadFile, uploadName); if (contractId) fd.append('contract_id', contractId); + fd.append('batch_id', batchId); xhr.open('POST', UPLOAD_URL); xhr.upload.onprogress = function(e) { if (e.lengthComputable && onProgress) onProgress(Math.round(e.loaded / e.total * 100)); diff --git a/index.cfm b/index.cfm index 22ac895..4e84a5b 100644 --- a/index.cfm +++ b/index.cfm @@ -75,7 +75,7 @@
Nubes - Сверка договоров — LLM AI-driven Event Sourcing v1.0.162 — Lucee + Сверка договоров — LLM AI-driven Event Sourcing v1.0.163 — Lucee