v1.0.177: buildGroupCard + markGroupDone — разная вёрстка для необработанных и готовых

This commit is contained in:
2026-06-24 20:02:46 +04:00
parent 08220fa4b9
commit 5955c03677
+56 -52
View File
@@ -405,32 +405,7 @@ async function loadGroups() {
'<div style="font-size:12px;">' + docsHtml + '</div>' + '<div style="font-size:12px;">' + docsHtml + '</div>' +
'<div style="font-size:11px;color:var(--muted);margin-top:4px;">Загрузите недостающие базовые договоры для этих номеров.</div>'; '<div style="font-size:11px;color:var(--muted);margin-top:4px;">Загрузите недостающие базовые договоры для этих номеров.</div>';
} else { } else {
card.innerHTML = '<div class="cmp-header" style="font-weight:600;margin-bottom:6px;cursor:pointer;"><span class="cmp-arrow" id="cmpArrow_' + gi + '" style="font-size:10px;margin-right:4px;">▸</span>📄 Договор №' + escHtml(g.contract_number || '?') + ' — ' + escHtml(g.counterparty || 'контрагент не определён') + '</div>' + buildGroupCard(g, gi, card);
'<div style="font-size:12px;">' +
g.documents.map(function(d) {
var typeLabel = {contract: 'договор', supplement: 'допсоглашение', specification: 'спецификация'}[d.doc_type] || d.doc_type;
return '<div style="padding:2px 0;">' +
'<span style="color:var(--muted);">' + escHtml(typeLabel || '?') + '</span> ' +
escHtml(d.filename) +
(d.doc_date ? ' <span style="color:var(--muted);">' + escHtml(d.doc_date) + '</span>' : '') +
'</div>';
}).join('') + '</div>' +
'<button class="btn btn-primary cmp-btn" style="margin-top:6px;font-size:12px;height:28px;" data-gi="' + gi + '">▶ Сравнить эту группу</button>' +
'<div class="cmp-body" id="cmpBody_' + gi + '" style="display:none;margin-top:8px;"></div>';
// Клик на заголовок → свернуть/развернуть результаты
card.querySelector('.cmp-header').addEventListener('click', function() {
var body = document.getElementById('cmpBody_' + gi);
var arrow = document.getElementById('cmpArrow_' + gi);
if (body) {
if (body.style.display === 'none') {
body.style.display = 'block';
if (arrow) arrow.textContent = '▾';
} else {
body.style.display = 'none';
if (arrow) arrow.textContent = '▸';
}
}
});
} }
diffBody.appendChild(card); diffBody.appendChild(card);
}); });
@@ -444,6 +419,59 @@ async function loadGroups() {
lucide.createIcons(); lucide.createIcons();
} }
// ── Карточка необработанной группы ──────────────────────────
function buildGroupCard(g, gi, card) {
card.innerHTML = '<div class="cmp-header" style="font-weight:600;margin-bottom:6px;">' +
'📄 Договор №' + escHtml(g.contract_number || '?') + ' — ' + escHtml(g.counterparty || 'контрагент не определён') +
'</div>' +
'<div style="font-size:12px;">' +
g.documents.map(function(d) {
var typeLabel = {contract: 'договор', supplement: 'допсоглашение', specification: 'спецификация'}[d.doc_type] || d.doc_type;
return '<div style="padding:2px 0;">' +
'<span style="color:var(--muted);">' + escHtml(typeLabel || '?') + '</span> ' +
escHtml(d.filename) +
(d.doc_date ? ' <span style="color:var(--muted);">' + escHtml(d.doc_date) + '</span>' : '') +
'</div>';
}).join('') + '</div>' +
'<button class="btn btn-primary cmp-btn" style="margin-top:6px;font-size:12px;height:28px;" data-gi="' + gi + '">▶ Сравнить эту группу</button>' +
'<div class="cmp-body" id="cmpBody_' + gi + '" style="display:none;margin-top:8px;"></div>';
}
// ── Заменить карточку на обработанную ───────────────────────
function markGroupDone(gi, time) {
var card = document.querySelector('.cmp-body[id="cmpBody_' + gi + '"]').parentNode;
var g = window._groupsData[gi];
card.innerHTML = '<div class="cmp-header" style="font-weight:600;margin-bottom:6px;cursor:pointer;">' +
'<span class="cmp-arrow" id="cmpArrow_' + gi + '" style="font-size:10px;margin-right:4px;">▾</span>' +
'📄 Договор №' + escHtml(g.contract_number || '?') + ' — ' + escHtml(g.counterparty || 'контрагент не определён') +
' <span style="font-weight:400;color:var(--green);font-size:11px;">✓ Готово (' + time + ')</span>' +
'</div>' +
'<div style="font-size:12px;">' +
g.documents.map(function(d) {
var typeLabel = {contract: 'договор', supplement: 'допсоглашение', specification: 'спецификация'}[d.doc_type] || d.doc_type;
return '<div style="padding:2px 0;">' +
'<span style="color:var(--muted);">' + escHtml(typeLabel || '?') + '</span> ' +
escHtml(d.filename) +
(d.doc_date ? ' <span style="color:var(--muted);">' + escHtml(d.doc_date) + '</span>' : '') +
'</div>';
}).join('') + '</div>' +
'<div class="cmp-body" id="cmpBody_' + gi + '" style="margin-top:8px;"></div>';
// Клик на заголовок → свернуть/развернуть
card.querySelector('.cmp-header').addEventListener('click', function() {
var body = document.getElementById('cmpBody_' + gi);
var arrow = document.getElementById('cmpArrow_' + gi);
if (body) {
if (body.style.display === 'none') {
body.style.display = 'block';
if (arrow) arrow.textContent = '▾';
} else {
body.style.display = 'none';
if (arrow) arrow.textContent = '▸';
}
}
});
}
// Текущий активный EventSource (только один одновременно) // Текущий активный EventSource (только один одновременно)
var _activeCompareES = null; var _activeCompareES = null;
var _activeCompareTimer = null; var _activeCompareTimer = null;
@@ -459,22 +487,6 @@ window.runCompareForGroup = async function(gi, btn) {
// Свернуть ТОЛЬКО тело текущей группы // Свернуть ТОЛЬКО тело текущей группы
var curBody = document.getElementById('cmpBody_' + gi); var curBody = document.getElementById('cmpBody_' + gi);
if (curBody) curBody.style.display = 'none'; if (curBody) curBody.style.display = 'none';
var curArrow = document.getElementById('cmpArrow_' + gi);
if (curArrow) curArrow.textContent = '▸';
// Заменить span «✓ Готово» обратно на кнопку ТОЛЬКО для текущей группы
var doneSpan = document.querySelector('.cmp-done[data-gi="' + gi + '"]');
if (doneSpan) {
var newBtn = document.createElement('button');
newBtn.className = 'btn btn-primary cmp-btn';
newBtn.setAttribute('data-gi', gi);
newBtn.textContent = '▶ Сравнить эту группу';
newBtn.style.cssText = 'margin-top:6px;font-size:12px;height:28px;';
newBtn.addEventListener('click', function() {
var g = parseInt(this.getAttribute('data-gi'));
runCompareForGroup(g, this);
});
doneSpan.parentNode.replaceChild(newBtn, doneSpan);
}
btn.disabled = true; btn.disabled = true;
btn.innerHTML = '<span class="spinner"></span> Применяю...'; btn.innerHTML = '<span class="spinner"></span> Применяю...';
@@ -557,18 +569,10 @@ window.runCompareForGroup = async function(gi, btn) {
es.close(); _activeCompareES = null; es.close(); _activeCompareES = null;
statusEl.textContent = '✓ ' + d.total_time_s + 'с'; statusEl.textContent = '✓ ' + d.total_time_s + 'с';
statusEl.style.color = 'var(--green)'; statusEl.style.color = 'var(--green)';
// Заменить кнопку на неактивный span — нельзя перезапустить // Заменить карточку на обработанную (другая вёрстка, нет кнопок)
var span = document.createElement('span'); markGroupDone(gi, d.total_time_s + 'с');
span.className = 'cmp-done';
span.setAttribute('data-gi', gi);
span.textContent = '✓ Готово (' + d.total_time_s + 'с)';
span.style.cssText = 'display:inline-block;margin-top:6px;font-size:12px;height:28px;line-height:28px;padding:0 12px;background:var(--green);color:#fff;border-radius:6px;';
btn.parentNode.replaceChild(span, btn);
// Разблокировать остальные кнопки // Разблокировать остальные кнопки
document.querySelectorAll('.cmp-btn').forEach(function(b) { b.disabled = false; }); document.querySelectorAll('.cmp-btn').forEach(function(b) { b.disabled = false; });
// Показать стрелку раскрытия
var arrow = document.getElementById('cmpArrow_' + gi);
if (arrow) arrow.textContent = '▾';
stepDone('stepCompare'); stepDone('stepCompare');
} }
else if (d.type === 'error') { else if (d.type === 'error') {