package handlers import ( "net/http" "code-review/config" "code-review/utils" "log" "strings" "github.com/gin-gonic/gin" ) type ConfigHandler struct { cfg *config.Config } func NewConfigHandler(cfg *config.Config) *ConfigHandler { return &ConfigHandler{ cfg: cfg, } } // GetConfig 获取当前配置 func (h *ConfigHandler) GetConfig(c *gin.Context) { // 使用 ToMap 方法转换配置 configMap := h.cfg.ToMapHtml() c.JSON(http.StatusOK, configMap) } // UpdateConfig 更新配置 func (h *ConfigHandler) UpdateConfig(c *gin.Context) { // 首先解析为 map var configMap map[string]interface{} if err := c.ShouldBindJSON(&configMap); err != nil { log.Printf("解析配置 JSON 失败: %v", err) c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } log.Printf("开始更新配置") // 使用当前配置作为基础 newConfig := *h.cfg // 处理自动禁用配置 if autoDisable, ok := configMap["auto_disable"].(map[string]interface{}); ok { log.Printf("更新自动禁用配置") if enabled, exists := autoDisable["enabled"].(bool); exists { newConfig.AutoDisableConfig.Enabled = enabled log.Printf("自动禁用功能状态设置为: %v", enabled) } if maxFailures, ok := autoDisable["max_failures"].(float64); ok { newConfig.AutoDisableConfig.MaxFailures = int(maxFailures) } if resetAfter, ok := autoDisable["reset_after"].(float64); ok { newConfig.AutoDisableConfig.ResetAfter = int(resetAfter) } } // 处理 AI 配置 newConfig.AIs = make([]config.AIConfig, 0) for key, value := range configMap { if strings.HasPrefix(key, "ais[") { if aiMap, ok := value.(map[string]interface{}); ok { aiConfig := config.AIConfig{ Name: utils.GetString(aiMap, "name"), Type: utils.GetString(aiMap, "type"), APIKey: utils.GetString(aiMap, "api_key"), APIBase: utils.GetString(aiMap, "url"), Model: utils.GetString(aiMap, "model"), SystemMsg: utils.GetString(aiMap, "system_msg"), Temperature: utils.GetFloat64(aiMap, "temperature"), Stream: utils.GetBool(aiMap, "stream"), Weight: utils.GetInt(aiMap, "weight"), Priority: utils.GetInt(aiMap, "priority"), Enabled: utils.GetBool(aiMap, "enabled"), AutoDisable: utils.GetBool(aiMap, "auto_disable"), MaxFailures: utils.GetIntPtr(aiMap, "max_failures"), ResetAfter: utils.GetIntPtr(aiMap, "reset_after"), } log.Printf("添加 AI 配置: %s, 类型: %s", aiConfig.Name, aiConfig.Type) newConfig.AIs = append(newConfig.AIs, aiConfig) } } } // 处理 Git 平台配置 newConfig.Git = make([]config.GitConfig, 0) for key, value := range configMap { if strings.HasPrefix(key, "git[") { if p, ok := value.(map[string]interface{}); ok { platformType := utils.GetString(p, "type") platformConfig := config.GitConfig{ Name: utils.GetString(p, "name"), Type: platformType, Token: utils.GetString(p, "token"), Secret: utils.GetString(p, "webhook_secret"), APIBase: utils.GetString(p, "api_base"), } // 根据平台类型设置对应的 header switch platformType { case "gitlab": platformConfig.SignatureHeader = "X-Gitlab-Token" platformConfig.EventHeader = "X-Gitlab-Event" case "gogs": platformConfig.SignatureHeader = "X-Gogs-Signature" platformConfig.EventHeader = "X-Gogs-Event" case "github": platformConfig.SignatureHeader = "X-Hub-Signature" platformConfig.EventHeader = "X-GitHub-Event" case "gitee": platformConfig.SignatureHeader = "X-Gitee-Token" platformConfig.EventHeader = "X-Gitee-Event" default: // 如果前端传入了自定义的 header,则使用前端传入的值 platformConfig.SignatureHeader = utils.GetString(p, "signature_header") platformConfig.EventHeader = utils.GetString(p, "event_header") } log.Printf("添加 Git 平台配置: %s, 类型: %s, SignatureHeader: %s, EventHeader: %s", platformConfig.Name, platformConfig.Type, platformConfig.SignatureHeader, platformConfig.EventHeader) newConfig.Git = append(newConfig.Git, platformConfig) } } } if err := config.Save(&newConfig); err != nil { log.Printf("保存配置失败: %v", err) c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } // 更新运行时配置 h.cfg = &newConfig // 重新初始化 AI 负载均衡器 config.ResetAIBalancer(newConfig.AIs) log.Printf("配置更新成功") c.JSON(http.StatusOK, gin.H{"message": "配置更新成功"}) } func AuthRequired() gin.HandlerFunc { return func(c *gin.Context) { token := c.GetHeader("X-Admin-Token") cfg := config.GetConfig() if token == "" || token != cfg.AdminToken { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "未授权访问"}) return } c.Next() } }