v1.0.109: ↕ arrows replace Базовый radio, order param in SSE, setInitial removed
This commit is contained in:
@@ -119,6 +119,12 @@ class Handler(BaseHTTPRequestHandler):
|
||||
f"JOIN documents d ON s.document_id=d.id "
|
||||
f"WHERE s.contract_id='{cid}' AND d.elements_json IS NOT NULL ORDER BY s.created_at"
|
||||
)
|
||||
# Reorder if client specified &order=...
|
||||
order_ids = (params.get("order", [None])[0] or "").strip()
|
||||
if order_ids:
|
||||
order_list = [x.strip() for x in order_ids.split(",") if x.strip()]
|
||||
order_map = {oid: i for i, oid in enumerate(order_list)}
|
||||
supps.sort(key=lambda s: order_map.get(s["id"], 999999))
|
||||
if not supps:
|
||||
self._sse({"type": "error", "message": "Нет распарсенных файлов"})
|
||||
return
|
||||
|
||||
@@ -39,6 +39,10 @@
|
||||
.info-btn { cursor: pointer; color: var(--muted); background: none; border: none; padding: 2px 4px; font-size: 14px; display: none; }
|
||||
.info-btn:hover { color: var(--brand-primary); }
|
||||
.info-btn.visible { display: inline; }
|
||||
.first-row td { background: rgba(37,99,235,.06); font-weight: 600; }
|
||||
.arrow-btn { cursor: pointer; color: var(--muted); background: none; border: none; padding: 2px; font-size: 12px; line-height: 1; }
|
||||
.arrow-btn:hover { color: var(--brand-primary); }
|
||||
.arrow-btn:disabled { opacity: .3; cursor: default; color: var(--muted); }
|
||||
.modal-overlay { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,.4); z-index: 100; justify-content: center; align-items: center; }
|
||||
.modal-overlay.open { display: flex; }
|
||||
.modal { background: var(--background); border-radius: 12px; border: 1px solid var(--brand-gray); box-shadow: 0 4px 24px rgba(0,0,0,.15); max-width: 520px; width: 90%; max-height: 80vh; display: flex; flex-direction: column; }
|
||||
@@ -71,7 +75,7 @@
|
||||
<body>
|
||||
<div class="topbar">
|
||||
<img src="/nubes-logo.svg" alt="Nubes">
|
||||
<span class="title">Сверка договоров — LLM AI-driven Event Sourcing <span style="font-weight:400;color:var(--muted);font-size:12px;">v1.0.108 — Lucee</span></span>
|
||||
<span class="title">Сверка договоров — LLM AI-driven Event Sourcing <span style="font-weight:400;color:var(--muted);font-size:12px;">v1.0.109 — Lucee</span></span>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
@@ -86,7 +90,7 @@
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>Имя</th><th style="width:130px;">Изменён</th><th style="width:90px;">Размер</th><th style="width:115px;">Парсинг</th><th style="width:30px;">Базовый</th><th style="width:30px;">Текст</th><th style="width:30px;">✕</th></tr>
|
||||
<tr><th>Имя</th><th style="width:130px;">Изменён</th><th style="width:90px;">Размер</th><th style="width:115px;">Парсинг</th><th style="width:30px;">↕</th><th style="width:30px;">Текст</th><th style="width:30px;">✕</th></tr>
|
||||
</thead>
|
||||
<tbody id="fileTable"></tbody>
|
||||
</table>
|
||||
@@ -172,16 +176,16 @@ function renderTable() {
|
||||
fileTable.innerHTML = '<tr class="empty-row"><td colspan="7">Нет файлов — выберите .docx / .pdf / .zip</td></tr>';
|
||||
} else {
|
||||
fileTable.innerHTML = fileQueue.map(function(f, i) {
|
||||
var radio = '';
|
||||
if (f.supp_id) {
|
||||
radio = '<input type="radio" name="base_doc" value="' + f.supp_id + '"' + (f.supp_type === 'initial' ? ' checked' : '') + ' onchange="setInitial(\'' + f.supp_id + '\')" title="Выбрать как базовый договор">';
|
||||
}
|
||||
return '<tr id="row_' + i + '">' +
|
||||
var isFirst = (i === 0);
|
||||
var isLast = (i === fileQueue.length - 1);
|
||||
var arrows = '<button class="arrow-btn" onclick="moveUp(' + i + ')" ' + (isFirst ? 'disabled' : '') + ' title="Вверх">▲</button>' +
|
||||
'<button class="arrow-btn" onclick="moveDown(' + i + ')" ' + (isLast ? 'disabled' : '') + ' title="Вниз">▼</button>';
|
||||
return '<tr id="row_' + i + '" class="' + (isFirst ? 'first-row' : '') + '">' +
|
||||
'<td class="name-cell">' + f.name + '</td>' +
|
||||
'<td style="font-size:12px;color:var(--muted);">' + formatDate(f.lastModified) + '</td>' +
|
||||
'<td class="num-cell" style="font-size:12px;color:var(--muted);">' + formatSize(f.size) + '</td>' +
|
||||
'<td class="status-cell">' + (f.status || '') + '</td>' +
|
||||
'<td style="text-align:center;">' + radio + '</td>' +
|
||||
'<td style="text-align:center;">' + arrows + '</td>' +
|
||||
'<td><button class="info-btn' + (f.doc_id ? ' visible' : '') + '" onclick="showText(' + i + ')" title="Текст / Распарсено"><i data-lucide="file-text" style="width:16px;height:16px;"></i></button></td>' +
|
||||
'<td><button class="remove-btn" onclick="removeFile(' + i + ')" title="Удалить"><i data-lucide="trash-2" style="width:16px;height:16px;"></i></button></td>' +
|
||||
'</tr>';
|
||||
@@ -197,6 +201,19 @@ function removeFile(i) {
|
||||
}
|
||||
window.removeFile = removeFile;
|
||||
|
||||
function moveUp(i) {
|
||||
if (i <= 0) return;
|
||||
var tmp = fileQueue[i]; fileQueue[i] = fileQueue[i-1]; fileQueue[i-1] = tmp;
|
||||
renderTable();
|
||||
}
|
||||
function moveDown(i) {
|
||||
if (i >= fileQueue.length - 1) return;
|
||||
var tmp = fileQueue[i]; fileQueue[i] = fileQueue[i+1]; fileQueue[i+1] = tmp;
|
||||
renderTable();
|
||||
}
|
||||
window.moveUp = moveUp;
|
||||
window.moveDown = moveDown;
|
||||
|
||||
// ── Автозагрузка при выборе файлов ──────────────────────────
|
||||
fileInput.addEventListener('change', async function() {
|
||||
var newFiles = Array.from(fileInput.files);
|
||||
@@ -337,7 +354,8 @@ document.getElementById('llmBtn').addEventListener('click', function() {
|
||||
diffStatus.textContent = '⏳ ' + ((Date.now() - llmStart) / 1000).toFixed(1) + 'с';
|
||||
}, 200);
|
||||
|
||||
var es = new EventSource('https://contracts.kube5s.ru/process-v2?contract_id=' + contractId);
|
||||
var order = fileQueue.map(function(f) { return f.supp_id; }).filter(Boolean).join(',');
|
||||
var es = new EventSource('https://contracts.kube5s.ru/process-v2?contract_id=' + contractId + (order ? '&order=' + encodeURIComponent(order) : ''));
|
||||
var sections = {}; // supplement_id → DOM element
|
||||
|
||||
es.onmessage = function(e) {
|
||||
@@ -444,12 +462,6 @@ async function refreshSupps() {
|
||||
} catch(e) { console.log('refreshSupps error:', e); }
|
||||
}
|
||||
|
||||
function setInitial(suppId) {
|
||||
fetch('/api.cfm?action=set_initial&supplement_id=' + suppId)
|
||||
.then(function() { refreshSupps(); });
|
||||
}
|
||||
window.setInitial = setInitial;
|
||||
|
||||
// ── Чат ──────────────────────────────────────────────────────
|
||||
document.getElementById('chatSend').addEventListener('click', function() {
|
||||
var input = document.getElementById('chatInput');
|
||||
|
||||
Reference in New Issue
Block a user