Phase 3: apply_events.cfm + process.cfm v2 + кнопка v2 (v1.0.74)
This commit is contained in:
@@ -61,7 +61,7 @@
|
||||
<body>
|
||||
<div class="topbar">
|
||||
<img src="/nubes-logo.svg" alt="Nubes">
|
||||
<span class="title">Сверка договоров — LLM <span style="font-weight:400;color:var(--muted);font-size:12px;">v1.0.72 — Lucee</span></span>
|
||||
<span class="title">Сверка договоров — LLM <span style="font-weight:400;color:var(--muted);font-size:12px;">v1.0.74 — Lucee</span></span>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
@@ -90,6 +90,10 @@
|
||||
<i data-lucide="scale" style="width:16px;height:16px;"></i> Сравнить (LLM)
|
||||
</button>
|
||||
|
||||
<button class="btn btn-primary" id="llmBtnV2" style="width:100%;justify-content:center;margin-top:8px;display:none;background:var(--green);border-color:var(--green);">
|
||||
<i data-lucide="scale" style="width:16px;height:16px;"></i> Сравнить v2 (Event Sourcing)
|
||||
</button>
|
||||
|
||||
<details style="margin-top:8px;font-size:12px;">
|
||||
<summary style="cursor:pointer;color:var(--muted);">⚙ Промпт LLM</summary>
|
||||
<textarea id="promptEditor" style="width:100%;height:200px;font-family:monospace;font-size:11px;border:1px solid var(--brand-gray);border-radius:6px;padding:8px;margin-top:4px;"></textarea>
|
||||
@@ -319,9 +323,81 @@ parseBtn.addEventListener('click', async function() {
|
||||
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;
|
||||
var btn = this;
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<span class="spinner"></span> LLM v2...';
|
||||
|
||||
var diffCard = document.getElementById('diffCard');
|
||||
var diffBody = document.getElementById('diffBody');
|
||||
var diffStatus = document.getElementById('diffStatus');
|
||||
diffCard.style.display = 'block';
|
||||
diffBody.innerHTML = '';
|
||||
diffStatus.textContent = '⏳ 0.0с';
|
||||
|
||||
var llmStart = Date.now();
|
||||
var timerInterval = setInterval(function() {
|
||||
diffStatus.textContent = '⏳ ' + ((Date.now() - llmStart) / 1000).toFixed(1) + 'с';
|
||||
}, 200);
|
||||
|
||||
var es = new EventSource('/process.cfm?contract_id=' + contractId + '&v=2');
|
||||
|
||||
es.onmessage = function(e) {
|
||||
var d = JSON.parse(e.data);
|
||||
|
||||
if (d.type === 'extract_start') {
|
||||
diffBody.innerHTML += '<div style="font-size:12px;color:var(--muted);margin-top:2px;">⏳ ' + d.filename + ' → LLM...</div>';
|
||||
}
|
||||
else if (d.type === 'llm_done') {
|
||||
diffBody.innerHTML += '<div style="font-size:12px;color:var(--green);">✓ ' + d.filename + ': ' + d.ops_count + ' операций, ' + d.mode + ' (' + d.time_s + 'с)</div>';
|
||||
}
|
||||
else if (d.type === 'applied') {
|
||||
var s = d.summary || {};
|
||||
diffBody.innerHTML += '<div style="font-size:12px;margin-left:8px;"> +' + (s.added||0) + ' ~' + (s.updated||0) + ' -' + (s.deleted||0) + ' ?' + (s.unresolved||0) + '</div>';
|
||||
}
|
||||
else if (d.type === 'extract_error' || d.type === 'apply_error') {
|
||||
diffBody.innerHTML += '<div style="font-size:12px;color:var(--destructive);">✗ ' + d.filename + ': ' + d.error + '</div>';
|
||||
}
|
||||
else if (d.type === 'done') {
|
||||
clearInterval(timerInterval);
|
||||
es.close();
|
||||
diffStatus.textContent = '✓ ' + d.total_time_s + 'с';
|
||||
btn.innerHTML = '<i data-lucide="check" style="width:16px;height:16px;"></i> ✓ Готово';
|
||||
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>';
|
||||
}
|
||||
document.getElementById('chatCard').style.display = 'block';
|
||||
lucide.createIcons();
|
||||
}
|
||||
else if (d.type === 'error') {
|
||||
clearInterval(timerInterval);
|
||||
es.close();
|
||||
diffBody.innerHTML += '<div style="color:var(--destructive);margin-top:8px;">✗ ' + d.message + '</div>';
|
||||
btn.innerHTML = '<i data-lucide="scale" style="width:16px;height:16px;"></i> Сравнить v2';
|
||||
btn.disabled = false;
|
||||
}
|
||||
};
|
||||
|
||||
es.onerror = function() {
|
||||
clearInterval(timerInterval);
|
||||
es.close();
|
||||
if (diffBody.innerHTML === '') {
|
||||
diffBody.innerHTML = '<div style="color:var(--destructive);">✗ Ошибка соединения</div>';
|
||||
}
|
||||
btn.innerHTML = '<i data-lucide="scale" style="width:16px;height:16px;"></i> Сравнить v2';
|
||||
btn.disabled = false;
|
||||
lucide.createIcons();
|
||||
};
|
||||
});
|
||||
|
||||
// ── Обновить supplement_id/type для radio ──────────────────
|
||||
async function refreshSupps() {
|
||||
if (!contractId) { console.log('refreshSupps: no contractId'); return; }
|
||||
|
||||
Reference in New Issue
Block a user