diff --git a/internal/lkgateway/setup.go b/internal/lkgateway/setup.go index b33e5f8..5ba5c70 100644 --- a/internal/lkgateway/setup.go +++ b/internal/lkgateway/setup.go @@ -1401,7 +1401,11 @@ func (h *setupHandlers) applyUpdate(w http.ResponseWriter, r *http.Request) { http.Error(w, "method", http.StatusMethodNotAllowed) return } - _ = r.ParseForm() + // форма может прийти и как multipart (окно обновления) — иначе имена компонентов теряются + // и «Обновить» у одной строки превращается в «Обновить всё» + if err := r.ParseMultipartForm(1 << 20); err != nil { + _ = r.ParseForm() + } names := r.Form["component"] rc := h.rc save := func(msg string, err error) string { diff --git a/internal/lkgateway/web/templates/layout.html b/internal/lkgateway/web/templates/layout.html index c8fdc24..25e95b3 100644 --- a/internal/lkgateway/web/templates/layout.html +++ b/internal/lkgateway/web/templates/layout.html @@ -612,7 +612,9 @@ label { font-size:13px; font-weight:500; } bar.style.width=Math.max(3,Math.round(e.loaded/e.total*25))+'%'; detail.textContent=mb(e.loaded)+' из '+mb(e.total); } }; } xhr.onloadend=function(){ postDone=true; }; - xhr.send(new FormData(form)); + // обычные формы — как браузер (urlencoded), с файлом — multipart + if(file && file.files.length){ xhr.send(new FormData(form)); } + else { xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); xhr.send(new URLSearchParams(new FormData(form)).toString()); } setTimeout(poll, 400); } function poll(){