继续更新 update 门户站点界面和功能
build-winui / winui (push) Has been cancelled

This commit is contained in:
QWQLwToo
2026-06-26 20:17:34 +08:00
parent f525e5f3ba
commit 2513eb2903
68 changed files with 5586 additions and 3195 deletions
@@ -0,0 +1,143 @@
package web
import (
"encoding/json"
"errors"
"net/http"
"strings"
"ymhut-box/server/unified-management/internal/notices"
"ymhut-box/server/unified-management/internal/releases"
)
func (r *router) handleAdminReleases(w http.ResponseWriter, req *http.Request) {
path := cleanPath(req.URL.Path)
if strings.HasPrefix(path, "/api/admin/releases/notices") {
r.handleAdminReleaseNotices(w, req)
return
}
switch path {
case "/api/admin/releases/packages":
if req.Method != http.MethodPost {
writeError(w, http.StatusMethodNotAllowed, "METHOD_NOT_ALLOWED", errors.New("POST required"))
return
}
if err := req.ParseMultipartForm(256 << 20); err != nil {
writeError(w, http.StatusBadRequest, "INVALID_UPLOAD", err)
return
}
file, header, err := req.FormFile("file")
if err != nil {
writeError(w, http.StatusBadRequest, "FILE_REQUIRED", err)
return
}
defer file.Close()
pkg, err := r.releases.SaveUploadedPackage(req, file, releases.UploadOptions{
FileName: firstNonEmpty(req.FormValue("fileName"), header.Filename),
Version: req.FormValue("version"),
Platform: req.FormValue("platform"),
Arch: req.FormValue("arch"),
Channel: req.FormValue("channel"),
Notes: req.FormValue("notes"),
UpdateManifest: req.FormValue("updateManifest") == "true" || req.FormValue("updateManifest") == "1",
}, "admin")
if err != nil {
writeError(w, http.StatusBadRequest, "PACKAGE_UPLOAD_FAILED", err)
return
}
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "package": pkg})
case "/api/admin/releases":
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "manifest": r.releases.Manifest(req)})
case "/api/admin/releases/legacy-preview":
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "updateInfo": r.releases.LegacyUpdateInfo(req), "toolStatus": r.releases.StaticJSON("tool-status.json")})
default:
http.NotFound(w, req)
}
}
func (r *router) handleAdminReleaseNotices(w http.ResponseWriter, req *http.Request) {
if r.notices == nil {
writeError(w, http.StatusNotFound, "NOTICES_DISABLED", errors.New("release notices are not configured"))
return
}
path := cleanPath(req.URL.Path)
if req.Method == http.MethodPost && path == "/api/admin/releases/notices/import" {
if err := r.notices.Import(req.Context()); err != nil {
writeError(w, http.StatusInternalServerError, "NOTICE_IMPORT_FAILED", err)
return
}
items, _ := r.notices.List(100)
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "items": items})
return
}
if req.Method == http.MethodGet && path == "/api/admin/releases/notices" {
items, err := r.notices.List(100)
if err != nil {
writeError(w, http.StatusInternalServerError, "NOTICE_LIST_FAILED", err)
return
}
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "items": items})
return
}
rest := strings.TrimPrefix(path, "/api/admin/releases/notices/")
if rest == "" || rest == path {
http.NotFound(w, req)
return
}
parts := strings.Split(rest, "/")
version := parts[0]
if req.Method == http.MethodGet && len(parts) == 1 {
doc, err := r.notices.Get(version)
if err != nil {
writeError(w, http.StatusNotFound, "NOTICE_NOT_FOUND", err)
return
}
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "document": doc})
return
}
if req.Method == http.MethodPut && len(parts) == 1 {
var body notices.SaveRequest
if err := json.NewDecoder(req.Body).Decode(&body); err != nil {
writeError(w, http.StatusBadRequest, "INVALID_PAYLOAD", err)
return
}
doc, err := r.notices.Save(req.Context(), version, body, "admin")
if err != nil {
writeError(w, http.StatusBadRequest, "NOTICE_SAVE_FAILED", err)
return
}
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "document": doc})
return
}
if req.Method == http.MethodPost && len(parts) == 2 && parts[1] == "validate" {
var body notices.SaveRequest
if err := json.NewDecoder(req.Body).Decode(&body); err != nil {
writeError(w, http.StatusBadRequest, "INVALID_PAYLOAD", err)
return
}
doc, err := r.notices.Validate(req.Context(), version, body)
if err != nil {
writeError(w, http.StatusBadRequest, "NOTICE_VALIDATE_FAILED", err)
return
}
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "document": doc})
return
}
if req.Method == http.MethodPost && len(parts) == 2 && parts[1] == "restore" {
var body struct {
RevisionID int64 `json:"revisionId"`
}
if err := json.NewDecoder(req.Body).Decode(&body); err != nil || body.RevisionID <= 0 {
writeError(w, http.StatusBadRequest, "INVALID_PAYLOAD", errors.New("revisionId is required"))
return
}
doc, err := r.notices.Restore(req.Context(), version, body.RevisionID, "admin")
if err != nil {
writeError(w, http.StatusBadRequest, "NOTICE_RESTORE_FAILED", err)
return
}
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "document": doc})
return
}
http.NotFound(w, req)
}