From 7dcfb6744d7f12b4b54b5a240a955fc91324ff2d Mon Sep 17 00:00:00 2001 From: qhd <1766646056@qq.com> Date: Sat, 29 Aug 2026 16:59:05 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=BC=95=E7=94=A8=E8=A1=8C=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=20Get=20=E5=90=88=E5=85=A5=E7=B3=BB=E7=BB=9F=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E9=85=8D=E7=BD=AE=E8=BF=94=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 引用行(ref_system_model_id>0)在 DB 只存个人字段(apiKey/enabled/chatModel), Get 之前返回空配置,前端编辑表单无法补全。新增 mergeReferenceConfigForQuery: 以引用行身份字段为基底,把系统行配置列合入返回(不替换 {apiKey} 占位、 不做 enabled AND 门禁,区别于调用时 mergeReferenceConfig)。 保留引用行自身 id,Update/Delete 仍命中引用行。 --- service/model_manage_service.go | 10 ++++++++ service/model_resolve.go | 28 ++++++++++++++++++++ service/model_resolve_test.go | 45 +++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) diff --git a/service/model_manage_service.go b/service/model_manage_service.go index f285d71..7a245bc 100644 --- a/service/model_manage_service.go +++ b/service/model_manage_service.go @@ -261,6 +261,16 @@ func (s *modelManageService) Get(ctx context.Context, req *dto.GetModelManageReq if get == nil { return new(dto.GetModelManageRes), nil } + // 引用行 → 合入系统模型配置返回(前端展示/编辑需要完整配置;保留引用行自身 id 供更新/删除) + if get.RefSystemModelId > 0 { + sys, e := dao.ModelManage.GetNotTenantId(ctx, &dto.GetModelManageReq{Id: get.RefSystemModelId}) + if e != nil { + return nil, e + } + if sys != nil { + get = mergeReferenceConfigForQuery(get, sys) + } + } // 系统模型 apiKey 对非创建者脱敏(引用行/自有行仅本人可见) user, err := utils.GetUserInfo(ctx) if err != nil { diff --git a/service/model_resolve.go b/service/model_resolve.go index 2c743f9..1a6b2ec 100644 --- a/service/model_resolve.go +++ b/service/model_resolve.go @@ -96,6 +96,34 @@ func mergeReferenceConfig(stub, sys *entity.ModelManage) *entity.ModelManage { return &out } +// mergeReferenceConfigForQuery 管理端 Get 查询展示用:以引用行为基底,把系统行的配置列合入, +// 保留引用行自身 Id/RefSystemModelId/SystemModel/Creator/时间戳与个人字段(apiKey/enabled/chatModel)。 +// 与 mergeReferenceConfig 的区别:不替换 {apiKey}(Get 非引用行也不替换,展示模板), +// enabled 不做 AND(展示引用行个人开关,调用时才按系统行生效状态门禁)。 +func mergeReferenceConfigForQuery(stub, sys *entity.ModelManage) *entity.ModelManage { + out := *stub + out.BaseURL = sys.BaseURL + out.HttpMethod = sys.HttpMethod + out.ResponseType = sys.ResponseType + out.RequestHeadMapping = sys.RequestHeadMapping + out.RequestBodyMapping = sys.RequestBodyMapping + out.RequestBusinessFieldMapping = sys.RequestBusinessFieldMapping + out.ResponseMapping = sys.ResponseMapping + out.ResponseBodyMapping = sys.ResponseBodyMapping + out.ResponseBusinessFieldMapping = sys.ResponseBusinessFieldMapping + out.MaxConcurrency = sys.MaxConcurrency + out.TokenMapping = sys.TokenMapping + out.AsyncTaskMapping = sys.AsyncTaskMapping + out.TokenPredictPrice = sys.TokenPredictPrice + out.TokenPredictPriceUnit = sys.TokenPredictPriceUnit + out.MaxTokens = sys.MaxTokens + out.MinDuration = sys.MinDuration + out.MaxDuration = sys.MaxDuration + out.LastFrame = sys.LastFrame + out.ErrorMessageMapping = sys.ErrorMessageMapping + return &out +} + // resolveModelConfig 把请求命中的模型行解析为可执行配置: // 引用行 → 系统行配置 + 引用行 apiKey(Id 覆盖为系统模型 id);非引用行 → 原配置 + 自身 apiKey 替换占位。 // 引用系统模型已删除 → 报错(调用方阻塞)。 diff --git a/service/model_resolve_test.go b/service/model_resolve_test.go index 7337790..2bbc5d8 100644 --- a/service/model_resolve_test.go +++ b/service/model_resolve_test.go @@ -107,6 +107,51 @@ func TestMergeReferenceConfig(t *testing.T) { } } +func TestMergeReferenceConfigForQuery(t *testing.T) { + sys := &entity.ModelManage{ + SQLBaseDO: beans.SQLBaseDO{Id: 100, Creator: "admin"}, BaseURL: "https://sys", + SystemModel: gconv.PtrBool(true), Enabled: gconv.PtrBool(false), + RequestHeadMapping: map[string]string{"Authorization": "Bearer {apiKey}"}, + TokenMapping: &entity.TokenMapping{PromptTokens: "a"}, + } + stub := &entity.ModelManage{ + SQLBaseDO: beans.SQLBaseDO{Id: 200, Creator: "user"}, RefSystemModelId: 100, + SystemModel: gconv.PtrBool(false), Enabled: gconv.PtrBool(true), ApiKey: "sk-user", + } + + out := mergeReferenceConfigForQuery(stub, sys) + // 保留引用行自身身份字段 + if out.Id != 200 { + t.Fatalf("id should keep stub: %d", out.Id) + } + if out.RefSystemModelId != 100 { + t.Fatalf("refSystemModelId should keep stub: %d", out.RefSystemModelId) + } + if out.Creator != "user" { + t.Fatalf("creator should keep stub: %s", out.Creator) + } + if out.SystemModel == nil || *out.SystemModel { + t.Fatalf("systemModel should keep stub (false)") + } + // 配置列合入系统行 + if out.BaseURL != "https://sys" { + t.Fatalf("baseURL should follow sys: %s", out.BaseURL) + } + if out.RequestHeadMapping["Authorization"] != "Bearer {apiKey}" { + t.Fatalf("head mapping should follow sys template (不替换占位): %v", out.RequestHeadMapping) + } + if out.TokenMapping == nil || out.TokenMapping.PromptTokens != "a" { + t.Fatalf("tokenMapping should follow sys") + } + // 个人字段保留引用行(不做系统 enabled 的 AND 门禁) + if out.ApiKey != "sk-user" { + t.Fatalf("apiKey should keep stub: %s", out.ApiKey) + } + if out.Enabled == nil || !*out.Enabled { + t.Fatalf("enabled should keep stub (系统停用不在此门禁)") + } +} + func TestResolveModelConfigNonReference(t *testing.T) { m := &entity.ModelManage{SQLBaseDO: beans.SQLBaseDO{Id: 5}, BaseURL: "https://x?key={apiKey}", ApiKey: "sk-sys"} out, err := resolveModelConfig(nil, m) // 非引用路径不触 DB,ctx 可为 nil