From 1ce1913437efadad9ad55607ef8bcc21e13b8ed2 Mon Sep 17 00:00:00 2001 From: WangLiZhao <1838393649@qq.com> Date: Fri, 3 Jul 2026 17:33:23 +0800 Subject: [PATCH] =?UTF-8?q?refactor(gateway):=20=E6=8F=90=E5=8F=96?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E5=A4=B4=E8=BD=AC=E5=8F=91=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=E6=A8=A1=E5=9E=8B=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E6=9D=83=E9=99=90=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dao/model_gateway_models_dao.go | 38 ++--- model/dto/model_gateway_models_dto.go | 106 ++++++------- model/entity/model_gateway_model.go | 200 +++++++++++------------- service/gateway/gateway_http_service.go | 150 +++--------------- service/model/model_service.go | 9 +- 5 files changed, 180 insertions(+), 323 deletions(-) diff --git a/dao/model_gateway_models_dao.go b/dao/model_gateway_models_dao.go index 7217b79..3593d66 100644 --- a/dao/model_gateway_models_dao.go +++ b/dao/model_gateway_models_dao.go @@ -5,6 +5,7 @@ import ( "model-gateway/consts/public" "model-gateway/model/dto" "model-gateway/model/entity" + "model-gateway/service/gateway" "strconv" "gitea.redpowerfuture.com/red-future/common/db/gfdb" @@ -119,8 +120,11 @@ func (d *modelGatewayModelsDao) GetByAcrossTenant(ctx context.Context, req *enti return &m, err } -// GetByCreatorAndPlatform 按创建者、平台获取 +// GetByCreatorAndPlatform 获取模型列表 func (d *modelGatewayModelsDao) GetByCreatorAndPlatform(ctx context.Context, req *dto.ListModelReq) (list []*entity.ModelGatewayModel, total int, err error) { + // 判断是否管理员 + isAdmin, _ := gateway.IsSuperAdmin(ctx) + sql := ` SELECT DISTINCT ON (model_name) * FROM ` + public.TableNameModel + ` @@ -131,9 +135,8 @@ WHERE deleted_at IS NULL req.ModelName, "%" + req.ModelName + "%", } - // modelType: 传 6 模糊匹配 6% if req.ModelType > 0 { - prefix := strconv.Itoa(req.ModelType)[:1] // 截取第一位 + prefix := strconv.Itoa(req.ModelType)[:1] sql += ` AND model_type::text LIKE ? ` args = append(args, prefix+"%") } @@ -143,27 +146,18 @@ WHERE deleted_at IS NULL args = append(args, req.IsPrivate) } - if req.IsOwner != nil && *req.IsOwner == 0 { - if req.Enabled != nil && *req.Enabled == 1 { - sql += ` AND creator = ? AND is_owner = ? AND enabled=1 ` - } else if req.Enabled != nil && *req.Enabled == 0 { - sql += ` AND creator = ? AND is_owner = ? AND enabled=0 ` - } else { - sql += ` AND creator = ? AND is_owner = ? ` - } - args = append(args, req.Creator, req.IsOwner) - } else if req.IsOwner != nil && *req.IsOwner == 1 { - if req.Enabled != nil && *req.Enabled == 1 { - sql += ` AND ((creator = ? AND is_owner = ? AND enabled=1) OR (is_owner = 0 AND enabled=1)) ` - } else if req.Enabled != nil && *req.Enabled == 0 { - sql += ` AND ((creator = ? AND is_owner = ? AND enabled=0) OR (is_owner = 0 AND enabled=1)) ` - } else { - sql += ` AND ((creator = ? AND is_owner = ?) OR (is_owner = 0 AND enabled=1)) ` - } - args = append(args, req.Creator, req.IsOwner) + // 非管理员只看自己的 + 公共启用的 + if !isAdmin { + sql += ` AND ((creator = ?) OR (is_private = 1 AND enabled = 1)) ` + args = append(args, req.Creator) } - sql += ` ORDER BY model_name, is_owner DESC, created_at DESC` + if req.Enabled != nil { + sql += ` AND enabled = ? ` + args = append(args, *req.Enabled) + } + + sql += ` ORDER BY model_name, created_at DESC` r, err := gfdb.DB(ctx, public.DbNameModelGateway).GetAll(ctx, sql, args...) if err != nil { diff --git a/model/dto/model_gateway_models_dto.go b/model/dto/model_gateway_models_dto.go index 7dea9f6..267178e 100644 --- a/model/dto/model_gateway_models_dto.go +++ b/model/dto/model_gateway_models_dto.go @@ -9,34 +9,30 @@ import ( // CreateModelReq 添加模型配置 type CreateModelReq struct { - g.Meta `path:"/createModel" method:"post" tags:"模型管理" summary:"创建模型配置" dc:"添加新的模型配置"` - ModelName string `p:"modelName" json:"modelName" v:"required#模型名称不能为空" dc:"模型名称(唯一标识)"` - ModelType int `p:"modelType" json:"modelType" v:"required#模型类型不能为空" dc:"模型类型"` - BaseURL string `p:"baseUrl" json:"baseUrl" v:"required#模型地址不能为空" dc:"模型服务地址"` - HttpMethod string `p:"httpMethod" json:"httpMethod" dc:"请求方式:GET/POST(默认POST)"` - HeadMsg map[string]any `p:"headMsg" json:"headMsg" dc:"请求头JSON结构"` - IsPrivate *int `p:"isPrivate" json:"isPrivate" dc:"是否私有化:0-私有 1-公共"` - Enabled *int `p:"enabled" json:"enabled" dc:"是否启用:0-停用 1-启用"` - IsChatModel *int `p:"isChatModel" json:"isChatModel" dc:"是否为对话模型:0-否 1-是"` - CallMode *int `p:"callMode" json:"callMode" dc:"调用模式:0-同步 1-异步 2-流式"` - RequiredFields []string `p:"requiredFields" json:"requiredFields" dc:"必填字段"` - IsOwner *int `p:"isOwner" json:"isOwner" dc:"是否为所有者:0-否 1-是"` - ApiKey string `p:"apiKey" json:"apiKey" dc:"调用凭证/密钥"` - Form []entity.Form `p:"form" json:"form" dc:"动态表单配置"` - RequestMapping map[string]any `p:"requestMapping" json:"requestMapping" dc:"请求映射"` - ResponseMapping map[string]any `p:"responseMapping" json:"responseMapping" dc:"返回映射"` - OperatorName string `p:"operatorName" json:"operatorName" dc:"运营商名称"` - TokenConfig map[string]any `p:"tokenConfig" json:"tokenConfig" dc:"token计算配置"` - ExtendMapping map[string]any `p:"extendMapping" json:"extendMapping" dc:"附加映射"` - QueryConfig map[string]any `p:"queryConfig" json:"queryConfig" dc:"查询/回调配置"` - StreamConfig map[string]any `p:"streamConfig" json:"streamConfig" dc:"流式输出配置"` - FirstFrame string `p:"firstFrame" json:"firstFrame" dc:"首帧图片参数"` - LastFrame string `p:"lastFrame" json:"lastFrame" dc:"尾帧图片参数"` - MaxConcurrency int `p:"maxConcurrency" json:"maxConcurrency" dc:"最大并发数(默认10)"` - TimeoutSeconds int `p:"timeoutSeconds" json:"timeoutSeconds" dc:"请求超时时间(秒,默认600)"` - RetryTimes int `p:"retryTimes" json:"retryTimes" dc:"失败重试次数(默认3)"` - AutoCleanSeconds int `p:"autoCleanSeconds" json:"autoCleanSeconds" dc:"任务完成后自动清理时间(秒,默认86400)"` - CallbackUrl string `p:"callbackUrl" json:"callbackUrl" dc:"回调地址"` + g.Meta `path:"/createModel" method:"post" tags:"模型管理" summary:"创建模型配置" dc:"添加新的模型配置"` + ModelName string `p:"modelName" json:"modelName" v:"required#模型名称不能为空" dc:"模型名称(唯一标识)"` + ModelType int `p:"modelType" json:"modelType" v:"required#模型类型不能为空" dc:"模型类型"` + BaseURL string `p:"baseUrl" json:"baseUrl" v:"required#模型地址不能为空" dc:"模型服务地址"` + HttpMethod string `p:"httpMethod" json:"httpMethod" dc:"请求方式:GET/POST(默认POST)"` + HeadMsg map[string]any `p:"headMsg" json:"headMsg" dc:"请求头JSON结构"` + IsPrivate *int `p:"isPrivate" json:"isPrivate" dc:"是否私有化:0-私有 1-公共"` + Enabled *int `p:"enabled" json:"enabled" dc:"是否启用:0-停用 1-启用"` + IsChatModel *int `p:"isChatModel" json:"isChatModel" dc:"是否为对话模型:0-否 1-是"` + CallMode *int `p:"callMode" json:"callMode" dc:"调用模式:0-同步 1-异步 2-流式"` + RequiredFields []string `p:"requiredFields" json:"requiredFields" dc:"必填字段"` + ApiKey string `p:"apiKey" json:"apiKey" dc:"调用凭证/密钥"` + Form []entity.Form `p:"form" json:"form" dc:"动态表单配置"` + RequestMapping map[string]any `p:"requestMapping" json:"requestMapping" dc:"请求映射"` + ResponseMapping map[string]any `p:"responseMapping" json:"responseMapping" dc:"返回映射"` + OperatorName string `p:"operatorName" json:"operatorName" dc:"运营商名称"` + TokenConfig map[string]any `p:"tokenConfig" json:"tokenConfig" dc:"token计算配置"` + ExtendMapping map[string]any `p:"extendMapping" json:"extendMapping" dc:"附加映射"` + QueryConfig map[string]any `p:"queryConfig" json:"queryConfig" dc:"查询/回调配置"` + StreamConfig map[string]any `p:"streamConfig" json:"streamConfig" dc:"流式输出配置"` + SpecialParams map[string]any `p:"specialParams" json:"specialParams" dc:"请求特殊参数(首尾帧等)"` + MaxConcurrency int `p:"maxConcurrency" json:"maxConcurrency" dc:"最大并发数(默认10)"` + TimeoutSeconds int `p:"timeoutSeconds" json:"timeoutSeconds" dc:"请求超时时间(秒,默认600)"` + RetryTimes int `p:"retryTimes" json:"retryTimes" dc:"失败重试次数(默认3)"` } type CreateModelRes struct { @@ -44,35 +40,31 @@ type CreateModelRes struct { } type UpdateModelReq struct { - g.Meta `path:"/updateModel" method:"put" tags:"模型管理" summary:"更新模型配置" dc:"更新指定ID的模型配置"` - ID int64 `p:"id" json:"id" v:"required#id不能为空" dc:"配置ID"` - ModelName string `p:"modelName" json:"modelName" v:"required#模型名称不能为空" dc:"模型名称(唯一标识)"` - ModelType int `p:"modelType" json:"modelType" v:"required#模型类型不能为空" dc:"模型类型"` - BaseURL string `p:"baseUrl" json:"baseUrl" v:"required#模型地址不能为空" dc:"模型服务地址"` - HttpMethod string `p:"httpMethod" json:"httpMethod" dc:"请求方式:GET/POST(默认POST)"` - HeadMsg map[string]any `p:"headMsg" json:"headMsg" dc:"请求头JSON结构"` - IsPrivate *int `p:"isPrivate" json:"isPrivate" dc:"是否私有化:0-私有 1-公共"` - Enabled *int `p:"enabled" json:"enabled" dc:"是否启用:0-停用 1-启用"` - IsChatModel *int `p:"isChatModel" json:"isChatModel" dc:"是否为对话模型:0-否 1-是"` - CallMode *int `p:"callMode" json:"callMode" dc:"调用模式:0-同步 1-异步 2-流式"` - RequiredFields []string `p:"requiredFields" json:"requiredFields" dc:"必填字段"` - IsOwner *int `p:"isOwner" json:"isOwner" dc:"是否为所有者:0-否 1-是"` - ApiKey string `p:"apiKey" json:"apiKey" dc:"调用凭证/密钥"` - Form []entity.Form `p:"form" json:"form" dc:"动态表单配置"` - RequestMapping map[string]any `p:"requestMapping" json:"requestMapping" dc:"请求映射"` - ResponseMapping map[string]any `p:"responseMapping" json:"responseMapping" dc:"返回映射"` - OperatorName string `p:"operatorName" json:"operatorName" dc:"运营商名称"` - TokenConfig map[string]any `p:"tokenConfig" json:"tokenConfig" dc:"token计算配置"` - ExtendMapping map[string]any `p:"extendMapping" json:"extendMapping" dc:"附加映射"` - QueryConfig map[string]any `p:"queryConfig" json:"queryConfig" dc:"查询/回调配置"` - StreamConfig map[string]any `p:"streamConfig" json:"streamConfig" dc:"流式输出配置"` - FirstFrame string `p:"firstFrame" json:"firstFrame" dc:"首帧图片参数"` - LastFrame string `p:"lastFrame" json:"lastFrame" dc:"尾帧图片参数"` - MaxConcurrency int `p:"maxConcurrency" json:"maxConcurrency" dc:"最大并发数(默认10)"` - TimeoutSeconds int `p:"timeoutSeconds" json:"timeoutSeconds" dc:"请求超时时间(秒,默认600)"` - RetryTimes int `p:"retryTimes" json:"retryTimes" dc:"失败重试次数(默认3)"` - AutoCleanSeconds int `p:"autoCleanSeconds" json:"autoCleanSeconds" dc:"任务完成后自动清理时间(秒,默认86400)"` - CallbackUrl string `p:"callbackUrl" json:"callbackUrl" dc:"回调地址"` + g.Meta `path:"/updateModel" method:"put" tags:"模型管理" summary:"更新模型配置" dc:"更新指定ID的模型配置"` + ID int64 `p:"id" json:"id" v:"required#id不能为空" dc:"配置ID"` + ModelName string `p:"modelName" json:"modelName" v:"required#模型名称不能为空" dc:"模型名称(唯一标识)"` + ModelType int `p:"modelType" json:"modelType" v:"required#模型类型不能为空" dc:"模型类型"` + BaseURL string `p:"baseUrl" json:"baseUrl" v:"required#模型地址不能为空" dc:"模型服务地址"` + HttpMethod string `p:"httpMethod" json:"httpMethod" dc:"请求方式:GET/POST(默认POST)"` + HeadMsg map[string]any `p:"headMsg" json:"headMsg" dc:"请求头JSON结构"` + IsPrivate *int `p:"isPrivate" json:"isPrivate" dc:"是否私有化:0-私有 1-公共"` + Enabled *int `p:"enabled" json:"enabled" dc:"是否启用:0-停用 1-启用"` + IsChatModel *int `p:"isChatModel" json:"isChatModel" dc:"是否为对话模型:0-否 1-是"` + CallMode *int `p:"callMode" json:"callMode" dc:"调用模式:0-同步 1-异步 2-流式"` + RequiredFields []string `p:"requiredFields" json:"requiredFields" dc:"必填字段"` + ApiKey string `p:"apiKey" json:"apiKey" dc:"调用凭证/密钥"` + Form []entity.Form `p:"form" json:"form" dc:"动态表单配置"` + RequestMapping map[string]any `p:"requestMapping" json:"requestMapping" dc:"请求映射"` + ResponseMapping map[string]any `p:"responseMapping" json:"responseMapping" dc:"返回映射"` + OperatorName string `p:"operatorName" json:"operatorName" dc:"运营商名称"` + TokenConfig map[string]any `p:"tokenConfig" json:"tokenConfig" dc:"token计算配置"` + ExtendMapping map[string]any `p:"extendMapping" json:"extendMapping" dc:"附加映射"` + QueryConfig map[string]any `p:"queryConfig" json:"queryConfig" dc:"查询/回调配置"` + StreamConfig map[string]any `p:"streamConfig" json:"streamConfig" dc:"流式输出配置"` + SpecialParams map[string]any `p:"specialParams" json:"specialParams" dc:"请求特殊参数(首尾帧等)"` + MaxConcurrency int `p:"maxConcurrency" json:"maxConcurrency" dc:"最大并发数(默认10)"` + TimeoutSeconds int `p:"timeoutSeconds" json:"timeoutSeconds" dc:"请求超时时间(秒,默认600)"` + RetryTimes int `p:"retryTimes" json:"retryTimes" dc:"失败重试次数(默认3)"` } type UpdateModelRes struct { diff --git a/model/entity/model_gateway_model.go b/model/entity/model_gateway_model.go index 3c4e3a7..df9f23b 100644 --- a/model/entity/model_gateway_model.go +++ b/model/entity/model_gateway_model.go @@ -4,128 +4,112 @@ import "gitea.redpowerfuture.com/red-future/common/beans" type modelGatewayModelCol struct { beans.SQLBaseCol - ModelName string - ModelType string - BaseURL string - HttpMethod string - HeadMsg string - FormJSON string - RequestMapping string - ResponseMapping string - RequiredFields string - IsPrivate string - IsChatModel string - CallMode string - ApiKey string - Enabled string - MaxConcurrency string - TimeoutSeconds string - RetryTimes string - AutoCleanSeconds string - IsOwner string - OperatorName string - TokenConfig string - ExtendMapping string - QueryConfig string - StreamConfig string - FirstFrame string - LastFrame string - BillingConfig string + ModelName string + ModelType string + BaseURL string + HttpMethod string + HeadMsg string + FormJSON string + RequestMapping string + ResponseMapping string + RequiredFields string + IsPrivate string + IsChatModel string + CallMode string + ApiKey string + Enabled string + MaxConcurrency string + TimeoutSeconds string + RetryTimes string + OperatorName string + TokenConfig string + ExtendMapping string + QueryConfig string + StreamConfig string + SpecialParams string + BillingConfig string } var ModelGatewayModelCol = modelGatewayModelCol{ - SQLBaseCol: beans.DefSQLBaseCol, - ModelName: "model_name", - ModelType: "model_type", - BaseURL: "base_url", - HttpMethod: "http_method", - HeadMsg: "head_msg", - FormJSON: "form_json", - RequestMapping: "request_mapping", - ResponseMapping: "response_mapping", - RequiredFields: "required_fields", - IsPrivate: "is_private", - IsChatModel: "is_chat_model", - CallMode: "call_mode", - ApiKey: "api_key", - Enabled: "enabled", - MaxConcurrency: "max_concurrency", - TimeoutSeconds: "timeout_seconds", - RetryTimes: "retry_times", - AutoCleanSeconds: "auto_clean_seconds", - IsOwner: "is_owner", - OperatorName: "operator_name", - TokenConfig: "token_config", - ExtendMapping: "extend_mapping", - QueryConfig: "query_config", - StreamConfig: "stream_config", - FirstFrame: "first_frame", - LastFrame: "last_frame", - BillingConfig: "billing_config", + SQLBaseCol: beans.DefSQLBaseCol, + ModelName: "model_name", + ModelType: "model_type", + BaseURL: "base_url", + HttpMethod: "http_method", + HeadMsg: "head_msg", + FormJSON: "form_json", + RequestMapping: "request_mapping", + ResponseMapping: "response_mapping", + RequiredFields: "required_fields", + IsPrivate: "is_private", + IsChatModel: "is_chat_model", + CallMode: "call_mode", + ApiKey: "api_key", + Enabled: "enabled", + MaxConcurrency: "max_concurrency", + TimeoutSeconds: "timeout_seconds", + RetryTimes: "retry_times", + OperatorName: "operator_name", + TokenConfig: "token_config", + ExtendMapping: "extend_mapping", + QueryConfig: "query_config", + StreamConfig: "stream_config", + SpecialParams: "special_params", + BillingConfig: "billing_config", } type ModelGatewayModel struct { - beans.SQLBaseDO `orm:",inline"` - ModelName string `orm:"model_name" json:"modelName"` - ModelType int `orm:"model_type" json:"modelType"` - BaseURL string `orm:"base_url" json:"baseUrl"` - HttpMethod string `orm:"http_method" json:"httpMethod"` - HeadMsg map[string]any `orm:"head_msg" json:"headMsg"` - Form []Form `orm:"form_json" json:"form"` - RequestMapping map[string]any `orm:"request_mapping" json:"requestMapping"` - ResponseMapping map[string]any `orm:"response_mapping" json:"responseMapping"` - RequiredFields []string `orm:"required_fields" json:"requiredFields"` - IsPrivate *int `orm:"is_private" json:"isPrivate"` - IsChatModel *int `orm:"is_chat_model" json:"isChatModel"` - CallMode *int `orm:"call_mode" json:"callMode"` - ApiKey string `orm:"api_key" json:"apiKey"` - Enabled *int `orm:"enabled" json:"enabled"` - MaxConcurrency int `orm:"max_concurrency" json:"maxConcurrency"` - TimeoutSeconds int `orm:"timeout_seconds" json:"timeoutSeconds"` - RetryTimes int `orm:"retry_times" json:"retryTimes"` - AutoCleanSeconds int `orm:"auto_clean_seconds" json:"autoCleanSeconds"` - IsOwner *int `orm:"is_owner" json:"isOwner"` - OperatorName string `orm:"operator_name" json:"operatorName"` - TokenConfig map[string]any `orm:"token_config" json:"tokenConfig"` - ExtendMapping map[string]any `orm:"extend_mapping" json:"extendMapping"` - QueryConfig map[string]any `orm:"query_config" json:"queryConfig"` - StreamConfig map[string]any `orm:"stream_config" json:"streamConfig"` - FirstFrame string `orm:"first_frame" json:"firstFrame"` - LastFrame string `orm:"last_frame" json:"lastFrame"` - BillingConfig map[string]any `orm:"billing_config" json:"billingConfig"` + beans.SQLBaseDO `orm:",inline"` + ModelName string `orm:"model_name" json:"modelName"` + ModelType int `orm:"model_type" json:"modelType"` + BaseURL string `orm:"base_url" json:"baseUrl"` + HttpMethod string `orm:"http_method" json:"httpMethod"` + HeadMsg map[string]any `orm:"head_msg" json:"headMsg"` + Form []Form `orm:"form_json" json:"form"` + RequestMapping map[string]any `orm:"request_mapping" json:"requestMapping"` + ResponseMapping map[string]any `orm:"response_mapping" json:"responseMapping"` + RequiredFields []string `orm:"required_fields" json:"requiredFields"` + IsPrivate *int `orm:"is_private" json:"isPrivate"` + IsChatModel *int `orm:"is_chat_model" json:"isChatModel"` + CallMode *int `orm:"call_mode" json:"callMode"` + ApiKey string `orm:"api_key" json:"apiKey"` + Enabled *int `orm:"enabled" json:"enabled"` + MaxConcurrency int `orm:"max_concurrency" json:"maxConcurrency"` + TimeoutSeconds int `orm:"timeout_seconds" json:"timeoutSeconds"` + RetryTimes int `orm:"retry_times" json:"retryTimes"` + OperatorName string `orm:"operator_name" json:"operatorName"` + TokenConfig map[string]any `orm:"token_config" json:"tokenConfig"` + ExtendMapping map[string]any `orm:"extend_mapping" json:"extendMapping"` + QueryConfig map[string]any `orm:"query_config" json:"queryConfig"` + StreamConfig map[string]any `orm:"stream_config" json:"streamConfig"` + SpecialParams map[string]any `orm:"special_params" json:"specialParams"` + BillingConfig map[string]any `orm:"billing_config" json:"billingConfig"` } type Form struct { - Key string `json:"key"` // 字段名 - Value any `json:"value"` // 值 - Label string `json:"label"` // 标签 - Type string `json:"type"` // 类型:string / number / boolean / select / radio / upload / json / array - DefaultValue any `json:"defaultValue"` // 默认值 - Required bool `json:"required"` // 是否必填 - IsForm bool `json:"isForm"` // 是否作为表单(用作工作流展示) - Options []map[string]any `json:"options"` // 选项(下拉/单选) + Key string `json:"key"` + Value any `json:"value"` + Label string `json:"label"` + Type string `json:"type"` + DefaultValue any `json:"defaultValue"` + Required bool `json:"required"` + IsForm bool `json:"isForm"` + Options []map[string]any `json:"options"` Role string `json:"role"` - FieldConstraint FieldConstraint `json:"fieldConstraint"` // 字段约束 + FieldConstraint FieldConstraint `json:"fieldConstraint"` } type FieldConstraint struct { - // 字符串校验 - MaxLength int `json:"maxLength"` // 最大长度 - MinLength int `json:"minLength"` // 最小长度 - - // 数字校验 - NumberType string `json:"numberType"` // 数字类型:integer / float / positiveInteger / positiveFloat / negativeInteger / negativeFloat - Min any `json:"min"` // 最小值 - Max any `json:"max"` // 最大值 - - // 文件上传校验 - MaxSize int `json:"maxSize"` // 最大文件(MB) - MaxCount int `json:"maxCount"` // 最大上传数量 - Accept string `json:"accept"` // 允许格式(逗号分隔) + MaxLength int `json:"maxLength"` + MinLength int `json:"minLength"` + NumberType string `json:"numberType"` + Min any `json:"min"` + Max any `json:"max"` + MaxSize int `json:"maxSize"` + MaxCount int `json:"maxCount"` + Accept string `json:"accept"` } - const ( - ResponseBody = "content" //返回主体(必填) - TotalTokens = "total_tokens" //总token数 + ResponseBody = "content" ) diff --git a/service/gateway/gateway_http_service.go b/service/gateway/gateway_http_service.go index 07d7041..9d8835e 100644 --- a/service/gateway/gateway_http_service.go +++ b/service/gateway/gateway_http_service.go @@ -16,6 +16,19 @@ import ( "github.com/gogf/gf/v2/util/guid" ) +// ForwardHeaders 获取转发请求头 +func ForwardHeaders(ctx context.Context) map[string]string { + headers := make(map[string]string) + if r := g.RequestFromCtx(ctx); r != nil { + for k, v := range r.Request.Header { + if len(v) > 0 { + headers[k] = v[0] + } + } + } + return headers +} + type UploadFileResponse struct { FileURL string `json:"fileURL"` // 文件 URL FileSize int `json:"fileSize"` // 文件大小(字节) @@ -88,15 +101,7 @@ type CallbackPayload struct { // TriggerCallback 任务的回调 func TriggerCallback(ctx context.Context, t *entity.ModelGatewayTask) { - //headers := util.ForwardHeaders(ctx) - headers := make(map[string]string) - if r := g.RequestFromCtx(ctx); r != nil { - for k, v := range r.Request.Header { - if len(v) > 0 { - headers[k] = v[0] - } - } - } + headers := ForwardHeaders(ctx) var resp struct{} payload := CallbackPayload{ TaskId: t.TaskID, @@ -137,15 +142,7 @@ type PromptsCallbackPayload struct { // TriggerPromptsCallback 任务成功后的提示词回调 func TriggerPromptsCallback(ctx context.Context, t *entity.ModelGatewayTask) { callbackURL := "prompts-core/session/callback" - //headers := util.ForwardHeaders(ctx) - headers := make(map[string]string) - if r := g.RequestFromCtx(ctx); r != nil { - for k, v := range r.Request.Header { - if len(v) > 0 { - headers[k] = v[0] - } - } - } + headers := ForwardHeaders(ctx) var resp struct{} payload := PromptsCallbackPayload{ EpicycleId: t.EpicycleId, @@ -176,14 +173,7 @@ type BuildCallbackPayload struct { // CallbackBuildResult 回调构建结果 func CallbackBuildResult(ctx context.Context, record *entity.ModelGatewayBuildRecord) { - headers := make(map[string]string) - if r := g.RequestFromCtx(ctx); r != nil { - for k, v := range r.Request.Header { - if len(v) > 0 { - headers[k] = v[0] - } - } - } + headers := ForwardHeaders(ctx) payload := BuildCallbackPayload{ TaskId: record.TaskID, Status: record.Status, @@ -202,15 +192,7 @@ func CallbackBuildResult(ctx context.Context, record *entity.ModelGatewayBuildRe // IsSuperAdmin 调用admin-go服务检查是否是超级管理员 func IsSuperAdmin(ctx context.Context) (res bool, err error) { - //headers := util.ForwardHeaders(ctx) - headers := make(map[string]string) - if r := g.RequestFromCtx(ctx); r != nil { - for k, v := range r.Request.Header { - if len(v) > 0 { - headers[k] = v[0] - } - } - } + headers := ForwardHeaders(ctx) var r = make(map[string]bool) if err = commonHttp.Get(ctx, "admin-go/api/v1/system/user/checkIsSuperAdmin", headers, &r); err != nil { return false, err @@ -233,15 +215,7 @@ type SkillUserVO struct { // GetSkillUser 获取技能用户信息 func GetSkillUser(ctx context.Context, name string) (*SkillUserVO, error) { fullURL := fmt.Sprintf("ai-agent/skill/user/getUserOrTemplate?name=%s", name) - //headers := util.ForwardHeaders(ctx) - headers := make(map[string]string) - if r := g.RequestFromCtx(ctx); r != nil { - for k, v := range r.Request.Header { - if len(v) > 0 { - headers[k] = v[0] - } - } - } + headers := ForwardHeaders(ctx) var resp SkillUserVO var req struct{} if err := commonHttp.Get(ctx, fullURL, headers, &resp, req); err != nil { @@ -259,14 +233,7 @@ type SessionHistoryItem struct { // GetSessionHistory 获取会话历史 func GetSessionHistory(ctx context.Context, nodeId, sessionId string) ([]SessionHistoryItem, error) { fullURL := fmt.Sprintf("model-session/session/history?nodeId=%s&sessionId=%s", nodeId, sessionId) - headers := make(map[string]string) - if r := g.RequestFromCtx(ctx); r != nil { - for k, v := range r.Request.Header { - if len(v) > 0 { - headers[k] = v[0] - } - } - } + headers := ForwardHeaders(ctx) var req struct{} var resp []SessionHistoryItem if err := commonHttp.Get(ctx, fullURL, headers, &resp, req); err != nil { @@ -293,15 +260,7 @@ type VideoInfo struct { // GetVideoDuration 获取视频时长 func GetVideoDuration(ctx context.Context, urls []string) (VideoDurationResp, error) { apiURL := "media/video/duration" - headers := make(map[string]string) - if r := g.RequestFromCtx(ctx); r != nil { - for k, v := range r.Request.Header { - if len(v) > 0 { - headers[k] = v[0] - } - } - } - + headers := ForwardHeaders(ctx) body := map[string]any{"video_urls": urls} jsonData, _ := json.Marshal(body) @@ -325,15 +284,7 @@ type DeductBalanceReq struct { // DeductBalance 扣减租户余额 func DeductBalance(ctx context.Context, tenantId uint64, amount float64) error { apiURL := "admin-go/api/v1/system/tenant/edit" - headers := make(map[string]string) - if r := g.RequestFromCtx(ctx); r != nil { - for k, v := range r.Request.Header { - if len(v) > 0 { - headers[k] = v[0] - } - } - } - + headers := ForwardHeaders(ctx) body := DeductBalanceReq{ Id: tenantId, Surplus: amount, @@ -358,15 +309,7 @@ type TenantSurplusResp struct { // GetTenantSurplus 获取租户余额 func GetTenantSurplus(ctx context.Context, tenantId uint64) (float64, error) { apiURL := fmt.Sprintf("admin-go/api/v1/system/tenant/getTenantDetails?tenantId=%d", tenantId) - headers := make(map[string]string) - if r := g.RequestFromCtx(ctx); r != nil { - for k, v := range r.Request.Header { - if len(v) > 0 { - headers[k] = v[0] - } - } - } - + headers := ForwardHeaders(ctx) var resp TenantSurplusResp err := commonHttp.Get(ctx, apiURL, headers, &resp, nil) if err != nil { @@ -375,52 +318,3 @@ func GetTenantSurplus(ctx context.Context, tenantId uint64) (float64, error) { } return resp.Surplus, nil } - -//// callback 向回调地址 POST 任务结果(与查询接口 GetTaskRes 出参一致) -//func (s *audioTaskService) callback(ctx context.Context, taskID, status, errMsg, callbackURL string) { -// if callbackURL == "" { -// return -// } -// -// task, _ := dao.TranscribeTask.GetByTaskID(ctx, taskID) -// if task == nil { -// g.Log().Errorf(ctx, "[回调 %s] 任务不存在", taskID) -// return -// } -// -// detailList, _ := dao.TranscribeTaskDetail.ListByTaskID(ctx, taskID) -// detailItems := make([]dto.TranscribeTaskDetailItem, 0, len(detailList)) -// for i := range detailList { -// detailItems = append(detailItems, dao.DetailEntityToItem(&detailList[i])) -// } -// -// // 构建与查询接口一致的 taskInfo -// taskInfo := dao.EntityToItem(task) -// -// // 兼容历史数据: 从 result 中补全 scenes 等字段 -// detailItems = enrichDetailsFromResult(task.Result, detailItems) -// -// payload := dto.CallbackPayload{ -// TaskInfo: taskInfo, -// DetailList: detailItems, -// } -// -// body, _ := json.Marshal(payload) -// -// // 透传调用方的用户信息 -// userJSON, _ := json.Marshal(beans.User{UserName: "admin", TenantId: 1}) -// -// req, _ := http.NewRequest("POST", callbackURL, bytes.NewReader(body)) -// req.Header.Set("Content-Type", "application/json") -// req.Header.Set("X-User-Info", string(userJSON)) -// -// resp, reqErr := http.DefaultClient.Do(req) -// if reqErr != nil { -// g.Log().Errorf(ctx, "[回调 %s] 请求失败: %v", taskID, reqErr) -// return -// } -// defer resp.Body.Close() -// -// respBody, _ := io.ReadAll(resp.Body) -// g.Log().Infof(ctx, "[回调 %s] 响应 status=%d, body=%s", taskID, resp.StatusCode, string(respBody)) -//} diff --git a/service/model/model_service.go b/service/model/model_service.go index 080b406..f2f301f 100644 --- a/service/model/model_service.go +++ b/service/model/model_service.go @@ -30,13 +30,8 @@ func (s *modelService) Create(ctx context.Context, req *dto.CreateModelReq) (*dt return nil, err } } - // 2)判断是否超管,决定 isOwner - req.IsOwner = gconv.PtrInt(1) - if isAdmin, _ := gateway.IsSuperAdmin(ctx); isAdmin { - req.IsOwner = gconv.PtrInt(0) - } - // 3)入库 + // 2)入库 id, err := dao.ModelGatewayModels.Insert(ctx, util.ConvertTo[entity.ModelGatewayModel](req)) if err != nil { return nil, err @@ -53,9 +48,7 @@ func (s *modelService) Update(ctx context.Context, req *dto.UpdateModelReq) erro } } // 2)超管创建/普通用户更新 - req.IsOwner = gconv.PtrInt(1) if isAdmin, _ := gateway.IsSuperAdmin(ctx); isAdmin { - req.IsOwner = gconv.PtrInt(0) _, err := dao.ModelGatewayModels.Update(ctx, util.ConvertTo[entity.ModelGatewayModel](req)) return err }