Мастер, шаг 3 DEPO — по экранам: описание → подключение (проверка сразу) → таблицы (bj или скрипт) → обработка (job) → готово; справочник участников M2M встроен снимком для чистой установки
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
package lkgateway
|
||||
|
||||
// Шаг 3 мастера настройки (учёт DEPO) — маленький мастер по экранам вместо простыни настроек:
|
||||
// описание → подключение → трансферные таблицы → обработка (job) → готово. Каждый экран делает
|
||||
// своё действие по «Далее» и сразу проверяет результат; при ошибке экран не меняется, ошибка
|
||||
// показывается понятным текстом. Полный раздел «Обмен Fancy» остаётся в «Настройке».
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// depoWizardSubs — экраны шага 3 по порядку.
|
||||
var depoWizardSubs = []struct{ Key, Title string }{
|
||||
{"intro", "Что это"},
|
||||
{"conn", "Подключение"},
|
||||
{"tables", "Таблицы обмена"},
|
||||
{"job", "Обработка"},
|
||||
{"done", "Готово"},
|
||||
}
|
||||
|
||||
func depoWizardSub(v string) string {
|
||||
for _, s := range depoWizardSubs {
|
||||
if s.Key == v {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return "intro"
|
||||
}
|
||||
|
||||
// wizDepoGo — перейти на экран шага 3 с сообщением (ok=false — сообщение об ошибке).
|
||||
func wizDepoGo(w http.ResponseWriter, r *http.Request, sub, msg string, ok bool) {
|
||||
u := "/admin/wizard?step=3&sub=" + sub
|
||||
if msg != "" {
|
||||
if ok {
|
||||
msg = "✓ " + msg
|
||||
} else {
|
||||
msg = "✗ " + msg
|
||||
}
|
||||
u += "&flash=" + url.QueryEscape(msg)
|
||||
}
|
||||
http.Redirect(w, r, u, http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// wizardDepoConn — POST /admin/setup/wizard-depo/conn: сохранить подключение и сразу проверить его.
|
||||
func (h *setupHandlers) wizardDepoConn(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost || !requireDepo(w, r) {
|
||||
return
|
||||
}
|
||||
s := h.fancyFromForm(r)
|
||||
if db := strings.TrimSpace(r.FormValue("depo_database")); db != "" {
|
||||
if !validDBName(db) {
|
||||
wizDepoGo(w, r, "conn", "имя базы DEPO — только латинские буквы, цифры и _, начинается с буквы", false)
|
||||
return
|
||||
}
|
||||
if db != s.DepoDatabase {
|
||||
s.DepoTablesCheck, s.DepoTablesCheckOK = "", false
|
||||
}
|
||||
s.DepoDatabase = db
|
||||
}
|
||||
if s.Server == "" || s.User == "" {
|
||||
wizDepoGo(w, r, "conn", "укажите адрес сервера и логин", false)
|
||||
return
|
||||
}
|
||||
if err := h.rc.UpdateFancy(s); err != nil {
|
||||
wizDepoGo(w, r, "conn", "не сохранилось: "+err.Error(), false)
|
||||
return
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 15*time.Second)
|
||||
defer cancel()
|
||||
if _, err := fancyPing(ctx, s, "master"); err != nil {
|
||||
wizDepoGo(w, r, "conn", "к серверу подключиться не удалось — "+err.Error()+". Проверьте адрес, порт, логин и пароль.", false)
|
||||
return
|
||||
}
|
||||
if _, err := fancyPing(ctx, s, s.DepoDB()); err != nil {
|
||||
wizDepoGo(w, r, "conn", "сервер отвечает, но база "+s.DepoDB()+" недоступна этим логином — "+err.Error(), false)
|
||||
return
|
||||
}
|
||||
wizDepoGo(w, r, "tables", "подключение к "+s.Server+", база "+s.DepoDB()+" — работает", true)
|
||||
}
|
||||
|
||||
// wizardDepoTables — POST /admin/setup/wizard-depo/tables: создать таблицы (bj) или проверить созданные
|
||||
// администратором по скрипту.
|
||||
func (h *setupHandlers) wizardDepoTables(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost || !requireDepo(w, r) {
|
||||
return
|
||||
}
|
||||
s := h.rc.Snapshot().Fancy
|
||||
mode := r.FormValue("depo_tables_mode")
|
||||
if mode != "script" {
|
||||
mode = "auto"
|
||||
}
|
||||
if s.DepoTablesMode != mode {
|
||||
s.DepoTablesMode = mode
|
||||
_ = h.rc.UpdateFancy(s)
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 2*time.Minute)
|
||||
defer cancel()
|
||||
if mode == "auto" && r.FormValue("action") != "check" {
|
||||
if _, err := depoTablesCreate(ctx, s, r.FormValue("admin_user"), r.FormValue("admin_password")); err != nil {
|
||||
wizDepoGo(w, r, "tables", "таблицы не созданы — "+err.Error()+". Если у логина bj нет прав, введите разово логин администратора SQL.", false)
|
||||
return
|
||||
}
|
||||
}
|
||||
msg, ok := depoTablesCheck(ctx, s)
|
||||
h.saveDepoTablesCheck(msg, ok)
|
||||
if !ok {
|
||||
wizDepoGo(w, r, "tables", msg, false)
|
||||
return
|
||||
}
|
||||
if !s.IsPostgres() {
|
||||
_ = depoWriteHandbook(h.rc)
|
||||
}
|
||||
wizDepoGo(w, r, "job", "таблицы обмена на месте: "+msg, true)
|
||||
}
|
||||
|
||||
// wizardDepoJob — POST /admin/setup/wizard-depo/job: выбрать, кто запускает обработку, сделать нужное
|
||||
// (для «джобу создаёт bj» — создать) и проверить служебным событием.
|
||||
func (h *setupHandlers) wizardDepoJob(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost || !requireDepo(w, r) {
|
||||
return
|
||||
}
|
||||
s := h.rc.Snapshot().Fancy
|
||||
mode := r.FormValue("depo_job_mode")
|
||||
if mode != "bj" && mode != "sql-auto" && mode != "sql-manual" {
|
||||
mode = "sql-auto"
|
||||
}
|
||||
if s.DepoJobMode != mode {
|
||||
s.DepoJobCheck, s.DepoJobCheckOK = "", false
|
||||
}
|
||||
s.DepoJobMode, s.DepoJobRun = mode, mode == "bj"
|
||||
if err := h.rc.UpdateFancy(s); err != nil {
|
||||
wizDepoGo(w, r, "job", "не сохранилось: "+err.Error(), false)
|
||||
return
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 90*time.Second)
|
||||
defer cancel()
|
||||
if mode == "sql-auto" && r.FormValue("action") != "check" {
|
||||
if err := depoJobCreateAgent(ctx, h.rc, r.FormValue("admin_user"), r.FormValue("admin_password")); err != nil && !strings.Contains(err.Error(), "уже существует") {
|
||||
wizDepoGo(w, r, "job", "джоба не создана — "+err.Error(), false)
|
||||
return
|
||||
}
|
||||
}
|
||||
msg, ok := depoJobCheck(ctx, h.rc)
|
||||
s = h.rc.Snapshot().Fancy
|
||||
s.DepoJobCheck, s.DepoJobCheckOK, s.DepoJobCheckAt = msg, ok, time.Now()
|
||||
_ = h.rc.UpdateFancy(s)
|
||||
if !ok {
|
||||
wizDepoGo(w, r, "job", "обработка пока не работает — "+msg, false)
|
||||
return
|
||||
}
|
||||
wizDepoGo(w, r, "done", "обработка работает: "+msg, true)
|
||||
}
|
||||
|
||||
// wizardDepoRecheck — POST /admin/setup/wizard-depo/recheck: перепроверить всё на экране «Готово».
|
||||
func (h *setupHandlers) wizardDepoRecheck(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost || !requireDepo(w, r) {
|
||||
return
|
||||
}
|
||||
s := h.rc.Snapshot().Fancy
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 90*time.Second)
|
||||
defer cancel()
|
||||
if _, err := fancyPing(ctx, s, s.DepoDB()); err != nil {
|
||||
wizDepoGo(w, r, "conn", "подключение не работает — "+err.Error(), false)
|
||||
return
|
||||
}
|
||||
msg, ok := depoTablesCheck(ctx, s)
|
||||
h.saveDepoTablesCheck(msg, ok)
|
||||
if !ok {
|
||||
wizDepoGo(w, r, "tables", msg, false)
|
||||
return
|
||||
}
|
||||
jmsg, jok := depoJobCheck(ctx, h.rc)
|
||||
s = h.rc.Snapshot().Fancy
|
||||
s.DepoJobCheck, s.DepoJobCheckOK, s.DepoJobCheckAt = jmsg, jok, time.Now()
|
||||
_ = h.rc.UpdateFancy(s)
|
||||
if !jok {
|
||||
wizDepoGo(w, r, "job", jmsg, false)
|
||||
return
|
||||
}
|
||||
wizDepoGo(w, r, "done", "всё перепроверено", true)
|
||||
}
|
||||
Reference in New Issue
Block a user