ИШ: этапы обновления шлюза в окне обновления bj, проверка нового ИШ, свежая версия в строке НРД
- окно обновления bj после перезапуска ведёт обновление ИШ по этапам (загрузка, остановка, резервная копия, установка, запуск, проверка) и закрывается только после проверки; пока шлюз обновляется, то же окно на любой странице - bj-igate-admin: этапы stop/backup/verify; после запуска сверяются версия, служба, движок, каналы и ключ с прежними (иначе автооткат), обмен с НРД - версия ИШ в строке НРД читается всегда заново (кэш 6 ч — только сайт НРД); после установки версии пересобираются сразу Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
This commit is contained in:
@@ -1030,6 +1030,9 @@ button.dq-link, .dq-link { background:none !important; border:0 !important; padd
|
||||
<div id="upd-bar" style="height:100%;width:0;background:var(--accent,#2b50d8);transition:width .4s"></div>
|
||||
</div>
|
||||
<p id="upd-detail" style="margin:8px 0 0;font-size:13px;color:var(--muted,#667);min-height:18px"></p>
|
||||
<ol id="upd-ig" style="display:none;list-style:none;padding:0;margin:12px 0 0;font-size:14px;line-height:1.9"></ol>
|
||||
<details id="upd-ig-logw" style="display:none;margin-top:8px"><summary class="muted" style="font-size:12.5px;cursor:pointer">Журнал установки ИШ</summary>
|
||||
<pre id="upd-ig-log" style="max-height:200px;overflow:auto;font-size:11.5px;white-space:pre-wrap;background:var(--card-2,#eef0f4);padding:8px;border-radius:8px;margin:6px 0 0"></pre></details>
|
||||
<div id="upd-done" style="display:none;margin-top:14px;text-align:right"><button type="button" class="btn" onclick="location.reload()">Готово</button></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1055,6 +1058,62 @@ button.dq-link, .dq-link { background:none !important; border:0 !important; padd
|
||||
tick();
|
||||
}
|
||||
}
|
||||
/* Обновление шлюза НРД (ИШ): с обновлением bj пришёл дистрибутив ИШ — bj ставит его сам после перезапуска.
|
||||
Окно не закрывается, пока новый ИШ не установлен и не проверен; на любой странице, пока идёт, —
|
||||
то же окно (страницы не показывают полуобновлённое состояние). Ошибка — текст, журнал и автооткат. */
|
||||
var IGS=[['prep','Загрузка и проверка дистрибутива ИШ'],['stop','Остановка старого ИШ'],['backup','Резервная копия старого ИШ'],
|
||||
['install','Установка нового ИШ'],['start','Запуск нового ИШ'],['verify','Проверка: версия, каналы, ключ, обмен с НРД']];
|
||||
function igKey(s){ var g=s.stage||''; if(/^(queued|deps|dist|user|db|package)$/.test(g)) return 'prep';
|
||||
if(g==='config'||g==='schema') return 'install'; return g; }
|
||||
var ig={on:false,t0:0,seen:false,rb:false,idx:-1};
|
||||
function igDraw(s, waiting){
|
||||
var k=igKey(s||{}), i=-1; IGS.forEach(function(x,j){ if(x[0]===k) i=j; });
|
||||
if(!ig.rb && i>ig.idx) ig.idx=i; if(waiting) ig.idx=-1;
|
||||
var list=document.getElementById('upd-ig'); list.style.display='block';
|
||||
list.innerHTML=IGS.map(function(x,j){
|
||||
var st=j<ig.idx||(s&&s.stage==='done'&&!waiting)?'<span style="color:var(--ok,#2e8b57)">✓</span>':j===ig.idx&&!ig.rb||(waiting&&j===0)?'<span style="color:var(--accent,#2b50d8)">⟳</span>':'<span style="color:var(--muted,#99a)">○</span>';
|
||||
var t=j===ig.idx&&!ig.rb&&s&&s.stage!=='done'?' <span class="muted" style="font-size:12.5px">— '+(s.msg||'')+', '+(s.elapsed||0)+' с</span>':'';
|
||||
return '<li>'+st+' '+x[1]+t+'</li>'; }).join('')+(s&&s.stage==='done'&&!waiting?'<li><span style="color:var(--ok,#2e8b57)">✓</span> <b>Шлюз установлен и работает</b></li>':'');
|
||||
var lw=document.getElementById('upd-ig-logw'), lg=document.getElementById('upd-ig-log');
|
||||
if(s&&s.log){ lw.style.display='block'; lg.textContent=s.log; lg.scrollTop=lg.scrollHeight; }
|
||||
}
|
||||
window.bjIgPhase=function(note){
|
||||
if(ig.on) return; ig.on=true; ig.t0=Date.now(); window.bjIgOv=true; finished=true;
|
||||
show(); document.querySelector('#upd-modal h3').textContent='Обновление шлюза НРД (ИШ)';
|
||||
doneEl.style.display='none'; bar.style.background='var(--accent,#2b50d8)'; bar.style.width='5%';
|
||||
if(note) detail.textContent=note.charAt(0).toUpperCase()+note.slice(1)+'.';
|
||||
(function tick(){
|
||||
fetch('/admin/setup/update/progress',{cache:'no-store',credentials:'same-origin'}).then(function(r){ if(!r.ok) throw 0; return r.json(); }).then(function(p){
|
||||
var s=p.igate||{}, run=s.busy===true, since=(Date.now()-ig.t0)/1000;
|
||||
var fresh=run||ig.seen||(s.elapsed!==undefined&&s.elapsed<since+5); // итог именно этой установки, не прошлой
|
||||
if(run) ig.seen=true;
|
||||
if(s.stage==='rollback'||(ig.rb&&run)){ ig.rb=true; igDraw(s,false);
|
||||
stageEl.innerHTML='<span style="color:var(--warn,#b7791f)">⟲ Обновление не прошло — возвращаю прежнюю версию ИШ</span>'; detail.textContent=s.msg||''; bar.style.width='90%'; }
|
||||
else if(run){ igDraw(s,false); stageEl.textContent='Идёт обновление шлюза НРД. Не закрывайте страницу: обмен с НРД на 1–3 минуты приостановлен.';
|
||||
bar.style.width=Math.max(8,Math.round((ig.idx+1)/(IGS.length+1)*100))+'%'; }
|
||||
else if(fresh&&s.stage==='done'&&!p.igate_to){ igDraw(s,false); finishIg(s.msg,true); return; }
|
||||
else if(fresh&&s.stage==='error'){ igDraw(s,false); finishIg(s.msg,false); return; }
|
||||
else { igDraw(null,true);
|
||||
if(since>15*60){ finishIg('bj не начал обновление шлюза за 15 минут. Шлюз работает на прежней версии; обновить можно на странице НРД → «Перенастроить» → «Шлюз».',false); return; }
|
||||
stageEl.textContent='Получен новый ИШ'+(p.igate_to?' '+p.igate_to:'')+' — bj начнёт обновление шлюза через несколько секунд.'; }
|
||||
setTimeout(tick,2500);
|
||||
}).catch(function(){ setTimeout(tick,3000); });
|
||||
})();
|
||||
};
|
||||
function finishIg(msg, ok){
|
||||
stageEl.innerHTML=ok?'<span style="color:var(--ok,#2e8b57)">✓ Готово</span>':'<span style="color:var(--err,#c0392b)">✗ Обновление шлюза не прошло</span>';
|
||||
detail.textContent=msg||''; bar.style.width='100%'; bar.style.background=ok?'var(--ok,#2e8b57)':'var(--err,#c0392b)';
|
||||
doneEl.style.display='block'; var b=doneEl.querySelector('button');
|
||||
if(ok){ var left=8, t=function(){ if(left<=0){ location.reload(); return; } b.textContent='Готово (страница обновится через '+left+' с)'; left--; setTimeout(t,1000); }; t(); }
|
||||
else { document.getElementById('upd-ig-logw').open=true; b.textContent='Закрыть'; }
|
||||
}
|
||||
function igPending(p){ return !!(p&&(p.igate_to||(p.igate&&p.igate.busy))); }
|
||||
// страница открыта, когда шлюз обновляется (или вот-вот начнёт после перезапуска bj) — то же окно
|
||||
fetch('/admin/setup/update/progress',{cache:'no-store',credentials:'same-origin'}).then(function(r){ return r.ok?r.json():null; }).then(function(p){
|
||||
if(!p||p.active) return;
|
||||
var s=p.igate||{};
|
||||
if(s.busy||(p.igate_to&&s.stage!=='error'&&p.up<12*60)) window.bjIgPhase('');
|
||||
}).catch(function(){});
|
||||
function run(form){
|
||||
var lastChange=Date.now(), lastKey='';
|
||||
// сторож: если отчёт не меняется полторы минуты, перезагружаем страницу — не оставляем «зависшее» окно
|
||||
@@ -1087,7 +1146,9 @@ button.dq-link, .dq-link { background:none !important; border:0 !important; padd
|
||||
// сменилась или отчёт начался заново (новый процесс) — обновление завершено
|
||||
if(!lost && startVer!==null && (p.version!==startVer || (seq0>0 && p.seq===0 && !p.active))){ lost=true; }
|
||||
if(lost){ // bj вернулся после перезапуска
|
||||
if(!target || p.version===target || p.version!==startVer){ finish('Готово: bj перезапущен, работает версия '+p.version+'.', true); detail.textContent=note ? note.charAt(0).toUpperCase()+note.slice(1)+'.' : ''; return; }
|
||||
if(!target || p.version===target || p.version!==startVer){
|
||||
if(igPending(p)){ window.bjIgPhase('bj обновлён до '+p.version+'; теперь обновляется шлюз НРД'); return; }
|
||||
finish('Готово: bj перезапущен, работает версия '+p.version+'.', true); detail.textContent=note ? note.charAt(0).toUpperCase()+note.slice(1)+'.' : ''; return; }
|
||||
}
|
||||
var fresh = p.seq!==seq0; // только отчёт этой попытки
|
||||
if(p.active){ seenActive=true;
|
||||
@@ -1099,6 +1160,7 @@ button.dq-link, .dq-link { background:none !important; border:0 !important; padd
|
||||
} else if(p.finished && fresh){
|
||||
if(p.error){ finish('Обновление не выполнено', false); detail.textContent=p.error; return; }
|
||||
if(target && p.version!==target){ stageEl.textContent='Шаг 4 из 4: перезапуск bj'; bar.style.width='90%'; detail.textContent='Ждём, пока bj поднимется с новой версией…'; }
|
||||
else if(igPending(p)){ window.bjIgPhase(p.result||''); return; }
|
||||
else { finish('Готово', true); detail.textContent=p.result||''; return; }
|
||||
} else if(postDone && !fresh && Date.now()-t0>8000){
|
||||
finish('Готово', true); detail.textContent='Результат — в строке «Последняя проверка».'; return;
|
||||
|
||||
@@ -354,7 +354,7 @@
|
||||
document.getElementById('ig-ov-h').innerHTML=h; document.getElementById('ig-ov-m').textContent=m||'';
|
||||
var l=document.getElementById('ig-ov-log'); if(log){ l.style.display='block'; l.textContent=log; l.scrollTop=l.scrollHeight; } else l.style.display='none';
|
||||
document.getElementById('ig-ov-btns').style.display=fin?'block':'none'; }
|
||||
function ovStart(){ if(ov.on) return; ov.on=true; ov.t0=Date.now(); ovTick(); ov.iv=setInterval(ovTick,3000); }
|
||||
function ovStart(){ if(window.bjIgPhase){ window.bjIgPhase(''); return; } if(ov.on) return; ov.on=true; ov.t0=Date.now(); ovTick(); ov.iv=setInterval(ovTick,3000); }
|
||||
function ovTick(){
|
||||
fetch('/admin/setup/igate/install-status',{cache:'no-store'}).then(function(r){return r.json()}).then(function(s){
|
||||
var run=s.stage&&s.stage!=='done'&&s.stage!=='error';
|
||||
|
||||
Reference in New Issue
Block a user