From a6c925572b7fb4296c012ffad64d5d7197dad475 Mon Sep 17 00:00:00 2001 From: fontvielle Date: Tue, 13 Oct 2026 18:08:34 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9A=D0=B0=D1=80=D1=82=D0=BE=D1=87=D0=BA?= =?UTF-8?q?=D0=B0:=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B2=20DOM=20=D0=BD=D0=B0=20=D0=BC=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=B5=20(=D0=B1=D0=B5=D0=B7=20=D0=BF=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B8)=20=E2=80=94?= =?UTF-8?q?=20=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B8=D1=86=D0=B0=20=D0=BD?= =?UTF-8?q?=D0=B5=20=D0=B4=D1=91=D1=80=D0=B3=D0=B0=D0=B5=D1=82=D1=81=D1=8F?= =?UTF-8?q?;=20=D0=B1=D0=B5=D0=B9=D0=B4=D0=B6=D0=B8=20=D0=BD=D0=B5=20?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=BD=D0=BE=D1=81=D1=8F=D1=82=D1=81?= =?UTF-8?q?=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Вместо location.reload при смене подписи карточка теперь обновляется рекурсивным морфингом
: догружаем ту же страницу и сливаем только изменившиеся узлы, одинаковые поддеревья не трогаем. Прокрутка окна и боковых блоков («Путь заявки» .claim-tl / .in-tl) не сбивается, выделение в неизменном тексте сохраняется, нет прыжков и мигания. Морфинг пропускается, если правится форма (dirty) или идёт выделение. Копи-кнопки переинициализируются (bjInitCopyBars). Плюс .badge { white-space:nowrap } — в журнале стрелка «↗ Исходящий» больше не переносится над словом. Co-Authored-By: Claude Opus 4.8 --- internal/lkgateway/web/templates/layout.html | 52 ++++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/internal/lkgateway/web/templates/layout.html b/internal/lkgateway/web/templates/layout.html index f8665e6..ae8c002 100644 --- a/internal/lkgateway/web/templates/layout.html +++ b/internal/lkgateway/web/templates/layout.html @@ -161,7 +161,7 @@ th { color:var(--muted); font-weight:600; font-size:11px; text-transform:upperca tbody tr:hover td { background:var(--accent-weak); } /* ---- Бейджи статусов ---- */ -.badge { display:inline-block; padding:3px 9px; border-radius:20px; font-size:11px; font-weight:600; } +.badge { display:inline-block; padding:3px 9px; border-radius:20px; font-size:11px; font-weight:600; white-space:nowrap; } .live { font-size:11.5px; margin-top:4px; color:var(--muted); display:flex; align-items:center; gap:6px; line-height:1.3 } .live::before { content:''; width:7px; height:7px; border-radius:50%; background:var(--muted); flex:none } .live-wait::before { background:var(--accent); animation:pulse 2.4s var(--ease) infinite } @@ -798,7 +798,8 @@ button.dq-link, .dq-link { background:none !important; border:0 !important; padd return Promise.resolve(fallback()); }; // Кнопка «Скопировать» над каждым блоком скрипта/кода (pre.copyable): копирует текст целиком. - (function(){ + // Вынесено в window.bjInitCopyBars, чтобы вызывать повторно после обновления карточки в DOM. + window.bjInitCopyBars = function(){ document.querySelectorAll('pre.copyable').forEach(function(pre){ if (pre.previousElementSibling && pre.previousElementSibling.classList.contains('copy-bar')) return; var bar=document.createElement('div'); bar.className='copy-bar'; @@ -812,7 +813,8 @@ button.dq-link, .dq-link { background:none !important; border:0 !important; padd }); bar.appendChild(b); pre.parentNode.insertBefore(bar, pre); }); - })(); + }; + bjInitCopyBars(); // Цепочка связи с НРД в шапке: обновляется каждые 30 с, чтобы открытая страница не показывала старое. (function(){ var el = document.getElementById('nsd-chain'); @@ -856,6 +858,48 @@ button.dq-link, .dq-link { background:none !important; border:0 !important; padd } catch(e){} location.reload(); } + // Обновление карточки заявки БЕЗ перезагрузки: догружаем ту же страницу и аккуратно + // сливаем изменения в DOM (рекурсивный морфинг
). Одинаковые поддеревья не трогаем — + // страница не дёргается, прокрутка окна и боковых блоков («Путь заявки») не сбивается, + // выделение в неизменном тексте сохраняется. Скролл прокручиваемых блоков восстанавливается. + function bjMorphKids(oldP, newP){ + if (!oldP || !newP) return; + var top = oldP.scrollTop, left = oldP.scrollLeft; + var olds = [].slice.call(oldP.childNodes), news = [].slice.call(newP.childNodes); + var common = Math.min(olds.length, news.length), i; + for (i = 0; i < common; i++) bjMorphNode(oldP, olds[i], news[i]); + for (i = olds.length - 1; i >= common; i--) oldP.removeChild(olds[i]); + for (i = common; i < news.length; i++) oldP.appendChild(news[i].cloneNode(true)); + oldP.scrollTop = top; oldP.scrollLeft = left; + } + function bjMorphNode(parent, o, n){ + if (o.nodeType === 3 || o.nodeType === 8) { // текст/комментарий + if (n.nodeType === o.nodeType) { if (o.nodeValue !== n.nodeValue) o.nodeValue = n.nodeValue; } + else parent.replaceChild(n.cloneNode(true), o); + return; + } + if (o.nodeType !== 1 || n.nodeType !== 1 || o.nodeName !== n.nodeName) { parent.replaceChild(n.cloneNode(true), o); return; } + if (o.outerHTML === n.outerHTML) return; // поддерево не изменилось — не трогаем (скролл/выделение целы) + var oa = o.attributes, na = n.attributes, j; + for (j = oa.length - 1; j >= 0; j--) { if (!n.hasAttribute(oa[j].name)) o.removeAttribute(oa[j].name); } + for (j = 0; j < na.length; j++) { if (o.getAttribute(na[j].name) !== na[j].value) o.setAttribute(na[j].name, na[j].value); } + bjMorphKids(o, n); // рекурсивно внутрь + } + var bjRefreshing = false; + function bjRefreshClaim(){ + if (bjRefreshing) return; + bjRefreshing = true; + fetch(location.href, {cache: 'no-store', credentials: 'same-origin'}) + .then(function(r){ return r.ok ? r.text() : Promise.reject(); }) + .then(function(html){ + if (dirty || (window.bjSelecting && window.bjSelecting())) return; // правит форму или выделяет — не трогаем + var doc = new DOMParser().parseFromString(html, 'text/html'); + bjMorphKids(document.querySelector('main'), doc.querySelector('main')); + if (window.bjInitCopyBars) window.bjInitCopyBars(); + }) + .catch(function(){}) + .then(function(){ bjRefreshing = false; }); + } try { var raw = sessionStorage.getItem(scrollKey); if (raw !== null) { @@ -895,7 +939,7 @@ button.dq-link, .dq-link { background:none !important; border:0 !important; padd if (!st) return; var big = e.classList.contains('live-big'), was = e.getAttribute('data-sig'); if (big && was && st.sig && st.sig !== was) { - if (!dirty) { bjReloadKeepScroll(); return; } + if (!dirty) { bjRefreshClaim(); e.setAttribute('data-sig', st.sig); return; } meta(e, 'Заявка изменилась. Обновить страницу (отмеченное в форме не сохранится)', 'changed'); e.setAttribute('data-sig', st.sig); }