Files
zlqy/templates/admin_contests.html
2026-02-27 10:37:11 +08:00

92 lines
4.1 KiB
HTML

{% extends "admin_base.html" %}
{% block title %}杯赛管理 - 智联青云管理后台{% endblock %}
{% block admin_content %}
<div class="space-y-6">
<h1 class="text-2xl font-bold text-slate-900">杯赛管理</h1>
<div class="bg-white shadow-sm rounded-lg border border-slate-200 overflow-hidden">
<table class="min-w-full divide-y divide-slate-200">
<thead class="bg-slate-50">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-slate-500 uppercase">ID</th>
<th class="px-6 py-3 text-left text-xs font-medium text-slate-500 uppercase">名称</th>
<th class="px-6 py-3 text-left text-xs font-medium text-slate-500 uppercase">主办方</th>
<th class="px-6 py-3 text-left text-xs font-medium text-slate-500 uppercase">状态</th>
<th class="px-6 py-3 text-left text-xs font-medium text-slate-500 uppercase">开始日期</th>
<th class="px-6 py-3 text-left text-xs font-medium text-slate-500 uppercase">操作</th>
</tr>
</thead>
<tbody id="contests-tbody" class="bg-white divide-y divide-slate-200">
</tbody>
</table>
<div id="empty-msg" class="text-center py-12 text-slate-400 hidden">暂无杯赛</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
const statusMap = {
'upcoming': ['即将开始', 'bg-blue-100 text-blue-800'],
'registering': ['正在报名', 'bg-green-100 text-green-800'],
'ongoing': ['进行中', 'bg-yellow-100 text-yellow-800'],
'ended': ['已结束', 'bg-slate-100 text-slate-800'],
'abolished': ['已废止', 'bg-red-100 text-red-800']
};
async function loadContests() {
try {
const res = await fetch('/api/admin/contests');
const data = await res.json();
const tbody = document.getElementById('contests-tbody');
const empty = document.getElementById('empty-msg');
if (!data.success || !data.contests.length) {
empty.classList.remove('hidden');
return;
}
let html = '';
data.contests.forEach(c => {
const [statusText, statusClass] = statusMap[c.status] || ['未知', 'bg-slate-100 text-slate-800'];
const abolishBtn = c.status !== 'abolished'
? `<button onclick="abolishContest(${c.id}, '${c.name.replace(/'/g, "\\'")}')" class="px-2 py-1 text-xs bg-red-100 text-red-700 border border-red-300 rounded hover:bg-red-200">废止</button>`
: '<span class="text-xs text-red-500">已废止</span>';
html += `<tr>
<td class="px-6 py-4 text-sm text-slate-900">${c.id}</td>
<td class="px-6 py-4 text-sm text-slate-900">${c.name}</td>
<td class="px-6 py-4 text-sm text-slate-500">${c.organizer || '-'}</td>
<td class="px-6 py-4"><span class="px-2 py-1 text-xs rounded-full ${statusClass}">${statusText}</span></td>
<td class="px-6 py-4 text-sm text-slate-500">${c.start_date || '-'}</td>
<td class="px-6 py-4 space-x-2">
<a href="/contests/${c.id}" class="text-xs text-primary hover:underline">查看</a>
${abolishBtn}
</td>
</tr>`;
});
tbody.innerHTML = html;
} catch(e) {
console.error(e);
}
}
async function abolishContest(id, name) {
if (!confirm(`确定要废止杯赛「${name}」吗?\n\n废止后:\n- 该杯赛下所有考试将被关闭\n- 无法再报名或参加考试\n- 数据将保留但杯赛不可恢复`)) return;
try {
const res = await fetch(`/api/admin/contests/${id}/abolish`, {method: 'POST'});
const data = await res.json();
if (data.success) {
alert('杯赛已废止');
loadContests();
} else {
alert(data.message || '操作失败');
}
} catch(e) {
alert('网络错误');
}
}
document.addEventListener('DOMContentLoaded', loadContests);
</script>
{% endblock %}