From caa5cc71c71a9ac2fed3d3ab7dd75933cdd808e0 Mon Sep 17 00:00:00 2001 From: 2910410219 <2910410219@qq.com> Date: Thu, 14 May 2026 11:36:41 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=A8=A1=E5=9E=8B=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E5=92=8C=E8=AE=BE=E7=BD=AE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改模型选择器,调整内置模型的标识逻辑,使用 `isOwner` 属性替代 `apiKey` 判断。 - 新增内置模型 API Key 输入弹窗,支持用户为内置模型配置 API Key 并创建模型副本。 - 更新模型配置页面,优化内置模型的 API Key 配置逻辑,确保用户体验流畅。 --- src/components/model/ModelSelector.vue | 60 +++++----- src/views/settings/creation/index.vue | 107 +++++++++++++++++- .../modelModule/component/editModule.vue | 2 +- .../modelConfig/modelModule/index.vue | 70 +++++++----- 4 files changed, 176 insertions(+), 63 deletions(-) diff --git a/src/components/model/ModelSelector.vue b/src/components/model/ModelSelector.vue index fca878a..4e1bf8c 100644 --- a/src/components/model/ModelSelector.vue +++ b/src/components/model/ModelSelector.vue @@ -19,13 +19,13 @@ v-for="model in modelList" :key="model.id" class="model-card" - :class="{ selected: selectedModel?.id === model.id, 'builtin-model': !model.apiKey }" + :class="{ selected: selectedModel?.id === model.id }" @click="handleSelectModel(model)" >
{{ getModelTypeName(model.modelType) }}
- 内置模型 + 内置模型
@@ -165,7 +165,7 @@ const apiKeyRules: FormRules = { apiKey: [{ required: true, message: '请输入 API Key', trigger: 'blur' }], }; const creatingModel = ref(false); -const systemModelToClone = ref(null); +const builtInModelToClone = ref(null); // 检查是否为管理员 const checkAdminStatus = async () => { @@ -240,10 +240,10 @@ const handleSelectModel = (model: ModelItem) => { return; } - // 非管理员:判断是否是内置模型(apiKey 为空) - if (!model.apiKey) { - // 内置模型,需要用户配置 API Key - systemModelToClone.value = model; + // 非管理员:判断是否是内置模型(isOwner === 0 表示管理员创建的内置模型) + if (model.isOwner === 0) { + // 内置模型,需要用户配置 API Key 创建副本 + builtInModelToClone.value = model; apiKeyForm.modelName = model.modelName; apiKeyForm.apiKey = ''; apiKeyDialogVisible.value = true; @@ -254,7 +254,7 @@ const handleSelectModel = (model: ModelItem) => { }; const handleCreatePrivateModel = async () => { - if (!apiKeyFormRef.value || !systemModelToClone.value) return; + if (!apiKeyFormRef.value || !builtInModelToClone.value) return; try { await apiKeyFormRef.value.validate(); @@ -262,30 +262,30 @@ const handleCreatePrivateModel = async () => { creatingModel.value = true; // 基于内置模型创建新模型(继承原模型的所有配置,只替换 apiKey) - const systemModel = systemModelToClone.value; + const builtInModel = builtInModelToClone.value; const createParams = { modelName: apiKeyForm.modelName, - modelType: systemModel.modelType, - baseUrl: systemModel.baseUrl, - httpMethod: systemModel.httpMethod || 'POST', - headMsg: systemModel.headMsg || '', - isPrivate: systemModel.isPrivate ?? 1, // 继承原模型的公有/私有属性 - enabled: systemModel.enabled ?? 1, - isChatModel: systemModel.isChatModel || 0, + modelType: builtInModel.modelType, + baseUrl: builtInModel.baseUrl, + httpMethod: builtInModel.httpMethod || 'POST', + headMsg: builtInModel.headMsg || '', + isPrivate: builtInModel.isPrivate ?? 1, // 继承原模型的公有/私有属性 + enabled: builtInModel.enabled ?? 1, + isChatModel: builtInModel.isChatModel || 0, apiKey: apiKeyForm.apiKey, // 使用用户输入的新 API Key - form: systemModel.form || {}, - requestMapping: systemModel.requestMapping || {}, - responseMapping: systemModel.responseMapping || {}, - responseBody: systemModel.responseBody || {}, // 杩斿洖涓讳綋瀛楁 - maxConcurrency: systemModel.maxConcurrency || 10, - queueLimit: systemModel.queueLimit || 100, - timeoutSeconds: systemModel.timeoutSeconds || 30, - expectedSeconds: systemModel.expectedSeconds || 15, - retryTimes: systemModel.retryTimes || 3, - retryQueueMaxSeconds: systemModel.retryQueueMaxSeconds || 60, - autoCleanSeconds: systemModel.autoCleanSeconds || 300, - remark: systemModel.remark || '', - tokenMapping: systemModel.tokenMapping || '', // Token鏄犲皠瀛楁 + form: builtInModel.form || {}, + requestMapping: builtInModel.requestMapping || {}, + responseMapping: builtInModel.responseMapping || {}, + responseBody: builtInModel.responseBody || {}, // 杩斿洖涓讳綋瀛楁 + maxConcurrency: builtInModel.maxConcurrency || 10, + queueLimit: builtInModel.queueLimit || 100, + timeoutSeconds: builtInModel.timeoutSeconds || 30, + expectedSeconds: builtInModel.expectedSeconds || 15, + retryTimes: builtInModel.retryTimes || 3, + retryQueueMaxSeconds: builtInModel.retryQueueMaxSeconds || 60, + autoCleanSeconds: builtInModel.autoCleanSeconds || 300, + remark: builtInModel.remark || '', + tokenMapping: builtInModel.tokenMapping || '', // Token鏄犲皠瀛楁 }; const res: any = await addModelModule(createParams); @@ -334,7 +334,7 @@ const handleClose = () => { visible.value = false; selectedModel.value = null; apiKeyDialogVisible.value = false; - systemModelToClone.value = null; + builtInModelToClone.value = null; }; // 鍔犺浇妯″瀷绫诲瀷鍒楄〃 diff --git a/src/views/settings/creation/index.vue b/src/views/settings/creation/index.vue index 6b5bbea..d35a00e 100644 --- a/src/views/settings/creation/index.vue +++ b/src/views/settings/creation/index.vue @@ -552,6 +552,30 @@ + + + + + + + + + + + + + + + +
@@ -591,7 +615,7 @@ import { type ExecuteFlowParams, } from '/@/api/settings/creation'; import { uploadFile } from '/@/api/common/upload'; -import { getModelModuleList, updateChatModel, getIsChatModel } from '/@/api/settings/modelConfig/modelModule'; +import { getModelModuleList, updateChatModel, getIsChatModel, addModelModule } from '/@/api/settings/modelConfig/modelModule'; import { checkIsSuperAdmin } from '/@/api/system/user'; type NodeType = 'date' | 'contentType' | 'theme' | 'title' | 'html' | 'image'; @@ -677,6 +701,19 @@ const chatModelPagination = reactive({ pageSize: 10, total: 0, }); +// 内置对话模型 API Key 配置 +const chatModelApiKeyDialogVisible = ref(false); +const chatModelApiKeyFormRef = ref(null); +const chatModelApiKeyForm = reactive({ + modelName: '', + apiKey: '', +}); +const chatModelApiKeyRules = { + modelName: [{ required: true, message: '请输入模型名称', trigger: 'blur' }], + apiKey: [{ required: true, message: '请输入 API Key', trigger: 'blur' }], +}; +const creatingChatModel = ref(false); +const builtInChatModelToClone = ref(null); const filteredChatModels = computed(() => { return chatModelList.value; }); @@ -1043,6 +1080,17 @@ const handleChatModelSearch = () => { const handleSetChatModel = async () => { if (!selectedChatModel.value) return; + // 判断是否是内置模型(isOwner === 0 表示管理员创建的内置模型) + if (selectedChatModel.value.isOwner === 0) { + // 内置模型,需要用户配置 API Key 创建副本 + builtInChatModelToClone.value = selectedChatModel.value; + chatModelApiKeyForm.modelName = selectedChatModel.value.modelName; + chatModelApiKeyForm.apiKey = ''; + chatModelApiKeyDialogVisible.value = true; + return; + } + + // 用户模型,直接设置为对话模型 settingChatModel.value = true; try { await updateChatModel({ @@ -1058,6 +1106,63 @@ const handleSetChatModel = async () => { settingChatModel.value = false; } }; +// 创建内置对话模型副本并设置为会话模型 +const handleCreateChatModelFromBuiltIn = async () => { + if (!chatModelApiKeyFormRef.value || !builtInChatModelToClone.value) return; + + try { + await chatModelApiKeyFormRef.value.validate(); + + creatingChatModel.value = true; + + // 基于内置模型创建新模型(继承原模型的所有配置,只替换 apiKey) + const builtInModel = builtInChatModelToClone.value; + const createParams = { + modelName: chatModelApiKeyForm.modelName, + modelType: builtInModel.modelType, + baseUrl: builtInModel.baseUrl, + httpMethod: builtInModel.httpMethod || 'POST', + headMsg: builtInModel.headMsg || '', + isPrivate: builtInModel.isPrivate ?? 1, + enabled: builtInModel.enabled ?? 1, + isChatModel: 1, // 设置为会话模型 + apiKey: chatModelApiKeyForm.apiKey, + form: builtInModel.form || {}, + requestMapping: builtInModel.requestMapping || {}, + responseMapping: builtInModel.responseMapping || {}, + responseBody: builtInModel.responseBody || {}, + tokenMapping: builtInModel.tokenMapping || '', + prompt: builtInModel.prompt || '', + maxConcurrency: builtInModel.maxConcurrency || 10, + queueLimit: builtInModel.queueLimit || 100, + timeoutSeconds: builtInModel.timeoutSeconds || 30, + expectedSeconds: builtInModel.expectedSeconds || 15, + retryTimes: builtInModel.retryTimes || 3, + retryQueueMaxSeconds: builtInModel.retryQueueMaxSeconds || 60, + autoCleanSeconds: builtInModel.autoCleanSeconds || 300, + remark: builtInModel.remark || '', + }; + + await addModelModule(createParams); + + ElMessage.success('模型创建成功并已设置为会话模型'); + + // 关闭对话框 + chatModelApiKeyDialogVisible.value = false; + showChatModelSelector.value = false; + + // 清空表单 + chatModelApiKeyForm.modelName = ''; + chatModelApiKeyForm.apiKey = ''; + builtInChatModelToClone.value = null; + } catch (error: any) { + if (error !== 'cancel') { + ElMessage.error(error?.message || '创建模型失败'); + } + } finally { + creatingChatModel.value = false; + } +}; // 使用工作流 const useWorkflow = async (workflow: WorkflowItem) => { // 管理员权限检查:管理员只能编辑,不能进入创作模式 diff --git a/src/views/settings/modelConfig/modelModule/component/editModule.vue b/src/views/settings/modelConfig/modelModule/component/editModule.vue index 869c83d..f9a6926 100644 --- a/src/views/settings/modelConfig/modelModule/component/editModule.vue +++ b/src/views/settings/modelConfig/modelModule/component/editModule.vue @@ -51,7 +51,7 @@ - + diff --git a/src/views/settings/modelConfig/modelModule/index.vue b/src/views/settings/modelConfig/modelModule/index.vue index 53797cb..6eef6b4 100644 --- a/src/views/settings/modelConfig/modelModule/index.vue +++ b/src/views/settings/modelConfig/modelModule/index.vue @@ -36,9 +36,14 @@ + + + @@ -97,12 +102,12 @@ - - + + @@ -156,7 +161,7 @@ const state = reactive({ }, }); -// 系统模型 API Key 配置 +// 内置模型 API Key 配置 const apiKeyDialogVisible = ref(false); const apiKeyFormRef = ref(); const apiKeyForm = reactive({ @@ -168,7 +173,7 @@ const apiKeyRules: FormRules = { apiKey: [{ required: true, message: '请输入 API Key', trigger: 'blur' }], }; const creatingModel = ref(false); -const systemModelToClone = ref(null); +const builtInModelToClone = ref(null); // 检查是否为管理员 const checkAdminStatus = async () => { @@ -192,15 +197,15 @@ const isInferenceModel = (modelType: number | string | undefined | null) => { // 设置为会话模型 const onSetChatModel = async (row: any) => { - // 判断是否是系统模型(tenantId === 1) - if (row.tenantId === 1) { - // 系统模型,需要用户配置 API Key - systemModelToClone.value = row; + // 判断是否是内置模型(isOwner === 0 表示管理员创建的内置模型) + if (row.isOwner === 0) { + // 内置模型,需要用户配置 API Key 创建副本 + builtInModelToClone.value = row; apiKeyForm.modelName = row.modelName; apiKeyForm.apiKey = ''; apiKeyDialogVisible.value = true; } else { - // 非系统模型,直接设置为会话模型 + // 用户自己的模型,直接设置为会话模型 try { await updateChatModel({ id: row.id!, @@ -216,36 +221,39 @@ const onSetChatModel = async (row: any) => { // 创建私有模型并设置为会话模型 const handleCreatePrivateModelAndSetChat = async () => { - if (!apiKeyFormRef.value || !systemModelToClone.value) return; + if (!apiKeyFormRef.value || !builtInModelToClone.value) return; try { await apiKeyFormRef.value.validate(); creatingModel.value = true; - // 基于系统模型创建新模型(继承原模型的所有配置,只替换 apiKey) - const systemModel = systemModelToClone.value; + // 基于内置模型创建新模型(继承原模型的所有配置,只替换 apiKey) + const builtInModel = builtInModelToClone.value; const createParams = { modelName: apiKeyForm.modelName, - modelType: systemModel.modelType, - baseUrl: systemModel.baseUrl, - httpMethod: systemModel.httpMethod || 'POST', - headMsg: systemModel.headMsg || '', - isPrivate: systemModel.isPrivate ?? 1, - enabled: systemModel.enabled ?? 1, + modelType: builtInModel.modelType, + baseUrl: builtInModel.baseUrl, + httpMethod: builtInModel.httpMethod || 'POST', + headMsg: builtInModel.headMsg || '', + isPrivate: builtInModel.isPrivate ?? 1, + enabled: builtInModel.enabled ?? 1, isChatModel: 1, // 设置为会话模型 apiKey: apiKeyForm.apiKey, - form: systemModel.form || [], - requestMapping: systemModel.requestMapping || {}, - responseMapping: systemModel.responseMapping || {}, - maxConcurrency: systemModel.maxConcurrency || 10, - queueLimit: systemModel.queueLimit || 100, - timeoutSeconds: systemModel.timeoutSeconds || 30, - expectedSeconds: systemModel.expectedSeconds || 15, - retryTimes: systemModel.retryTimes || 3, - retryQueueMaxSeconds: systemModel.retryQueueMaxSeconds || 60, - autoCleanSeconds: systemModel.autoCleanSeconds || 300, - remark: systemModel.remark || '', + form: builtInModel.form || {}, + requestMapping: builtInModel.requestMapping || {}, + responseMapping: builtInModel.responseMapping || {}, + responseBody: builtInModel.responseBody || {}, + tokenMapping: builtInModel.tokenMapping || '', + prompt: builtInModel.prompt || '', + maxConcurrency: builtInModel.maxConcurrency || 10, + queueLimit: builtInModel.queueLimit || 100, + timeoutSeconds: builtInModel.timeoutSeconds || 30, + expectedSeconds: builtInModel.expectedSeconds || 15, + retryTimes: builtInModel.retryTimes || 3, + retryQueueMaxSeconds: builtInModel.retryQueueMaxSeconds || 60, + autoCleanSeconds: builtInModel.autoCleanSeconds || 300, + remark: builtInModel.remark || '', }; await addModelModule(createParams);