1. 我的模型页面修改

This commit is contained in:
2026-01-29 17:34:59 +08:00
parent 49393fefa0
commit d0675aede3
3 changed files with 670 additions and 77 deletions

View File

@@ -316,14 +316,46 @@
// 加载模型列表
async function loadModels() {
try {
const response = await fetch(`${API_BASE}/model-manage`);
const result = await response.json();
if (result.code === 0) {
allModels = result.data || [];
renderModels();
} else {
showMessage('错误', result.message || '加载模型失败', 'error');
// 并行加载数据库模型和已训练模型
const [dbResponse, trainedResponse] = await Promise.all([
fetch(`${API_BASE}/model-manage`),
fetch(`${API_BASE}/model-manage/trained-models`)
]);
const dbResult = await dbResponse.json();
const trainedResult = await trainedResponse.json();
let dbModels = [];
let trainedModels = [];
// 数据库模型
if (dbResult.code === 0) {
dbModels = dbResult.data || [];
}
// 已训练模型
if (trainedResult.code === 0) {
const trainedData = trainedResult.data?.models || [];
trainedData.forEach(model => {
if (model.train_methods && model.train_methods.length > 0) {
model.train_methods.forEach(method => {
trainedModels.push({
id: `trained_${model.name}_${method.name}`.replace(/[^a-zA-Z0-9]/g, '_'),
name: `${model.name} (${method.name})`,
type: 'LLM',
source: 'trained',
model_path: model.path,
train_method: method.name
});
});
}
});
}
// 合并所有模型
allModels = [...dbModels, ...trainedModels];
console.log('[DEBUG] 数据库模型:', dbModels.length, '已训练模型:', trainedModels.length);
renderModels();
} catch (error) {
console.error('加载模型失败:', error);
document.getElementById('modelList').innerHTML = `
@@ -335,9 +367,14 @@
}
}
// 渲染模型列表
// 渲染模型列表 - 使用分栏显示数据库模型和已训练模型
function renderModels() {
const container = document.getElementById('modelList');
// 分离数据库模型和已训练模型
const dbModels = allModels.filter(m => m.source !== 'trained');
const trainedModels = allModels.filter(m => m.source === 'trained');
if (allModels.length === 0) {
container.innerHTML = `
<div class="p-8 text-center text-gray-400">
@@ -348,42 +385,74 @@
return;
}
container.innerHTML = allModels.map(model => {
const isSelected = selectedModels.has(model.id);
const isDisabled = !isSelected && selectedModels.size >= 4;
const typeText = {
'LLM': '大语言模型',
'CV': '计算机视觉',
'NLP': '自然语言处理',
'Embedding': '向量模型',
'Other': '其他'
}[model.type] || model.type || '其他';
let html = '';
return `
<div class="model-card border-b border-gray-100 last:border-b-0 p-4 cursor-pointer ${isSelected ? 'selected bg-blue-50/50' : ''} ${isDisabled ? 'disabled opacity-50' : ''} hover:bg-gray-50 transition-colors"
onclick="toggleModel(${model.id})">
<div class="flex items-center justify-between">
<div class="flex items-center flex-1 min-w-0">
<div class="w-5 h-5 rounded-full border-2 ${isSelected ? 'border-primary bg-primary' : 'border-gray-300'} flex items-center justify-center mr-3 flex-shrink-0">
${isSelected ? '<i class="fa fa-check text-white text-xs"></i>' : ''}
</div>
<div class="min-w-0">
<div class="flex items-center mb-1">
<span class="font-medium text-gray-800 truncate">${model.name}</span>
<span class="ml-2 px-2 py-0.5 bg-blue-100 text-blue-700 text-xs rounded flex-shrink-0">${typeText}</span>
</div>
<p class="text-sm text-gray-500 truncate">${model.description || '暂无描述'}</p>
</div>
// 数据库模型区域
if (dbModels.length > 0) {
html += `
<div class="border-b border-gray-200">
<div class="px-4 py-2 bg-gray-50 text-xs font-medium text-gray-600 flex items-center">
<i class="fa fa-database mr-1"></i> 数据库模型 (${dbModels.length})
</div>
<div class="divide-y divide-gray-100">
`;
html += dbModels.map(model => renderModelCard(model)).join('');
html += '</div>';
}
// 已训练模型区域
if (trainedModels.length > 0) {
html += `
<div class="border-b border-gray-200">
<div class="px-4 py-2 bg-green-50 text-xs font-medium text-green-700 flex items-center">
<i class="fa fa-check-circle mr-1"></i> 已训练模型 (${trainedModels.length})
</div>
<div class="divide-y divide-gray-100">
`;
html += trainedModels.map(model => renderModelCard(model)).join('');
html += '</div>';
}
container.innerHTML = html;
updateSelectedCount();
}
// 渲染单个模型卡片
function renderModelCard(model) {
const isSelected = selectedModels.has(model.id);
const isDisabled = !isSelected && selectedModels.size >= 4;
const typeText = {
'LLM': '大语言模型',
'CV': '计算机视觉',
'NLP': '自然语言处理',
'Embedding': '向量模型',
'Other': '其他'
}[model.type] || model.type || '其他';
// 处理字符串类型的ID
const modelId = typeof model.id === 'string' ? `'${model.id.replace(/'/g, "\\'")}'` : model.id;
return `
<div class="model-card border-b border-gray-100 last:border-b-0 p-4 cursor-pointer ${isSelected ? 'selected bg-blue-50/50' : ''} ${isDisabled ? 'disabled opacity-50' : ''} hover:bg-gray-50 transition-colors"
onclick="toggleModel(${modelId})">
<div class="flex items-center justify-between">
<div class="flex items-center flex-1 min-w-0">
<div class="w-5 h-5 rounded-full border-2 ${isSelected ? 'border-primary bg-primary' : 'border-gray-300'} flex items-center justify-center mr-3 flex-shrink-0">
${isSelected ? '<i class="fa fa-check text-white text-xs"></i>' : ''}
</div>
<div class="ml-4 text-xs text-gray-400 flex-shrink-0">
${model.model_source === 'local' ? '本地模型' : '在线模型'}
<div class="min-w-0">
<div class="flex items-center mb-1">
<span class="font-medium text-gray-800 truncate">${model.name}</span>
<span class="ml-2 px-2 py-0.5 bg-blue-100 text-blue-700 text-xs rounded flex-shrink-0">${typeText}</span>
</div>
<p class="text-sm text-gray-500 truncate">${model.description || '暂无描述'}</p>
</div>
</div>
<div class="ml-4 text-xs text-gray-400 flex-shrink-0">
${model.source === 'trained' || model.model_source === 'local' ? '本地模型' : '在线模型'}
</div>
</div>
`;
}).join('');
updateSelectedCount();
</div>
`;
}
// 切换模型选择
@@ -399,6 +468,11 @@
renderModels();
}
// 暴露到全局作用域供 onclick 调用
window.toggleModel = toggleModel;
window.goBack = goBack;
window.submitForm = submitForm;
// 筛选模型
function filterModels(keyword) {
const filtered = allModels.filter(model => {
@@ -411,7 +485,7 @@
renderFilteredModels(filtered);
}
// 渲染筛选后的模型列表
// 渲染筛选后的模型列表 - 使用分栏显示
function renderFilteredModels(models) {
const container = document.getElementById('modelList');
if (models.length === 0) {
@@ -424,40 +498,39 @@
return;
}
container.innerHTML = models.map(model => {
const isSelected = selectedModels.has(model.id);
const isDisabled = !isSelected && selectedModels.size >= 4;
const typeText = {
'LLM': '大语言模型',
'CV': '计算机视觉',
'NLP': '自然语言处理',
'Embedding': '向量模型',
'Other': '其他'
}[model.type] || model.type || '其他';
// 分离数据库模型和已训练模型
const dbModels = models.filter(m => m.source !== 'trained');
const trainedModels = models.filter(m => m.source === 'trained');
return `
<div class="model-card border-b border-gray-100 last:border-b-0 p-4 cursor-pointer ${isSelected ? 'selected bg-blue-50/50' : ''} ${isDisabled ? 'disabled opacity-50' : ''} hover:bg-gray-50 transition-colors"
onclick="toggleModel(${model.id})">
<div class="flex items-center justify-between">
<div class="flex items-center flex-1 min-w-0">
<div class="w-5 h-5 rounded-full border-2 ${isSelected ? 'border-primary bg-primary' : 'border-gray-300'} flex items-center justify-center mr-3 flex-shrink-0">
${isSelected ? '<i class="fa fa-check text-white text-xs"></i>' : ''}
</div>
<div class="min-w-0">
<div class="flex items-center mb-1">
<span class="font-medium text-gray-800 truncate">${model.name}</span>
<span class="ml-2 px-2 py-0.5 bg-blue-100 text-blue-700 text-xs rounded flex-shrink-0">${typeText}</span>
</div>
<p class="text-sm text-gray-500 truncate">${model.description || '暂无描述'}</p>
</div>
</div>
<div class="ml-4 text-xs text-gray-400 flex-shrink-0">
${model.model_source === 'local' ? '本地模型' : '在线模型'}
</div>
let html = '';
// 数据库模型区域
if (dbModels.length > 0) {
html += `
<div class="border-b border-gray-200">
<div class="px-4 py-2 bg-gray-50 text-xs font-medium text-gray-600 flex items-center">
<i class="fa fa-database mr-1"></i> 数据库模型 (${dbModels.length})
</div>
</div>
<div class="divide-y divide-gray-100">
`;
}).join('');
html += dbModels.map(model => renderModelCard(model)).join('');
html += '</div>';
}
// 已训练模型区域
if (trainedModels.length > 0) {
html += `
<div class="border-b border-gray-200">
<div class="px-4 py-2 bg-green-50 text-xs font-medium text-green-700 flex items-center">
<i class="fa fa-check-circle mr-1"></i> 已训练模型 (${trainedModels.length})
</div>
<div class="divide-y divide-gray-100">
`;
html += trainedModels.map(model => renderModelCard(model)).join('');
html += '</div>';
}
container.innerHTML = html;
}
// 更新已选数量