feat(admin): вкладка «Инструкции» + русификация статусов в UI

В admin-панели lk-gateway добавлен раздел /admin/help — справка по
основным интеграциям, читается прямо на сервере, без выхода во
внешнюю документацию.

Состав /admin/help:
- /admin/help — hub-страница с 4 карточками-ссылками
- /admin/help/database — подключение PostgreSQL, схемы fansy/fansy_staging/m2m_core,
  что подгружается через ETL Fansy и что пишет сама система, роли,
  миграции, полезные запросы
- /admin/help/lk-api — REST-контракт ESIA Finance V1: аутентификация,
  POST/GET/PATCH/list, формат callback'ов и ошибок, эмулятор для тестов,
  примеры curl
- /admin/help/cryptopro — установка КриптоПро CSP на РЕД ОС и Ubuntu,
  ввод серийного номера лицензии (cpconfig), путь к PKCS#11 модулю
  libcppkcs11.so, подключение Рутокен ЭЦП 2.0 для подписи оператора,
  тестирование подписи через csptest и cryptcp
- /admin/help/systems — Интеграционный шлюз НРД (профили guest/test3/prod),
  команда Fansy (порядок согласования контракта), уведомления
  (SMTP/Yandex Messenger/Telegram), контакты команд

Русификация статусов:
- Добавлены template-функции ruState и ruOutcome (в lkgateway и lkemulator)
- "draft" → "Черновик", "confirmed" → "Подтверждена", "rejected" → "Отклонена" и т.д.
- CSS-классы бейджей сохраняются (по исходному state), меняется только
  отображаемый текст. Технические термины (PostgreSQL, ИНН, GUID, REST)
  остаются как есть — они являются именами программного обеспечения.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
fontvielle
2026-05-14 13:53:37 +03:00
parent 978777ff6a
commit 67e81e5d7f
12 changed files with 574 additions and 13 deletions
+89 -3
View File
@@ -19,12 +19,65 @@ var templatesFS embed.FS
// конкретный content-шаблон). Так html/template не путается с несколькими
// {{define "content"}} в разных файлах.
type admin struct {
home, claims, claim, status, setup *template.Template
home, claims, claim, status, setup *template.Template
help, helpDatabase, helpLK, helpCryptoPro, helpSystems *template.Template
}
// templateFuncs — функции, доступные внутри шаблонов. Главная задача —
// русификация статусов и других технических обозначений (см. требование
// «всё UI на русском, кроме программных терминов»).
var templateFuncs = template.FuncMap{
"ru": russianText,
"ruState": russianState,
"ruOutcome": russianOutcome,
}
// russianState переводит технический FSM-state в человекочитаемый
// русский, сохраняя CSS-класс для бейджа.
func russianState(s string) string {
switch s {
case "draft":
return "Черновик"
case "validated":
return "Валидирована"
case "submitted_to_nsd":
return "Отправлена в НРД"
case "awaiting_decision":
return "Ожидает решение"
case "confirmed":
return "Подтверждена"
case "awaiting_sub16":
return "Ожидает SUB16"
case "done":
return "Завершена"
case "rejected":
return "Отклонена"
case "timed_out":
return "Таймаут SLA"
case "manual_approval":
return "На ручном разборе"
}
return s
}
// russianOutcome — для NSDDecisionSecurity.Outcome.
func russianOutcome(o string) string {
switch o {
case "confirmed":
return "Подтверждено"
case "rejected":
return "Отказ"
}
return o
}
// russianText — fallback функция для произвольных строк (на случай
// будущих расширений). Сейчас возвращает строку без изменений.
func russianText(s string) string { return s }
func newAdmin() (*admin, error) {
parse := func(content string) (*template.Template, error) {
return template.ParseFS(templatesFS,
return template.New("layout.html").Funcs(templateFuncs).ParseFS(templatesFS,
"web/templates/layout.html",
"web/templates/"+content)
}
@@ -48,7 +101,30 @@ func newAdmin() (*admin, error) {
if err != nil {
return nil, fmt.Errorf("parse admin_setup: %w", err)
}
return &admin{home: home, claims: claims, claim: claim, status: status, setup: setup}, nil
help, err := parse("admin_help.html")
if err != nil {
return nil, fmt.Errorf("parse admin_help: %w", err)
}
helpDB, err := parse("admin_help_database.html")
if err != nil {
return nil, fmt.Errorf("parse admin_help_database: %w", err)
}
helpLK, err := parse("admin_help_lk.html")
if err != nil {
return nil, fmt.Errorf("parse admin_help_lk: %w", err)
}
helpCP, err := parse("admin_help_cryptopro.html")
if err != nil {
return nil, fmt.Errorf("parse admin_help_cryptopro: %w", err)
}
helpSys, err := parse("admin_help_systems.html")
if err != nil {
return nil, fmt.Errorf("parse admin_help_systems: %w", err)
}
return &admin{
home: home, claims: claims, claim: claim, status: status, setup: setup,
help: help, helpDatabase: helpDB, helpLK: helpLK, helpCryptoPro: helpCP, helpSystems: helpSys,
}, nil
}
// page — общий "конверт" данных для всех шаблонов.
@@ -111,6 +187,16 @@ func RegisterAdmin(mux *http.ServeMux, svc *Service, getOpts func() CheckOptions
a.renderClaim(w, r, svc, id)
case p == "status":
a.renderStatus(w, r, getOpts())
case p == "help":
render(w, a.help, nowPage("Инструкции", "help"))
case p == "help/database":
render(w, a.helpDatabase, nowPage("База данных", "help"))
case p == "help/lk-api":
render(w, a.helpLK, nowPage("API ЛК", "help"))
case p == "help/cryptopro":
render(w, a.helpCryptoPro, nowPage("КриптоПро", "help"))
case p == "help/systems":
render(w, a.helpSystems, nowPage("Внешние системы", "help"))
default:
http.NotFound(w, r)
}