From b7360b93b26a745cd042ca12c110417ad07e72c0 Mon Sep 17 00:00:00 2001 From: fontvielle Date: Mon, 19 Oct 2026 17:22:29 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9C=D0=B0=D1=81=D1=82=D0=B5=D1=80:=20=C2=AB?= =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=C2=BB=20=E2=80=94=20=D0=BF=D0=B5=D1=80=D0=B2=D1=8B=D0=B9=20?= =?UTF-8?q?=D0=BF=D1=83=D0=BD=D0=BA=D1=82,=20=D0=BA=20=D0=BA=D0=BE=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=BE=D0=BC=D1=83=20=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE?= =?UTF-8?q?=20=D0=B2=D0=B5=D1=80=D0=BD=D1=83=D1=82=D1=8C=D1=81=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Новый шаг 14 «Обновление» в отдельной первой главе мастера. Секция «Обновления» вынесена из admin_setup.html в {{define "updateSection"}} (part_fancy.html) и переиспользуется и в настройках, и в шаге мастера — один источник правды. В мастере рендерится обычным блоком (без settings-section/active), заголовок h1 скрыт (есть свой h2 шага). Шаг необязательный (не блокирует путь), зелёный пока нет версии новее; при наличии обновления — предупреждающая точка. Добавлена пятая глава, поэтому wizChaptersLine расширен до «Пять глав». Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01XG3zNMMf2LMoDpXo22mwMX --- internal/lkgateway/onboarding_test.go | 12 +-- internal/lkgateway/setup.go | 7 +- .../lkgateway/web/templates/admin_setup.html | 83 +----------------- .../lkgateway/web/templates/admin_wizard.html | 10 +++ .../lkgateway/web/templates/part_fancy.html | 86 +++++++++++++++++++ internal/lkgateway/wizchapters.go | 5 +- 6 files changed, 110 insertions(+), 93 deletions(-) diff --git a/internal/lkgateway/onboarding_test.go b/internal/lkgateway/onboarding_test.go index 6c9ec7a..912298e 100644 --- a/internal/lkgateway/onboarding_test.go +++ b/internal/lkgateway/onboarding_test.go @@ -210,11 +210,11 @@ func TestWizardChaptersWithoutLicense(t *testing.T) { rc, _ := NewRuntimeConfig(t.TempDir() + "/setup.json") done := map[int]bool{2: true, 6: true} path, chapters := wizPath(rc, done, 4) - want := []int{1, 12, 4, 7, 8, 9, 13, 10} // без лицензии нет учёта DEPO, QUIK и модулей; база и Валидата — сделаны; учётные записи — перед проверкой + want := []int{14, 1, 12, 4, 7, 8, 9, 13, 10} // обновление — первый пункт; без лицензии нет учёта DEPO, QUIK и модулей; база и Валидата — сделаны; учётные записи — перед проверкой if fmt.Sprint(path) != fmt.Sprint(want) { t.Fatalf("путь %v, ожидался %v", path, want) } - if len(chapters) != 4 || !chapters[1].Current || chapters[1].Steps[0].N != 4 { + if len(chapters) != 5 || !chapters[2].Current || chapters[2].Steps[0].N != 4 { t.Fatalf("главы: %+v", chapters) } if p, n := wizNeighbours(path, 4); p != 12 || n != 7 { @@ -233,10 +233,10 @@ func TestWizardChaptersWithoutLicense(t *testing.T) { if len(wizModuleViews(rc, rc.Snapshot())) != 0 { t.Fatal("без лицензии модулей в мастере быть не должно") } - if chapters[1].Title != "Организация" { - t.Fatalf("без учёта DEPO и QUIK глава 2 — «Организация», а не %q", chapters[1].Title) + if chapters[2].Title != "Организация" { + t.Fatalf("без учёта DEPO и QUIK глава «Организация», а не %q", chapters[2].Title) } - if l := wizChaptersLine(chapters); l != "Четыре главы: сервер, организация, НРД, запуск." { + if l := wizChaptersLine(chapters); l != "Пять глав: обновление, сервер, организация, НРД, запуск." { t.Fatalf("подзаголовок: %q", l) } } @@ -437,7 +437,7 @@ func TestWizardStepsRender(t *testing.T) { t.Fatal(err) } h := &setupHandlers{rc: rc, tpl: &adminTemplates{a: a}} - for step, want := range map[string]string{"1": "QUIK: неторговые поручения", "3": "wiz-depo", "5": "Сохранить и проверить", "12": "wiz-tz-suggest", "10": "Проверка"} { + for step, want := range map[string]string{"1": "QUIK: неторговые поручения", "3": "wiz-depo", "5": "Сохранить и проверить", "12": "wiz-tz-suggest", "10": "Проверка", "14": "sec-update"} { w := httptest.NewRecorder() h.renderWizard(w, httptest.NewRequest(http.MethodGet, "/admin/wizard?step="+step, nil)) body := w.Body.String() diff --git a/internal/lkgateway/setup.go b/internal/lkgateway/setup.go index ac02af6..276aed8 100644 --- a/internal/lkgateway/setup.go +++ b/internal/lkgateway/setup.go @@ -288,8 +288,9 @@ func (h *setupHandlers) renderWizard(w http.ResponseWriter, r *http.Request) { // Главы (wizchapters.go): в пути только шаги, нужные этой установке — по лицензии и без сделанного // установщиком. Без ?step — первый несделанный обязательный шаг, а если всё сделано — проверка. d.Done.Users = doneUsers() + _, wizUpdAvail := updateComponentRows(h.rc) // шаг 14 «Обновление»: зелёный, пока нет версии новее done := map[int]bool{1: d.Done.License, 2: d.Done.Postgres, 3: d.Done.Depo, 4: d.Done.Org, 5: d.Done.Quik, 6: d.Done.Crypto, - 7: d.Done.NSD, 8: d.Done.Certs, 9: d.Done.Alerts, 10: d.Done.TestRun, 11: d.Done.Modules, 12: d.Done.Server, 13: d.Done.Users} + 7: d.Done.NSD, 8: d.Done.Certs, 9: d.Done.Alerts, 10: d.Done.TestRun, 11: d.Done.Modules, 12: d.Done.Server, 13: d.Done.Users, 14: !wizUpdAvail} path, _ := wizPath(h.rc, done, 0) step := wizDefaultStep(path, done) if v := r.URL.Query().Get("step"); v != "" { @@ -327,7 +328,7 @@ func (h *setupHandlers) renderWizard(w http.ResponseWriter, r *http.Request) { } cancel() } - if (step >= 3 && step <= 5) || step == 9 || step == 11 || step == 13 { // DEPO, организация, QUIK МНП, оповещения и копии, модули, учётные записи — общие блоки из «Настройки» + if (step >= 3 && step <= 5) || step == 9 || step == 11 || step == 13 || step == 14 { // DEPO, организация, QUIK МНП, оповещения и копии, модули, учётные записи, обновление — общие блоки из «Настройки» fd := h.setupData(w, r, "") fd.InWizard = true d.Fancy = &fd @@ -398,7 +399,7 @@ func depoServerEdition(ctx context.Context, f FancyMSSQLSettings) (string, bool) // wizardSteps — шагов в мастере: 1 лицензия, 2 база bj, 3 учёт DEPO, 4 наша организация, 5 QUIK МНП, // 6 Валидата, 7 шлюз НРД, 8 ключ и сертификаты (ключ ставится в профиль ИШ — после шлюза), // 9 оповещения и резервные копии, 10 проверка готовности. -const wizardSteps = 13 // 11 — модули по лицензии (глава «Запуск»), 12 — время и сеть (глава «Сервер»), 13 — учётные записи +const wizardSteps = 14 // 11 — модули, 12 — время и сеть, 13 — учётные записи, 14 — обновление (первый пункт, глава «Обновление») // dsnSummary — «host:port, база name» из строки подключения PostgreSQL, без логина и пароля. func dsnSummary(dsn string) string { diff --git a/internal/lkgateway/web/templates/admin_setup.html b/internal/lkgateway/web/templates/admin_setup.html index e127c1d..cd80a54 100644 --- a/internal/lkgateway/web/templates/admin_setup.html +++ b/internal/lkgateway/web/templates/admin_setup.html @@ -936,88 +936,7 @@ {{/* ============ ОБНОВЛЕНИЯ ============ */}} -
-

Обновления

- {{template "verline" (.Versions.Get "bj-server")}} - -
- {{if .UpdatesAvailable}} -
Доступно обновление{{with .Settings.Update.Available}} {{.}}{{end}}{{if .Settings.Update.Notes}}{{.Settings.Update.Notes}}{{else}}новые версии компонентов — список ниже, в «Компоненты и версии»{{end}}
-
- {{else if and (not .Settings.Update.LastCheck.IsZero) .UpdateFailed}} -
Проверить обновления не удалось{{.Settings.Update.LastResult}} · {{msk .Settings.Update.LastCheck}}
-
- {{else}} -
Установлены последние версии{{if .Settings.Update.LastCheck.IsZero}}ещё не проверялось{{else}}проверено {{msk .Settings.Update.LastCheck}}{{end}}{{if .Settings.Update.AutoCheck}} · bj проверяет сам каждые 6 часов{{end}}
-
- {{end}} - {{if and .License.Present (not .License.AllowsUpdates)}}

В лицензии нет модуля «Обновления».

{{end}} -
- - -
-
- Компоненты и версиичто установлено на этом сервере и что есть в выпуске; можно обновить один компонент -
- - - {{range .Components}} - - - - - - {{end}} - -
КомпонентУстановленаДоступнаСлужба
{{.Title}}
{{.Name}}{{if eq .Name "crypto-service.jar"}}{{with $.Versions.Get "validata"}}{{if .Version}} · работает с «Валидата Клиент L» {{.Version}}{{end}}{{end}}{{end}}
{{if .Present}}{{if .Installed}}{{.Installed}}{{else}}неизвестна{{end}}{{else}}не установлен{{end}}{{if .Available}}{{.Available}}{{if .New}} к установке{{else if .Update}} новее{{end}}{{if .Blocked}}
{{.Blocked}}
{{end}}{{else}}нет данных{{end}}
{{.Unit}}{{if .Update}}
{{end}}
-
-
- -
-
- Расширенные настройкиисточник и канал обновлений, обновление из файла для сервера без выхода в интернет -

Обновление из файла

-

Закрытый контур. Если у сервера нет выхода к серверу обновлений, скачайте пакет обновления на портале клиента (lic.zetit.ru → Установка → «Пакет обновления») и загрузите его кнопкой «Обновить из файла». Система сама распознаёт, что внутри — ядро, модули или всё вместе — и ставит в правильном порядке. Модуль, которому нужно более новое ядро, чем установлено, будет пропущен с подсказкой обновить сначала ядро.

-
-
- - - -
-
-

Источник обновлений

-
- - - - - - - -
-
-
-
-
+ {{template "updateSection" .}} {{/* ============ ЛИЦЕНЗИЯ ============ */}} {{/* ============ РЕЗЕРВНОЕ КОПИРОВАНИЕ ============ */}} diff --git a/internal/lkgateway/web/templates/admin_wizard.html b/internal/lkgateway/web/templates/admin_wizard.html index fa4fa63..3f6aeee 100644 --- a/internal/lkgateway/web/templates/admin_wizard.html +++ b/internal/lkgateway/web/templates/admin_wizard.html @@ -611,6 +611,16 @@ {{end}} +{{/* ============= ШАГ 14: Обновление (глава «Обновление») ============= */}} +{{if eq .Step 14}} +
+

Обновление

+

Проверка и установка обновлений bj. Это первый пункт мастера — сюда можно вернуться в любой момент.

+ {{with .Fancy}}{{template "updateSection" .}}{{end}} + {{template "wizNav" .}} +
+{{end}} + {{/* ============= ШАГ 11: Модули по лицензии (глава «Запуск») ============= */}} {{if eq .Step 11}}
diff --git a/internal/lkgateway/web/templates/part_fancy.html b/internal/lkgateway/web/templates/part_fancy.html index c75ab0f..ee4c934 100644 --- a/internal/lkgateway/web/templates/part_fancy.html +++ b/internal/lkgateway/web/templates/part_fancy.html @@ -137,3 +137,89 @@ {{end}}
{{end}} + +{{/* Секция «Обновления»: общий блок для страницы настроек и шага 14 мастера. */}} +{{define "updateSection"}} + {{if .InWizard}}
{{else}}
{{end}} + {{if not .InWizard}}

Обновления

{{end}} + {{template "verline" (.Versions.Get "bj-server")}} + +
+ {{if .UpdatesAvailable}} +
Доступно обновление{{with .Settings.Update.Available}} {{.}}{{end}}{{if .Settings.Update.Notes}}{{.Settings.Update.Notes}}{{else}}новые версии компонентов — список ниже, в «Компоненты и версии»{{end}}
+
+ {{else if and (not .Settings.Update.LastCheck.IsZero) .UpdateFailed}} +
Проверить обновления не удалось{{.Settings.Update.LastResult}} · {{msk .Settings.Update.LastCheck}}
+
+ {{else}} +
Установлены последние версии{{if .Settings.Update.LastCheck.IsZero}}ещё не проверялось{{else}}проверено {{msk .Settings.Update.LastCheck}}{{end}}{{if .Settings.Update.AutoCheck}} · bj проверяет сам каждые 6 часов{{end}}
+
+ {{end}} + {{if and .License.Present (not .License.AllowsUpdates)}}

В лицензии нет модуля «Обновления».

{{end}} +
+ + +
+
+ Компоненты и версиичто установлено на этом сервере и что есть в выпуске; можно обновить один компонент +
+ + + {{range .Components}} + + + + + + {{end}} + +
КомпонентУстановленаДоступнаСлужба
{{.Title}}
{{.Name}}{{if eq .Name "crypto-service.jar"}}{{with $.Versions.Get "validata"}}{{if .Version}} · работает с «Валидата Клиент L» {{.Version}}{{end}}{{end}}{{end}}
{{if .Present}}{{if .Installed}}{{.Installed}}{{else}}неизвестна{{end}}{{else}}не установлен{{end}}{{if .Available}}{{.Available}}{{if .New}} к установке{{else if .Update}} новее{{end}}{{if .Blocked}}
{{.Blocked}}
{{end}}{{else}}нет данных{{end}}
{{.Unit}}{{if .Update}}
{{end}}
+
+
+ +
+
+ Расширенные настройкиисточник и канал обновлений, обновление из файла для сервера без выхода в интернет +

Обновление из файла

+

Закрытый контур. Если у сервера нет выхода к серверу обновлений, скачайте пакет обновления на портале клиента (lic.zetit.ru → Установка → «Пакет обновления») и загрузите его кнопкой «Обновить из файла». Система сама распознаёт, что внутри — ядро, модули или всё вместе — и ставит в правильном порядке. Модуль, которому нужно более новое ядро, чем установлено, будет пропущен с подсказкой обновить сначала ядро.

+
+
+ + + +
+
+

Источник обновлений

+
+ + + + + + + +
+
+
+
+ {{if .InWizard}}
{{else}}{{end}} +{{end}} diff --git a/internal/lkgateway/wizchapters.go b/internal/lkgateway/wizchapters.go index 001f505..7770cbf 100644 --- a/internal/lkgateway/wizchapters.go +++ b/internal/lkgateway/wizchapters.go @@ -14,6 +14,7 @@ var wizChapters = []struct { Title string Steps []int }{ + {"Обновление", []int{14}}, {"Сервер", []int{1, 2, 6, 12}}, {"Учёт и организация", []int{3, 4, 5}}, {"НРД", []int{7, 8}}, @@ -22,7 +23,7 @@ var wizChapters = []struct { // wizStepTitles — короткие названия шагов (подзаголовки внутри главы). var wizStepTitles = map[int]string{ - 1: "Лицензия", 2: "База bj", 6: "Валидата", 12: "Время и сеть", + 1: "Лицензия", 2: "База bj", 6: "Валидата", 12: "Время и сеть", 14: "Обновление", 3: "Учёт DEPO", 4: "Организация", 5: "QUIK МНП", 7: "Шлюз НРД", 8: "Ключ подписи", 11: "Модули", 9: "Оповещения и копии", 13: "Учётные записи", 10: "Проверка", @@ -111,7 +112,7 @@ func wizPath(rc *RuntimeConfig, done map[int]bool, current int) (path []int, cha // wizChaptersLine — подзаголовок мастера: «Четыре главы: сервер, организация, НРД, запуск». func wizChaptersLine(chapters []WizChapter) string { - words := []string{"", "Одна глава", "Две главы", "Три главы", "Четыре главы"} + words := []string{"", "Одна глава", "Две главы", "Три главы", "Четыре главы", "Пять глав"} var names []string for _, c := range chapters { t := c.Title