update: 2026-03-28 20:59
This commit is contained in:
109
infogenie-backend-go/internal/handler/ai_runtime.go
Normal file
109
infogenie-backend-go/internal/handler/ai_runtime.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"infogenie-backend/config"
|
||||
"infogenie-backend/internal/database"
|
||||
"infogenie-backend/internal/model"
|
||||
)
|
||||
|
||||
type AIRuntimeHandler struct{}
|
||||
|
||||
func NewAIRuntimeHandler() *AIRuntimeHandler { return &AIRuntimeHandler{} }
|
||||
|
||||
func maskAPIKey(k string) (set bool, hint string) {
|
||||
k = strings.TrimSpace(k)
|
||||
if k == "" {
|
||||
return false, ""
|
||||
}
|
||||
if len(k) <= 4 {
|
||||
return true, "****"
|
||||
}
|
||||
return true, "****" + k[len(k)-4:]
|
||||
}
|
||||
|
||||
// GetAIRuntime 管理员读取当前 AI 上游配置(密钥脱敏)
|
||||
func (h *AIRuntimeHandler) GetAIRuntime(c *gin.Context) {
|
||||
if config.Cfg == nil || strings.TrimSpace(config.Cfg.SiteAdminToken) == "" {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "admin_not_configured"})
|
||||
return
|
||||
}
|
||||
if !siteAdminTokenOK(c.GetHeader("X-Site-Admin-Token")) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "forbidden"})
|
||||
return
|
||||
}
|
||||
|
||||
var row model.SiteAIRuntime
|
||||
_ = database.DB.First(&row, 1).Error
|
||||
keySet, keyHint := maskAPIKey(row.APIKey)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"api_base": strings.TrimSpace(row.APIBase),
|
||||
"api_key_set": keySet,
|
||||
"api_key_hint": keyHint,
|
||||
"default_model": strings.TrimSpace(row.DefaultModel),
|
||||
"default_provider": strings.TrimSpace(row.DefaultProv),
|
||||
})
|
||||
}
|
||||
|
||||
type putAIRuntimeBody struct {
|
||||
APIBase string `json:"api_base"`
|
||||
APIKey string `json:"api_key"`
|
||||
DefaultModel string `json:"default_model"`
|
||||
DefaultProvider string `json:"default_provider"`
|
||||
}
|
||||
|
||||
// PutAIRuntime 管理员写入;api_key 留空或不传则保留原密钥
|
||||
func (h *AIRuntimeHandler) PutAIRuntime(c *gin.Context) {
|
||||
if config.Cfg == nil || strings.TrimSpace(config.Cfg.SiteAdminToken) == "" {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "admin_not_configured"})
|
||||
return
|
||||
}
|
||||
if !siteAdminTokenOK(c.GetHeader("X-Site-Admin-Token")) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "forbidden"})
|
||||
return
|
||||
}
|
||||
|
||||
var body putAIRuntimeBody
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid_json"})
|
||||
return
|
||||
}
|
||||
|
||||
var row model.SiteAIRuntime
|
||||
err := database.DB.First(&row, 1).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
row = model.SiteAIRuntime{ID: 1}
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "db_error"})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
row.APIBase = strings.TrimSpace(body.APIBase)
|
||||
if strings.TrimSpace(body.DefaultModel) != "" {
|
||||
row.DefaultModel = strings.TrimSpace(body.DefaultModel)
|
||||
}
|
||||
if strings.TrimSpace(body.DefaultProvider) != "" {
|
||||
row.DefaultProv = strings.TrimSpace(body.DefaultProvider)
|
||||
} else if row.DefaultProv == "" {
|
||||
row.DefaultProv = "deepseek"
|
||||
}
|
||||
|
||||
newKey := strings.TrimSpace(body.APIKey)
|
||||
if newKey != "" && !strings.Contains(newKey, "****") {
|
||||
row.APIKey = newKey
|
||||
}
|
||||
|
||||
if err := database.DB.Save(&row).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "db_error"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"ok": true})
|
||||
}
|
||||
Reference in New Issue
Block a user