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) }