AI分析功能:LLM Key 改为数据库管理,支持管理员后台配置

This commit is contained in:
fish
2026-05-10 16:21:15 +08:00
parent ad9edf7ad4
commit 99c2a5bcbf
12 changed files with 814 additions and 23 deletions

View File

@@ -0,0 +1,86 @@
package handlers
import (
"encoding/json"
"net/http"
"strings"
"trade/web/internal/store"
)
type llmConfigReq struct {
BaseURL string `json:"base_url"`
APIKey string `json:"api_key"`
Model string `json:"model"`
}
type llmConfigResp struct {
BaseURL string `json:"base_url"`
APIKey string `json:"api_key"` // 脱敏:仅显示首尾
Model string `json:"model"`
HasAPIKey bool `json:"has_api_key"` // 前端据此判断是否已配置
}
// maskKey 将 sk-abc123xyz 脱敏为 sk-a...xyz。
func maskKey(key string) string {
if len(key) <= 8 {
return strings.Repeat("*", len(key))
}
return key[:4] + "..." + key[len(key)-4:]
}
// GetLLMConfig 返回当前 LLM 配置API Key 脱敏)。
func (d *Deps) GetLLMConfig(w http.ResponseWriter, r *http.Request) {
cfg, err := d.Futures.GetLLMConfig()
if err != nil {
writeErr(w, http.StatusInternalServerError, err.Error())
return
}
resp := llmConfigResp{
BaseURL: cfg.BaseURL,
Model: cfg.Model,
HasAPIKey: cfg.APIKey != "",
}
if cfg.APIKey != "" {
resp.APIKey = maskKey(cfg.APIKey)
}
writeJSON(w, http.StatusOK, resp)
}
// SaveLLMConfig 保存 LLM 配置。api_key 为脱敏占位时保留原值。
func (d *Deps) SaveLLMConfig(w http.ResponseWriter, r *http.Request) {
var req llmConfigReq
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeErr(w, http.StatusBadRequest, "invalid json")
return
}
req.BaseURL = strings.TrimSpace(req.BaseURL)
req.Model = strings.TrimSpace(req.Model)
if req.BaseURL == "" {
req.BaseURL = "https://api.deepseek.com/v1"
}
if req.Model == "" {
req.Model = "deepseek-chat"
}
// 如果前端传的是脱敏值(含 ...),说明未修改 Key保留旧值
if strings.Contains(req.APIKey, "...") {
old, err := d.Futures.GetLLMConfig()
if err != nil {
writeErr(w, http.StatusInternalServerError, err.Error())
return
}
req.APIKey = old.APIKey
}
cfg := &store.LLMConfig{
BaseURL: req.BaseURL,
APIKey: req.APIKey,
Model: req.Model,
}
if err := d.Futures.SaveLLMConfig(cfg); err != nil {
writeErr(w, http.StatusInternalServerError, err.Error())
return
}
writeJSON(w, http.StatusOK, map[string]string{"status": "ok"})
}