修复模型管理v2对话模型回显与异步弹窗崩溃问题
- 修复 chatModel 开关回显:字段大小写与后端对齐(chatModel) - 修复异步模型 asyncTaskMapping 内字段为 null 时编辑弹窗崩溃 - lastFrame 提交仅限视频模型,避免占位符误提交 - 切换返回类型时清空 responseBodyMapping 残留 - 列表页访问类型列改为供应商列(后端不再返回 PrivateModel) - ModelManageItem 类型与后端返回字段对齐(modelSupplier/chatModel/minDuration 等)
This commit is contained in:
@@ -40,21 +40,24 @@ export interface ModelManageItem {
|
||||
updater: string;
|
||||
updatedAt: string;
|
||||
deletedAt: null | string;
|
||||
modelSupplier: string;
|
||||
modelSupplier: number;
|
||||
modelName: string;
|
||||
modelType: number;
|
||||
baseUrl: string;
|
||||
responseType: number;
|
||||
apiKey: string;
|
||||
enabled: boolean;
|
||||
ChatModel: boolean;
|
||||
chatModel?: boolean;
|
||||
maxConcurrency: number;
|
||||
maxTokens: number;
|
||||
tokenPredictPrice: number;
|
||||
requestHeadMapping: Record<string, unknown>;
|
||||
requestBodyMapping: Record<string, unknown>;
|
||||
requestBusinessFieldMapping?: Record<string, string>;
|
||||
responseMapping: Record<string, unknown>;
|
||||
responseBodyMapping: Record<string, string>;
|
||||
responseBusinessFieldMapping?: Record<string, string>;
|
||||
minDuration?: number;
|
||||
tokenMapping?: TokenMapping;
|
||||
asyncTaskMapping?: AsyncTaskMapping;
|
||||
lastFrame?: string;
|
||||
|
||||
@@ -155,7 +155,7 @@
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="回调响应映射">
|
||||
<el-button @click="openMappingEditor('asyncResponseMapping')" style="width: 100%">
|
||||
配置 ({{ Object.keys(formData.asyncTaskMapping.responseMapping).length }})
|
||||
配置 ({{ Object.keys((formData.asyncTaskMapping.responseMapping || {})).length }})
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -529,6 +529,7 @@ const hasTaskStatusConfig = computed(() => taskStatusOptions.value.length > 0);
|
||||
/** 用户手动切换返回类型时清空 token 映射(编程赋值不触发) */
|
||||
function handleResponseTypeChange() {
|
||||
formData.tokenMapping = { ...defaultTokenMapping };
|
||||
formData.responseBodyMapping = [];
|
||||
}
|
||||
|
||||
|
||||
@@ -661,7 +662,7 @@ const openDialog = async (type: 'add' | 'edit', id?: string) => {
|
||||
formData.apiKey = row.apiKey || '';
|
||||
formData.responseType = row.responseType ?? row.invokeType;
|
||||
formData.enabled = row.enabled ?? true;
|
||||
formData.chatModel = row.ChatModel ?? false;
|
||||
formData.chatModel = row.chatModel ?? row.ChatModel ?? false;
|
||||
formData.maxConcurrency = row.maxConcurrency || 10;
|
||||
formData.maxTokens = row.maxTokens || 4096;
|
||||
formData.tokenPredictPrice = row.tokenPredictPrice ?? 0;
|
||||
@@ -672,7 +673,14 @@ const openDialog = async (type: 'add' | 'edit', id?: string) => {
|
||||
? (Array.isArray(row.responseBodyMapping) ? row.responseBodyMapping : Object.keys(row.responseBodyMapping))
|
||||
: [];
|
||||
formData.tokenMapping = row.tokenMapping ? { ...defaultTokenMapping, ...row.tokenMapping } : { ...defaultTokenMapping };
|
||||
formData.asyncTaskMapping = row.asyncTaskMapping ? { ...defaultAsyncTaskMapping, ...row.asyncTaskMapping } : { ...defaultAsyncTaskMapping };
|
||||
formData.asyncTaskMapping = row.asyncTaskMapping
|
||||
? {
|
||||
...defaultAsyncTaskMapping,
|
||||
...row.asyncTaskMapping,
|
||||
requestHeadMapping: row.asyncTaskMapping.requestHeadMapping || {},
|
||||
responseMapping: row.asyncTaskMapping.responseMapping || {},
|
||||
}
|
||||
: { ...defaultAsyncTaskMapping };
|
||||
formData.lastFrame = row.lastFrame || '';
|
||||
formData.maxDuration = row.maxDuration ?? 0;
|
||||
formData.tokenPredictPriceUnit = row.tokenPredictPriceUnit || '';
|
||||
@@ -730,7 +738,7 @@ const handleSubmit = async () => {
|
||||
asyncTaskMapping = hasAsyncConfig ? ({ ...atm } as AsyncTaskMapping) : undefined;
|
||||
}
|
||||
|
||||
if (formData.lastFrame) {
|
||||
if (isVideoModel.value && formData.lastFrame) {
|
||||
lastFrame = formData.lastFrame;
|
||||
}
|
||||
let maxDuration: number | undefined;
|
||||
|
||||
@@ -43,9 +43,9 @@
|
||||
<el-tag :type="scope.row.systemModel ? 'warning' : 'success'">{{ scope.row.systemModel ? '系统' : '用户' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="访问类型">
|
||||
<el-table-column label="供应商" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.PrivateModel ? 'info' : 'primary'">{{ scope.row.PrivateModel ? '服务商模型' : '本地模型' }}</el-tag>
|
||||
{{ resolveSupplierLabel(scope.row.modelSupplier) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态">
|
||||
@@ -85,7 +85,7 @@ import { ref, reactive, onMounted } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { Search, Plus } from '@element-plus/icons-vue';
|
||||
import EditModule from './component/editModule.vue';
|
||||
import { listModelManage, getModelManageTypes, deleteModelManage, type ModelManageItem, type ModelTypeTreeNode } from '/@/api/settings/modelConfigV2';
|
||||
import { listModelManage, getModelManageTypes, deleteModelManage, getModelSupplierList, type ModelManageItem, type ModelTypeTreeNode, type ModelSupplierItem } from '/@/api/settings/modelConfigV2';
|
||||
|
||||
const searchParams = reactive({
|
||||
modelName: '',
|
||||
@@ -101,6 +101,7 @@ const pagination = reactive({
|
||||
const modelList = ref<ModelManageItem[]>([]);
|
||||
const loading = ref(false);
|
||||
const modelTypes = ref<ModelTypeTreeNode[]>([]);
|
||||
const supplierList = ref<ModelSupplierItem[]>([]);
|
||||
const editModuleRef = ref();
|
||||
|
||||
/** 级联选择器的选中路径(例:[200, 201]) */
|
||||
@@ -139,6 +140,22 @@ const loadModelTypes = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
/** 加载模型供应商列表 */
|
||||
const loadSupplierList = async () => {
|
||||
try {
|
||||
const res = await getModelSupplierList();
|
||||
supplierList.value = res.data?.list || [];
|
||||
} catch {
|
||||
supplierList.value = [];
|
||||
}
|
||||
};
|
||||
|
||||
/** 根据供应商值显示名称 */
|
||||
const resolveSupplierLabel = (supplier: number | undefined | null): string => {
|
||||
if (supplier === undefined || supplier === null) return '—';
|
||||
return supplierList.value.find((s) => s.value === supplier)?.label ?? String(supplier);
|
||||
};
|
||||
|
||||
/** 获取模型列表 */
|
||||
const fetchModelList = async () => {
|
||||
loading.value = true;
|
||||
@@ -204,6 +221,7 @@ const handleDelete = (row: ModelManageItem) => {
|
||||
|
||||
onMounted(async () => {
|
||||
await loadModelTypes();
|
||||
loadSupplierList();
|
||||
fetchModelList();
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user