feat: complete 2.0.7.12 platform overhaul
This commit is contained in:
@@ -11,7 +11,6 @@ import (
|
||||
|
||||
"ymhut-box/server/unified-management/internal/config"
|
||||
"ymhut-box/server/unified-management/internal/db"
|
||||
"ymhut-box/server/unified-management/internal/health"
|
||||
feedbackmail "ymhut-box/server/unified-management/internal/mail"
|
||||
)
|
||||
|
||||
@@ -54,6 +53,7 @@ func (r *router) handleAdminDatabase(w http.ResponseWriter, req *http.Request) {
|
||||
writeError(w, http.StatusInternalServerError, "DATABASE_SAVE_FAILED", err)
|
||||
return
|
||||
}
|
||||
r.health.RefreshPreflight()
|
||||
_ = r.store.InsertAudit(db.AuditLog{Actor: "admin", Type: "system.database.saved", Target: body.Provider, Message: "数据库配置已保存并热切换", IP: req.RemoteAddr, UserAgent: req.UserAgent()})
|
||||
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "database": r.store.Status(), "config": config.SafeDatabase(r.cfg.BaseDir, r.cfg.Database)})
|
||||
case req.Method == http.MethodPost && path == "/api/admin/database/sync/jobs":
|
||||
@@ -161,15 +161,47 @@ func (r *router) handleAdminDashboard(w http.ResponseWriter, req *http.Request)
|
||||
http.NotFound(w, req)
|
||||
return
|
||||
}
|
||||
overview, err := r.store.DashboardOverview(80)
|
||||
window, duration, points := dashboardWindow(req.URL.Query().Get("window"))
|
||||
overview, cacheHit, err := r.dashboardCache.Get(window, func() (map[string]any, error) {
|
||||
since := time.Now().UTC().Add(-duration).Format(time.RFC3339)
|
||||
result, buildErr := r.store.DashboardOverviewWindow(points, since)
|
||||
if buildErr != nil {
|
||||
return nil, buildErr
|
||||
}
|
||||
result["window"] = window
|
||||
jobs := r.sources.CheckJobs()
|
||||
if len(jobs) > 5 {
|
||||
jobs = jobs[:5]
|
||||
}
|
||||
result["sourceCheckJobs"] = jobs
|
||||
result["health"] = r.healthSnapshot()
|
||||
return result, nil
|
||||
})
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, "DASHBOARD_FAILED", err)
|
||||
return
|
||||
}
|
||||
overview["health"] = health.Snapshot(r.cfg, r.store)
|
||||
if cacheHit {
|
||||
w.Header().Set("X-Admin-Cache", "hit")
|
||||
} else {
|
||||
w.Header().Set("X-Admin-Cache", "miss")
|
||||
}
|
||||
writeJSON(w, http.StatusOK, overview)
|
||||
}
|
||||
|
||||
func dashboardWindow(value string) (string, time.Duration, int) {
|
||||
switch strings.ToLower(strings.TrimSpace(value)) {
|
||||
case "1h":
|
||||
return "1h", time.Hour, 60
|
||||
case "6h":
|
||||
return "6h", 6 * time.Hour, 72
|
||||
case "7d":
|
||||
return "7d", 7 * 24 * time.Hour, 112
|
||||
default:
|
||||
return "24h", 24 * time.Hour, 96
|
||||
}
|
||||
}
|
||||
|
||||
func (r *router) handleAdminSync(w http.ResponseWriter, req *http.Request) {
|
||||
if r.syncer == nil {
|
||||
writeError(w, http.StatusNotFound, "SYNC_DISABLED", errors.New("legacy sync service is not configured"))
|
||||
@@ -239,7 +271,18 @@ func (r *router) handleAdminSystem(w http.ResponseWriter, req *http.Request) {
|
||||
path := cleanPath(req.URL.Path)
|
||||
switch path {
|
||||
case "/api/admin/system/health":
|
||||
writeJSON(w, http.StatusOK, health.Snapshot(r.cfg, r.store))
|
||||
if req.Method != http.MethodGet {
|
||||
writeError(w, http.StatusMethodNotAllowed, "METHOD_NOT_ALLOWED", errors.New("GET required"))
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, r.healthSnapshot())
|
||||
case "/api/admin/system/preflight":
|
||||
if req.Method != http.MethodPost {
|
||||
writeError(w, http.StatusMethodNotAllowed, "METHOD_NOT_ALLOWED", errors.New("POST required"))
|
||||
return
|
||||
}
|
||||
r.health.RefreshPreflight()
|
||||
writeJSON(w, http.StatusOK, r.healthSnapshot())
|
||||
case "/api/admin/system/audit":
|
||||
page, err := r.store.ListAuditLogsPage(db.AuditFilters{
|
||||
Page: queryInt(req, "page", 1),
|
||||
@@ -293,6 +336,12 @@ func (r *router) handleAdminSystem(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *router) healthSnapshot() map[string]any {
|
||||
snapshot := r.health.Snapshot()
|
||||
snapshot["adminAssets"] = r.adminAssets.Diagnostics()
|
||||
return snapshot
|
||||
}
|
||||
|
||||
func queryInt(req *http.Request, key string, fallback int) int {
|
||||
value, err := strconv.Atoi(req.URL.Query().Get(key))
|
||||
if err != nil || value <= 0 {
|
||||
|
||||
Reference in New Issue
Block a user