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 @@
@@ -86,16 +86,12 @@
- Имя Изменён Размер Парсинг Базовый View Текст Инфо ✕
+ Имя Изменён Размер Парсинг Базовый Текст ✕
-
- Парсинг
-
-
Сравнить (LLM)
@@ -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;
// ── Промпт ───────────────────────────────────────────────────