package configsection import ( "encoding/json" "strings" "github.com/gin-gonic/gin" "gorm.io/gorm" ) type templateConfig struct { ID uint `gorm:"primaryKey"` ConfigData string `gorm:"type:json;column:config_data;not null"` } func (templateConfig) TableName() string { return "template_configs" } var ( db *gorm.DB requireAdmin func(*gin.Context) bool ) var configSectionKeys = map[string][]string{ "basic": { "groom", "bride", "date", "lunar", "calendarDate", "hotel", "address", "heroImg", "heroImgResized", "heroImgResizedMeta", "endImg", "endImgResized", "endImgResizedMeta", }, "copy": { "formalText1", "formalText2", "formalPageHeight", }, "visual": { "introExitEffect", "scrollMode", "freeScrollInterval", "pageSwitchDuration", "firstScreenDuration", "petalEnabled", "bubbleEnabled", "introEnabled", "danmakuEnabled", "danmakuShowTime", "nineGridAnimate", }, "music": { "musicList", "activeMusicUrl", "musicPlayMode", "musicRandomEnabled", "musicCacheEnabled", "musicCacheHours", }, "photos": { "photoPages", }, "schedule": { "schedule", }, } // Register 由 main 入口调用:注入依赖并挂载分段配置路由 func Register(api *gin.RouterGroup, database *gorm.DB, adminGuard func(*gin.Context) bool) { db = database requireAdmin = adminGuard api.GET("/config/section", handleGetConfigSection) api.POST("/config/section", handleSaveConfigSection) } func loadConfigMap() (map[string]interface{}, error) { var config templateConfig if err := db.First(&config, 1).Error; err != nil { return map[string]interface{}{}, nil } raw := strings.TrimSpace(config.ConfigData) if raw == "" { raw = "{}" } var m map[string]interface{} if err := json.Unmarshal([]byte(raw), &m); err != nil { return nil, err } if m == nil { m = map[string]interface{}{} } return m, nil } func saveConfigMap(m map[string]interface{}) error { jsonBytes, err := json.Marshal(m) if err != nil { return err } var config templateConfig db.Attrs(templateConfig{ConfigData: "{}"}).FirstOrCreate(&config, templateConfig{ID: 1}) config.ConfigData = string(jsonBytes) return db.Save(&config).Error } func pickSection(full map[string]interface{}, keys []string) map[string]interface{} { out := make(map[string]interface{}, len(keys)) for _, k := range keys { if v, ok := full[k]; ok { out[k] = v } } return out } func handleGetConfigSection(c *gin.Context) { if !requireAdmin(c) { return } section := strings.TrimSpace(c.Query("section")) keys, ok := configSectionKeys[section] if !ok { c.JSON(400, gin.H{"error": "未知的 section"}) return } full, err := loadConfigMap() if err != nil { c.JSON(500, gin.H{"error": "读取配置失败"}) return } c.JSON(200, gin.H{"code": 200, "data": pickSection(full, keys)}) } func handleSaveConfigSection(c *gin.Context) { if !requireAdmin(c) { return } var body struct { Section string `json:"section"` Data map[string]interface{} `json:"data"` } if err := c.ShouldBindJSON(&body); err != nil { c.JSON(400, gin.H{"error": "参数错误"}) return } section := strings.TrimSpace(body.Section) keys, ok := configSectionKeys[section] if !ok { c.JSON(400, gin.H{"error": "未知的 section"}) return } if body.Data == nil { body.Data = map[string]interface{}{} } full, err := loadConfigMap() if err != nil { c.JSON(500, gin.H{"error": "读取配置失败"}) return } for _, k := range keys { if v, ok := body.Data[k]; ok { full[k] = v } } if err := saveConfigMap(full); err != nil { c.JSON(500, gin.H{"error": "保存配置失败"}) return } c.JSON(200, gin.H{"code": 200, "msg": "配置段已保存", "data": pickSection(full, keys)}) }