diff --git a/controller/model_manage_controller.go b/controller/model_manage_controller.go index 8361af7..dc9f75e 100644 --- a/controller/model_manage_controller.go +++ b/controller/model_manage_controller.go @@ -18,11 +18,6 @@ func (c *modelManage) CreateModel(ctx context.Context, req *dto.CreateModelManag return service.ModelManage.Create(ctx, req) } -// ReferenceModel 引用系统模型 -func (c *modelManage) ReferenceModel(ctx context.Context, req *dto.ReferenceSystemModelReq) (res *dto.ReferenceSystemModelRes, err error) { - return service.ModelManage.ReferenceSystemModel(ctx, req) -} - // UpdateModel 更改配置 func (c *modelManage) UpdateModel(ctx context.Context, req *dto.UpdateModelManageReq) (res *dto.GetModelManageRes, err error) { return service.ModelManage.Update(ctx, req) diff --git a/model/dto/model_manage_dto.go b/model/dto/model_manage_dto.go index 5321bda..e4d9b33 100644 --- a/model/dto/model_manage_dto.go +++ b/model/dto/model_manage_dto.go @@ -155,15 +155,3 @@ type BuildSchemaMappingRes struct { SchemaMapping map[string]any `json:"schemaMapping" dc:"生成的 Schema 映射 JSON"` } -// ReferenceSystemModelReq 引用系统模型请求:用户只填 apiKey + 个人开关,配置实时跟随系统模型 -type ReferenceSystemModelReq struct { - g.Meta `path:"/referenceSystemModel" method:"post" tags:"模型管理" summary:"引用系统模型" dc:"用户引用系统模型,只填 apiKey 等个人字段,配置实时跟随系统模型(不再全量拷贝)"` - SystemModelId int64 `json:"systemModelId" v:"required#系统模型ID不能为空" dc:"被引用的系统模型ID"` - ApiKey string `json:"apiKey" v:"required#apiKey不能为空" dc:"调用凭证/密钥"` - ChatModel *bool `json:"chatModel" dc:"设为我的会话模型"` - Enabled *bool `json:"enabled" dc:"启用(默认启用)"` -} - -type ReferenceSystemModelRes struct { - Id int64 `json:"id,string" dc:"引用行ID"` -} diff --git a/service/model_manage_service.go b/service/model_manage_service.go index 87006b8..f285d71 100644 --- a/service/model_manage_service.go +++ b/service/model_manage_service.go @@ -63,67 +63,10 @@ func (s *modelManageService) Create(ctx context.Context, req *dto.CreateModelMan return } -// ReferenceSystemModel 用户引用系统模型:只填 apiKey + 个人开关,配置实时跟随系统模型。 -// 不拷贝配置(解析层实时取系统行);同名唯一(复用 Create 语义);会话模型开关复用 CancelChatModel。 -func (s *modelManageService) ReferenceSystemModel(ctx context.Context, req *dto.ReferenceSystemModelReq) (res *dto.ReferenceSystemModelRes, err error) { - err = gfdb.DB(ctx, public.DbNameModelGateway).Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) { - user, err := utils.GetUserInfo(ctx) - if err != nil { - return err - } - // 1)目标必须是系统模型 - sys, err := dao.ModelManage.GetNotTenantId(ctx, &dto.GetModelManageReq{Id: req.SystemModelId}) - if err != nil { - return err - } - if sys == nil || sys.SystemModel == nil || !*sys.SystemModel { - return fmt.Errorf("被引用的模型不存在或不是系统模型") - } - // 2)同名唯一:同一用户下不允许重复(引用行与自有模型同名同样拒绝) - exist, err := dao.ModelManage.GetByCreatorAndName(ctx, user.UserName, sys.ModelName) - if err != nil { - return err - } - if exist != nil { - return fmt.Errorf("模型名称 [%s] 已存在,同一用户下不能重复添加同名模型", sys.ModelName) - } - // 3)设为会话模型 → 先取消旧会话模型(isSuperAdmin 语义与 Create 一致) - var isSuperAdmin bool - isSuperAdmin, err = IsSuperAdmin(ctx) - if err != nil { - return err - } - if err = s.CancelChatModel(ctx, sys.ModelType, req.ChatModel, isSuperAdmin); err != nil { - return err - } - // 4)插引用行(配置列零值即可,解析层只读系统行配置) - enabled := true - if req.Enabled != nil { - enabled = *req.Enabled - } - id, err := dao.ModelManage.Insert(ctx, &dto.CreateModelManageReq{ - ModelSupplier: sys.ModelSupplier, - ModelName: sys.ModelName, - ModelType: sys.ModelType, - SystemModel: gconv.PtrBool(false), - ChatModel: req.ChatModel, - ApiKey: req.ApiKey, - Enabled: gconv.PtrBool(enabled), - RefSystemModelId: sys.Id, - }) - if err != nil { - return err - } - res = &dto.ReferenceSystemModelRes{Id: id} - return nil - }) - return -} - // Update 更新模型配置 // 引用行:只改 apiKey/enabled/chatModel,配置锁定跟随系统模型(其余字段忽略); // 系统模型:仅创建者(超管)可改配置,改名时同步引用行 model_name; -// 用户自有模型:创建者可改全配置。非创建者操作他人行 → 无权限(引用不再靠"编辑系统模型"触发拷贝,改走 referenceSystemModel)。 +// 非超管编辑系统模型 → 建引用行(不拷贝配置,apiKey 必填);用户自有模型:创建者可改全配置。非创建者操作他人行 → 无权限。 func (s *modelManageService) Update(ctx context.Context, req *dto.UpdateModelManageReq) (res *dto.GetModelManageRes, err error) { err = gfdb.DB(ctx, public.DbNameModelGateway).Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) { var get *entity.ModelManage @@ -142,8 +85,11 @@ func (s *modelManageService) Update(ctx context.Context, req *dto.UpdateModelMan return } - // 引用行:只应用个人字段,配置忽略(跟随系统模型;isSuperAdmin=false=个人会话模型开关) + // 引用行:只改 apiKey/enabled/chatModel,配置锁定跟随系统模型(其余字段忽略;isSuperAdmin=false=个人会话模型开关) if get.RefSystemModelId > 0 { + if get.Creator != user.UserName { + return fmt.Errorf("无权限操作") + } if err = s.CancelChatModel(ctx, get.ModelType, req.ChatModel, false); err != nil { return err } @@ -156,27 +102,7 @@ func (s *modelManageService) Update(ctx context.Context, req *dto.UpdateModelMan return } - // 非创建者 → 无权限(引用已由 referenceSystemModel 端点管理,不再拷贝) - if get.Creator != user.UserName { - return fmt.Errorf("无权限操作") - } - - // 1)检查是否是超管 - var isSuperAdmin bool - isSuperAdmin, err = IsSuperAdmin(ctx) - if err != nil { - return - } - modelType := req.ModelType - if g.IsEmpty(modelType) { - modelType = get.ModelType - } - // 1)如果设为会话模型,先把该用户旧会话模型取消 - err = s.CancelChatModel(ctx, modelType, req.ChatModel, isSuperAdmin) - if err != nil { - return - } - // 2)模型名称唯一性:同一用户下不允许同名模型(排除自身) + // 同名唯一性:同一用户下不允许同名模型(排除自身,允许不改名编辑) if !g.IsEmpty(req.ModelName) { var exist *entity.ModelManage exist, err = dao.ModelManage.GetByCreatorAndName(ctx, user.UserName, req.ModelName) @@ -187,10 +113,66 @@ func (s *modelManageService) Update(ctx context.Context, req *dto.UpdateModelMan return fmt.Errorf("模型名称 [%s] 已存在,同一用户下不能重复添加同名模型", req.ModelName) } } - // 3)系统模型改名 → 同步引用行 model_name(保列表 DISTINCT ON 去重正确) - if get.SystemModel != nil && *get.SystemModel && req.ModelName != "" && req.ModelName != get.ModelName { - if _, err = dao.ModelManage.UpdateReferencesName(ctx, get.Id, req.ModelName); err != nil { - return err + + // 1)检查是否是超管 + var isSuperAdmin bool + isSuperAdmin, err = IsSuperAdmin(ctx) + if err != nil { + return + } + if err = s.CancelChatModel(ctx, get.ModelType, req.ChatModel, isSuperAdmin); err != nil { + return err + } + if isSuperAdmin { + if get.Creator != user.UserName { + return fmt.Errorf("无权限操作") + } + // 3)系统模型改名 → 同步引用行 model_name(保列表 DISTINCT ON 去重正确) + if get.SystemModel != nil && *get.SystemModel && req.ModelName != "" && req.ModelName != get.ModelName { + if _, err = dao.ModelManage.UpdateReferencesName(ctx, get.Id, req.ModelName); err != nil { + return err + } + } + } else { + if get.SystemModel != nil && *get.SystemModel { + // 用户引用系统模型:apiKey 必填(与旧拷贝分支一致,空 key 引用行无意义) + if g.IsEmpty(req.ApiKey) { + return fmt.Errorf("模型apiKey不能为空") + } + var exist *entity.ModelManage + exist, err = dao.ModelManage.GetByCreatorAndName(ctx, user.UserName, get.ModelName) + if err != nil { + return + } + if exist != nil { + return fmt.Errorf("模型名称 [%s] 已存在,同一用户下不能重复添加同名模型", get.ModelName) + } + // 4)插引用行(配置列零值即可,解析层只读系统行配置) + enabled := true + if req.Enabled != nil { + enabled = *req.Enabled + } + var id int64 + id, err = dao.ModelManage.Insert(ctx, &dto.CreateModelManageReq{ + ModelSupplier: get.ModelSupplier, + ModelName: get.ModelName, + ModelType: get.ModelType, + SystemModel: gconv.PtrBool(false), + ChatModel: req.ChatModel, + ApiKey: req.ApiKey, + Enabled: gconv.PtrBool(enabled), + RefSystemModelId: get.Id, + }) + if err != nil { + return err + } + res, err = s.Get(ctx, &dto.GetModelManageReq{ + Id: id, + }) + return + } + if get.Creator != user.UserName { + return fmt.Errorf("无权限操作") } } // 4)更新数据