Карточки заявок обновляются сами: отпечаток состояния, перерисовка без ручного обновления, индикатор «обновляется автоматически»
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
@@ -35,7 +35,7 @@
|
||||
<b>Перевод не доставлен в НРД</b> — {{sendFailText .}}.<br>
|
||||
<span class="muted">Попытка {{.At.Format "02.01.2006 15:04:05"}}{{if .PackageID}}, пакет ИШ {{.PackageID}}{{end}}{{if gt .Attempts 1}}, попыток: {{.Attempts}}{{end}}. Отправка в DEPO не отмечена, блокировка в QUIK МНП сохраняется. Когда НРД снова будет доступен, нажмите «Отправить повторно» — уйдёт тот же запрос с тем же GUID.</span>
|
||||
</div>{{end}}
|
||||
{{$l := liveOut .Claim}}<div class="live live-big live-{{$l.Kind}}" data-live="out:{{.Claim.ID}}"{{if $l.Active}} data-active="1"{{else}} title="Завершено: состояние больше не проверяется"{{end}}>{{$l.Text}}</div>
|
||||
{{$l := liveOut .Claim}}<div class="live live-big live-{{$l.Kind}}" data-live="out:{{.Claim.ID}}" data-sig="{{$l.Sig}}"{{if $l.Active}} data-active="1"{{else}} title="Завершено: состояние больше не проверяется"{{end}}>{{$l.Text}}</div>
|
||||
<table>
|
||||
<tr><td style="width:200px" class="muted">Создана</td><td>{{.Claim.CreatedAt.Format "02.01.2006 15:04:05"}}</td></tr>
|
||||
<tr><td class="muted">Обновлена</td><td>{{.Claim.UpdatedAt.Format "02.01.2006 15:04:05"}}</td></tr>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<h2>Входящий перевод <code>{{short 8 .It.GUID}}</code>
|
||||
{{if $answered}}<span class="badge confirmed">отвечено</span>{{else}}<span class="badge awaiting_decision">ждёт решения</span>{{end}}
|
||||
</h2>
|
||||
{{$l := liveIn .It}}<div class="live live-big live-{{$l.Kind}}" data-live="in:{{.It.ID}}"{{if $l.Active}} data-active="1"{{else}} title="Завершено: состояние больше не проверяется"{{end}}>{{$l.Text}}</div>
|
||||
{{$l := liveIn .It}}<div class="live live-big live-{{$l.Kind}}" data-live="in:{{.It.ID}}" data-sig="{{$l.Sig}}"{{if $l.Active}} data-active="1"{{else}} title="Завершено: состояние больше не проверяется"{{end}}>{{$l.Text}}</div>
|
||||
<table>
|
||||
<tr><td style="width:220px" class="muted">Запрос сформирован (отправитель)</td><td>{{msk .It.RequestCreated}}</td></tr>
|
||||
<tr><td class="muted">Забрали из шлюза (получено нами)</td><td>{{msk .It.ReceivedAt}}{{if not .It.RequestCreated.IsZero}} <span class="muted" style="font-size:12px">· прохождение: {{transit .It.RequestCreated .It.ReceivedAt}}</span>{{end}}</td></tr>
|
||||
|
||||
@@ -158,6 +158,12 @@ tbody tr:hover td { background:var(--accent-weak); }
|
||||
.live-bad { color:var(--err) } .live-bad::before { background:var(--err) }
|
||||
.live-big { font-size:14px; margin:-6px 0 12px; font-weight:500 }
|
||||
.live[data-active] { color:var(--text-2) } .live-warn[data-active] { color:var(--warn) }
|
||||
.live-meta { font-size:12px; color:var(--muted); margin:2px 0 10px; display:flex; align-items:center; gap:6px; }
|
||||
.live-meta .dot { width:7px; height:7px; border-radius:50%; background:var(--ok,#2e7d32); display:inline-block; animation:livedot 2s ease-in-out infinite; }
|
||||
.live-meta.changed { color:var(--warn,#8a5a00); }
|
||||
.live-meta.lost { color:var(--err,#b3261e); }
|
||||
@keyframes livedot { 50% { opacity:.3 } }
|
||||
@media (prefers-reduced-motion: reduce) { .live-meta .dot { animation:none } }
|
||||
.badge.draft, .badge.validated, .badge.submitted_to_nsd { background:var(--accent-weak); color:var(--accent); }
|
||||
.badge.awaiting_decision, .badge.manual_approval { background:var(--warn-weak); color:var(--warn); }
|
||||
.badge.confirmed, .badge.awaiting_sub16, .badge.done { background:var(--ok-weak); color:var(--ok); }
|
||||
@@ -550,7 +556,22 @@ label { font-size:13px; font-weight:500; }
|
||||
poll();
|
||||
setInterval(poll, 12000); // каждые 12 сек
|
||||
// Онлайн-статус заявок в работе: строки с data-live и data-active опрашиваются, пока ждут.
|
||||
// Карточка заявки (live-big с data-sig): изменилось что-то кроме строки статуса — страница
|
||||
// перерисовывается сама; если оператор уже начал заполнять форму — только предложение обновить.
|
||||
(function(){
|
||||
var dirty = false;
|
||||
document.addEventListener('input', function(e){ if (e.target.closest('main form')) dirty = true; }, true);
|
||||
document.addEventListener('change', function(e){ if (e.target.closest('main form')) dirty = true; }, true);
|
||||
try { var u = new URL(location.href); if (u.searchParams.has('flash')) { u.searchParams.delete('flash'); history.replaceState(null, '', u.pathname + u.search + u.hash); } } catch(e){}
|
||||
function hhmmss(){ var d = new Date(); return ('0'+d.getHours()).slice(-2)+':'+('0'+d.getMinutes()).slice(-2)+':'+('0'+d.getSeconds()).slice(-2); }
|
||||
function meta(e, text, cls){
|
||||
var m = e.nextElementSibling;
|
||||
if (!m || !m.classList.contains('live-meta')) { m = document.createElement('div'); m.className = 'live-meta'; e.parentNode.insertBefore(m, e.nextSibling); }
|
||||
m.className = 'live-meta' + (cls ? ' ' + cls : ''); m.innerHTML = text;
|
||||
}
|
||||
document.querySelectorAll('.live-big[data-live]').forEach(function(e){
|
||||
meta(e, e.hasAttribute('data-active') ? '<span class="dot"></span>обновляется автоматически' : 'заявка завершена — автообновление не требуется');
|
||||
});
|
||||
function tick(){
|
||||
var els = document.querySelectorAll('.live[data-live][data-active]');
|
||||
if (!els.length) return;
|
||||
@@ -561,11 +582,23 @@ label { font-size:13px; font-weight:500; }
|
||||
els.forEach(function(e){
|
||||
var k = e.getAttribute('data-live').split(':'), st = (d[k[0]]||{})[k[1]];
|
||||
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) { location.reload(); return; }
|
||||
meta(e, 'Заявка изменилась. <a href="' + location.pathname + location.search + '">Обновить страницу</a> (отмеченное в форме не сохранится)', 'changed');
|
||||
e.setAttribute('data-sig', st.sig);
|
||||
}
|
||||
e.textContent = st.text;
|
||||
e.className = 'live ' + (e.classList.contains('live-big') ? 'live-big ' : '') + 'live-' + st.kind;
|
||||
e.className = 'live ' + (big ? 'live-big ' : '') + 'live-' + st.kind;
|
||||
if (!st.active) e.removeAttribute('data-active');
|
||||
var nx = e.nextElementSibling;
|
||||
if (big && !(nx && nx.classList.contains('changed'))) {
|
||||
meta(e, st.active ? '<span class="dot"></span>обновляется автоматически · проверено в ' + hhmmss() : 'заявка завершена — автообновление не требуется');
|
||||
}
|
||||
});
|
||||
}).catch(function(){});
|
||||
}).catch(function(){
|
||||
document.querySelectorAll('.live-big[data-live][data-active]').forEach(function(e){ meta(e, 'нет связи с bj — статус не обновляется, повторим через несколько секунд', 'lost'); });
|
||||
});
|
||||
}
|
||||
setInterval(tick, 8000);
|
||||
if (document.querySelector('.live[data-live][data-active]')) setTimeout(tick, 1500);
|
||||
|
||||
Reference in New Issue
Block a user