合并本地领先源码:旧UI、GM疲劳燃烧、白金徽章孔、宠物修复、支援兵普攻开关
This commit is contained in:
1 parent
f2debaf9bf
commit
70b3c5a6dc
57 files changed
+4256
-30
No files matched your search
@@ -0,0 +1,126 @@
|
||||
package dnf90
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
appkit "longheng.io/server/internal/platform/app"
|
||||
httpx "longheng.io/server/internal/platform/httpx"
|
||||
"longheng.io/server/internal/services/dnfbridge"
|
||||
)
|
||||
|
||||
// companionPanelAdminPath is the local-only endpoint used by the GM tool's
|
||||
// "支援兵属性" page. It is intentionally unauthenticated: the admin mux binds
|
||||
// to loopback, like the existing /local endpoints, and the page is served by
|
||||
// the local GM tool.
|
||||
const companionPanelAdminPath = "/local/companion-panel"
|
||||
|
||||
func registerCompanionPanelAdmin(env *appkit.Env, bridge *dnfbridge.Service) {
|
||||
if env == nil || env.AdminMux == nil || bridge == nil {
|
||||
return
|
||||
}
|
||||
env.AdminMux.HandleFunc(companionPanelAdminPath, func(w http.ResponseWriter, r *http.Request) {
|
||||
applyCompanionPanelCORS(w)
|
||||
if r.Method == http.MethodOptions {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
characterID := strings.TrimSpace(r.URL.Query().Get("character_id"))
|
||||
if characterID == "" {
|
||||
characterID = strings.TrimSpace(r.URL.Query().Get("characterId"))
|
||||
}
|
||||
values, found, err := bridge.CompanionPanelValues(r.Context(), characterID)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(w, http.StatusOK, map[string]any{
|
||||
"character_id": characterID,
|
||||
"found": found,
|
||||
"values": values,
|
||||
})
|
||||
case http.MethodPost:
|
||||
var body struct {
|
||||
CharacterID string `json:"character_id"`
|
||||
Values map[string]string `json:"values"`
|
||||
}
|
||||
decoder := json.NewDecoder(io.LimitReader(r.Body, 1<<20))
|
||||
if err := decoder.Decode(&body); err != nil {
|
||||
httpx.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(body.CharacterID) == "" {
|
||||
httpx.WriteJSON(w, http.StatusBadRequest, map[string]string{
|
||||
"error": "character_id is required",
|
||||
})
|
||||
return
|
||||
}
|
||||
if err := bridge.SaveCompanionPanelValues(r.Context(), body.CharacterID, body.Values); err != nil {
|
||||
httpx.WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
values, found, _ := bridge.CompanionPanelValues(r.Context(), body.CharacterID)
|
||||
httpx.WriteJSON(w, http.StatusOK, map[string]any{
|
||||
"ok": true,
|
||||
"character_id": body.CharacterID,
|
||||
"found": found,
|
||||
"values": values,
|
||||
})
|
||||
default:
|
||||
w.Header().Set("Allow", "GET, POST, OPTIONS")
|
||||
httpx.WriteJSON(w, http.StatusMethodNotAllowed, map[string]string{
|
||||
"error": "method not allowed",
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Base-estimate generation: PVF growth + worn equipment + weapon forging.
|
||||
// Enchant cards, amplification, reinforcement, quality, sets, titles, auras
|
||||
// and pets are intentionally not modelled; the GM page marks the result as
|
||||
// an estimate and lets the operator correct it.
|
||||
env.AdminMux.HandleFunc(companionPanelGeneratePath, func(w http.ResponseWriter, r *http.Request) {
|
||||
applyCompanionPanelCORS(w)
|
||||
if r.Method == http.MethodOptions {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
if r.Method != http.MethodPost {
|
||||
w.Header().Set("Allow", "POST, OPTIONS")
|
||||
httpx.WriteJSON(w, http.StatusMethodNotAllowed, map[string]string{
|
||||
"error": "method not allowed",
|
||||
})
|
||||
return
|
||||
}
|
||||
var body struct {
|
||||
CharacterID string `json:"character_id"`
|
||||
}
|
||||
if err := json.NewDecoder(io.LimitReader(r.Body, 1<<20)).Decode(&body); err != nil {
|
||||
httpx.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
values, err := bridge.GenerateCompanionPanelSnapshot(r.Context(), body.CharacterID)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(w, http.StatusOK, map[string]any{
|
||||
"ok": true,
|
||||
"character_id": body.CharacterID,
|
||||
"estimate": true,
|
||||
"values": values,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const companionPanelGeneratePath = "/local/companion-panel/generate"
|
||||
|
||||
func applyCompanionPanelCORS(w http.ResponseWriter) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, X-Admin-Token")
|
||||
w.Header().Set("Access-Control-Allow-Private-Network", "true")
|
||||
}
|
||||
Reference in new issue
Block a user