b4cfa65699
- «Подготовка модулей»: ИШ нет на сервере — bj ставит его из дистрибутива на сервере (образ или обновление bj — версия, проверенная ZETIT), ход — в списке. - Шаг «Шлюз НРД»: установлен и работает — версия; не стоит или не работает — одна кнопка «Установить ИШ» / «Установить ИШ заново» (систему переставлять не нужно). «Скачать с сайта НРД» и «Установить из файла» — только в режиме разработки: версию ИШ меняем после своей проверки, вместе с обновлением bj. - Каналы TEST3 и боевого: до установки ИШ — «канал создаётся после установки ИШ», после — «Создать канал». - «Письма в НРД о доступе к контурам» убраны: НРД подключает заявкой на сайте — ссылка на «MOEX МОСТ для M2M», раздел «Как подключиться». Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
127 lines
13 KiB
HTML
127 lines
13 KiB
HTML
{{/* Шлюз НРД: установка ИШ, каналы контуров TEST3 и боевого, переключение bj между контурами (мастер, шаг 8). */}}
|
|
{{define "igateInstall"}}
|
|
<style>
|
|
#ig-box h3{margin:0 0 6px;font-size:15px}
|
|
#ig-box label.f{display:block;margin:0;font-size:13px}
|
|
#ig-box label.f input,#ig-box label.f select{display:block;margin-top:4px;padding:7px 9px;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px}
|
|
#ig-ct{width:100%;margin-top:8px}
|
|
#ig-ct td{vertical-align:top;padding:6px 8px 6px 0}
|
|
#ig-box .btn.sm{padding:4px 10px;font-size:12.5px}
|
|
#ig-box .btn.ghost{background:var(--card);color:var(--text);border:1px solid var(--border-strong,#c9cdd8)}
|
|
</style>
|
|
<div id="ig-box">
|
|
<div class="card" style="margin:10px 0">
|
|
<h3>Шлюз на этом сервере</h3>
|
|
<div id="ig-head" class="muted">Проверяю…</div>
|
|
<p class="muted" style="font-size:13px;margin:6px 0 0">Версия ИШ — та, что проверена ZETIT вместе с bj; новые версии приходят с обновлением bj. bj ставит шлюз сам при подготовке.</p>
|
|
<div id="ig-reinst" style="display:none;margin-top:10px"><button type="button" class="btn" id="ig-bnd">Установить ИШ</button> <span class="muted" id="ig-bnd-v" style="font-size:12.5px"></span></div>
|
|
<div id="ig-out" style="margin-top:8px;font-size:13px"></div>
|
|
<pre id="ig-log" style="display:none;max-height:180px;overflow:auto;font-size:11px;margin-top:6px"></pre>
|
|
{{if devOn}}<details style="margin-top:8px"><summary style="cursor:pointer;color:var(--accent);font-size:13px">Для разработчиков: другая версия ИШ</summary>
|
|
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:end;margin-top:8px">
|
|
<label class="f">Версия на сайте НРД<input id="ig-ver" value="107.0.930" style="width:140px"></label>
|
|
<button type="button" class="btn" id="ig-dl">Скачать с сайта НРД и установить</button>
|
|
</div>
|
|
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-top:10px">
|
|
<input type="file" id="ig-file" accept=".zip,.deb">
|
|
<button type="button" class="btn ghost" id="ig-up">Установить из файла</button>
|
|
</div>
|
|
</details>{{end}}
|
|
</div>
|
|
|
|
<div class="card" style="margin:10px 0">
|
|
<h3>Контуры НРД</h3>
|
|
<p class="muted" style="font-size:13px;margin:0 0 8px">Сначала — тестовый контур TEST3; когда переводы на нём проходят, переходите на боевой. У каждого контура свой ключ.</p>
|
|
<label class="f" style="max-width:220px">Криптография<select id="ig-crypto"><option value="gost">ГОСТ</option><option value="rsa">RSA</option></select></label>
|
|
<table id="ig-ct"><tbody></tbody></table>
|
|
<div id="ig-prod" style="display:none;border:1px solid var(--warn);border-radius:8px;padding:10px 12px;margin-top:10px">
|
|
<b>Переход на боевой контур</b>
|
|
<p class="muted" style="font-size:13px;margin:6px 0">После перехода bj отправляет в НРД настоящие переводы. На боевом контуре обычно работает настоящий учёт DEPO — укажите его базу (на TEST3 часто использовали копию). Вернуться на TEST3 можно здесь же.</p>
|
|
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:end">
|
|
<label class="f">База DEPO для боевого контура<input id="ig-depo" placeholder="как сейчас" style="width:220px"></label>
|
|
<label class="f">Для подтверждения введите БОЕВОЙ<input id="ig-confirm" autocomplete="off" style="width:160px"></label>
|
|
<button type="button" class="btn" id="ig-goprod" style="background:var(--err);border-color:var(--err)">Перейти на боевой</button>
|
|
</div>
|
|
</div>
|
|
<div id="ig-cout" style="margin-top:8px;font-size:13px"></div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
(function(){
|
|
var head=document.getElementById('ig-head'), tb=document.querySelector('#ig-ct tbody'), cout=document.getElementById('ig-cout'), out=document.getElementById('ig-out'), lg=document.getElementById('ig-log');
|
|
function esc(s){return String(s==null?'':s).replace(/[&<>"]/g,function(c){return{'&':'&','<':'<','>':'>','"':'"'}[c]})}
|
|
function ok(t){return '<span style="color:var(--ok)">✓ '+esc(t)+'</span>'} function bad(t){return '<span style="color:var(--err)">✗ '+esc(t)+'</span>'}
|
|
function post(u,p){return fetch(u,{method:'POST',body:p,cache:'no-store'}).then(function(r){return r.json()})}
|
|
var st=null;
|
|
function load(){
|
|
fetch('/admin/setup/igate/status',{cache:'no-store'}).then(function(r){return r.json()}).then(function(d){
|
|
st=d;
|
|
if(!d.ok){ head.innerHTML=bad(d.error); return; }
|
|
var ri=document.getElementById('ig-reinst'), bb=document.getElementById('ig-bnd'), bv=document.getElementById('ig-bnd-v');
|
|
var running=d.installed&&d.engine==='Running';
|
|
if(!d.installed) head.innerHTML=bad('ИШ на этом сервере не установлен');
|
|
else head.innerHTML=(running?ok('ИШ '+d.version+' установлен и работает'):bad('ИШ '+d.version+' установлен, но не работает: движок '+(d.engine||'не отвечает')+', служба '+d.service));
|
|
// не стоит или не работает — одна кнопка: поставить заново проверенную версию с сервера (систему переставлять не нужно)
|
|
ri.style.display=running?'none':'block';
|
|
if(!running){
|
|
if(d.bundled){ bb.style.display=''; bb.textContent=d.installed?'Установить ИШ заново':'Установить ИШ'; bv.textContent='версия '+d.bundled+' — проверена ZETIT, дистрибутив на сервере'; }
|
|
else { bb.style.display='none'; bv.textContent='Дистрибутива ИШ на сервере нет — он приходит с обновлением bj («Настройка → Обновления»).'; }
|
|
}
|
|
var dep=d.deponent||'', cr=document.getElementById('ig-crypto').value;
|
|
var rows=[['test3','Тестовый TEST3'],['prod','Боевой']].map(function(x){
|
|
var code=(x[0]==='prod'?'PROD':'TEST3')+dep, ch=(d.channels||[]).filter(function(c){return c.code===code})[0], act=d.active_contour===x[0];
|
|
var s=[], a=[];
|
|
if(!dep) s.push(bad('нет депозитарного кода (мастер → «Организация»)'));
|
|
else if(!ch){ if(d.installed){ s.push('<span class="muted">канала в ИШ нет — bj создаст его: адрес и сертификат контура НРД известны</span>'); a.push('<button type="button" class="btn sm" data-act="contour" data-c="'+x[0]+'">Создать канал</button>'); } else s.push('<span class="muted">канал создаётся после установки ИШ</span>'); }
|
|
else {
|
|
s.push(ok('канал '+ch.code)+' <span class="muted" style="font-size:12px">'+esc(ch.crypto+' · '+ch.endpoint)+'</span>');
|
|
s.push(ch.profile?ok('ключ: профиль '+ch.profile):bad('ключ этого контура не установлен'));
|
|
s.push(ch.enabled?ok('канал включён'):'<span class="muted">канал выключен до установки ключа</span>');
|
|
a.push('<button type="button" class="btn sm ghost" data-act="contour" data-c="'+x[0]+'">Обновить канал</button>');
|
|
if(!ch.profile) a.push('<a class="btn sm" href="/admin/setup/keywizard" style="text-decoration:none">Установить ключ</a>');
|
|
if(ch.enabled && !act) a.push(x[0]==='prod'?'<button type="button" class="btn sm" data-act="showprod">Перейти на боевой…</button>':'<button type="button" class="btn sm" data-act="switch" data-c="test3">Сделать активным</button>');
|
|
}
|
|
return '<tr><td style="white-space:nowrap;width:130px"><b>'+x[1]+'</b>'+(act?'<br><span style="color:var(--accent);font-size:12px">● активный</span>':'')+'</td><td>'+s.join('<br>')+(a.length?'<div style="display:flex;gap:6px;flex-wrap:wrap;margin-top:6px">'+a.join('')+'</div>':'')+'</td></tr>';
|
|
});
|
|
tb.innerHTML=rows.join('');
|
|
document.getElementById('ig-depo').placeholder=d.depo_db_prod||d.depo_db||'как сейчас';
|
|
tb.querySelectorAll('button[data-act]').forEach(function(b){ b.onclick=function(){ act(b.dataset.act,b.dataset.c,b); }; });
|
|
}).catch(function(){ head.textContent='Состояние ИШ не получено.'; });
|
|
}
|
|
function act(a,c,b){
|
|
if(a==='showprod'){ document.getElementById('ig-prod').style.display='block'; return; }
|
|
var p=new URLSearchParams(); p.set('contour',c); p.set('crypto',document.getElementById('ig-crypto').value);
|
|
if(a==='contour'){ b.disabled=true; cout.textContent='Записываю канал и перезапускаю ИШ (до 2 минут)…';
|
|
post('/admin/setup/igate/contour',p).then(function(d){ b.disabled=false; cout.innerHTML=d.ok?ok(d.output):bad(d.error); load(); }); }
|
|
if(a==='switch'){ if(!confirm('Переключить bj на тестовый контур TEST3?')) return; cout.textContent='Переключаю…';
|
|
post('/admin/setup/igate/switch',p).then(function(d){ cout.innerHTML=d.ok?ok(d.output):bad(d.error); if(d.ok) setTimeout(function(){location.reload()},15000); }); }
|
|
}
|
|
document.getElementById('ig-goprod').onclick=function(){
|
|
var p=new URLSearchParams(); p.set('contour','prod'); p.set('crypto',document.getElementById('ig-crypto').value);
|
|
p.set('depo_db',document.getElementById('ig-depo').value.trim()); p.set('confirm',document.getElementById('ig-confirm').value.trim());
|
|
if(!confirm('Перейти на БОЕВОЙ контур? bj начнёт отправлять в НРД настоящие переводы.')) return;
|
|
cout.textContent='Переключаю…';
|
|
post('/admin/setup/igate/switch',p).then(function(d){ cout.innerHTML=d.ok?ok(d.output):bad(d.error); if(d.ok) setTimeout(function(){location.reload()},15000); });
|
|
};
|
|
document.getElementById('ig-crypto').onchange=load;
|
|
function poll(){ var t0=Date.now(), iv=setInterval(function(){
|
|
fetch('/admin/setup/igate/install-status',{cache:'no-store'}).then(function(r){return r.json()}).then(function(s){
|
|
if(!s.stage) return; out.textContent='Установка: '+s.msg; if(s.log){ lg.style.display='block'; lg.textContent=s.log; lg.scrollTop=lg.scrollHeight; }
|
|
if(s.stage==='done'){ clearInterval(iv); out.innerHTML=ok(s.msg); load(); }
|
|
if(s.stage==='error'){ clearInterval(iv); out.innerHTML=bad(s.msg); }
|
|
}).catch(function(){});
|
|
if(Date.now()-t0>1200000) clearInterval(iv); },3000); }
|
|
document.getElementById('ig-bnd').onclick=function(){ var p=new URLSearchParams(); p.set('bundled','1');
|
|
out.textContent='Запускаю…'; post('/admin/setup/igate/install',p).then(function(d){ if(!d.ok){out.innerHTML=bad(d.error);return} out.textContent=d.output; poll(); }); };
|
|
if(document.getElementById('ig-dl')) document.getElementById('ig-dl').onclick=function(){ var p=new URLSearchParams(); p.set('version',document.getElementById('ig-ver').value.trim());
|
|
out.textContent='Запускаю…'; post('/admin/setup/igate/install',p).then(function(d){ if(!d.ok){out.innerHTML=bad(d.error);return} out.textContent=d.output; poll(); }); };
|
|
if(document.getElementById('ig-up')) document.getElementById('ig-up').onclick=function(){ var f=document.getElementById('ig-file').files[0]; if(!f){ out.textContent='Выберите файл igate-…-amd64.zip'; return; }
|
|
var fd=new FormData(); fd.append('file',f); out.textContent='Загружаю '+f.name+'…';
|
|
fetch('/admin/setup/igate/install',{method:'POST',body:fd}).then(function(r){return r.json()}).then(function(d){ if(!d.ok){out.innerHTML=bad(d.error);return} out.textContent=d.output; poll(); }); };
|
|
load();
|
|
// установка уже идёт (например, её начала «Подготовка модулей») — показать ход
|
|
fetch('/admin/setup/igate/install-status',{cache:'no-store'}).then(function(r){return r.json()}).then(function(s){ if(s.stage&&s.stage!=='done'&&s.stage!=='error'){ out.textContent='Установка: '+s.msg; poll(); } }).catch(function(){});
|
|
})();
|
|
</script>
|
|
{{end}}
|