mobile app database models admin_contests admin_dashboard admin_exams admin_posts admin_teacher_applications admin_users apply_contest apply_teacher base chat contest_detail contest_list exam_result forum notifications profile themes

This commit is contained in:
2026-03-03 16:02:23 +08:00
parent 0764566742
commit 9a08140623
30 changed files with 1531 additions and 834 deletions

View File

@@ -4,92 +4,101 @@
{% block content %}
<div class="max-w-3xl mx-auto py-8">
<div class="bg-white shadow-sm rounded-lg border border-slate-200 p-6">
<h1 class="text-2xl font-bold text-slate-900 mb-6">申请举办杯赛</h1>
<form method="POST" action="{{ url_for('apply_contest') }}" class="space-y-6">
<div class="futuristic-card p-6">
<h1 class="text-2xl font-bold bg-gradient-to-r from-cyan-400 to-blue-400 bg-clip-text text-transparent mb-6">申请举办杯赛</h1>
<form method="POST" action="{{ url_for('apply_contest') }}" enctype="multipart/form-data" class="space-y-6">
<div>
<label for="name" class="block text-sm font-medium text-slate-700 mb-1">杯赛名称 <span class="text-red-500">*</span></label>
<label for="name" class="block text-sm font-medium text-slate-300 mb-1">杯赛名称 <span class="text-red-400">*</span></label>
<input type="text" id="name" name="name" required
class="w-full px-3 py-2 border border-slate-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary sm:text-sm"
class="input-futuristic w-full px-3 py-2 sm:text-sm"
placeholder="例如2026年星火杯">
</div>
<div>
<label for="organizer" class="block text-sm font-medium text-slate-700 mb-1">主办方 <span class="text-red-500">*</span></label>
<label for="organizer" class="block text-sm font-medium text-slate-300 mb-1">主办方 <span class="text-red-400">*</span></label>
<input type="text" id="organizer" name="organizer" required
class="w-full px-3 py-2 border border-slate-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary sm:text-sm"
class="input-futuristic w-full px-3 py-2 sm:text-sm"
placeholder="例如:星火杯组委会">
</div>
<div>
<label for="description" class="block text-sm font-medium text-slate-700 mb-1">描述 <span class="text-red-500">*</span></label>
<label for="image" class="block text-sm font-medium text-slate-300 mb-1">杯赛图片</label>
<input type="file" id="image" name="image" accept="image/*"
class="input-futuristic w-full px-3 py-2 sm:text-sm">
<p class="mt-1 text-xs text-slate-400">上传杯赛封面图片(可选,支持 JPG、PNG、GIF 格式,最大 5MB</p>
<div id="image-preview" class="mt-3 hidden">
<img id="preview-img" src="" alt="预览" class="max-w-xs rounded-lg border border-white/10 shadow-sm">
</div>
</div>
<div>
<label for="description" class="block text-sm font-medium text-slate-300 mb-1">描述 <span class="text-red-400">*</span></label>
<textarea id="description" name="description" rows="4" required
class="w-full px-3 py-2 border border-slate-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary sm:text-sm"
class="input-futuristic w-full px-3 py-2 sm:text-sm"
placeholder="简要介绍杯赛的目的、规则等"></textarea>
</div>
<div>
<label for="contact" class="block text-sm font-medium text-slate-700 mb-1">联系方式 <span class="text-red-500">*</span></label>
<label for="contact" class="block text-sm font-medium text-slate-300 mb-1">联系方式 <span class="text-red-400">*</span></label>
<input type="text" id="contact" name="contact" required
class="w-full px-3 py-2 border border-slate-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary sm:text-sm"
class="input-futuristic w-full px-3 py-2 sm:text-sm"
placeholder="邮箱或手机号">
<p class="mt-1 text-xs text-slate-500">用于管理员与您联系,不会公开显示</p>
<p class="mt-1 text-xs text-slate-400">用于管理员与您联系,不会公开显示</p>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label for="start_date" class="block text-sm font-medium text-slate-700 mb-1">开始日期 <span class="text-red-500">*</span></label>
<label for="start_date" class="block text-sm font-medium text-slate-300 mb-1">开始日期 <span class="text-red-400">*</span></label>
<input type="date" id="start_date" name="start_date" required
class="w-full px-3 py-2 border border-slate-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary sm:text-sm">
class="input-futuristic w-full px-3 py-2 sm:text-sm">
</div>
<div>
<label for="end_date" class="block text-sm font-medium text-slate-700 mb-1">结束日期 <span class="text-red-500">*</span></label>
<label for="end_date" class="block text-sm font-medium text-slate-300 mb-1">结束日期 <span class="text-red-400">*</span></label>
<input type="date" id="end_date" name="end_date" required
class="w-full px-3 py-2 border border-slate-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary sm:text-sm">
class="input-futuristic w-full px-3 py-2 sm:text-sm">
</div>
</div>
<div>
<label for="total_score" class="block text-sm font-medium text-slate-700 mb-1">杯赛满分 <span class="text-red-500">*</span></label>
<label for="total_score" class="block text-sm font-medium text-slate-300 mb-1">杯赛满分 <span class="text-red-400">*</span></label>
<input type="number" id="total_score" name="total_score" required min="1" value="150"
class="w-full px-3 py-2 border border-slate-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary sm:text-sm"
class="input-futuristic w-full px-3 py-2 sm:text-sm"
placeholder="例如150">
<p class="mt-1 text-xs text-slate-500">杯赛考试的默认满分分数</p>
<p class="mt-1 text-xs text-slate-400">杯赛考试的默认满分分数</p>
</div>
<!-- 报备信息 -->
<div class="border-t border-slate-200 pt-6 mt-2">
<h2 class="text-lg font-semibold text-slate-900 mb-4">报备信息</h2>
<div class="border-t border-white/10 pt-6 mt-2">
<h2 class="text-lg font-semibold bg-gradient-to-r from-cyan-400 to-blue-400 bg-clip-text text-transparent mb-4">报备信息</h2>
<div class="space-y-4">
<div>
<label for="responsible_person" class="block text-sm font-medium text-slate-700 mb-1">责任人姓名 <span class="text-red-500">*</span></label>
<label for="responsible_person" class="block text-sm font-medium text-slate-300 mb-1">责任人姓名 <span class="text-red-400">*</span></label>
<input type="text" id="responsible_person" name="responsible_person" required
class="w-full px-3 py-2 border border-slate-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary sm:text-sm"
class="input-futuristic w-full px-3 py-2 sm:text-sm"
placeholder="赛事责任人真实姓名">
</div>
<div>
<label for="responsible_phone" class="block text-sm font-medium text-slate-700 mb-1">责任人电话 <span class="text-red-500">*</span></label>
<label for="responsible_phone" class="block text-sm font-medium text-slate-300 mb-1">责任人电话 <span class="text-red-400">*</span></label>
<input type="tel" id="responsible_phone" name="responsible_phone" required
pattern="1[3-9]\d{9}"
class="w-full px-3 py-2 border border-slate-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary sm:text-sm"
class="input-futuristic w-full px-3 py-2 sm:text-sm"
placeholder="11位手机号码">
<p class="mt-1 text-xs text-slate-500">请填写有效的手机号码,审核通过后将公开展示</p>
<p class="mt-1 text-xs text-slate-400">请填写有效的手机号码,审核通过后将公开展示</p>
</div>
<div>
<label for="responsible_email" class="block text-sm font-medium text-slate-700 mb-1">责任人邮箱 <span class="text-red-500">*</span></label>
<label for="responsible_email" class="block text-sm font-medium text-slate-300 mb-1">责任人邮箱 <span class="text-red-400">*</span></label>
<input type="email" id="responsible_email" name="responsible_email" required
class="w-full px-3 py-2 border border-slate-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary sm:text-sm"
class="input-futuristic w-full px-3 py-2 sm:text-sm"
placeholder="example@email.com">
</div>
<div>
<label for="organization" class="block text-sm font-medium text-slate-700 mb-1">所属机构/学校 <span class="text-red-500">*</span></label>
<label for="organization" class="block text-sm font-medium text-slate-300 mb-1">所属机构/学校 <span class="text-red-400">*</span></label>
<input type="text" id="organization" name="organization" required
class="w-full px-3 py-2 border border-slate-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary sm:text-sm"
class="input-futuristic w-full px-3 py-2 sm:text-sm"
placeholder="例如XX大学、XX教育机构">
</div>
</div>
<p class="mt-3 text-xs text-amber-600 bg-amber-50 border border-amber-200 rounded-md p-3">以上报备信息将在杯赛详情页公开展示,请确保信息真实有效。</p>
<p class="mt-3 text-xs text-amber-300 bg-amber-500/10 border border-amber-500/30 rounded-md p-3">以上报备信息将在杯赛详情页公开展示,请确保信息真实有效。</p>
</div>
<div class="flex justify-end gap-3">
<a href="{{ url_for('contest_list') }}" class="px-5 py-2.5 border border-slate-300 rounded-md text-sm font-medium text-slate-700 bg-white hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary">
<a href="{{ url_for('contest_list') }}" class="btn-outline-futuristic px-5 py-2.5 text-sm font-medium">
取消
</a>
<button type="submit" id="submit-btn"
class="px-5 py-2.5 bg-primary text-white rounded-md text-sm font-medium hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary">
class="btn-futuristic px-5 py-2.5 text-sm font-medium">
提交申请
</button>
</div>
@@ -100,6 +109,30 @@
{% block scripts %}
<script>
// 图片预览功能
document.getElementById('image').addEventListener('change', function(e) {
const file = e.target.files[0];
if (file) {
// 检查文件大小5MB
if (file.size > 5 * 1024 * 1024) {
alert('图片大小不能超过 5MB');
e.target.value = '';
document.getElementById('image-preview').classList.add('hidden');
return;
}
// 显示预览
const reader = new FileReader();
reader.onload = function(e) {
document.getElementById('preview-img').src = e.target.result;
document.getElementById('image-preview').classList.remove('hidden');
};
reader.readAsDataURL(file);
} else {
document.getElementById('image-preview').classList.add('hidden');
}
});
document.querySelector('form').addEventListener('submit', function() {
const btn = document.getElementById('submit-btn');
btn.disabled = true;