diff --git a/main/manager-web/src/apis/module/model.js b/main/manager-web/src/apis/module/model.js index e27c69ad..38cc946e 100644 --- a/main/manager-web/src/apis/module/model.js +++ b/main/manager-web/src/apis/module/model.js @@ -159,5 +159,23 @@ export default { }) }).send() }, - + // 更新模型配置 + updateModel(params, callback) { + const { modelType, provideCode, id, formData } = params; + RequestService.sendRequest() + .url(`${getServiceUrl()}/models/${modelType}/${provideCode}/${id}`) + .method('PUT') + .data(formData) + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .fail((err) => { + console.error('更新模型失败:', err); + this.$message.error(err.msg || '更新模型失败'); + RequestService.reAjaxFun(() => { + this.updateModel(params, callback); + }); + }).send(); + }, } diff --git a/main/manager-web/src/components/AddModelDialog.vue b/main/manager-web/src/components/AddModelDialog.vue index 3e6022cd..5c119da1 100644 --- a/main/manager-web/src/components/AddModelDialog.vue +++ b/main/manager-web/src/components/AddModelDialog.vue @@ -6,7 +6,7 @@ 添加模型 - + @@ -61,23 +61,27 @@
调用信息
-
+
- -
- - - - - - -
- - - - + + @@ -101,6 +105,8 @@ export default { return { providers: [], providersLoaded: false, + providerFields: [], + currentProvider: null, formData: { modelName: '', modelCode: '', @@ -110,14 +116,35 @@ export default { remark: '', isEnabled: true, isDefault: true, - configJson: { - param1: '', - param2: '', - apiKey: '' - } + configJson: {} } } }, + watch: { + visible(val) { + if(val) { + this.initConfigJson(); + } + }, + 'formData.supplier'(newVal) { + this.currentProvider = this.providers.find(p => p.value === newVal); + this.providerFields = this.currentProvider?.fields || []; + this.initDynamicConfig(); + } + }, + computed: { + dynamicCallInfoFields() { + return this.providerFields; + }, + chunkedCallInfoFields() { + const chunkSize = 2; + const result = []; + for (let i = 0; i < this.dynamicCallInfoFields.length; i += chunkSize) { + result.push(this.dynamicCallInfoFields.slice(i, i + chunkSize)); + } + return result; + } + }, methods: { loadProviders() { if (this.providersLoaded) @@ -126,23 +153,54 @@ export default { Api.model.getModelProviders(this.modelType, (data) => { this.providers = data.map(item => ({ label: item.name, - value: item.providerCode + value: item.providerCode, + fields: JSON.parse(item.fields || '[]').map(f => ({ + label: f.label, + prop: f.key, + type: f.type === 'password' ? 'password' : 'text', + placeholder: `请输入${f.label}` + })) })) this.providersLoaded = true }) }, + initConfigJson() { + const defaultConfig = {}; + this.providerFields.forEach(field => { + defaultConfig[field.prop] = ''; + }); + this.formData.configJson = { ...defaultConfig }; + }, + initDynamicConfig() { + const newConfig = {}; + this.providerFields.forEach(field => { + newConfig[field.prop] = this.formData.configJson[field.prop] || ''; + }); + this.formData.configJson = newConfig; + }, confirm() { - if (!this.formData.modelName || !this.formData.modelCode || !this.formData.supplier || - !this.formData.configJson.param1 || !this.formData.configJson.param2 || !this.formData.configJson.apiKey) { - this.$message.error('请填写所有必填字段'); + if (!this.formData.supplier) { + this.$message.error('请选择供应器'); return; } - this.$emit('confirm', { - ...this.formData, + const submitData = { + modelName: this.formData.modelName || '', + modelCode: this.formData.modelCode || '', + supplier: this.formData.supplier, + sort: this.formData.sort || 1, + docLink: this.formData.docLink || '', + remark: this.formData.remark || '', + isEnabled: this.formData.isEnabled ? 1 : 0, + isDefault: this.formData.isDefault ? 1 : 0, provideCode: this.formData.supplier, - configJson: this.formData.configJson - }); + configJson: { + ...this.formData.configJson, + type: this.formData.supplier + } + }; + + this.$emit('confirm', submitData); this.$emit('update:visible', false); this.resetForm(); }, @@ -156,15 +214,14 @@ export default { remark: '', isEnabled: true, isDefault: true, - configJson: { - param1: '', - param2: '', - apiKey: '' - } + configJson: {} }; // 重置加载状态 this.providers = []; this.providersLoaded = false; + // 重置字段配置 + this.providerFields = []; + this.currentProvider = null; }, handleClose() { this.resetForm(); diff --git a/main/manager-web/src/components/ModelEditDialog.vue b/main/manager-web/src/components/ModelEditDialog.vue index 594efb17..a6a71a6d 100644 --- a/main/manager-web/src/components/ModelEditDialog.vue +++ b/main/manager-web/src/components/ModelEditDialog.vue @@ -15,11 +15,11 @@
是否启用 - +
设为默认 - +
@@ -38,7 +38,7 @@
- @@ -59,21 +59,26 @@
调用信息
-
+
- -
- - - - - - -
- - - - + +
@@ -89,7 +94,6 @@ import Api from '@/apis/api'; const DEFAULT_CONFIG_JSON = { - provider: "", type: "", base_url: "", model_name: "", @@ -97,8 +101,8 @@ const DEFAULT_CONFIG_JSON = { raw: {}, config: { keyComparator: {}, - ignoreError: 0, - ignoreCase: 0, + ignoreError: false, + ignoreCase: false, dateFormat: "", ignoreNullValue: false, transientSupport: false, @@ -111,7 +115,7 @@ const DEFAULT_CONFIG_JSON = { export default { name: "ModelEditDialog", - props: { + props: { visible: { type: Boolean, default: false }, modelData: { type: Object, @@ -135,12 +139,62 @@ export default { docLink: "", remark: "", sort: 0, - apiKey: "", - apiUrl: "", configJson: JSON.parse(JSON.stringify(DEFAULT_CONFIG_JSON)) } }; }, + computed: { + callInfoFields() { + const fieldsMap = { + llm: [ + { label: '模型名称', prop: 'model_name', placeholder: '请输入model_name' }, + { label: '接口地址', prop: 'base_url', placeholder: '请输入base_url' }, + { label: '秘钥信息', prop: 'api_key', placeholder: '请输入api_key', type: 'password' } + ], + vad: [ + { label: '模型名称', prop: 'model_name', placeholder: '请输入model_name' }, + { label: '模型目录', prop: 'model_dir', placeholder: '请输入model_dir' }, + { label: '阈值', prop: 'threshold', placeholder: '请输入threshold' }, + { label: '静音时长', prop: 'min_silence_duration_ms', placeholder: '请输入min_silence_duration_ms' }, + { label: '接口地址', prop: 'base_url', placeholder: '请输入base_url' }, + { label: '秘钥信息', prop: 'api_key', placeholder: '请输入api_key', type: 'password' } + ], + asr: [ + { label: '模型名称', prop: 'model_name', placeholder: '请输入model_name' }, + { label: '集群', prop: 'cluster', placeholder: '请输入cluster' }, + { label: '接口地址', prop: 'base_url', placeholder: '请输入base_url' }, + { label: '秘钥信息', prop: 'api_key', placeholder: '请输入api_key', type: 'password' } + ], + intent: [ + { label: '模型名称', prop: 'model_name', placeholder: '请输入model_name' }, + { label: 'LLM模型', prop: 'llm', placeholder: '请输入llm' }, + { label: '接口地址', prop: 'base_url', placeholder: '请输入base_url' }, + { label: '秘钥信息', prop: 'api_key', placeholder: '请输入api_key', type: 'password' } + ], + tts: [ + { label: '模型名称', prop: 'model_name', placeholder: '请输入model_name' }, + { label: '语音ID', prop: 'voice_id', placeholder: '请输入voice_id' }, + { label: '接口地址', prop: 'base_url', placeholder: '请输入base_url' }, + { label: '秘钥信息', prop: 'api_key', placeholder: '请输入api_key', type: 'password' } + ], + memory: [ + { label: '模型名称', prop: 'model_name', placeholder: '请输入model_name' }, + { label: '接口地址', prop: 'base_url', placeholder: '请输入base_url' }, + { label: '秘钥信息', prop: 'api_key', placeholder: '请输入api_key', type: 'password' } + ] + }; + + return fieldsMap[this.modelType] || []; + }, + chunkedCallInfoFields() { + const chunkSize = 2; + const result = []; + for (let i = 0; i < this.callInfoFields.length; i += chunkSize) { + result.push(this.callInfoFields.slice(i, i + chunkSize)); + } + return result; + }, + }, watch: { modelType() { this.resetProviders() @@ -169,8 +223,6 @@ export default { docLink: "", remark: "", sort: 0, - apiKey: "", - apiUrl: "", configJson: JSON.parse(JSON.stringify(DEFAULT_CONFIG_JSON)) }; }, @@ -184,14 +236,18 @@ export default { if (data.code === 0 && data.data) { const model = data.data; - this.loadProviders(); - let configJson = model.configJson || {}; if (typeof configJson !== 'object' || Array.isArray(configJson)) { console.warn('Invalid configJson format, using default'); configJson = {}; } + this.callInfoFields.forEach(field => { + if (!configJson.hasOwnProperty(field.prop)) { + configJson[field.prop] = ''; + } + }); + this.form = { id: model.id || "", modelType: model.modelType || "", @@ -202,9 +258,6 @@ export default { docLink: model.docLink || "", remark: model.remark || "", sort: model.sort || 0, - apiKey: configJson.api_key || "", - apiUrl: configJson.base_url || "", - name:configJson.model_name, configJson: { ...JSON.parse(JSON.stringify(DEFAULT_CONFIG_JSON)), ...configJson, @@ -219,23 +272,27 @@ export default { } }, handleSave() { + const provideCode = this.form.configJson.type; + const { provider, ...restConfigJson } = this.form.configJson; const formData = { - modelCode: this.form.code, - modelName: this.form.name, - supplier: this.form.supplier, + id: this.form.id, + modelCode: this.form.modelCode, + modelName: this.form.modelName, isDefault: this.form.isDefault ? 1 : 0, - isEnabled: this.form.isEnable ? 1 : 0, - docLink: this.form.docUrl, - sort: this.form.sort, + isEnabled: this.form.isEnabled ? 1 : 0, + docLink: this.form.docLink, remark: this.form.remark, + sort: this.form.sort || 0, configJson: { - provider: this.form.supplier, - modelName: this.form.modelName, - apiUrl: this.form.apiUrl, - apiKey: this.form.apiKey + ...restConfigJson, + config: { + ...restConfigJson.config, + ignoreError: !!restConfigJson.config?.ignoreError, + ignoreCase: !!restConfigJson.config?.ignoreCase, + } } }; - this.$emit("save", formData); + this.$emit("save", { provideCode, formData }); this.dialogVisible = false; }, loadProviders() { @@ -249,7 +306,6 @@ export default { this.providersLoaded = true; }); }, - } }; @@ -414,4 +470,22 @@ export default { .custom-input-bg .el-input__inner { height: 32px; } + + +.custom-form .el-form-item { + margin-bottom: 20px; +} + + +.custom-input-bg .el-input__inner { + height: 32px; +} + + +.custom-form .el-form-item__label { + color: #3d4566; + font-weight: normal; + text-align: right; + padding-right: 20px; +} diff --git a/main/manager-web/src/views/ModelConfig.vue b/main/manager-web/src/views/ModelConfig.vue index 01d149bd..71df5d2d 100644 --- a/main/manager-web/src/views/ModelConfig.vue +++ b/main/manager-web/src/views/ModelConfig.vue @@ -53,7 +53,7 @@
- + 查询 @@ -212,8 +212,8 @@ export default { this.loadData(); }, handleSearch() { - // TODO: 查询 - console.log('查询:', this.search); + this.currentPage = 1; + this.loadData(); }, // 批量删除 batchDelete() { @@ -301,9 +301,21 @@ export default { // TODO: 导出配置 console.log('导出配置'); }, - handleModelSave(formData) { - // TODO: 保存模型数据 - console.log('保存的模型数据:', formData); + handleModelSave({ provideCode, formData }) { + const modelType = this.activeTab; + const id = formData.id; + Api.model.updateModel( + { modelType, provideCode, id, formData }, + ({ data }) => { + if (data.code === 0) { + this.$message.success('保存成功'); + this.loadData(); + this.editDialogVisible = false; + } else { + this.$message.error(data.msg || '保存失败'); + } + } + ); }, selectAll() { if (this.isAllSelected) {