Files
st/server/api/v1/app/provider.go

477 lines
14 KiB
Go

package app
import (
"strconv"
"git.echol.cn/loser/st/server/global"
"git.echol.cn/loser/st/server/middleware"
"git.echol.cn/loser/st/server/model/app/request"
"git.echol.cn/loser/st/server/model/common/response"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
type ProviderApi struct{}
// ==================== 提供商接口 ====================
// CreateProvider 创建AI提供商
// @Tags AI配置
// @Summary 创建AI提供商
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.CreateProviderRequest true "提供商信息"
// @Success 200 {object} response.Response{data=appResponse.ProviderResponse} "创建成功"
// @Router /app/provider [post]
func (pa *ProviderApi) CreateProvider(c *gin.Context) {
userID := middleware.GetAppUserID(c)
var req request.CreateProviderRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
provider, err := providerService.CreateProvider(req, userID)
if err != nil {
global.GVA_LOG.Error("创建AI提供商失败", zap.Error(err))
response.FailWithMessage("创建失败: "+err.Error(), c)
return
}
response.OkWithData(provider, c)
}
// GetProviderList 获取AI提供商列表
// @Tags AI配置
// @Summary 获取AI提供商列表
// @Security ApiKeyAuth
// @Produce application/json
// @Param page query int true "页码"
// @Param pageSize query int true "每页数量"
// @Param keyword query string false "搜索关键词"
// @Success 200 {object} response.Response{data=appResponse.ProviderListResponse} "获取成功"
// @Router /app/provider/list [get]
func (pa *ProviderApi) GetProviderList(c *gin.Context) {
userID := middleware.GetAppUserID(c)
var req request.ProviderListRequest
if err := c.ShouldBindQuery(&req); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
// 默认分页
if req.Page == 0 {
req.Page = 1
}
if req.PageSize == 0 {
req.PageSize = 20
}
list, err := providerService.GetProviderList(req, userID)
if err != nil {
global.GVA_LOG.Error("获取AI提供商列表失败", zap.Error(err))
response.FailWithMessage("获取失败", c)
return
}
response.OkWithData(list, c)
}
// GetProviderDetail 获取AI提供商详情
// @Tags AI配置
// @Summary 获取AI提供商详情
// @Security ApiKeyAuth
// @Produce application/json
// @Param id path uint true "提供商ID"
// @Success 200 {object} response.Response{data=appResponse.ProviderResponse} "获取成功"
// @Router /app/provider/:id [get]
func (pa *ProviderApi) GetProviderDetail(c *gin.Context) {
userID := middleware.GetAppUserID(c)
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.FailWithMessage("无效的ID", c)
return
}
provider, err := providerService.GetProviderDetail(uint(id), userID)
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}
response.OkWithData(provider, c)
}
// UpdateProvider 更新AI提供商
// @Tags AI配置
// @Summary 更新AI提供商
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.UpdateProviderRequest true "更新信息"
// @Success 200 {object} response.Response{data=appResponse.ProviderResponse} "更新成功"
// @Router /app/provider [put]
func (pa *ProviderApi) UpdateProvider(c *gin.Context) {
userID := middleware.GetAppUserID(c)
var req request.UpdateProviderRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
provider, err := providerService.UpdateProvider(req, userID)
if err != nil {
global.GVA_LOG.Error("更新AI提供商失败", zap.Error(err))
response.FailWithMessage("更新失败: "+err.Error(), c)
return
}
response.OkWithData(provider, c)
}
// DeleteProvider 删除AI提供商
// @Tags AI配置
// @Summary 删除AI提供商
// @Security ApiKeyAuth
// @Produce application/json
// @Param id path uint true "提供商ID"
// @Success 200 {object} response.Response{msg=string} "删除成功"
// @Router /app/provider/:id [delete]
func (pa *ProviderApi) DeleteProvider(c *gin.Context) {
userID := middleware.GetAppUserID(c)
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.FailWithMessage("无效的ID", c)
return
}
if err := providerService.DeleteProvider(uint(id), userID); err != nil {
global.GVA_LOG.Error("删除AI提供商失败", zap.Error(err))
response.FailWithMessage("删除失败: "+err.Error(), c)
return
}
response.OkWithMessage("删除成功", c)
}
// SetDefaultProvider 设置默认提供商
// @Tags AI配置
// @Summary 设置默认AI提供商
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.SetDefaultProviderRequest true "提供商ID"
// @Success 200 {object} response.Response{msg=string} "设置成功"
// @Router /app/provider/setDefault [post]
func (pa *ProviderApi) SetDefaultProvider(c *gin.Context) {
userID := middleware.GetAppUserID(c)
var req request.SetDefaultProviderRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
if err := providerService.SetDefaultProvider(req.ProviderID, userID); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
response.OkWithMessage("设置成功", c)
}
// TestProvider 测试提供商连通性(不需要先保存)
// @Tags AI配置
// @Summary 测试AI提供商连通性
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.TestProviderRequest true "测试参数"
// @Success 200 {object} response.Response{data=appResponse.TestProviderResponse} "测试结果"
// @Router /app/provider/test [post]
func (pa *ProviderApi) TestProvider(c *gin.Context) {
var req request.TestProviderRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
result, err := providerService.TestProvider(req)
if err != nil {
response.FailWithMessage("测试失败: "+err.Error(), c)
return
}
response.OkWithData(result, c)
}
// TestExistingProvider 测试已保存的提供商连通性
// @Tags AI配置
// @Summary 测试已保存的提供商连通性
// @Security ApiKeyAuth
// @Produce application/json
// @Param id path uint true "提供商ID"
// @Success 200 {object} response.Response{data=appResponse.TestProviderResponse} "测试结果"
// @Router /app/provider/test/:id [get]
func (pa *ProviderApi) TestExistingProvider(c *gin.Context) {
userID := middleware.GetAppUserID(c)
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.FailWithMessage("无效的ID", c)
return
}
result, err := providerService.TestExistingProvider(uint(id), userID)
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}
response.OkWithData(result, c)
}
// ==================== 模型接口 ====================
// AddModel 为提供商添加模型
// @Tags AI配置
// @Summary 添加AI模型
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.CreateModelRequest true "模型信息"
// @Success 200 {object} response.Response{data=appResponse.ModelResponse} "创建成功"
// @Router /app/provider/model [post]
func (pa *ProviderApi) AddModel(c *gin.Context) {
userID := middleware.GetAppUserID(c)
var req request.CreateModelRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
model, err := providerService.AddModel(req, userID)
if err != nil {
global.GVA_LOG.Error("添加模型失败", zap.Error(err))
response.FailWithMessage("添加失败: "+err.Error(), c)
return
}
response.OkWithData(model, c)
}
// UpdateModel 更新模型
// @Tags AI配置
// @Summary 更新AI模型
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.UpdateModelRequest true "更新信息"
// @Success 200 {object} response.Response{data=appResponse.ModelResponse} "更新成功"
// @Router /app/provider/model [put]
func (pa *ProviderApi) UpdateModel(c *gin.Context) {
userID := middleware.GetAppUserID(c)
var req request.UpdateModelRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
model, err := providerService.UpdateModel(req, userID)
if err != nil {
global.GVA_LOG.Error("更新模型失败", zap.Error(err))
response.FailWithMessage("更新失败: "+err.Error(), c)
return
}
response.OkWithData(model, c)
}
// DeleteModel 删除模型
// @Tags AI配置
// @Summary 删除AI模型
// @Security ApiKeyAuth
// @Produce application/json
// @Param id path uint true "模型ID"
// @Success 200 {object} response.Response{msg=string} "删除成功"
// @Router /app/provider/model/:id [delete]
func (pa *ProviderApi) DeleteModel(c *gin.Context) {
userID := middleware.GetAppUserID(c)
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.FailWithMessage("无效的ID", c)
return
}
if err := providerService.DeleteModel(uint(id), userID); err != nil {
global.GVA_LOG.Error("删除模型失败", zap.Error(err))
response.FailWithMessage("删除失败: "+err.Error(), c)
return
}
response.OkWithMessage("删除成功", c)
}
// ==================== 远程模型获取 ====================
// FetchRemoteModels 获取远程可用模型列表(不需要先保存)
// @Tags AI配置
// @Summary 从远程获取可用模型列表
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.FetchRemoteModelsRequest true "提供商配置"
// @Success 200 {object} response.Response{data=appResponse.FetchRemoteModelsResponse} "获取结果"
// @Router /app/provider/fetchModels [post]
func (pa *ProviderApi) FetchRemoteModels(c *gin.Context) {
var req request.FetchRemoteModelsRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
result, err := providerService.FetchRemoteModels(req)
if err != nil {
response.FailWithMessage("获取失败: "+err.Error(), c)
return
}
response.OkWithData(result, c)
}
// FetchRemoteModelsExisting 获取已保存提供商的远程模型列表
// @Tags AI配置
// @Summary 获取已保存提供商的远程可用模型
// @Security ApiKeyAuth
// @Produce application/json
// @Param id path uint true "提供商ID"
// @Success 200 {object} response.Response{data=appResponse.FetchRemoteModelsResponse} "获取结果"
// @Router /app/provider/fetchModels/:id [get]
func (pa *ProviderApi) FetchRemoteModelsExisting(c *gin.Context) {
userID := middleware.GetAppUserID(c)
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.FailWithMessage("无效的ID", c)
return
}
result, err := providerService.FetchRemoteModelsExisting(uint(id), userID)
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}
response.OkWithData(result, c)
}
// ==================== 测试消息 ====================
// SendTestMessage 发送测试消息(不需要先保存)
// @Tags AI配置
// @Summary 发送测试消息验证AI接口
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.SendTestMessageRequest true "测试参数"
// @Success 200 {object} response.Response{data=appResponse.SendTestMessageResponse} "测试结果"
// @Router /app/provider/testMessage [post]
func (pa *ProviderApi) SendTestMessage(c *gin.Context) {
var req request.SendTestMessageRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
result, err := providerService.SendTestMessage(req)
if err != nil {
response.FailWithMessage("测试失败: "+err.Error(), c)
return
}
response.OkWithData(result, c)
}
// SendTestMessageExisting 使用已保存的提供商发送测试消息
// @Tags AI配置
// @Summary 使用已保存的提供商发送测试消息
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param id path uint true "提供商ID"
// @Param data body object{modelName=string,message=string} true "测试参数"
// @Success 200 {object} response.Response{data=appResponse.SendTestMessageResponse} "测试结果"
// @Router /app/provider/testMessage/:id [post]
func (pa *ProviderApi) SendTestMessageExisting(c *gin.Context) {
userID := middleware.GetAppUserID(c)
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.FailWithMessage("无效的ID", c)
return
}
var body struct {
ModelName string `json:"modelName" binding:"required"`
Message string `json:"message"`
}
if err := c.ShouldBindJSON(&body); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
result, err := providerService.SendTestMessageExisting(uint(id), userID, body.ModelName, body.Message)
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}
response.OkWithData(result, c)
}
// ==================== 辅助接口 ====================
// GetProviderTypes 获取支持的提供商类型列表
// @Tags AI配置
// @Summary 获取支持的AI提供商类型
// @Produce application/json
// @Success 200 {object} response.Response{data=[]appResponse.ProviderTypeOption} "获取成功"
// @Router /app/provider/types [get]
func (pa *ProviderApi) GetProviderTypes(c *gin.Context) {
types := providerService.GetProviderTypes()
response.OkWithData(types, c)
}
// GetPresetModels 获取预设模型列表
// @Tags AI配置
// @Summary 获取指定提供商类型的预设模型
// @Produce application/json
// @Param type query string true "提供商类型(openai/claude/gemini/custom)"
// @Success 200 {object} response.Response{data=[]appResponse.PresetModelOption} "获取成功"
// @Router /app/provider/presetModels [get]
func (pa *ProviderApi) GetPresetModels(c *gin.Context) {
providerType := c.Query("type")
if providerType == "" {
response.FailWithMessage("请指定提供商类型", c)
return
}
models := providerService.GetPresetModels(providerType)
response.OkWithData(models, c)
}