package web import ( "net/http" "net/url" "strconv" "time" "github.com/gin-gonic/gin" "cmautobuy/admin/service" ) func (h *Handler) AIConfigList(c *gin.Context) { result, err := service.ListAIProviderConfigs(h.db, currentUser(c), h.aiSecrets) if err != nil { fail(c, http.StatusInternalServerError, "读取 AI 模型配置失败,配置没有被改动。") return } c.HTML(http.StatusOK, "ai/list", page(c, "ai-settings", "AI 模型配置", gin.H{ "Rows": result.Items, "SecretStoreError": result.SecretStoreError, "Message": c.Query("msg"), "Error": c.Query("error"), })) } func (h *Handler) AIConfigSave(c *gin.Context) { timeoutSeconds, _ := strconv.Atoi(c.PostForm("timeout_seconds")) maxConcurrency, _ := strconv.Atoi(c.PostForm("max_concurrency")) threshold, err := service.ParseConfidenceThresholdBPS(c.PostForm("confidence_threshold")) if err != nil { redirectAIConfig(c, "", err.Error()) return } _, err = service.SaveAIProviderConfig(h.db, currentUser(c), service.AIProviderInput{ ProviderID: c.PostForm("provider_id"), Name: c.PostForm("name"), BaseURL: c.PostForm("base_url"), Model: c.PostForm("model"), TimeoutSeconds: timeoutSeconds, MaxConcurrency: maxConcurrency, ConfidenceThresholdBPS: threshold, }, h.aiPolicy, time.Now()) if err != nil { if service.IsValidationError(err) { redirectAIConfig(c, "", err.Error()) return } fail(c, http.StatusInternalServerError, "保存 AI 服务商失败,原有效配置保持不变。") return } redirectAIConfig(c, "AI 服务商配置已保存;请保存密钥并测试连接后再启用", "") } func (h *Handler) AIConfigSecretSave(c *gin.Context) { if err := service.SetAIProviderSecret(h.db, currentUser(c), h.aiSecrets, c.PostForm("provider_id"), c.PostForm("api_key"), time.Now()); err != nil { redirectAIConfig(c, "", err.Error()) return } redirectAIConfig(c, "API Key 已安全替换;当前服务商已停用,请重新测试后启用", "") } func (h *Handler) AIConfigSecretClear(c *gin.Context) { if err := service.ClearAIProviderSecret(h.db, currentUser(c), h.aiSecrets, c.PostForm("provider_id"), time.Now()); err != nil { redirectAIConfig(c, "", err.Error()) return } redirectAIConfig(c, "API Key 已清除,服务商已停用", "") } func (h *Handler) AIConfigTest(c *gin.Context) { if err := service.TestAIProviderConnection(c.Request.Context(), h.db, currentUser(c), h.aiSecrets, c.PostForm("provider_id"), h.aiPolicy, nil, time.Now()); err != nil { redirectAIConfig(c, "", err.Error()) return } redirectAIConfig(c, "连接测试成功;现在可以启用这个服务商", "") } func (h *Handler) AIConfigEnable(c *gin.Context) { if err := service.EnableAIProviderConfig(h.db, currentUser(c), h.aiSecrets, c.PostForm("provider_id"), time.Now()); err != nil { redirectAIConfig(c, "", err.Error()) return } redirectAIConfig(c, "AI 服务商已启用,新批次将使用这份配置", "") } func (h *Handler) AIConfigDisable(c *gin.Context) { if err := service.DisableAIProviderConfig(h.db, currentUser(c), c.PostForm("provider_id"), time.Now()); err != nil { redirectAIConfig(c, "", err.Error()) return } redirectAIConfig(c, "AI 服务商已停用,不会影响已经启动的批次", "") } func redirectAIConfig(c *gin.Context, message, errorMessage string) { values := url.Values{} if message != "" { values.Set("msg", message) } if errorMessage != "" { values.Set("error", errorMessage) } target := "/settings/ai" if encoded := values.Encode(); encoded != "" { target += "?" + encoded } c.Redirect(http.StatusSeeOther, target) }