mobile app admin_base admin_contests admin_dashboard chat contest_detail exam_create exam_detail exam_grade exam_list profile themes

This commit is contained in:
2026-03-07 19:07:01 +08:00
parent 2d3163a1a0
commit 86a6c7dd03
13 changed files with 656 additions and 169 deletions

View File

@@ -30,6 +30,7 @@
{% block scripts %}
<script>
const isAdmin = {{ 'true' if user and user.role == 'admin' else 'false' }};
const statusMap = {
'upcoming': ['即将开始', 'bg-blue-500/20 text-blue-400 border-blue-500/30'],
'registering': ['正在报名', 'bg-green-500/20 text-green-400 border-green-500/30'],
@@ -53,7 +54,10 @@ async function loadContests() {
const [statusText, statusClass] = statusMap[c.status] || ['未知', 'bg-slate-500/20 text-slate-400 border-slate-500/30'];
const abolishBtn = c.status !== 'abolished'
? `<button onclick="abolishContest(${c.id}, '${c.name.replace(/'/g, "\\'")}')" class="btn-outline-futuristic px-3 py-1 text-xs border-red-500/30 text-red-400 hover:bg-red-500/20 hover:border-red-500/50">废止</button>`
: '<span class="text-xs text-red-500">已废止</span>';
: '';
const deleteBtn = isAdmin && c.status === 'abolished'
? `<button onclick="deleteContest(${c.id}, '${c.name.replace(/'/g, "\\'")}')" class="btn-outline-futuristic px-3 py-1 text-xs border-orange-500/30 text-orange-400 hover:bg-orange-500/20 hover:border-orange-500/50">删除</button>`
: '';
html += `<tr>
<td>${c.id}</td>
<td class="font-medium text-slate-200" style="max-width: 200px; white-space: normal; word-wrap: break-word;">${c.name}</td>
@@ -63,6 +67,7 @@ async function loadContests() {
<td class="space-x-2">
<a href="/contests/${c.id}" class="text-xs text-cyan-400 hover:text-cyan-300 hover:underline">查看</a>
${abolishBtn}
${deleteBtn}
</td>
</tr>`;
});
@@ -73,7 +78,7 @@ async function loadContests() {
}
async function abolishContest(id, name) {
if (!confirm(`确定要废止杯赛「${name}」吗?\n\n废止后:\n- 该杯赛下所有考试将被关闭\n- 无法再报名或参加考试\n- 数据将保留但杯赛不可恢复`)) return;
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();
@@ -88,6 +93,22 @@ async function abolishContest(id, name) {
}
}
async function deleteContest(id, name) {
if (!confirm(`确定要彻底删除杯赛「${name}」吗?\n\n删除后:\n- 杯赛将从系统中完全移除\n- 不再显示在首页杯赛数量中\n- 用户无法再看到该杯赛\n- 此操作不可恢复!`)) return;
try {
const res = await fetch(`/api/admin/contests/${id}/delete`, {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 %}