56643cbe56
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
405 lines
48 KiB
HTML
405 lines
48 KiB
HTML
{{define "content"}}
|
||
<style>
|
||
.wiz-head { text-align:center; padding:8px 0 4px; }
|
||
.wiz-head h1 { font-size:26px; font-weight:720; letter-spacing:-0.02em; margin:0 0 6px; }
|
||
.wiz-head p { color:var(--muted); margin:0; }
|
||
.wizard-progress { display:flex; align-items:center; justify-content:center; gap:0; margin:24px auto 28px; max-width:680px; }
|
||
a.wstep { text-decoration:none; cursor:pointer; }
|
||
a.wstep:hover .bub { box-shadow:0 0 0 4px var(--accent-weak); }
|
||
.wstep { display:flex; flex-direction:column; align-items:center; gap:7px; flex:1; position:relative; }
|
||
.wstep .bub { width:34px; height:34px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:14px; font-weight:650; background:var(--card-2); border:1.5px solid var(--border-strong); color:var(--muted); z-index:1; transition:all .2s; }
|
||
.wstep .lbl { font-size:12px; color:var(--muted); font-weight:550; }
|
||
.wstep::before { content:""; position:absolute; top:17px; left:-50%; width:100%; height:2px; background:var(--border); z-index:0; }
|
||
.wstep:first-child::before { display:none; }
|
||
.wstep.done .bub { background:var(--ok); border-color:var(--ok); color:#fff; }
|
||
.wstep.done .lbl { color:var(--text-2); }
|
||
.wstep.done::before { background:var(--ok); }
|
||
.wstep.current .bub { background:var(--accent); border-color:var(--accent); color:#fff; box-shadow:0 0 0 4px var(--accent-weak); }
|
||
.wstep.current .lbl { color:var(--accent); font-weight:650; }
|
||
.tooltip { display:inline-block; background:var(--border); color:var(--muted); border-radius:50%; width:16px; height:16px; line-height:16px; text-align:center; font-size:11px; cursor:help; margin-left:4px; }
|
||
.where { font-size:12px; color:var(--accent); margin-left:8px; }
|
||
.help-block { background:var(--accent-weak); background:var(--accent-weak); padding:10px 14px; margin:10px 0; font-size:13px; border-radius:0 8px 8px 0; }
|
||
.help-block strong { color:var(--accent); }
|
||
.wiz-card { max-width:680px; margin:0 auto; }
|
||
</style>
|
||
|
||
<div class="wiz-head">
|
||
<h1>Настройка Bridge&Join</h1>
|
||
<p>Пошаговый мастер первого запуска — состояние сохраняется после каждого шага</p>
|
||
</div>
|
||
|
||
<div class="wizard-progress" style="max-width:860px">
|
||
<a href="/admin/wizard?step=1" title="Перейти к шагу 1" class="wstep {{if .Done.License}}done{{end}} {{if eq .Step 1}}current{{end}}"><span class="bub">{{if .Done.License}}✓{{else}}1{{end}}</span><span class="lbl">Лицензия</span></a>
|
||
<a href="/admin/wizard?step=2" title="Перейти к шагу 2" class="wstep {{if .Done.Postgres}}done{{end}} {{if eq .Step 2}}current{{end}}"><span class="bub">{{if .Done.Postgres}}✓{{else}}2{{end}}</span><span class="lbl">База bj</span></a>
|
||
<a href="/admin/wizard?step=3" title="Перейти к шагу 3" class="wstep {{if .Done.Depo}}done{{end}} {{if eq .Step 3}}current{{end}}"><span class="bub">{{if .Done.Depo}}✓{{else}}3{{end}}</span><span class="lbl">Учёт DEPO</span></a>
|
||
<a href="/admin/wizard?step=4" title="Перейти к шагу 4" class="wstep {{if .Done.Crypto}}done{{end}} {{if eq .Step 4}}current{{end}}"><span class="bub">{{if .Done.Crypto}}✓{{else}}4{{end}}</span><span class="lbl">Валидата</span></a>
|
||
<a href="/admin/wizard?step=5" title="Перейти к шагу 5" class="wstep {{if .Done.Certs}}done{{end}} {{if eq .Step 5}}current{{end}}"><span class="bub">{{if .Done.Certs}}✓{{else}}5{{end}}</span><span class="lbl">Сертификаты</span></a>
|
||
<a href="/admin/wizard?step=6" title="Перейти к шагу 6" class="wstep {{if .Done.NSD}}done{{end}} {{if eq .Step 6}}current{{end}}"><span class="bub">{{if .Done.NSD}}✓{{else}}6{{end}}</span><span class="lbl">Шлюз НРД</span></a>
|
||
<a href="/admin/wizard?step=7" title="Перейти к шагу 7" class="wstep {{if .Done.TestRun}}done{{end}} {{if eq .Step 7}}current{{end}}"><span class="bub">{{if .Done.TestRun}}✓{{else}}7{{end}}</span><span class="lbl">Проверка</span></a>
|
||
</div>
|
||
<p style="text-align:center;margin:-14px 0 18px;font-size:13px"><a href="/admin/">Пропустить мастер и перейти в систему →</a> <span class="muted">— вернуться к нему можно из «Настройка → Мастер настройки»</span></p>
|
||
|
||
{{if .Flash}}<div class="card wiz-card" style="background:var(--accent-weak)"><p style="margin:0">{{.Flash}}</p></div>{{end}}
|
||
|
||
<div class="wiz-card">
|
||
|
||
|
||
|
||
{{/* ============= ШАГ 1: Лицензия ============= */}}
|
||
{{if eq .Step 1}}
|
||
<div class="card">
|
||
<h2><span class="dot {{if .Done.License}}ok{{else}}err{{end}}"></span>Шаг 1. Лицензия</h2>
|
||
<div class="help-block"><strong>Что это.</strong> Ключ продукта (BJ-XXXX-XXXX-XXXX) привязывает этот сервер к вашей лицензии.<br>
|
||
<strong>Зачем.</strong> От лицензии зависят модули (обмен с DEPO и QUIK, личный кабинет, НПР/УДС) и получение обновлений: bj скачает и поставит модули, входящие в лицензию, автоматически.<br>
|
||
<strong>Где взять.</strong> Портал клиента <a href="https://lic.zetit.ru/portal/" target="_blank">lic.zetit.ru/portal</a> или письмо от ZETIT.</div>
|
||
{{if .Done.License}}<p>✓ <strong>Ключ продукта введён</strong>, лицензия активна: <strong>{{.Lic.Tenant}}</strong>, план {{.Lic.Plan}}, модули: {{if .Lic.Features}}{{range $i, $f := .Lic.Features}}{{if $i}}, {{end}}{{$f}}{{end}}{{else}}только ядро{{end}}; {{.Lic.Message}}</p>{{end}}
|
||
{{with .Update}}{{if .HasUpdate}}
|
||
<div style="border:1px solid var(--accent);border-radius:8px;padding:12px 14px;margin-top:12px;background:var(--accent-weak)">
|
||
<p style="margin:0 0 6px;font-weight:600">На сервере лицензий есть что поставить (выпуск {{.Available}})</p>
|
||
<p class="muted" style="margin:0 0 10px;font-size:13px">Образ установил ту версию bj, с которой был собран. На сервере лицензий есть более новая — с исправлениями ядра, установщика и служб. Поставьте её сейчас, до настройки: bj перезапустится примерно на 10 секунд, затем обновите страницу.<br>{{.Message}}</p>
|
||
<form method="post" action="/admin/setup/update/apply" style="margin:0">
|
||
<input type="hidden" name="return_to" value="/admin/wizard?step=1">
|
||
<button type="submit" class="btn">Обновить сейчас</button>
|
||
</form>
|
||
</div>
|
||
{{else}}<p class="muted" style="font-size:13px">✓ Установлена последняя версия bj ({{.Available}}).</p>{{end}}{{end}}
|
||
{{if .Done.License}}<details style="margin-top:12px"><summary style="cursor:pointer;color:var(--accent);font-size:13px">Сменить ключ продукта (обычно не нужно)</summary>
|
||
<form method="post" action="/admin/setup/license/activate" style="margin-top:12px;display:grid;gap:10px">
|
||
<input type="hidden" name="return_to" value="/admin/wizard?step=1">
|
||
<label>Ключ продукта</label>
|
||
<input type="text" name="code" placeholder="BJ-XXXX-XXXX-XXXX" autocomplete="off" style="padding:8px;text-transform:uppercase;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px">
|
||
<button type="submit" class="btn" style="justify-self:start">{{if .Done.License}}Сменить ключ{{else}}Активировать{{end}}</button>
|
||
</form>
|
||
</details>{{else}}
|
||
<form method="post" action="/admin/setup/license/activate" style="margin-top:12px;display:grid;gap:10px">
|
||
<input type="hidden" name="return_to" value="/admin/wizard?step=1">
|
||
<label>Ключ продукта</label>
|
||
<input type="text" name="code" placeholder="BJ-XXXX-XXXX-XXXX" autocomplete="off" style="padding:8px;text-transform:uppercase;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px">
|
||
<button type="submit" class="btn" style="justify-self:start">{{if .Done.License}}Сменить ключ{{else}}Активировать{{end}}</button>
|
||
</form>{{end}}
|
||
<div style="margin-top:20px;display:flex;justify-content:space-between"><span></span>
|
||
{{if .Done.License}}<a href="/admin/wizard?step=2" class="btn" style="text-decoration:none">К шагу 2 →</a>{{else}}<a href="/admin/wizard?step=2" class="btn" style="background:var(--card);color:var(--text);border:1px solid var(--border-strong,#c9cdd8);text-decoration:none">Пропустить (ввести позже) →</a>{{end}}</div>
|
||
</div>
|
||
{{end}}
|
||
|
||
{{/* ============= ШАГ 3: Учёт DEPO (Fancy) ============= */}}
|
||
{{if eq .Step 3}}
|
||
<div class="card">
|
||
<h2><span class="dot {{if .Done.Depo}}ok{{else}}err{{end}}"></span>Шаг 3. Учётная система DEPO (Fancy)</h2>
|
||
<div class="help-block"><strong>Что это.</strong> Подключение к базе депозитарного учёта DEPO (MS SQL / PostgreSQL).<br>
|
||
<strong>Зачем.</strong> bj сверяет с DEPO каждый перевод (клиент, счёт, остаток, квалификация) и передаёт в DEPO поручения и их исполнение — документы создаются в учёте автоматически. Отсюда же bj возьмёт ваши реквизиты в НРД (шаг 6), чтобы не вводить их вручную.<br>
|
||
<strong>Что нужно.</strong> Адрес сервера БД и логин с правами чтения DEPO и записи в трансферные таблицы FTV_M2M (выдаёт администратор СУБД).</div>
|
||
{{if not .DepoLicensed}}
|
||
<p class="muted">Модуль обмена с DEPO и QUIK не входит в текущую лицензию — шаг пропускается. После добавления модуля в лицензию он станет доступен здесь и в «Настройка → Обмен Fancy».</p>
|
||
{{else}}
|
||
<p class="muted" style="margin:6px 0 0">Три части: подключение к базе, трансферные таблицы обмена, обработка (job), которая превращает записи bj в документы DEPO.</p>
|
||
|
||
<h3 style="margin-top:16px">1. Подключение к базе DEPO {{if .Settings.Fancy.Server}}<span style="color:var(--ok);font-size:14px">✓ {{.Settings.Fancy.Server}}</span>{{end}}</h3>
|
||
<form method="post" action="/admin/setup/fancy" style="margin-top:12px;display:grid;gap:10px">
|
||
<input type="hidden" name="return_to" value="/admin/wizard?step=3">
|
||
<div><label>Тип СУБД</label><select name="db_type" style="padding:8px;width:100%;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px"><option value="mssql" {{if ne .Settings.Fancy.DBType "postgres"}}selected{{end}}>MS SQL Server</option><option value="postgres" {{if eq .Settings.Fancy.DBType "postgres"}}selected{{end}}>PostgreSQL</option></select></div>
|
||
<div><label>Сервер (адрес или host\instance)</label><input type="text" name="server" value="{{.Settings.Fancy.Server}}" placeholder="10.0.0.21" style="padding:8px;width:100%;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px"></div>
|
||
<div><label>Порт</label><input type="text" name="port" value="{{if .Settings.Fancy.Port}}{{.Settings.Fancy.Port}}{{else}}1433{{end}}" style="padding:8px;width:100%;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px"></div>
|
||
<div><label>Логин БД</label><input type="text" name="user" value="{{.Settings.Fancy.User}}" autocomplete="off" style="padding:8px;width:100%;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px"></div>
|
||
<div><label>Пароль {{if .Settings.Fancy.Server}}<span class="muted">(пусто — оставить прежний)</span>{{end}}</label><input type="password" name="password" autocomplete="new-password" style="padding:8px;width:100%;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px"></div>
|
||
<input type="hidden" name="encrypt" value="{{if .Settings.Fancy.Encrypt}}{{.Settings.Fancy.Encrypt}}{{else}}disable{{end}}">
|
||
<div style="display:flex;gap:10px;flex-wrap:wrap"><button type="submit" class="btn">Сохранить</button>
|
||
{{if .Settings.Fancy.Server}}<button type="submit" class="btn" formaction="/admin/setup/fancy/test" style="background:var(--card);color:var(--text);border:1px solid var(--border-strong,#c9cdd8)">Проверить соединение</button>{{end}}</div>
|
||
</form>
|
||
{{if .Settings.Fancy.Server}}
|
||
{{$btn2 := "background:var(--card);color:var(--text);border:1px solid var(--border-strong,#c9cdd8)"}}
|
||
<h3 style="margin-top:22px">2. Трансферные таблицы FTV_M2M {{if .Settings.Fancy.DepoTablesCheckOK}}<span style="color:var(--ok);font-size:14px">✓ на месте</span>{{end}}</h3>
|
||
<div class="help-block" style="font-size:13px"><strong>Что это.</strong> Четыре таблицы в базе DEPO, через которые идёт обмен: поручения <code>FTV_M2M</code> и их строки, события <code>FTV_M2M_EVENTS</code>, справочник участников НРД. Данные учёта они не трогают; создание можно повторять — добавляется только недостающее.</div>
|
||
<form method="post" action="/admin/setup/fancy/depo-tables" style="display:flex;gap:10px;align-items:flex-end;flex-wrap:wrap">
|
||
<input type="hidden" name="return_to" value="/admin/wizard?step=3">
|
||
<input type="hidden" name="depo_tables_mode" value="auto">
|
||
<input type="hidden" name="iis_contract_marker" value="{{.Settings.Fancy.IISContractMarker}}">
|
||
<label style="flex:1;min-width:220px">База DEPO на сервере <input type="text" name="depo_database" value="{{.Settings.Fancy.DepoDatabase}}" placeholder="{{.DepoTables.DB}}" pattern="[A-Za-z][A-Za-z0-9_]*" style="width:100%;padding:8px"></label>
|
||
<button type="submit" class="btn" style="{{$btn2}}">Сохранить имя базы</button>
|
||
</form>
|
||
{{if not .Settings.Fancy.DepoTablesCheckOK}}
|
||
<form method="post" action="/admin/setup/fancy/depo-tables/create" style="margin-top:10px;display:grid;gap:8px">
|
||
<input type="hidden" name="return_to" value="/admin/wizard?step=3">
|
||
<p style="margin:0"><b>Создать таблицы в базе {{.DepoTables.DB}}.</b> <span class="muted" style="font-size:13px">Логин администратора СУБД ({{if .DepoTables.Postgres}}владелец базы{{else}}db_owner в базе или sa{{end}}) нужен один раз и не сохраняется; bj заодно выдаст права своему логину {{.DepoTables.User}}. Пусто — попробовать логином bj.</span></p>
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:8px">
|
||
<input type="text" name="admin_user" autocomplete="off" placeholder="логин, например {{if .DepoTables.Postgres}}postgres{{else}}sa{{end}}" style="padding:8px">
|
||
<input type="password" name="admin_password" autocomplete="new-password" placeholder="пароль" style="padding:8px">
|
||
</div>
|
||
<div><button type="submit" class="btn">Создать таблицы</button> <a href="/admin/setup/fancy/depo-tables/script.sql" style="font-size:13px;margin-left:8px">или скачать скрипт для администратора</a></div>
|
||
</form>
|
||
{{end}}
|
||
<form method="post" action="/admin/setup/fancy/depo-tables/check" style="margin-top:8px"><input type="hidden" name="return_to" value="/admin/wizard?step=3"><button type="submit" class="btn" style="{{$btn2}}">Проверить таблицы</button></form>
|
||
{{if .Settings.Fancy.DepoTablesCheck}}<p style="font-size:13px;margin-top:6px;{{if .Settings.Fancy.DepoTablesCheckOK}}color:var(--ok){{else}}color:var(--err){{end}}">{{if .Settings.Fancy.DepoTablesCheckOK}}✓{{else}}✗{{end}} {{.Settings.Fancy.DepoTablesCheck}}</p>{{end}}
|
||
|
||
<h3 style="margin-top:22px">3. Обработка обмена (job) {{if .Settings.Fancy.DepoJobCheckOK}}<span style="color:var(--ok);font-size:14px">✓ работает</span>{{end}}</h3>
|
||
<div class="help-block" style="font-size:13px"><strong>Что это.</strong> Процедура <code>{{.DepoJob.Proc}}</code> в базе DEPO каждые {{.DepoJob.Every}} с забирает записи bj из трансферных таблиц и создаёт по ним документы и операции DEPO. Кто-то должен её запускать.<br>
|
||
{{if .DepoEdition}}<strong>Ваш сервер:</strong> {{.DepoEdition}} — {{if .DepoAgent}}есть SQL Server Agent, рекомендуем джобу Agent, её создаст bj.{{else}}редакция без SQL Server Agent, процедуру будет запускать сам bj.{{end}}{{else if .DepoTables.Postgres}}<strong>Ваш сервер:</strong> PostgreSQL — процедуру будет запускать сам bj.{{end}}</div>
|
||
{{$mode := .Settings.Fancy.DepoJobMode}}{{if not $mode}}{{$mode = .DepoJobDef}}{{end}}
|
||
<form method="post" action="/admin/setup/fancy/depo-job" style="display:grid;gap:6px">
|
||
<input type="hidden" name="return_to" value="/admin/wizard?step=3">
|
||
<input type="hidden" name="depo_job_every_sec" value="{{.DepoJob.Every}}">
|
||
<input type="hidden" name="depo_job_proc" value="{{.Settings.Fancy.DepoJobProc}}">
|
||
<input type="hidden" name="depo_job_run_as" value="{{.Settings.Fancy.DepoJobRunAs}}">
|
||
{{if not .DepoTables.Postgres}}<label style="display:flex;gap:8px;align-items:flex-start"><input type="radio" name="depo_job_mode" value="sql-auto" {{if eq $mode "sql-auto"}}checked{{end}}> <span><b>Джоба SQL Server Agent, создаёт bj</b> <span class="muted" style="font-size:13px">— рекомендуется: работает, даже когда bj перезапускается; нужен разовый логин администратора SQL.</span></span></label>{{end}}
|
||
<label style="display:flex;gap:8px;align-items:flex-start"><input type="radio" name="depo_job_mode" value="bj" {{if eq $mode "bj"}}checked{{end}}> <span><b>Запускает сам bj</b> <span class="muted" style="font-size:13px">— для SQL Server Express и PostgreSQL; нужно одно право на процедуру.</span></span></label>
|
||
{{if not .DepoTables.Postgres}}<label style="display:flex;gap:8px;align-items:flex-start"><input type="radio" name="depo_job_mode" value="sql-manual" {{if eq $mode "sql-manual"}}checked{{end}}> <span><b>Джоба SQL Server Agent, создаёт администратор</b> <span class="muted" style="font-size:13px">— bj даст готовый скрипт.</span></span></label>{{end}}
|
||
<div><button type="submit" class="btn" style="{{$btn2}}">{{if .Settings.Fancy.DepoJobMode}}Сменить способ{{else}}Выбрать способ{{end}}</button></div>
|
||
</form>
|
||
{{if eq .Settings.Fancy.DepoJobMode "sql-auto"}}
|
||
<form method="post" action="/admin/setup/fancy/depo-job/create" style="margin-top:10px;display:grid;gap:8px">
|
||
<input type="hidden" name="return_to" value="/admin/wizard?step=3">
|
||
<p style="margin:0"><b>Создать джобу {{.DepoJob.Name}}.</b> <span class="muted" style="font-size:13px">Логин администратора SQL (sysadmin, например sa) нужен один раз и не сохраняется. SQL Server Agent должен быть запущен.</span></p>
|
||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:8px">
|
||
<input type="text" name="admin_user" autocomplete="off" placeholder="логин, например sa" style="padding:8px">
|
||
<input type="password" name="admin_password" autocomplete="new-password" placeholder="пароль" style="padding:8px">
|
||
</div>
|
||
<div><button type="submit" class="btn">Создать джобу и проверить</button></div>
|
||
</form>
|
||
{{else if eq .Settings.Fancy.DepoJobMode "bj"}}
|
||
<p style="margin:10px 0 4px"><b>Администратору SQL — выполнить один раз:</b></p><pre class="copyable" style="font-size:12px">{{.DepoJob.GrantScript}}</pre>
|
||
{{else if eq .Settings.Fancy.DepoJobMode "sql-manual"}}
|
||
<p style="margin:10px 0 4px"><b>Скрипт для администратора SQL:</b></p><pre class="copyable" style="font-size:12px;max-height:260px;overflow:auto">{{.DepoJob.AgentScript}}</pre>
|
||
{{end}}
|
||
{{if .Settings.Fancy.DepoJobMode}}
|
||
<form method="post" action="/admin/setup/fancy/depo-job/check" style="margin-top:8px"><input type="hidden" name="return_to" value="/admin/wizard?step=3"><button type="submit" class="btn" style="{{$btn2}}">Проверить обработку</button> <span class="muted" style="font-size:12px">bj кладёт служебное событие и ждёт до 40 с, пока его обработают</span></form>
|
||
{{if .Settings.Fancy.DepoJobCheck}}<p style="font-size:13px;margin-top:6px;{{if .Settings.Fancy.DepoJobCheckOK}}color:var(--ok){{else}}color:var(--err){{end}}">{{if .Settings.Fancy.DepoJobCheckOK}}✓{{else}}✗{{end}} {{.Settings.Fancy.DepoJobCheck}}</p>{{end}}
|
||
{{end}}
|
||
{{end}}
|
||
{{end}}
|
||
<div style="margin-top:20px;display:flex;justify-content:space-between">
|
||
<a href="/admin/wizard?step=2" class="btn" style="background:var(--card);color:var(--text);border:1px solid var(--border-strong,#c9cdd8);text-decoration:none">← К шагу 2</a>
|
||
<a href="/admin/wizard?step=4" class="btn" style="{{if not .Done.Depo}}background:var(--card);color:var(--text);border:1px solid var(--border-strong,#c9cdd8);{{end}}text-decoration:none">{{if .Done.Depo}}К шагу 4 →{{else}}Пропустить →{{end}}</a></div>
|
||
</div>
|
||
{{end}}
|
||
{{/* ============= ШАГ 1: PostgreSQL ============= */}}
|
||
{{if eq .Step 2}}
|
||
<div class="card">
|
||
<h2><span class="dot {{if .Done.Postgres}}ok{{else}}err{{end}}"></span>Шаг 2. База данных bj (PostgreSQL)</h2>
|
||
<p>База самого bj: журнал заявок и поручений, история обмена с НРД и DEPO, пользователи.</p>
|
||
{{if .Done.Postgres}}<p>✓ База готова{{if .PGSummary}}: {{.PGSummary}}{{end}}. Её создал установщик — ничего делать не нужно, переходите к следующему шагу.</p>{{end}}
|
||
|
||
{{if not .Done.Postgres}}<div class="help-block">
|
||
<strong>Что выбрать?</strong> Если у вас уже есть рабочий PostgreSQL — нажмите «У меня уже есть PostgreSQL» и введите DSN. Если впервые настраиваете — выберите «Поднять автоматически», система сама развернёт контейнер с PostgreSQL и накатит миграции.
|
||
</div>{{end}}
|
||
|
||
{{if and devOn (not .Settings.Postgres.DSN)}}
|
||
<div style="background:var(--bg);border:1px solid var(--accent);border-radius:6px;padding:14px;margin-top:12px">
|
||
<h3 style="margin:0 0 8px 0;font-size:15px">Вариант А — для тех, у кого нет своего PostgreSQL</h3>
|
||
<p class="muted" style="margin:0 0 10px 0">Bridge-and-Join-s сам поднимет PostgreSQL в контейнере (podman-compose), создаст БД <code>bj</code> и накатит миграции. Подходит для дев-стенда. Для продакшена лучше указать свой DSN.</p>
|
||
<form method="post" action="/admin/setup/postgres/quick-start" style="margin:0">
|
||
<button type="submit" class="btn" style="background:var(--ok)">Поднять локальный PostgreSQL автоматически</button>
|
||
<span class="muted" style="margin-left:10px;font-size:12px">~10-30 сек</span>
|
||
</form>
|
||
</div>
|
||
{{end}}
|
||
|
||
<details style="margin-top:14px" {{if not .Settings.Postgres.DSN}}open{{end}}>
|
||
<summary style="cursor:pointer;color:var(--accent)">{{if .Settings.Postgres.DSN}}Подключить другую базу (обычно не нужно){{else}}Вариант Б — у меня уже есть PostgreSQL, введу DSN сам{{end}}</summary>
|
||
<form method="post" action="/admin/setup/postgres" style="margin-top:12px">
|
||
<label>DSN (строка подключения) <span class="tooltip" title="Формат: postgres://пользователь:пароль@хост:порт/база?sslmode=disable. Например: postgres://bj:secret@db.example.com:5432/bj?sslmode=require">?</span></label>
|
||
<input type="text" name="dsn" value="{{.Settings.Postgres.DSN}}" placeholder="postgres://bj:secret@127.0.0.1:5432/bj?sslmode=disable" style="width:100%;padding:8px;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px;margin-top:6px">
|
||
<p class="muted" style="margin-top:8px">При сохранении выполняется проверка подключения (Ping). Если БД недоступна — будет ошибка.</p>
|
||
<button type="submit" class="btn" style="margin-top:8px">Сохранить и проверить</button>
|
||
</form>
|
||
</details>
|
||
|
||
<div style="margin-top:20px;display:flex;justify-content:space-between">
|
||
<a href="/admin/wizard?step=1" class="btn" style="background:var(--card);color:var(--text);border:1px solid var(--border-strong,#c9cdd8);text-decoration:none">← К шагу 1</a>
|
||
{{if .Done.Postgres}}<a href="/admin/wizard?step=3" class="btn" style="text-decoration:none">К шагу 3 →</a>{{else}}<button class="btn" disabled style="opacity:0.5;cursor:not-allowed">К шагу 2 → (сначала настройте PostgreSQL или нажмите «in-memory режим»)</button>{{end}}
|
||
</div>
|
||
{{if not .Done.Postgres}}<p style="margin-top:8px"><a href="/admin/wizard?step=3&skip=postgres" style="font-size:13px">Пропустить (буду работать в режиме in-memory — без сохранения сделок)</a></p>{{end}}
|
||
</div>
|
||
{{end}}
|
||
|
||
{{/* ============= ШАГ 2: Крипто (Валидата) ============= */}}
|
||
{{if eq .Step 4}}
|
||
<div class="card">
|
||
<h2><span class="dot {{if .Done.Crypto}}ok{{else}}err{{end}}"></span>Шаг 4. СКЗИ «Валидата Клиент L»</h2>
|
||
<p>СКЗИ «Валидата Клиент L» проверяет подписи НРД на квитанциях и сообщениях и нужно для работы с ключами и сертификатами (шаг 5).</p>
|
||
{{if .ValidataVer}}
|
||
<p>✓ Валидата установлена вместе с bj: версия {{.ValidataVer}}, каталог <code>/opt/Validata/VDCSP</code>. Ничего настраивать на этом шаге не нужно.</p>
|
||
<p class="muted" style="font-size:13px">bj работает с Валидатой через свою службу криптографии <code>bj-crypto</code>{{if eq .CryptoSvc "active"}} — она запущена{{else}} — сейчас она не запущена: служба ставится обновлением с сервера лицензий (шаг 1, кнопка «Обновить сейчас»), а работает с ключом, установленным на шаге 5{{end}}.</p>
|
||
{{else}}
|
||
<p style="color:var(--err)">Валидата на этом сервере не найдена.</p>
|
||
<div class="help-block">
|
||
<strong>Как поставить.</strong> С образа Bridge&Join она ставится сама. Если bj ставили на готовую систему: пакеты <code>zpki</code> и <code>zsdk</code> из дистрибутива НРД (<a href="https://fs.moex.com/cdp/po/ClientL_Other.zip" target="_blank">ClientL_Other.zip</a> для Ubuntu 22.04, <a href="https://fs.moex.com/cdp/po/ClientL_ALSE.zip" target="_blank">ClientL_ALSE.zip</a> для Astra Linux) — <code>sudo apt install ./zpki_*.deb ./zsdk_*.deb</code>, подробнее — <a href="/admin/help/crypto">справка</a>. После установки обновите эту страницу.
|
||
</div>
|
||
{{if devOn}}<form method="post" action="/admin/setup/crypto" style="margin-top:12px">
|
||
<input type="hidden" name="provider" value="stub">
|
||
<button type="submit" class="btn" style="background:var(--card);color:var(--text);border:1px solid var(--border-strong,#c9cdd8)">Режим разработки: работать без криптографии (stub)</button>
|
||
</form>{{end}}
|
||
{{end}}
|
||
|
||
<div style="margin-top:20px;display:flex;justify-content:space-between">
|
||
<a href="/admin/wizard?step=3" class="btn" style="background:var(--card);color:var(--text);border:1px solid var(--border-strong,#c9cdd8);text-decoration:none">← К шагу 3</a>
|
||
{{if .Done.Crypto}}<a href="/admin/wizard?step=5" class="btn" style="text-decoration:none">К шагу 5 →</a>{{else}}<a href="/admin/wizard?step=5&skip=crypto" class="btn" style="background:var(--card);color:var(--text);border:1px solid var(--border-strong,#c9cdd8);text-decoration:none">Пропустить →</a>{{end}}
|
||
</div>
|
||
</div>
|
||
{{end}}
|
||
|
||
{{/* ============= ШАГ 3: Сертификаты ============= */}}
|
||
{{if eq .Step 5}}
|
||
<div class="card">
|
||
<h2><span class="dot {{if .Done.Certs}}ok{{else}}err{{end}}"></span>Шаг 5. Сертификаты</h2>
|
||
<p>Здесь две части: ключ и сертификат вашей организации (ставите вы) и сертификаты НРД и удостоверяющих центров (bj ведёт их сам).</p>
|
||
|
||
<h3 style="margin-top:14px">1. Ключ и сертификат организации</h3>
|
||
<div class="help-block"><strong>Что это.</strong> Ключ ЭП, которым подписываются сообщения в НРД, и его сертификат (выдаёт УЦ Московской биржи). Архив ключа с паролем вам передаёт НРД/УЦ.<br>
|
||
<strong>Как поставить.</strong> Мастер установки ключа: загрузить архив → запись на носитель → справочник сертификатов → проверка подписи Валидатой.</div>
|
||
<a href="/admin/setup/keywizard" class="btn" style="text-decoration:none;display:inline-block">Открыть мастер установки ключа →</a>
|
||
|
||
<h3 style="margin-top:22px">2. Сертификаты НРД и УЦ — автоматически</h3>
|
||
<p>✓ <strong>Автоматическое обновление {{if .Settings.NSDCerts.Manual}}<span style="color:var(--warn)">выключено</span> (включается в «Настройка → Криптография»){{else}}включено{{end}}.</strong> Делать на этом шаге ничего не нужно.</p>
|
||
<div class="help-block" style="font-size:13px">
|
||
<strong>Как это работает.</strong> Действующие сертификаты НРД и удостоверяющих центров Московской биржи поставляются вместе с bj и приезжают с обновлениями. Каждые 6 часов bj сверяет их со справочником сертификатов ИШ: добавляет недостающие, а заменённые НРД убирает строго после срока, который НРД объявил в уведомлении. Перед каждым изменением делается резервная копия и проверка подписи, при ошибке всё откатывается.<br>
|
||
<strong>Тестовые и боевые.</strong> Сертификат попадает только в справочник своего контура: боевые (издатель «Корневой УЦ») — только к боевому ключу, тестовые (издатель «Тестовый УЦ») — только к тестовому. Поэтому смешать контуры нельзя.<br>
|
||
<strong>Откуда берутся.</strong> НРД и Московская биржа публикуют сертификаты в постоянных местах: комплект ГОСТ МБ, НКЦ и НРД — <code>https://fs.moex.com/cdp/sert/GOST.zip</code>, сертификаты УЦ — <code>https://fs.moex.com/cdp/</code>. Когда там появляется новый сертификат, мы добавляем его в комплект bj, и он приезжает к вам с обновлением.<br>
|
||
Состояние, ручная проверка и выключение — «Настройка → Криптография → Сертификаты НРД в справочнике ИШ».
|
||
</div>
|
||
{{if .Settings.NSDCerts.LastRows}}<p class="muted" style="font-size:13px">Последняя сверка: {{.Settings.NSDCerts.LastRun.Format "02.01.2006 15:04"}}{{if .Settings.NSDCerts.LastProfile}}, профиль ИШ {{.Settings.NSDCerts.LastProfile}}{{end}}.</p>{{else}}<p class="muted" style="font-size:13px">Первая сверка пройдёт, когда будут настроены ключ и шлюз НРД (шаг 6).</p>{{end}}
|
||
|
||
{{if .Certs}}
|
||
<h3 style="margin-top:18px">Установленные сертификаты ({{len .Certs}})</h3>
|
||
<table>
|
||
<thead><tr><th>Владелец</th><th>Издатель</th><th>Действителен до</th><th>ИНН</th><th>Ключ</th></tr></thead>
|
||
<tbody>
|
||
{{range .Certs}}
|
||
<tr>
|
||
<td>{{.SubjectCN}}</td>
|
||
<td>{{.IssuerCN}}</td>
|
||
<td>{{.NotAfter.Format "02.01.2006"}}</td>
|
||
<td>{{if .INN}}<code>{{.INN}}</code>{{else}}—{{end}}</td>
|
||
<td>{{if .HasPrivateKey}}<span style="color:var(--ok)">есть</span>{{else}}<span class="muted">нет</span>{{end}}</td>
|
||
</tr>
|
||
{{end}}
|
||
</tbody>
|
||
</table>
|
||
{{else}}
|
||
<p class="muted" style="margin-top:12px">Ключ организации ещё не установлен. Можно пропустить этот шаг и вернуться к нему, когда будет архив ключа.</p>
|
||
{{end}}
|
||
|
||
<div style="margin-top:20px;display:flex;justify-content:space-between">
|
||
<a href="/admin/wizard?step=4" class="btn" style="background:var(--card);color:var(--text);border:1px solid var(--border-strong,#c9cdd8);text-decoration:none">← К шагу 4</a>
|
||
<a href="/admin/wizard?step=6" class="btn" style="text-decoration:none">К шагу 6 →</a>
|
||
</div>
|
||
</div>
|
||
{{end}}
|
||
|
||
{{/* ============= ШАГ 4: НРД ============= */}}
|
||
{{if eq .Step 6}}
|
||
<div class="card">
|
||
<h2><span class="dot {{if .Done.NSD}}ok{{else}}err{{end}}"></span>Шаг 6. Интеграционный шлюз НРД</h2>
|
||
<p>Адрес web-сервиса ONYX и имя ключевого контейнера НРД.</p>
|
||
|
||
<div class="help-block">
|
||
<strong>Что это?</strong> Интеграционный шлюз (ИШ) НРД — это компонент, через который наши M2M-сообщения отправляются в НРД. {{if devOn}}У НРД есть 4 контура: <em>GUEST</em> (для разработки) и <em>TEST3</em> (предпродакшен), каждый в варианте ГОСТ или RSA.{{else}}У НРД есть тестовый контур (<em>TEST3</em>) и боевой контур, каждый в варианте ГОСТ или RSA.{{end}}<br>
|
||
<strong>Где взять?</strong> Дистрибутив ИШ и инструкции — на сайте НРД <a href="https://www.nsd.ru/workflow/system/programs/" target="_blank">nsd.ru/workflow/system/programs/</a>. Доступ к тестовым контурам выдаётся НРД по заявке (см. <code>DOC/instr_podkl_stend_v3.pdf</code>).
|
||
</div>
|
||
|
||
<form method="post" action="/admin/setup/nsd" style="margin-top:12px;display:grid;gap:10px">
|
||
<div>
|
||
<label>Профиль <span class="tooltip" title="{{if devOn}}GUEST — гостевой контур для разработчиков (gost-gt.nsd.ru), {{end}}TEST3 — тестовый контур НРД (gost-t3.nsd.ru), prod — боевой контур НРД">?</span></label>
|
||
<select name="profile" id="nsd-profile" style="padding:8px;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px;width:100%">
|
||
<option value="test3-gost" {{if eq .Settings.NSD.Profile "test3-gost"}}selected{{end}}>TEST3 · ГОСТ — тестовый контур НРД</option>
|
||
<option value="test3-rsa" {{if eq .Settings.NSD.Profile "test3-rsa"}}selected{{end}}>TEST3 · RSA — тестовый контур НРД</option>
|
||
{{if or devOn (eq .Settings.NSD.Profile "guest-gost") (eq .Settings.NSD.Profile "guest-rsa")}} <option value="guest-gost" {{if eq .Settings.NSD.Profile "guest-gost"}}selected{{end}}>GUEST · ГОСТ</option>
|
||
<option value="guest-rsa" {{if eq .Settings.NSD.Profile "guest-rsa"}}selected{{end}}>GUEST · RSA</option>{{end}}
|
||
<option value="prod" {{if eq .Settings.NSD.Profile "prod"}}selected{{end}}>prod — боевой контур НРД (осторожно)</option>
|
||
</select>
|
||
</div>
|
||
<div>
|
||
<label>URL ONYX <span class="tooltip" title="Базовый URL веб-сервиса ONYX. При выборе профиля выше — заполняется автоматически.">?</span></label>
|
||
<input type="text" name="igw_base_url" id="nsd-url" value="{{.Settings.NSD.IGWBaseURL}}" placeholder="https://gost-t3.nsd.ru/onyx-ms/OnyxEdoWSService/OnyxEdo" style="padding:8px;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px;width:100%">
|
||
</div>
|
||
<div>
|
||
<label>Ключевой контейнер НРД <span class="tooltip" title="Имя контейнера Валидаты с ключами ЭДО НРД (выдаются УЦ НРД)">?</span></label>
|
||
<input type="text" name="key_container" value="{{.Settings.NSD.KeyContainer}}" placeholder="nrd-edo" style="padding:8px;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px;width:100%">
|
||
</div>
|
||
<hr style="border:none;border-top:1px solid var(--border);margin:4px 0">
|
||
<p class="muted" style="margin:0">Депозитарные реквизиты организации в НРД. {{if .Settings.Fancy.Server}}Их можно взять из базы DEPO (Fancy): кнопка «Определить из DEPO» подставит найденное в пустые поля — проверьте и сохраните.{{else}}Если учёт ведётся в Fancy DEPO — сначала подключите базу DEPO на <a href="/admin/wizard?step=3">шаге 3</a>, тогда реквизиты подставятся из DEPO автоматически; иначе введите их из договора с НРД.{{end}}</p>
|
||
{{if .Settings.Fancy.Server}}<button type="submit" class="btn" formaction="/admin/setup/fancy/detect" formmethod="post" style="justify-self:start;background:var(--card);color:var(--text);border:1px solid var(--border-strong,#c9cdd8)">Определить из DEPO</button>{{end}}
|
||
{{if .Suggest}}{{if .Suggest.AccountID}}<div class="help-block" style="margin:0"><strong>Найдено в DEPO:</strong> счёт {{.Suggest.AccountID}}, код {{.Suggest.DeponentCode}}, раздел {{.Suggest.SectionID}}{{if .Suggest.OrgName}}; организация {{.Suggest.OrgName}}, ИНН {{.Suggest.OrgINN}}{{end}}.{{range .Suggest.Notes}}<br><span class="muted">⚠ {{.}}</span>{{end}}</div>{{end}}{{end}}
|
||
<div><label>Депозитарный код</label><input type="text" name="deponent_code" value="{{if .Settings.NSD.DeponentCode}}{{.Settings.NSD.DeponentCode}}{{else if .Suggest}}{{.Suggest.DeponentCode}}{{end}}" placeholder="MC0000000000" style="padding:8px;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px;width:100%"></div>
|
||
<div><label>Депозитарный счёт</label><input type="text" name="account_id" value="{{if .Settings.NSD.AccountID}}{{.Settings.NSD.AccountID}}{{else if .Suggest}}{{.Suggest.AccountID}}{{end}}" placeholder="HL000000000C" style="padding:8px;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px;width:100%"></div>
|
||
<div><label>Раздел счёта</label><input type="text" name="section_id" value="{{if .Settings.NSD.SectionID}}{{.Settings.NSD.SectionID}}{{else if .Suggest}}{{.Suggest.SectionID}}{{end}}" placeholder="36MC0000000000F00" style="padding:8px;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px;width:100%"></div>
|
||
<button type="submit" class="btn" style="justify-self:start">Сохранить</button>
|
||
</form>
|
||
{{if .Suggest}}{{if .Suggest.OrgName}}<form method="post" action="/admin/setup/org" style="margin-top:12px;display:grid;gap:10px">
|
||
<p class="muted" style="margin:0">Организация (из DEPO — проверьте): код участника, ИНН, наименование.</p>
|
||
<input type="hidden" name="return_to" value="/admin/wizard?step=6">
|
||
<div><label>Код участника</label><input type="text" name="org_code" value="{{if .Settings.NSD.OrgCode}}{{.Settings.NSD.OrgCode}}{{else}}{{.Suggest.OrgCode}}{{end}}" style="padding:8px;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px;width:100%"></div>
|
||
<div><label>ИНН</label><input type="text" name="org_inn" value="{{if .Settings.NSD.OrgINN}}{{.Settings.NSD.OrgINN}}{{else}}{{.Suggest.OrgINN}}{{end}}" style="padding:8px;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px;width:100%"></div>
|
||
<div><label>Наименование</label><input type="text" name="org_name" value="{{if .Settings.NSD.OrgName}}{{.Settings.NSD.OrgName}}{{else}}{{.Suggest.OrgName}}{{end}}" style="padding:8px;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px;width:100%"></div>
|
||
<button type="submit" class="btn" style="justify-self:start">Сохранить организацию</button>
|
||
</form>{{end}}{{end}}
|
||
<script>
|
||
// Автозаполнение URL по выбранному профилю
|
||
document.getElementById('nsd-profile').addEventListener('change', function(e){
|
||
var urls = {
|
||
'test3-gost': 'https://gost-t3.nsd.ru/onyx-ms/OnyxEdoWSService/OnyxEdo',
|
||
'test3-rsa': 'https://rsa-t3.nsd.ru/onyx-ms/OnyxEdoWSService/OnyxEdo',
|
||
'guest-gost': 'https://gost-gt.nsd.ru/onyx-ms/OnyxEdoWSService/OnyxEdo',
|
||
'guest-rsa': 'https://rsa-gt.nsd.ru/onyx-ms/OnyxEdoWSService/OnyxEdo',
|
||
'prod': ''
|
||
};
|
||
var u = document.getElementById('nsd-url');
|
||
if (urls[e.target.value]) u.value = urls[e.target.value];
|
||
});
|
||
</script>
|
||
|
||
<div style="margin-top:20px;display:flex;justify-content:space-between">
|
||
<a href="/admin/wizard?step=5" class="btn" style="background:var(--card);color:var(--text);border:1px solid var(--border-strong,#c9cdd8);text-decoration:none">← К шагу 5</a>
|
||
{{if .Done.NSD}}<a href="/admin/wizard?step=7" class="btn" style="text-decoration:none">К шагу 7 →</a>{{else}}<a href="/admin/wizard?step=7&skip=nsd" class="btn" style="background:var(--card);color:var(--text);border:1px solid var(--border-strong,#c9cdd8);text-decoration:none">Пропустить ({{if devOn}}mock-режим{{else}}обмен с НРД не настроен{{end}}) →</a>{{end}}
|
||
</div>
|
||
</div>
|
||
{{end}}
|
||
|
||
{{/* ============= ШАГ 5: Тест-ран (режим разработки) / проверка подключений ============= */}}
|
||
{{if eq .Step 7}}
|
||
<div class="card">
|
||
{{if devOn}}
|
||
<h2><span class="dot {{if .Done.TestRun}}ok{{else}}err{{end}}"></span>Шаг 7. Тестовая заявка</h2>
|
||
<p>Прогон полного цикла: создание заявки → валидация → подпись → отправка в НРД (или mock) → ожидание Decision → подтверждение.</p>
|
||
|
||
<div class="help-block">
|
||
<strong>Что произойдёт?</strong> Система создаст тестовую M2M-сделку, проведёт её через всю стейт-машину, и покажет результат каждого этапа. Если ИШ НРД не настроен — сработает mock (синтетический Decision через 3 секунды).
|
||
</div>
|
||
|
||
<form method="post" action="/admin/setup/test-run" style="margin-top:12px">
|
||
<button type="submit" class="btn" style="background:var(--ok);font-size:15px;padding:10px 20px">▶ Запустить тестовую заявку</button>
|
||
</form>
|
||
|
||
{{if .Settings.LastTest}}
|
||
<h3 style="margin-top:18px">Последний прогон: {{.Settings.LastTest.StartedAt.Format "02.01.2006 15:04:05"}}</h3>
|
||
<table>
|
||
<tr><td class="muted">Заявка</td><td><a href="/admin/claims/{{.Settings.LastTest.ClaimID}}">{{.Settings.LastTest.ClaimID}}</a></td></tr>
|
||
<tr><td class="muted">Финальное состояние</td><td>{{ruState .Settings.LastTest.FinalStatus}}</td></tr>
|
||
<tr><td class="muted">Результат</td><td>{{if .Settings.LastTest.OK}}<span style="color:var(--ok)">успех</span>{{else}}<span style="color:var(--err)">ошибка</span>{{end}}</td></tr>
|
||
{{if .Settings.LastTest.Message}}<tr><td class="muted">Сообщение</td><td>{{.Settings.LastTest.Message}}</td></tr>{{end}}
|
||
</table>
|
||
{{end}}
|
||
{{else}}
|
||
<h2><span class="dot {{if .Done.TestRun}}ok{{else}}err{{end}}"></span>Шаг 7. Проверка подключений</h2>
|
||
<p>Проверьте, что база данных, СКЗИ и шлюз НРД доступны: на странице «Статус» bj проверяет каждое подключение и показывает, что нужно исправить.</p>
|
||
<a href="/admin/status" class="btn" style="background:var(--ok);font-size:15px;padding:10px 20px;text-decoration:none;display:inline-block;margin-top:12px">Открыть проверку подключений →</a>
|
||
{{end}}
|
||
|
||
<h3 style="margin-top:18px">Итоговая сводка</h3>
|
||
<table>
|
||
<tr><td class="muted">PostgreSQL</td><td>{{if .Done.Postgres}}<span style="color:var(--ok)">настроен</span>{{else}}<span class="muted">in-memory</span>{{end}}</td></tr>
|
||
<tr><td class="muted">Крипто-провайдер</td><td>{{if .Done.Crypto}}<span style="color:var(--ok)">Валидата Клиент L{{if .ValidataVer}} {{.ValidataVer}}{{end}}</span>{{else}}<span style="color:var(--err)">не настроен</span>{{end}}</td></tr>
|
||
<tr><td class="muted">Сертификатов установлено</td><td>{{len .Certs}}</td></tr>
|
||
<tr><td class="muted">ИШ НРД</td><td>{{if .Done.NSD}}<span style="color:var(--ok)">{{.Settings.NSD.Profile}}</span>{{else}}<span class="muted">{{if devOn}}mock-режим{{else}}не настроен{{end}}</span>{{end}}</td></tr>
|
||
{{if devOn}}<tr><td class="muted">Тестовый прогон</td><td>{{if .Done.TestRun}}<span style="color:var(--ok)">пройден</span>{{else}}<span class="muted">не запускался</span>{{end}}</td></tr>{{end}}
|
||
</table>
|
||
|
||
<div style="margin-top:20px;display:flex;justify-content:space-between">
|
||
<a href="/admin/wizard?step=6" class="btn" style="background:var(--card);color:var(--text);border:1px solid var(--border-strong,#c9cdd8);text-decoration:none">← К шагу 6</a>
|
||
<a href="/admin/" class="btn" style="text-decoration:none">Перейти к дашборду</a>
|
||
</div>
|
||
</div>
|
||
{{end}}
|
||
|
||
</div>
|
||
{{end}}
|