1
0
Files
nex/backend/internal/handler/provider_handler.go
lanyuanxiaoyao 915b004924 feat: 初始化 AI Gateway 项目
实现支持 OpenAI 和 Anthropic 双协议的统一大模型 API 网关 MVP 版本,包含:
- OpenAI 和 Anthropic 协议代理
- 供应商和模型管理
- 用量统计
- 前端配置界面
2026-04-15 16:53:28 +08:00

168 lines
3.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package handler
import (
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"nex/backend/internal/config"
)
// ProviderHandler 供应商管理处理器
type ProviderHandler struct{}
// NewProviderHandler 创建供应商处理器
func NewProviderHandler() *ProviderHandler {
return &ProviderHandler{}
}
// CreateProvider 创建供应商
func (h *ProviderHandler) CreateProvider(c *gin.Context) {
var req struct {
ID string `json:"id" binding:"required"`
Name string `json:"name" binding:"required"`
APIKey string `json:"api_key" binding:"required"`
BaseURL string `json:"base_url" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "缺少必需字段: id, name, api_key, base_url",
})
return
}
// 创建供应商对象
provider := &config.Provider{
ID: req.ID,
Name: req.Name,
APIKey: req.APIKey,
BaseURL: req.BaseURL,
Enabled: true, // 默认启用
}
// 保存到数据库
err := config.CreateProvider(provider)
if err != nil {
// 检查是否是唯一约束错误ID 重复)
if err.Error() == "UNIQUE constraint failed: providers.id" {
c.JSON(http.StatusConflict, gin.H{
"error": "供应商 ID 已存在",
})
return
}
c.JSON(http.StatusInternalServerError, gin.H{
"error": "创建供应商失败: " + err.Error(),
})
return
}
// 掩码 API Key 后返回
provider.MaskAPIKey()
c.JSON(http.StatusCreated, provider)
}
// ListProviders 列出所有供应商
func (h *ProviderHandler) ListProviders(c *gin.Context) {
providers, err := config.ListProviders()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "查询供应商失败: " + err.Error(),
})
return
}
c.JSON(http.StatusOK, providers)
}
// GetProvider 获取供应商
func (h *ProviderHandler) GetProvider(c *gin.Context) {
id := c.Param("id")
provider, err := config.GetProvider(id, true) // 掩码 API Key
if err != nil {
if err == gorm.ErrRecordNotFound {
c.JSON(http.StatusNotFound, gin.H{
"error": "供应商未找到",
})
return
}
c.JSON(http.StatusInternalServerError, gin.H{
"error": "查询供应商失败: " + err.Error(),
})
return
}
c.JSON(http.StatusOK, provider)
}
// UpdateProvider 更新供应商
func (h *ProviderHandler) UpdateProvider(c *gin.Context) {
id := c.Param("id")
var req map[string]interface{}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "无效的请求格式",
})
return
}
// 更新供应商
err := config.UpdateProvider(id, req)
if err != nil {
if err == gorm.ErrRecordNotFound {
c.JSON(http.StatusNotFound, gin.H{
"error": "供应商未找到",
})
return
}
c.JSON(http.StatusInternalServerError, gin.H{
"error": "更新供应商失败: " + err.Error(),
})
return
}
// 返回更新后的供应商
provider, err := config.GetProvider(id, true)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "查询更新后的供应商失败: " + err.Error(),
})
return
}
c.JSON(http.StatusOK, provider)
}
// DeleteProvider 删除供应商
func (h *ProviderHandler) DeleteProvider(c *gin.Context) {
id := c.Param("id")
// 删除供应商(级联删除模型)
err := config.DeleteProvider(id)
if err != nil {
if err == gorm.ErrRecordNotFound {
c.JSON(http.StatusNotFound, gin.H{
"error": "供应商未找到",
})
return
}
c.JSON(http.StatusInternalServerError, gin.H{
"error": "删除供应商失败: " + err.Error(),
})
return
}
// 删除关联的模型
models, _ := config.ListModels("")
for _, model := range models {
if model.ProviderID == id {
_ = config.DeleteModel(model.ID)
}
}
c.Status(http.StatusNoContent)
}