From 4cd4b6ef52f669409c6b7697693163e90fea56b3 Mon Sep 17 00:00:00 2001 From: unknown <1251316345@qq.com> Date: Fri, 27 Feb 2026 20:36:34 +0800 Subject: [PATCH] mobile app apply_contest contest_detail contest_edit notifications theme --- app.py | 19 +++++++++++++++++++ templates/apply_contest.html | 13 ++++++++++++- templates/contest_detail.html | 3 +++ templates/contest_edit.html | 2 +- templates/notifications.html | 22 ++++++++++++++++++---- 5 files changed, 53 insertions(+), 6 deletions(-) diff --git a/app.py b/app.py index b5c0a7a..b2e640d 100644 --- a/app.py +++ b/app.py @@ -914,6 +914,12 @@ def api_change_name(): @login_required def apply_contest(): if request.method == 'POST': + user_id = session['user']['id'] + # 防止重复提交:如果已有 pending 状态的申请,不允许再提交 + existing = ContestApplication.query.filter_by(user_id=user_id, status='pending').first() + if existing: + flash('您已有一个待审核的杯赛申请,请等待审核结果后再提交新申请') + return redirect(url_for('contest_list')) name = request.form.get('name') organizer = request.form.get('organizer') description = request.form.get('description') @@ -1136,6 +1142,19 @@ def api_mark_all_notifications_read(): db.session.commit() return jsonify({'success': True}) +@app.route('/api/notifications/', methods=['DELETE']) +@login_required +def api_delete_notification(nid): + """删除单条通知(仅管理员可删除已处理的通知)""" + n = Notification.query.get_or_404(nid) + if n.user_id != session['user']['id']: + return jsonify({'success': False, 'message': '无权操作'}), 403 + if session['user'].get('role') != 'admin': + return jsonify({'success': False, 'message': '仅管理员可删除通知'}), 403 + db.session.delete(n) + db.session.commit() + return jsonify({'success': True}) + @app.route('/notifications') @login_required def notifications_page(): diff --git a/templates/apply_contest.html b/templates/apply_contest.html index 70682b7..0e0a28c 100644 --- a/templates/apply_contest.html +++ b/templates/apply_contest.html @@ -88,7 +88,7 @@ 取消 - @@ -96,4 +96,15 @@ +{% endblock %} + +{% block scripts %} + {% endblock %} \ No newline at end of file diff --git a/templates/contest_detail.html b/templates/contest_detail.html index 5b2cd9a..d6f783a 100644 --- a/templates/contest_detail.html +++ b/templates/contest_detail.html @@ -59,6 +59,9 @@ 审批老师申请 + + 上传历年真题 + 编辑主页 diff --git a/templates/contest_edit.html b/templates/contest_edit.html index c491bdb..c816f44 100644 --- a/templates/contest_edit.html +++ b/templates/contest_edit.html @@ -44,7 +44,7 @@ -
+

往届真题管理

{% for paper in contest.get_past_papers() %} diff --git a/templates/notifications.html b/templates/notifications.html index 23f7646..533dd48 100644 --- a/templates/notifications.html +++ b/templates/notifications.html @@ -209,8 +209,8 @@ function buildActions(n) {
`; } - if (n.type === 'teacher_application' && n.application_status === 'approved') return '
已同意
'; - if (n.type === 'teacher_application' && n.application_status === 'rejected') return '
已拒绝
'; + if (n.type === 'teacher_application' && n.application_status === 'approved') return '
已同意' + (currentUser.role === 'admin' ? `` : '') + '
'; + if (n.type === 'teacher_application' && n.application_status === 'rejected') return '
已拒绝' + (currentUser.role === 'admin' ? `` : '') + '
'; if (n.type === 'contest_application' && n.application_status === 'pending' && n.post_id && currentUser.role === 'admin') { return `
@@ -218,8 +218,8 @@ function buildActions(n) {
`; } - if (n.type === 'contest_application' && n.application_status === 'approved') return '
已同意
'; - if (n.type === 'contest_application' && n.application_status === 'rejected') return '
已拒绝
'; + if (n.type === 'contest_application' && n.application_status === 'approved') return '
已同意' + (currentUser.role === 'admin' ? `` : '') + '
'; + if (n.type === 'contest_application' && n.application_status === 'rejected') return '
已拒绝' + (currentUser.role === 'admin' ? `` : '') + '
'; // 如果有考试关联的通知,添加快捷入口 if (n.type === 'contest_new_exam' || n.type === 'exam_graded') { @@ -283,6 +283,20 @@ function markAllRead() { }); } +async function deleteNotif(nid) { + if (!confirm('确定删除该通知?')) return; + try { + const res = await fetch(`/api/notifications/${nid}`, {method:'DELETE'}); + const d = await res.json(); + if (d.success) { + allNotifs = allNotifs.filter(n => n.id !== nid); + renderNotifications(); + } else { + alert(d.message || '删除失败'); + } + } catch(e) { alert('删除失败'); } +} + async function loadAll() { const [notifRes, annRes] = await Promise.all([ fetch('/api/notifications').then(r => r.json()),