2026-01-21 15:33:43 +08:00
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html lang="zh-CN">
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
|
<title>模型评测 / 远光软件微调平台</title>
|
|
|
|
|
<script src="../lib/tailwindcss/tailwind.js"></script>
|
|
|
|
|
<link href="../lib/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
|
|
|
|
<style>
|
|
|
|
|
.bg-primary { background-color: #1890ff; }
|
|
|
|
|
.text-primary { color: #1890ff; }
|
|
|
|
|
.border-primary { border-color: #1890ff; }
|
|
|
|
|
:root { --primary: #1890ff; }
|
|
|
|
|
</style>
|
|
|
|
|
</head>
|
2026-01-26 15:25:05 +08:00
|
|
|
<body class="antialiased bg-gray-50">
|
|
|
|
|
<!-- 表格容器 -->
|
|
|
|
|
<div id="tableContainer" style="padding: 16px;">
|
2026-01-21 15:33:43 +08:00
|
|
|
<!-- 评测任务表格 -->
|
|
|
|
|
<div id="tasksTable" class="tab-content active">
|
|
|
|
|
<div class="bg-white rounded-lg shadow-sm">
|
|
|
|
|
<div class="px-6 py-4 border-b border-gray-100">
|
|
|
|
|
<h3 class="text-lg font-medium text-gray-800">评测任务列表</h3>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="overflow-x-auto">
|
|
|
|
|
<table class="w-full">
|
|
|
|
|
<thead class="bg-gray-50">
|
|
|
|
|
<tr>
|
|
|
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">模型名称</th>
|
|
|
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">数据集</th>
|
|
|
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">指标</th>
|
|
|
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">得分</th>
|
|
|
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">状态</th>
|
|
|
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">创建时间</th>
|
|
|
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">操作</th>
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody id="tasksBody" class="bg-white divide-y divide-gray-200">
|
|
|
|
|
<!-- 动态加载 -->
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 排行榜表格 -->
|
|
|
|
|
<div id="leaderboardTable" class="tab-content hidden">
|
|
|
|
|
<div class="bg-white rounded-lg shadow-sm">
|
|
|
|
|
<div class="px-6 py-4 border-b border-gray-100">
|
|
|
|
|
<h3 class="text-lg font-medium text-gray-800">模型排行榜</h3>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="overflow-x-auto">
|
|
|
|
|
<table class="w-full">
|
|
|
|
|
<thead class="bg-gray-50">
|
|
|
|
|
<tr>
|
|
|
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">排名</th>
|
|
|
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">模型名称</th>
|
|
|
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">平均得分</th>
|
|
|
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">评测次数</th>
|
|
|
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">最后评测</th>
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody id="leaderboardBody" class="bg-white divide-y divide-gray-200">
|
|
|
|
|
<!-- 动态加载 -->
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 评测维度表格 -->
|
|
|
|
|
<div id="dimensionsTable" class="tab-content hidden">
|
|
|
|
|
<div class="bg-white rounded-lg shadow-sm">
|
|
|
|
|
<div class="px-6 py-4 border-b border-gray-100">
|
|
|
|
|
<h3 class="text-lg font-medium text-gray-800">评测维度管理</h3>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="overflow-x-auto">
|
|
|
|
|
<table class="w-full">
|
|
|
|
|
<thead class="bg-gray-50">
|
|
|
|
|
<tr>
|
|
|
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">维度名称</th>
|
|
|
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">指标类型</th>
|
|
|
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">描述</th>
|
|
|
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">状态</th>
|
|
|
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">操作</th>
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody id="dimensionsBody" class="bg-white divide-y divide-gray-200">
|
|
|
|
|
<!-- 动态加载 -->
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-01-23 11:07:09 +08:00
|
|
|
<!-- 自定义确认弹窗 -->
|
|
|
|
|
<div id="confirmModal" class="hidden fixed inset-0 bg-black/50 z-50 flex items-center justify-center">
|
|
|
|
|
<div class="bg-white rounded-xl shadow-xl max-w-sm w-full mx-4 overflow-hidden">
|
|
|
|
|
<div class="p-6 text-center">
|
|
|
|
|
<div id="confirmIcon" class="w-12 h-12 mx-auto mb-4 rounded-full bg-yellow-100 flex items-center justify-center">
|
|
|
|
|
<i class="fa fa-exclamation text-xl text-yellow-600"></i>
|
|
|
|
|
</div>
|
|
|
|
|
<h3 id="confirmTitle" class="text-lg font-medium text-gray-800 mb-2"></h3>
|
|
|
|
|
<p id="confirmMessage" class="text-gray-600 text-sm"></p>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="px-6 pb-6 flex justify-center space-x-4">
|
|
|
|
|
<button id="confirmCancelBtn" class="px-6 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition-colors">取消</button>
|
|
|
|
|
<button id="confirmOkBtn" class="px-6 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 transition-colors">确定</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-01-21 15:33:43 +08:00
|
|
|
<script>
|
2026-01-26 14:33:00 +08:00
|
|
|
// API 基础地址 - 使用 config.yaml 中的 app.port (7861)
|
2026-01-21 15:33:43 +08:00
|
|
|
const getApiBase = () => {
|
|
|
|
|
const protocol = window.location.protocol;
|
|
|
|
|
const hostname = window.location.hostname;
|
2026-01-26 14:33:00 +08:00
|
|
|
return `${protocol}//${hostname}:7861/api`;
|
2026-01-21 15:33:43 +08:00
|
|
|
};
|
|
|
|
|
const API_BASE = getApiBase();
|
|
|
|
|
|
|
|
|
|
// Tab 内容切换函数(供 main.html 调用)
|
|
|
|
|
window.switchTabContent = function(tabId) {
|
2026-01-26 15:25:05 +08:00
|
|
|
// 隐藏所有 tab 内容
|
2026-01-21 15:33:43 +08:00
|
|
|
document.querySelectorAll('.tab-content').forEach(content => {
|
|
|
|
|
content.classList.add('hidden');
|
|
|
|
|
content.classList.remove('active');
|
|
|
|
|
});
|
2026-01-26 15:25:05 +08:00
|
|
|
// 显示选中的 tab 内容
|
2026-01-21 15:33:43 +08:00
|
|
|
const activeContent = document.getElementById(tabId + 'Table');
|
|
|
|
|
if (activeContent) {
|
|
|
|
|
activeContent.classList.remove('hidden');
|
|
|
|
|
activeContent.classList.add('active');
|
|
|
|
|
}
|
2026-01-26 15:25:05 +08:00
|
|
|
// 更新面包屑标题
|
|
|
|
|
const titles = {
|
|
|
|
|
'tasks': '评测任务列表',
|
|
|
|
|
'leaderboard': '模型排行榜',
|
|
|
|
|
'dimensions': '评测维度管理'
|
|
|
|
|
};
|
|
|
|
|
const breadcrumbTitle = document.getElementById('breadcrumbTitle');
|
|
|
|
|
if (breadcrumbTitle) {
|
|
|
|
|
breadcrumbTitle.textContent = titles[tabId] || tabId;
|
|
|
|
|
}
|
2026-01-22 16:46:12 +08:00
|
|
|
// 切换到评测维度tab时刷新数据
|
|
|
|
|
if (tabId === 'dimensions') {
|
|
|
|
|
loadDimensions();
|
|
|
|
|
}
|
2026-01-21 15:33:43 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 加载评测任务数据
|
|
|
|
|
async function loadTasks() {
|
|
|
|
|
try {
|
|
|
|
|
const response = await fetch(`${API_BASE}/model-eval`);
|
|
|
|
|
const result = await response.json();
|
|
|
|
|
|
|
|
|
|
if (result.code === 0) {
|
|
|
|
|
const data = result.data || [];
|
|
|
|
|
const tbody = document.getElementById('tasksBody');
|
|
|
|
|
|
|
|
|
|
if (data.length === 0) {
|
|
|
|
|
tbody.innerHTML = `
|
|
|
|
|
<tr>
|
|
|
|
|
<td colspan="7" class="px-6 py-12 text-center text-gray-400">
|
|
|
|
|
<i class="fa fa-inbox text-4xl mb-3"></i>
|
|
|
|
|
<p>暂无评测任务</p>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
`;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tbody.innerHTML = data.map(item => `
|
|
|
|
|
<tr class="hover:bg-gray-50">
|
|
|
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">${item.model_name || '-'}</td>
|
|
|
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.dataset || '-'}</td>
|
|
|
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.metric || '-'}</td>
|
|
|
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.score ? item.score + '%' : '-'}</td>
|
|
|
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
|
|
|
<span class="px-2 py-1 text-xs font-medium rounded-full ${getStatusClass(item.status)}">
|
|
|
|
|
${item.status || '未知'}
|
|
|
|
|
</span>
|
|
|
|
|
</td>
|
|
|
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
|
|
|
|
${item.create_time ? new Date(item.create_time).toLocaleString('zh-CN') : '-'}
|
|
|
|
|
</td>
|
|
|
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
|
|
|
|
<button onclick="viewReport(${item.id})" class="text-primary hover:text-primary/80 mr-3">
|
|
|
|
|
<i class="fa fa-bar-chart"></i> 报告
|
|
|
|
|
</button>
|
|
|
|
|
<button onclick="deleteTask(${item.id})" class="text-red-500 hover:text-red-600">
|
|
|
|
|
<i class="fa fa-trash"></i> 删除
|
|
|
|
|
</button>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
`).join('');
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('加载评测任务失败:', error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 加载排行榜数据(模拟数据)
|
|
|
|
|
async function loadLeaderboard() {
|
|
|
|
|
// 模拟排行榜数据
|
|
|
|
|
const mockData = [
|
|
|
|
|
{ rank: 1, model_name: 'GPT-4', avg_score: 95.2, eval_count: 128, last_eval: '2026-01-20' },
|
|
|
|
|
{ rank: 2, model_name: 'Claude-3', avg_score: 93.8, eval_count: 96, last_eval: '2026-01-19' },
|
|
|
|
|
{ rank: 3, model_name: '文心一言', avg_score: 89.5, eval_count: 64, last_eval: '2026-01-18' },
|
|
|
|
|
{ rank: 4, model_name: '通义千问', avg_score: 87.3, eval_count: 52, last_eval: '2026-01-17' },
|
|
|
|
|
{ rank: 5, model_name: 'ChatGLM', avg_score: 84.6, eval_count: 45, last_eval: '2026-01-16' }
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const tbody = document.getElementById('leaderboardBody');
|
|
|
|
|
tbody.innerHTML = mockData.map(item => `
|
|
|
|
|
<tr class="hover:bg-gray-50">
|
|
|
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
|
|
|
<span class="px-2 py-1 text-xs font-bold rounded-full ${getRankClass(item.rank)}">
|
|
|
|
|
#${item.rank}
|
|
|
|
|
</span>
|
|
|
|
|
</td>
|
|
|
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">${item.model_name}</td>
|
|
|
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.avg_score}%</td>
|
|
|
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.eval_count}次</td>
|
|
|
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.last_eval}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
`).join('');
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-22 16:46:12 +08:00
|
|
|
// 加载评测维度数据
|
2026-01-22 17:29:48 +08:00
|
|
|
window.loadDimensions = async function() {
|
2026-01-22 16:46:12 +08:00
|
|
|
try {
|
|
|
|
|
const response = await fetch(`${API_BASE}/dimension`);
|
|
|
|
|
const result = await response.json();
|
2026-01-21 15:33:43 +08:00
|
|
|
|
2026-01-22 16:46:12 +08:00
|
|
|
const tbody = document.getElementById('dimensionsBody');
|
|
|
|
|
|
|
|
|
|
if (result.code !== 0 || !result.data || result.data.length === 0) {
|
|
|
|
|
tbody.innerHTML = `
|
|
|
|
|
<tr>
|
|
|
|
|
<td colspan="5" class="px-6 py-12 text-center text-gray-400">
|
|
|
|
|
<i class="fa fa-inbox text-4xl mb-3"></i>
|
|
|
|
|
<p>暂无评测维度</p>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
`;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tbody.innerHTML = result.data.map(item => `
|
|
|
|
|
<tr class="hover:bg-gray-50">
|
|
|
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">${item.name || '-'}</td>
|
|
|
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.type || '-'}</td>
|
|
|
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.description || '-'}</td>
|
|
|
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
|
|
|
<span class="px-2 py-1 text-xs font-medium rounded-full bg-green-100 text-green-700">
|
|
|
|
|
启用
|
|
|
|
|
</span>
|
|
|
|
|
</td>
|
|
|
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
|
|
|
|
<button onclick="editDimension(${item.id})" class="text-primary hover:text-primary/80 mr-3">
|
|
|
|
|
<i class="fa fa-edit"></i> 编辑
|
|
|
|
|
</button>
|
|
|
|
|
<button onclick="deleteDimension(${item.id})" class="text-red-500 hover:text-red-600">
|
|
|
|
|
<i class="fa fa-trash"></i> 删除
|
|
|
|
|
</button>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
`).join('');
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('加载评测维度失败:', error);
|
|
|
|
|
}
|
2026-01-21 15:33:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 状态样式
|
|
|
|
|
function getStatusClass(status) {
|
|
|
|
|
const map = {
|
|
|
|
|
'completed': 'bg-green-100 text-green-700',
|
|
|
|
|
'running': 'bg-blue-100 text-blue-700',
|
|
|
|
|
'pending': 'bg-yellow-100 text-yellow-700',
|
|
|
|
|
'failed': 'bg-red-100 text-red-700'
|
|
|
|
|
};
|
|
|
|
|
return map[status?.toLowerCase()] || 'bg-gray-100 text-gray-500';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 排名样式
|
|
|
|
|
function getRankClass(rank) {
|
|
|
|
|
if (rank === 1) return 'bg-yellow-100 text-yellow-700';
|
|
|
|
|
if (rank === 2) return 'bg-gray-100 text-gray-600';
|
|
|
|
|
if (rank === 3) return 'bg-orange-100 text-orange-700';
|
|
|
|
|
return 'bg-gray-50 text-gray-500';
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-23 11:07:09 +08:00
|
|
|
// 自定义确认弹窗
|
|
|
|
|
function showConfirm(title, message, onConfirm) {
|
|
|
|
|
const modal = document.getElementById('confirmModal');
|
|
|
|
|
const modalTitle = document.getElementById('confirmTitle');
|
|
|
|
|
const modalMessage = document.getElementById('confirmMessage');
|
|
|
|
|
const cancelBtn = document.getElementById('confirmCancelBtn');
|
|
|
|
|
const okBtn = document.getElementById('confirmOkBtn');
|
|
|
|
|
|
|
|
|
|
modalTitle.textContent = title;
|
|
|
|
|
modalMessage.textContent = message;
|
|
|
|
|
|
|
|
|
|
modal.classList.remove('hidden');
|
|
|
|
|
document.body.style.overflow = 'hidden';
|
|
|
|
|
|
|
|
|
|
cancelBtn.onclick = function() {
|
|
|
|
|
modal.classList.add('hidden');
|
|
|
|
|
document.body.style.overflow = '';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
okBtn.onclick = function() {
|
|
|
|
|
modal.classList.add('hidden');
|
|
|
|
|
document.body.style.overflow = '';
|
|
|
|
|
if (typeof onConfirm === 'function') {
|
|
|
|
|
onConfirm();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 自定义消息弹窗
|
|
|
|
|
function showMessage(title, message, type = 'info', onConfirm) {
|
|
|
|
|
const modal = document.getElementById('confirmModal');
|
|
|
|
|
const modalTitle = document.getElementById('confirmTitle');
|
|
|
|
|
const modalMessage = document.getElementById('confirmMessage');
|
|
|
|
|
const cancelBtn = document.getElementById('confirmCancelBtn');
|
|
|
|
|
const okBtn = document.getElementById('confirmOkBtn');
|
|
|
|
|
|
|
|
|
|
// 隐藏取消按钮,只显示确定按钮
|
|
|
|
|
cancelBtn.classList.add('hidden');
|
|
|
|
|
|
|
|
|
|
modalTitle.textContent = title;
|
|
|
|
|
modalMessage.innerHTML = message;
|
|
|
|
|
|
|
|
|
|
// 根据类型设置图标和按钮颜色
|
|
|
|
|
const iconContainer = document.getElementById('confirmIcon');
|
|
|
|
|
if (type === 'success') {
|
|
|
|
|
iconContainer.className = 'w-12 h-12 mx-auto mb-4 rounded-full bg-green-100 flex items-center justify-center';
|
|
|
|
|
iconContainer.innerHTML = '<i class="fa fa-check text-xl text-green-600"></i>';
|
|
|
|
|
okBtn.className = 'px-6 py-2 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors';
|
|
|
|
|
} else if (type === 'error') {
|
|
|
|
|
iconContainer.className = 'w-12 h-12 mx-auto mb-4 rounded-full bg-red-100 flex items-center justify-center';
|
|
|
|
|
iconContainer.innerHTML = '<i class="fa fa-times text-xl text-red-600"></i>';
|
|
|
|
|
okBtn.className = 'px-6 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 transition-colors';
|
|
|
|
|
} else if (type === 'warning') {
|
|
|
|
|
iconContainer.className = 'w-12 h-12 mx-auto mb-4 rounded-full bg-yellow-100 flex items-center justify-center';
|
|
|
|
|
iconContainer.innerHTML = '<i class="fa fa-exclamation text-xl text-yellow-600"></i>';
|
|
|
|
|
okBtn.className = 'px-6 py-2 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors';
|
|
|
|
|
} else {
|
|
|
|
|
iconContainer.className = 'w-12 h-12 mx-auto mb-4 rounded-full bg-blue-100 flex items-center justify-center';
|
|
|
|
|
iconContainer.innerHTML = '<i class="fa fa-info text-xl text-blue-600"></i>';
|
|
|
|
|
okBtn.className = 'px-6 py-2 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
modal.classList.remove('hidden');
|
|
|
|
|
document.body.style.overflow = 'hidden';
|
|
|
|
|
|
|
|
|
|
okBtn.onclick = function() {
|
|
|
|
|
modal.classList.add('hidden');
|
|
|
|
|
document.body.style.overflow = '';
|
|
|
|
|
// 恢复取消按钮
|
|
|
|
|
cancelBtn.classList.remove('hidden');
|
|
|
|
|
if (typeof onConfirm === 'function') {
|
|
|
|
|
onConfirm();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-22 17:29:48 +08:00
|
|
|
// 操作函数(挂载到 window 以便 onclick 调用)
|
|
|
|
|
window.viewReport = function(id) {
|
2026-01-21 15:33:43 +08:00
|
|
|
alert('查看报告功能开发中');
|
2026-01-22 17:29:48 +08:00
|
|
|
};
|
2026-01-21 15:33:43 +08:00
|
|
|
|
2026-01-22 17:29:48 +08:00
|
|
|
window.deleteTask = function(id) {
|
2026-01-23 11:07:09 +08:00
|
|
|
showConfirm('确认删除', '确定要删除此评测任务吗?', () => {
|
|
|
|
|
executeDeleteTask(id);
|
|
|
|
|
});
|
2026-01-22 17:29:48 +08:00
|
|
|
};
|
2026-01-21 15:33:43 +08:00
|
|
|
|
2026-01-23 11:07:09 +08:00
|
|
|
async function executeDeleteTask(id) {
|
|
|
|
|
try {
|
|
|
|
|
const response = await fetch(`${API_BASE}/model-eval/${id}`, {
|
|
|
|
|
method: 'DELETE'
|
|
|
|
|
});
|
|
|
|
|
const result = await response.json();
|
|
|
|
|
if (result.code === 0) {
|
|
|
|
|
showMessage('成功', '删除成功', 'success', () => {
|
|
|
|
|
loadTasks();
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
showMessage('错误', result.message || '删除失败', 'error');
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('删除评测任务失败:', error);
|
|
|
|
|
showMessage('错误', '删除失败: ' + error.message, 'error');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-22 17:29:48 +08:00
|
|
|
window.addDimension = function() {
|
2026-01-21 16:59:01 +08:00
|
|
|
window.location.href = 'model-dimension-create.html';
|
2026-01-22 17:29:48 +08:00
|
|
|
};
|
2026-01-21 15:33:43 +08:00
|
|
|
|
2026-01-22 17:29:48 +08:00
|
|
|
window.editDimension = function(id) {
|
|
|
|
|
window.location.href = `model-dimension-create.html?id=${id}`;
|
|
|
|
|
};
|
2026-01-21 15:33:43 +08:00
|
|
|
|
2026-01-22 17:29:48 +08:00
|
|
|
window.deleteDimension = function(id) {
|
2026-01-22 16:46:12 +08:00
|
|
|
showConfirm('确认删除', '确定要删除此评测维度吗?', () => {
|
|
|
|
|
executeDelete(id);
|
|
|
|
|
});
|
2026-01-22 17:29:48 +08:00
|
|
|
};
|
2026-01-22 16:46:12 +08:00
|
|
|
|
|
|
|
|
async function executeDelete(id) {
|
|
|
|
|
try {
|
|
|
|
|
const response = await fetch(`${API_BASE}/dimension/${id}`, {
|
|
|
|
|
method: 'DELETE'
|
|
|
|
|
});
|
|
|
|
|
const result = await response.json();
|
|
|
|
|
if (result.code === 0) {
|
|
|
|
|
// 切换到评测维度tab并刷新列表
|
|
|
|
|
switchToDimensionsTab();
|
|
|
|
|
showMessage('成功', '删除成功', 'success');
|
|
|
|
|
} else {
|
|
|
|
|
showMessage('错误', result.message || '删除失败', 'error');
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('删除维度失败:', error);
|
|
|
|
|
showMessage('错误', '删除失败: ' + error.message, 'error');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 切换到评测维度tab
|
2026-01-22 17:29:48 +08:00
|
|
|
window.switchToDimensionsTab = function() {
|
2026-01-22 16:46:12 +08:00
|
|
|
const dimBtn = document.querySelector('[data-tab="dimensions"]');
|
|
|
|
|
if (dimBtn) {
|
|
|
|
|
dimBtn.click();
|
2026-01-21 15:33:43 +08:00
|
|
|
}
|
2026-01-22 17:29:48 +08:00
|
|
|
};
|
2026-01-21 15:33:43 +08:00
|
|
|
|
|
|
|
|
// 页面加载时初始化
|
|
|
|
|
async function initPage() {
|
|
|
|
|
await loadTasks();
|
|
|
|
|
loadLeaderboard();
|
|
|
|
|
loadDimensions();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 支持通过 main.html fetch 加载
|
|
|
|
|
if (document.readyState === 'loading') {
|
|
|
|
|
document.addEventListener('DOMContentLoaded', initPage);
|
|
|
|
|
} else {
|
|
|
|
|
initPage();
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|