diff --git a/index.cfm b/index.cfm index 9d84ed3..8e1433d 100644 --- a/index.cfm +++ b/index.cfm @@ -61,7 +61,7 @@ .text-pane { flex: 1; min-width: 0; overflow-y: auto; max-height: 65vh; } .text-pane:first-child { border-right: 1px solid var(--brand-gray); padding-right: 12px; } .text-pane:last-child { padding-left: 12px; } - .text-pane pre { background: var(--brand-grey-light); padding: 10px; border-radius: 6px; font-size: 11px; white-space: pre-wrap; margin: 0; } + .text-pane pre { background: var(--brand-grey-light); padding: 10px; border-radius: 6px; font-size: 11px; white-space: pre-wrap; word-break: break-word; overflow-x: auto; margin: 0; max-height: 60vh; overflow-y: auto; } .text-pane table { font-size: 11px; width: 100%; } .text-pane th { font-size: 10px; padding: 4px 6px; } .text-pane td { padding: 3px 6px; font-size: 11px; } @@ -71,7 +71,7 @@
Nubes - Сверка договоров — LLM v1.0.77 — Lucee + Сверка договоров — LLM v1.0.78 — Lucee
@@ -86,16 +86,12 @@
- +
ИмяИзменёнРазмерПарсингБазовыйViewТекстИнфо
ИмяИзменёнРазмерПарсингБазовыйТекст
- - @@ -158,7 +154,6 @@ var CONVERT_URL = 'https://contracts.kube5s.ru/convert-doc'; var SITE_URL = ''; // same origin for api calls var fileInput = document.getElementById('fileInput'); -var parseBtn = document.getElementById('parseBtn'); var fileTable = document.getElementById('fileTable'); var fileQueue = []; var contractId = null; @@ -178,8 +173,7 @@ function formatDate(ts) { function renderTable() { if (fileQueue.length === 0) { - fileTable.innerHTML = 'Нет файлов — выберите .docx / .pdf / .zip'; - parseBtn.disabled = true; + fileTable.innerHTML = 'Нет файлов — выберите .docx / .pdf / .zip'; } else { fileTable.innerHTML = fileQueue.map(function(f, i) { var radio = ''; @@ -192,9 +186,7 @@ function renderTable() { '' + formatSize(f.size) + '' + '' + (f.status || '') + '' + '' + radio + '' + - '' + - '' + - '' + + '' + '' + ''; }).join(''); @@ -215,8 +207,6 @@ fileInput.addEventListener('change', async function() { if (newFiles.length === 0) return; fileInput.disabled = true; - parseBtn.disabled = true; - parseBtn.innerHTML = ' Загрузка...'; for (var i = 0; i < newFiles.length; i++) { var f = newFiles[i]; @@ -264,8 +254,6 @@ fileInput.addEventListener('change', async function() { fileInput.value = ''; fileInput.disabled = false; - parseBtn.disabled = false; - parseBtn.innerHTML = ' Парсинг'; // Показать кнопки LLM после авто-парсинга var llmBtn = document.getElementById('llmBtn'); llmBtn.style.display = 'flex'; @@ -326,47 +314,6 @@ function uploadFile(file, onProgress) { }); } -// ── Парсинг ────────────────────────────────────────────────── -parseBtn.addEventListener('click', async function() { - if (!contractId) return; - parseBtn.disabled = true; - parseBtn.innerHTML = ' Парсинг...'; - - for (var i = 0; i < fileQueue.length; i++) { - var f = fileQueue[i]; - if (!f.doc_id || f.parsed) continue; - f.status = '⏳'; - renderTable(); - try { - var resp = await fetch('/parser.cfm?doc_id=' + f.doc_id); - var d = await resp.json(); - if (d.OK && d.STATUS === 'parsed') { - f.parsed = true; - f.parseInfo = d; - f.status = '✓ ' + d.ELEMENT_COUNT + ' эл.'; - } else { - f.status = '✗ ' + (d.ERROR_COUNT > 0 ? (d.ERRORS && d.ERRORS[0] || 'ошибка') : 'ошибка') + ''; - f.parseInfo = d; - } - } catch(e) { - f.status = '✗ сеть'; - } - renderTable(); - } - - // Обновить информацию о supplement_id/type для radio - await refreshSupps(); - - parseBtn.innerHTML = ' ✓ Готово'; - var llmBtn = document.getElementById('llmBtn'); - llmBtn.style.display = 'flex'; - llmBtn.disabled = false; - var llmBtnV2 = document.getElementById('llmBtnV2'); - llmBtnV2.style.display = 'flex'; - llmBtnV2.disabled = false; - lucide.createIcons(); -}); - // ── LLM v2: Event Sourcing ───────────────────────────────── document.getElementById('llmBtnV2').addEventListener('click', function() { if (!contractId) return; @@ -600,132 +547,96 @@ document.getElementById('chatInput').addEventListener('keydown', function(e) { if (e.key === 'Enter') document.getElementById('chatSend').click(); }); -// ── Инфо ───────────────────────────────────────────────────── -function showInfo(i) { - var f = fileQueue[i]; - document.getElementById('modalTitle').textContent = f.name; - var html = '
Размер' + formatSize(f.size) + '
'; - html += '
Изменён' + formatDate(f.lastModified) + '
'; - html += '
Тип' + (f.type || '—') + '
'; - if (f.parseInfo) { - var d = f.parseInfo; - html += '
Элементов' + (d.ELEMENT_COUNT||0) + '
'; - html += '
Параграфов' + (d.PARAGRAPHS||0) + '
'; - html += '
Таблиц' + (d.TABLES||0) + '
'; - html += '
Строк таблиц' + (d.TABLE_ROWS||0) + '
'; - html += '
Страниц' + (d.PAGES||'—') + '
'; - if (d.PARSE_TIME_MS) { - html += '
Время парсинга' + (d.PARSE_TIME_MS > 1000 ? (d.PARSE_TIME_MS/1000).toFixed(1) + ' с' : d.PARSE_TIME_MS + ' мс') + '
'; - } - if (d.TEXT_LENGTH) { - html += '
Символов текста' + d.TEXT_LENGTH.toLocaleString() + '
'; - } - if (d.TEXT_PREVIEW) { - html += '
Превью текста (первые 3000 симв.):
'; - html += '
' + d.TEXT_PREVIEW.substring(0, 3000) + '
'; - } - if (d.TABLE_HEADERS && d.TABLE_HEADERS.length > 0) { - html += '
Заголовки таблиц:
'; - d.TABLE_HEADERS.forEach(function(hdr, ti) { - html += '
Таблица ' + (ti+1) + ' (' + (hdr||[]).length + ' колонок):
'; - html += '
' + (hdr||[]).map(function(c){return c||'(пусто)';}).join(' | ') + '
'; - }); - } - if (d.TABLE_SAMPLES && d.TABLE_SAMPLES.length > 0) { - html += '
Первые строки таблиц:
'; - d.TABLE_SAMPLES.forEach(function(sample, ti) { - html += '
Таблица ' + (ti+1) + ':
'; - html += '
' + sample.map(function(row){ return (row||[]).map(function(c){return c||'(пусто)';}).join(' | '); }).join('\n') + '
'; - }); - } - if (d.ERRORS && d.ERRORS.length > 0) { - html += '
Ошибки:
'; - html += '
' + d.ERRORS.join('\n') + '
'; - } - } - html += '
doc_id' + (f.doc_id || '—') + '
'; - if (f.supp_id) { - html += '
supp_id' + f.supp_id + '
'; - html += '
Тип ДС' + (f.supp_type || '—') + '
'; - } - document.getElementById('modalBody').innerHTML = html; - document.getElementById('modalOverlay').classList.add('open'); -} function closeModal(e) { if (e && e.target !== document.getElementById('modalOverlay')) return; + document.querySelector('.modal').classList.remove('wide'); document.getElementById('modalOverlay').classList.remove('open'); } -async function showView(docId) { - document.getElementById('modalTitle').textContent = 'Просмотр документа'; - document.getElementById('modalBody').innerHTML = 'Загрузка...'; - document.getElementById('modalOverlay').classList.add('open'); - try { - var resp = await fetch('/view.cfm?doc_id=' + docId); - var text = await resp.text(); - document.getElementById('modalBody').innerHTML = '
' + text.replace(//g,'>') + '
'; - } catch(e) { - document.getElementById('modalBody').innerHTML = 'Ошибка загрузки'; - } -} - -async function showText(docId) { - document.getElementById('modalTitle').textContent = 'Текст / Распарсено'; +async function showText(i) { + var f = fileQueue[i]; + var docId = f.doc_id; + document.getElementById('modalTitle').textContent = f.name; document.getElementById('modalBody').innerHTML = 'Загрузка...'; var modal = document.querySelector('.modal'); modal.classList.add('wide'); document.getElementById('modalOverlay').classList.add('open'); - try { - var resp = await fetch('/view.cfm?doc_id=' + docId); - var rawText = await resp.text(); - // Clean leading whitespace from CFML - rawText = rawText.replace(/^\s+/, ''); - // Fetch parsed elements via API - var qResp = await fetch('/api.cfm?action=query&sql=SELECT%20elements_json%20FROM%20documents%20WHERE%20id%3D\'' + docId + '\''); - var qData = await qResp.json(); - var parsedHtml = 'Нет данных парсинга'; - if (qData.OK && qData.ROWS && qData.ROWS.length > 0) { - var ej = qData.ROWS[0].ELEMENTS_JSON; - if (typeof ej === 'object' && ej.Value) ej = ej.Value; - var elements = JSON.parse(ej); - if (elements.length > 0) { - var rows = ''; - elements.forEach(function(el, idx) { - var etype = el.type || el.TYPE || '?'; - var style = el.style || el.STYLE || ''; - var content = ''; - if (etype === 'paragraph') { - content = (el.text || el.TEXT || '').substring(0, 200); - } else if (etype === 'table') { - var tblRows = el.rows || el.ROWS || []; - content = tblRows.length + '×' + (tblRows[0] ? tblRows[0].length : 0) + ' ячеек'; - } - rows += '' + (idx+1) + '' + etype + '' + style + '' + (content||'').replace(//g,'>') + ''; - }); - parsedHtml = '
' + rows + '
ТипСтильСодержание
'; - } + + // Левая панель: сырой текст + var leftHtml = 'Загрузка...'; + if (docId) { + try { + var vResp = await fetch('/view.cfm?doc_id=' + docId); + var rawText = await vResp.text(); + rawText = rawText.replace(/^\s+/, ''); + leftHtml = '
' + rawText.replace(//g,'>') + '
'; + } catch(e) { + leftHtml = 'Ошибка'; } - var html = '
' + - '
Сырой текст
' + rawText.replace(//g,'>') + '
' + - '
Распарсено
' + parsedHtml + '
' + - '
'; - document.getElementById('modalBody').innerHTML = html; - } catch(e) { - document.getElementById('modalBody').innerHTML = 'Ошибка загрузки'; + } else { + leftHtml = '(ещё не загружен)'; } + + // Правая панель: распарсено (статистика + структура) + var rightHtml = ''; + // Базовая инфа + rightHtml += '
Размер' + formatSize(f.size) + '
'; + rightHtml += '
Изменён' + formatDate(f.lastModified) + '
'; + if (f.parseInfo) { + var d = f.parseInfo; + rightHtml += '
Элементов' + (d.ELEMENT_COUNT||0) + '
'; + rightHtml += '
Параграфов' + (d.PARAGRAPHS||0) + '
'; + rightHtml += '
Таблиц' + (d.TABLES||0) + '
'; + rightHtml += '
Строк таблиц' + (d.TABLE_ROWS||0) + '
'; + if (d.PAGES) rightHtml += '
Страниц' + d.PAGES + '
'; + if (d.PARSE_TIME_MS) { + rightHtml += '
Время парсинга' + (d.PARSE_TIME_MS > 1000 ? (d.PARSE_TIME_MS/1000).toFixed(1) + ' с' : d.PARSE_TIME_MS + ' мс') + '
'; + } + if (d.TEXT_LENGTH) rightHtml += '
Символов' + d.TEXT_LENGTH.toLocaleString() + '
'; + + // Заголовки таблиц + if (d.TABLE_HEADERS && d.TABLE_HEADERS.length > 0) { + rightHtml += '
Заголовки таблиц:
'; + d.TABLE_HEADERS.forEach(function(hdr, ti) { + rightHtml += '
Таблица ' + (ti+1) + ' (' + (hdr||[]).length + ' кол.):
'; + rightHtml += '
' + (hdr||[]).map(function(c){return c||'(пусто)';}).join(' | ') + '
'; + }); + } + // Первые строки таблиц + if (d.TABLE_SAMPLES && d.TABLE_SAMPLES.length > 0) { + rightHtml += '
Первые строки:
'; + d.TABLE_SAMPLES.forEach(function(sample, ti) { + rightHtml += '
Таблица ' + (ti+1) + ':
'; + rightHtml += '
' + sample.map(function(row){ return (row||[]).map(function(c){return c||'(пусто)';}).join(' | '); }).join('\n') + '
'; + }); + } + // Ошибки + if (d.ERRORS && d.ERRORS.length > 0) { + rightHtml += '
Ошибки:
'; + rightHtml += '
' + d.ERRORS.join('\n') + '
'; + } + // Превью текста + if (d.TEXT_PREVIEW) { + rightHtml += '
Превью текста:
'; + rightHtml += '
' + d.TEXT_PREVIEW.substring(0, 5000).replace(//g,'>') + '
'; + } + } else { + rightHtml += '
(ещё не распарсен)
'; + } + rightHtml += '
doc_id' + (f.doc_id || '—') + '
'; + if (f.supp_id) { + rightHtml += '
supp_id' + f.supp_id + '
'; + rightHtml += '
Тип ДС' + (f.supp_type || '—') + '
'; + } + + var html = '
' + + '
Сырой текст
' + leftHtml + '
' + + '
Распарсено
' + rightHtml + '
' + + '
'; + document.getElementById('modalBody').innerHTML = html; } -// closeModal — сбросить wide при закрытии -var origCloseModal = closeModal; -closeModal = function(e) { - if (e && e.target !== document.getElementById('modalOverlay')) return; - document.querySelector('.modal').classList.remove('wide'); - document.getElementById('modalOverlay').classList.remove('open'); -}; - -window.showInfo = showInfo; window.closeModal = closeModal; -window.showView = showView; window.showText = showText; // ── Промпт ───────────────────────────────────────────────────