-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
479 lines (439 loc) · 27.5 KB
/
Copy pathindex.html
File metadata and controls
479 lines (439 loc) · 27.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>算子生成比赛 2026</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
/* 基础平滑 & 导航点样式 (保持不变) */
html { scroll-behavior: smooth; }
.page-section {
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
padding: 80px 20px 40px;
}
.leaderboard-container {
max-height: 400px;
overflow-y: auto;
}
.leaderboard-container::-webkit-scrollbar { width: 8px; }
.leaderboard-container::-webkit-scrollbar-track { background: #1f2937; border-radius: 4px; }
.leaderboard-container::-webkit-scrollbar-thumb { background: #4b5563; border-radius: 4px; }
.leaderboard-container::-webkit-scrollbar-thumb:hover { background: #6b7280; }
.nav-dot {
width: 12px;
height: 12px;
border-radius: 50%;
background: #4b5563;
transition: all 0.3s;
}
.nav-dot.active {
background: #fbbf24;
transform: scale(1.2);
}
.nav-dot:hover { background: #9ca3af; }
.faq-content {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease-out;
}
.faq-content.open { max-height: 200px; }
/* ----- 白色主题 (追加class = white-theme) ----- */
body.white-theme {
background-color: #f9fafb !important;
color: #111827 !important;
}
/* 导航背景 & 边框 */
body.white-theme nav {
background-color: rgba(255, 255, 255, 0.95) !important;
border-bottom-color: #e5e7eb !important;
}
body.white-theme nav .text-yellow-400 { color: #b45309 !important; } /* 加深 amber 更可见 */
body.white-theme nav a { color: #374151 !important; }
body.white-theme nav a:hover { color: #b45309 !important; }
/* 右侧导航点 —— 白底时变灰 */
body.white-theme .nav-dot { background: #9ca3af; }
body.white-theme .nav-dot.active { background: #f59e0b; }
/* 区块背景 (原本深色带灰/黑) 改为浅灰/白 */
body.white-theme .page-section { background: #ffffff !important; }
body.white-theme .bg-gray-900 { background-color: #ffffff !important; }
body.white-theme .bg-gray-800 { background-color: #f3f4f6 !important; }
body.white-theme .bg-gray-800\/50 { background-color: rgba(243, 244, 246, 0.7) !important; }
body.white-theme .bg-gray-700 { background-color: #e5e7eb !important; }
body.white-theme .bg-gray-700\/50 { background-color: rgba(229, 231, 235, 0.5) !important; }
body.white-theme .border-gray-700 { border-color: #d1d5db !important; }
body.white-theme .border-gray-800 { border-color: #d1d5db !important; }
body.white-theme .border-yellow-500\/50 { border-color: #fbbf24 !important; }
body.white-theme .border-gray-400\/50 { border-color: #9ca3af !important; }
body.white-theme .border-orange-500\/50 { border-color: #fb923c !important; }
/* 文本颜色修正 */
body.white-theme .text-gray-300,
body.white-theme .text-gray-400 { color: #4b5563 !important; }
body.white-theme .text-gray-500 { color: #6b7280 !important; }
body.white-theme .text-yellow-400 { color: #b45309 !important; } /* 提高对比度 */
body.white-theme .text-blue-400 { color: #2563eb !important; }
body.white-theme .text-blue-400:hover { color: #1d4ed8 !important; }
/* 卡片内部微调 */
body.white-theme .bg-gradient-to-b.from-gray-900 { background: #f9fafb !important; }
body.white-theme .from-yellow-500\/20 { background: #fef3c7 !important; } /* 简单处理梯度 */
body.white-theme .from-gray-400\/20 { background: #f3f4f6 !important; }
body.white-theme .from-orange-500\/20 { background: #ffedd5 !important; }
/* 输入框、按钮 */
body.white-theme input.bg-gray-800 {
background-color: #ffffff !important;
border-color: #d1d5db !important;
color: #111827 !important;
}
body.white-theme .bg-gray-700 { background-color: #e5e7eb !important; }
body.white-theme .bg-gray-700:hover { background-color: #d1d5db !important; }
body.white-theme button.bg-yellow-500 {
background-color: #f59e0b !important;
color: #ffffff;
}
body.white-theme button.bg-yellow-500:hover { background-color: #d97706 !important; }
/* 排行榜表头 */
body.white-theme .bg-gray-700\/50 { background-color: #e5e7eb !important; }
body.white-theme .leaderboard-container .border-gray-700 { border-color: #d1d5db !important; }
/* FAQ */
body.white-theme .faq-content .text-gray-400 { color: #4b5563 !important; }
/* 页脚 */
body.white-theme .border-gray-700 { border-color: #d1d5db !important; }
/* 切换按钮固定样式 (始终可见) */
.theme-toggle-btn {
position: fixed;
bottom: 24px;
right: 24px;
z-index: 100;
background: #1f2937;
color: #fbbf24;
border: 1px solid #4b5563;
border-radius: 40px;
padding: 10px 20px;
font-size: 0.9rem;
font-weight: 500;
cursor: pointer;
box-shadow: 0 10px 20px -5px rgba(0,0,0,0.5);
transition: all 0.2s;
backdrop-filter: blur(4px);
}
.theme-toggle-btn:hover {
background: #374151;
color: #fcd34d;
}
body.white-theme .theme-toggle-btn {
background: white;
color: #b45309;
border-color: #d1d5db;
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}
body.white-theme .theme-toggle-btn:hover {
background: #f3f4f6;
}
</style>
</head>
<body class="bg-gray-900 text-white">
<!-- 固定切换按钮 (置于右下角, 不干扰布局) -->
<button class="theme-toggle-btn" id="themeSwitchBtn">🌓 切换白色风格</button>
<!-- 顶部导航 (深色默认) -->
<nav class="fixed top-0 left-0 right-0 bg-gray-900/95 backdrop-blur z-50 border-b border-gray-800">
<div class="max-w-6xl mx-auto px-4 py-4 flex justify-between items-center">
<div class="text-xl font-bold text-yellow-400">⚡ Algorithm Contest</div>
<div class="hidden md:flex gap-6 text-sm">
<a href="#home" class="hover:text-yellow-400 transition">首页</a>
<a href="#leaderboard" class="hover:text-yellow-400 transition">排行榜</a>
<a href="#schedule" class="hover:text-yellow-400 transition">赛程安排</a>
<a href="#prizes" class="hover:text-yellow-400 transition">奖项设置</a>
<a href="#rules" class="hover:text-yellow-400 transition">比赛规则</a>
<a href="#faq" class="hover:text-yellow-400 transition">FAQ</a>
<a href="#contact" class="hover:text-yellow-400 transition">联系我们</a>
</div>
</div>
</nav>
<!-- 右侧导航点 -->
<div class="fixed right-4 top-1/2 -translate-y-1/2 z-50 flex flex-col gap-3" id="navDots">
<a href="#home" class="nav-dot active" title="首页"></a>
<a href="#leaderboard" class="nav-dot" title="排行榜"></a>
<a href="#schedule" class="nav-dot" title="赛程安排"></a>
<a href="#prizes" class="nav-dot" title="奖项设置"></a>
<a href="#rules" class="nav-dot" title="比赛规则"></a>
<a href="#faq" class="nav-dot" title="FAQ"></a>
<a href="#contact" class="nav-dot" title="联系我们"></a>
</div>
<!-- 第1页:首页 (深色结构完全保留) -->
<section id="home" class="page-section bg-gradient-to-b from-gray-900 via-gray-800 to-gray-900">
<div class="max-w-4xl mx-auto text-center">
<h1 class="text-5xl md:text-6xl font-bold mb-6">
⚡ 算子生成比赛 <span class="text-yellow-400">2026</span>
</h1>
<p class="text-xl text-gray-300 mb-12">
挑战极限,突破自我。在这里,用代码证明你的实力,与顶尖选手同台竞技。
</p>
<div class="grid grid-cols-3 gap-8 max-w-2xl mx-auto">
<div class="bg-gray-800/50 rounded-xl p-6 border border-gray-700">
<div class="text-4xl font-bold text-yellow-400 mb-2" id="participantCount">--</div>
<div class="text-gray-400">参赛选手</div>
</div>
<div class="bg-gray-800/50 rounded-xl p-6 border border-gray-700">
<div class="text-4xl font-bold text-yellow-400 mb-2" id="submissionCount">--</div>
<div class="text-gray-400">提交次数</div>
</div>
<div class="bg-gray-800/50 rounded-xl p-6 border border-gray-700">
<div class="text-4xl font-bold text-yellow-400 mb-2">¥50,000</div>
<div class="text-gray-400">奖金池</div>
</div>
</div>
<div class="mt-12">
<a href="#leaderboard" class="inline-block bg-yellow-500 hover:bg-yellow-400 text-gray-900 font-bold py-3 px-8 rounded-lg transition">
查看排行榜 ↓
</a>
</div>
</div>
</section>
<!-- 第2页:排行榜 (数据区域) -->
<section id="leaderboard" class="page-section bg-gray-900">
<div class="max-w-4xl mx-auto w-full">
<div class="text-center mb-8">
<h2 class="text-4xl font-bold mb-4">🏆 实时排行榜</h2>
<!-- 搜索框 -->
<div class="flex justify-center items-center gap-4 mt-4 mb-4">
<div class="relative">
<input
type="text"
id="searchInput"
placeholder="搜索 GitHub 用户名..."
class="bg-gray-800 border border-gray-600 rounded-lg px-4 py-2 pl-10 w-64 focus:outline-none focus:border-yellow-400 transition"
onkeyup="handleSearch(event)"
>
<span class="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400">🔍</span>
</div>
<button onclick="searchLeaderboard()" class="bg-yellow-500 hover:bg-yellow-400 text-gray-900 px-4 py-2 rounded-lg font-semibold transition">
搜索
</button>
<button onclick="clearSearch()" class="bg-gray-700 hover:bg-gray-600 px-4 py-2 rounded-lg transition">
清除
</button>
</div>
<button onclick="loadLeaderboard()" class="text-yellow-400 hover:text-yellow-300 transition">
🔄 刷新数据
</button>
</div>
<div class="bg-gray-800 rounded-xl border border-gray-700 overflow-hidden">
<!-- 表头 -->
<div class="grid grid-cols-12 gap-4 p-4 bg-gray-700/50 font-semibold text-sm">
<div class="col-span-2 text-center">排名</div>
<div class="col-span-4">选手</div>
<div class="col-span-2 text-center">分数</div>
<div class="col-span-2 text-center">提交时间</div>
<div class="col-span-2 text-center">Commit</div>
</div>
<div class="leaderboard-container" id="leaderboardBody">
<div class="p-8 text-center text-gray-400">数据加载中...</div>
</div>
</div>
<!-- 分页 -->
<div class="flex justify-center items-center gap-4 mt-6" id="pagination">
<button onclick="changePage(-1)" class="px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded-lg transition" id="prevBtn">← 上一页</button>
<span class="text-gray-400" id="pageInfo">第 1 页</span>
<button onclick="changePage(1)" class="px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded-lg transition" id="nextBtn">下一页 →</button>
</div>
</div>
</section>
<!-- 第3页:赛程安排 -->
<section id="schedule" class="page-section bg-gradient-to-b from-gray-900 via-gray-800 to-gray-900">
<div class="max-w-3xl mx-auto w-full"> <!-- 内容与原来完全相同,省略内部细节以节省篇幅,但保证完整结构 -->
<h2 class="text-4xl font-bold text-center mb-12">📅 赛程安排</h2>
<div class="space-y-6">
<div class="flex gap-4 items-start"><div class="w-4 h-4 rounded-full bg-green-500 mt-2 flex-shrink-0"></div><div class="flex-1 bg-gray-800/50 rounded-xl p-6 border border-gray-700"><div class="text-yellow-400 text-sm mb-1">2026.03.02 - 2026.03.08</div><h3 class="text-xl font-bold mb-2">报名阶段</h3><p class="text-gray-400">开放报名通道,完成实名认证和团队组建</p><span class="inline-block mt-2 text-green-400 text-sm">✓ 已结束</span></div></div>
<div class="flex gap-4 items-start"><div class="w-4 h-4 rounded-full bg-yellow-500 mt-2 flex-shrink-0 animate-pulse"></div><div class="flex-1 bg-gray-800/50 rounded-xl p-6 border border-yellow-500/50"><div class="text-yellow-400 text-sm mb-1">2026.02.20 - 2026.03.20</div><h3 class="text-xl font-bold mb-2">初赛阶段</h3><p class="text-gray-400">线上提交代码,系统自动评测,实时更新排行榜</p><span class="inline-block mt-2 text-yellow-400 text-sm">● 进行中</span></div></div>
<div class="flex gap-4 items-start"><div class="w-4 h-4 rounded-full bg-gray-500 mt-2 flex-shrink-0"></div><div class="flex-1 bg-gray-800/50 rounded-xl p-6 border border-gray-700"><div class="text-yellow-400 text-sm mb-1">2026.03.25</div><h3 class="text-xl font-bold mb-2">初赛结果公布</h3><p class="text-gray-400">公布晋级名单,前50名进入复赛</p><span class="inline-block mt-2 text-gray-400 text-sm">○ 即将开始</span></div></div>
<div class="flex gap-4 items-start"><div class="w-4 h-4 rounded-full bg-gray-500 mt-2 flex-shrink-0"></div><div class="flex-1 bg-gray-800/50 rounded-xl p-6 border border-gray-700"><div class="text-yellow-400 text-sm mb-1">2026.04.01 - 2026.04.15</div><h3 class="text-xl font-bold mb-2">复赛阶段</h3><p class="text-gray-400">更高难度题目,限时完成,代码审核</p><span class="inline-block mt-2 text-gray-400 text-sm">○ 即将开始</span></div></div>
<div class="flex gap-4 items-start"><div class="w-4 h-4 rounded-full bg-gray-500 mt-2 flex-shrink-0"></div><div class="flex-1 bg-gray-800/50 rounded-xl p-6 border border-gray-700"><div class="text-yellow-400 text-sm mb-1">2026.04.25</div><h3 class="text-xl font-bold mb-2">总决赛 & 颁奖典礼</h3><p class="text-gray-400">线下答辩,专家评审,现场颁奖</p><span class="inline-block mt-2 text-gray-400 text-sm">○ 即将开始</span></div></div>
</div>
</div>
</section>
<!-- 第4页:奖项设置 -->
<section id="prizes" class="page-section bg-gray-900">
<div class="max-w-4xl mx-auto w-full">
<h2 class="text-4xl font-bold text-center mb-12">🏆 奖项设置</h2>
<div class="grid md:grid-cols-3 gap-6 mb-8">
<div class="bg-gradient-to-b from-yellow-500/20 to-gray-800 rounded-xl p-8 border border-yellow-500/50 text-center"><div class="text-5xl mb-4">🥇</div><h3 class="text-2xl font-bold mb-2">冠军</h3><div class="text-3xl font-bold text-yellow-400 mb-4">¥20,000</div><ul class="text-gray-400 text-sm space-y-1"><li>冠军证书</li><li>冠军专属纪念礼品</li></ul></div>
<div class="bg-gradient-to-b from-gray-400/20 to-gray-800 rounded-xl p-8 border border-gray-400/50 text-center"><div class="text-5xl mb-4">🥈</div><h3 class="text-2xl font-bold mb-2">亚军</h3><div class="text-3xl font-bold text-gray-300 mb-4">¥15,000</div><ul class="text-gray-400 text-sm space-y-1"><li>亚军证书</li><li>亚军纪念礼品</li></ul></div>
<div class="bg-gradient-to-b from-orange-500/20 to-gray-800 rounded-xl p-8 border border-orange-500/50 text-center"><div class="text-5xl mb-4">🥉</div><h3 class="text-2xl font-bold mb-2">季军</h3><div class="text-3xl font-bold text-orange-400 mb-4">¥10,000</div><ul class="text-gray-400 text-sm space-y-1"><li>季军证书</li><li>季军纪念礼品</li></ul></div>
</div>
<div class="grid md:grid-cols-2 gap-6">
<div class="bg-gray-800/50 rounded-xl p-6 border border-gray-700 text-center"><div class="text-3xl mb-2">⭐</div><h3 class="text-xl font-bold mb-2">优秀奖 (4-10名)</h3><div class="text-xl font-bold text-yellow-400 mb-2">¥1,000</div><p class="text-gray-400 text-sm">优秀奖证书 + 精美周边礼包</p></div>
<div class="bg-gray-800/50 rounded-xl p-6 border border-gray-700 text-center"><div class="text-3xl mb-2">🎯</div><h3 class="text-xl font-bold mb-2">参与奖</h3><div class="text-xl font-bold text-gray-400 mb-2">参与证书</div><p class="text-gray-400 text-sm">电子参赛证书</p></div>
</div>
</div>
</section>
<!-- 第5页:比赛规则 -->
<section id="rules" class="page-section bg-gradient-to-b from-gray-900 via-gray-800 to-gray-900">
<div class="max-w-4xl mx-auto w-full">
<h2 class="text-4xl font-bold text-center mb-12">📋 比赛规则</h2>
<div class="grid md:grid-cols-2 gap-6">
<div class="bg-gray-800/50 rounded-xl p-6 border border-gray-700"><h3 class="text-xl font-bold mb-4 text-yellow-400">📝 参赛要求</h3><ul class="space-y-2 text-gray-300"><li>• 参赛者需完成实名认证</li><li>• 支持个人或团队参赛(团队最多3人)</li><li>• 每位选手只能参加一支队伍</li><li>• 参赛者需同意并遵守比赛规则</li></ul></div>
<div class="bg-gray-800/50 rounded-xl p-6 border border-gray-700"><h3 class="text-xl font-bold mb-4 text-yellow-400">💻 提交规范</h3><ul class="space-y-2 text-gray-300"><li>• 代码需通过 Git 提交到指定仓库</li><li>• 每天最多提交 10 次</li><li>• 提交后系统自动评测,实时更新分数</li><li>• 以最高分数作为最终成绩</li></ul></div>
<div class="bg-gray-800/50 rounded-xl p-6 border border-gray-700"><h3 class="text-xl font-bold mb-4 text-yellow-400">⚖️ 评分标准</h3><ul class="space-y-2 text-gray-300"><li>• 正确性 (60%): 测试用例通过率</li><li>• 性能 (30%): 运行时间和内存占用</li><li>• 代码质量 (10%): 可读性和规范性</li><li>• 同分情况按提交时间排序</li></ul></div>
<div class="bg-gray-800/50 rounded-xl p-6 border border-gray-700"><h3 class="text-xl font-bold mb-4 text-red-400">🚫 禁止行为</h3><ul class="space-y-2 text-gray-300"><li>• 禁止抄袭他人代码或使用非法手段</li><li>• 禁止恶意攻击评测系统</li><li>• 禁止多账号参赛</li><li>• 违规者将取消参赛资格</li></ul></div>
</div>
</div>
</section>
<!-- 第6页:FAQ -->
<section id="faq" class="page-section bg-gray-900">
<div class="max-w-3xl mx-auto w-full">
<h2 class="text-4xl font-bold text-center mb-12">❓ 常见问题</h2>
<div class="space-y-4">
<div class="bg-gray-800/50 rounded-xl border border-gray-700 overflow-hidden"><button class="w-full p-6 text-left flex justify-between items-center hover:bg-gray-700/50 transition" onclick="toggleFaq(this)"><span class="font-semibold">如何提交代码?</span><span class="text-yellow-400">▼</span></button><div class="faq-content px-6 pb-6"><p class="text-gray-400">参赛选手需要创建私有github仓库,将机器人帐号@kernerl-competition-bot作为合作者加入仓库并按照指南配置仓库的webhook。配置完成后,选手每次 push 会自动触发评测。评测结果由自动更新至排行榜和提交记录评论区</p></div></div>
<div class="bg-gray-800/50 rounded-xl border border-gray-700 overflow-hidden"><button class="w-full p-6 text-left flex justify-between items-center hover:bg-gray-700/50 transition" onclick="toggleFaq(this)"><span class="font-semibold">评测系统的运行环境是什么?</span><span class="text-yellow-400">▼</span></button><div class="faq-content px-6 pb-6"><p class="text-gray-400">评测系统运行在 Linux 环境下,配置为 MLU370(具体型号待备注,设备详细信息查询寒武纪官网),每道题目的时间限制为1分钟。</p></div></div>
<div class="bg-gray-800/50 rounded-xl border border-gray-700 overflow-hidden"><button class="w-full p-6 text-left flex justify-between items-center hover:bg-gray-700/50 transition" onclick="toggleFaq(this)"><span class="font-semibold">如何联系组委会?</span><span class="text-yellow-400">▼</span></button><div class="faq-content px-6 pb-6"><p class="text-gray-400">可以通过邮件联系我们,详见联系我们页面。工作日 24 小时内会回复。</p></div></div>
</div>
</div>
</section>
<!-- 第7页:联系我们 -->
<section id="contact" class="page-section bg-gradient-to-b from-gray-900 via-gray-800 to-gray-900">
<div class="max-w-2xl mx-auto w-full text-center">
<h2 class="text-4xl font-bold mb-12">📬 联系我们</h2>
<div class="bg-gray-800/50 rounded-xl p-8 border border-gray-700 mb-8">
<h3 class="text-xl font-bold mb-6 text-yellow-400">联系邮箱</h3>
<div class="space-y-4">
<div class="flex items-center justify-center gap-3"><span class="text-2xl">📧</span><a href="mailto:doubh25@mail.ustc.edu.cn" class="text-lg text-blue-400 hover:text-blue-300 transition">doubh25@mail.ustc.edu.cn</a></div>
<div class="flex items-center justify-center gap-3"><span class="text-2xl">📧</span><a href="mailto:huangdi@ict.ac.cn" class="text-lg text-blue-400 hover:text-blue-300 transition">huangdi@ict.ac.cn</a></div>
</div>
</div>
<p class="text-gray-400">如有任何问题,欢迎通过邮件联系我们。<br>工作日 24 小时内会回复。</p>
<div class="mt-12 pt-8 border-t border-gray-700 text-gray-500 text-sm">Powered by Express | © 2026 Algorithm Contest. All rights reserved.</div>
</div>
</section>
<script>
let currentPage = 1;
const pageSize = 10;
let allEntries = [];
let filteredEntries = [];
let searchKeyword = '';
let cachedData = null; // 缓存数据,避免重复请求
async function loadData() {
if (cachedData) return cachedData;
try {
const res = await fetch('./data.json');
cachedData = await res.json();
return cachedData;
} catch (e) {
console.error('加载 data.json 失败:', e);
return null;
}
}
async function loadStats() {
try {
const data = await loadData();
if (data && data.stats) {
document.getElementById('participantCount').textContent = data.stats.participantCount || 0;
document.getElementById('submissionCount').textContent = data.stats.submissionCount || 0;
}
} catch (e) {
console.error('加载统计数据失败:', e);
}
}
async function loadLeaderboard() {
const container = document.getElementById('leaderboardBody');
container.innerHTML = '<div class="p-8 text-center text-gray-400">加载中...</div>';
try {
const data = await loadData();
if (data && data.entries && data.entries.length > 0) {
// 按 rank 排序(如果有的话),或按 score 降序
allEntries = data.entries.sort((a, b) => (a.rank || 0) - (b.rank || 0) || b.score - a.score);
filteredEntries = allEntries;
currentPage = 1;
renderLeaderboard();
} else {
container.innerHTML = '<div class="p-8 text-center text-gray-400">暂无数据</div>';
document.getElementById('pagination').style.display = 'none';
}
} catch (e) {
container.innerHTML = '<div class="p-8 text-center text-red-400">加载失败,请稍后重试</div>';
console.error('加载排行榜失败:', e);
}
}
function renderLeaderboard() {
const container = document.getElementById('leaderboardBody');
const dataToShow = searchKeyword ? filteredEntries : allEntries;
const totalPages = Math.ceil(dataToShow.length / pageSize);
const start = (currentPage - 1) * pageSize;
const end = start + pageSize;
const pageEntries = dataToShow.slice(start, end);
let html = '';
pageEntries.forEach((entry, index) => {
const rank = searchKeyword ? allEntries.findIndex(e => e.github === entry.github) + 1 : start + index + 1;
let rankClass = '', rankIcon = rank;
if (rank === 1) { rankClass = 'text-yellow-400'; rankIcon = '🥇'; }
else if (rank === 2) { rankClass = 'text-gray-300'; rankIcon = '🥈'; }
else if (rank === 3) { rankClass = 'text-orange-400'; rankIcon = '🥉'; }
const submitTime = entry.submitTime ? new Date(entry.submitTime).toLocaleDateString('zh-CN') : '-';
const githubUrl = `https://github.com/${entry.github}`;
html += `<div class="grid grid-cols-12 gap-4 p-4 border-b border-gray-700 hover:bg-gray-700/30 transition"><div class="col-span-2 text-center ${rankClass} font-bold">${rankIcon}</div><div class="col-span-4"><a href="${githubUrl}" target="_blank" class="text-blue-400 hover:text-blue-300 hover:underline transition">${entry.github}</a></div><div class="col-span-2 text-center font-mono text-yellow-400">${entry.score}</div><div class="col-span-2 text-center text-gray-400 text-sm">${submitTime}</div><div class="col-span-2 text-center font-mono text-gray-500 text-sm">${entry.commitHash || '-'}</div></div>`;
});
container.innerHTML = html;
document.getElementById('pageInfo').textContent = `第 ${currentPage} / ${totalPages} 页`;
document.getElementById('prevBtn').disabled = currentPage === 1;
document.getElementById('nextBtn').disabled = currentPage === totalPages;
document.getElementById('prevBtn').classList.toggle('opacity-50', currentPage === 1);
document.getElementById('nextBtn').classList.toggle('opacity-50', currentPage === totalPages);
if (totalPages <= 1) document.getElementById('pagination').style.display = 'none';
else document.getElementById('pagination').style.display = 'flex';
}
function changePage(delta) {
const totalPages = Math.ceil((searchKeyword ? filteredEntries : allEntries).length / pageSize);
const newPage = currentPage + delta;
if (newPage >= 1 && newPage <= totalPages) { currentPage = newPage; renderLeaderboard(); document.getElementById('leaderboardBody').scrollTop = 0; }
}
function searchLeaderboard() {
const input = document.getElementById('searchInput');
searchKeyword = input.value.trim().toLowerCase();
filteredEntries = searchKeyword ? allEntries.filter(entry => entry.github.toLowerCase().includes(searchKeyword)) : allEntries;
currentPage = 1;
renderLeaderboard();
if (filteredEntries.length === 0) document.getElementById('leaderboardBody').innerHTML = `<div class="p-8 text-center text-gray-400">未找到用户 "${searchKeyword}"</div>`;
}
function handleSearch(event) { if (event.key === 'Enter') searchLeaderboard(); }
function clearSearch() {
document.getElementById('searchInput').value = '';
searchKeyword = '';
filteredEntries = allEntries;
currentPage = 1;
renderLeaderboard();
}
function toggleFaq(btn) {
const content = btn.nextElementSibling;
const arrow = btn.querySelector('span:last-child');
content.classList.toggle('open');
arrow.textContent = content.classList.contains('open') ? '▲' : '▼';
}
function updateNavDots() {
const sections = document.querySelectorAll('.page-section');
const dots = document.querySelectorAll('.nav-dot');
let currentSection = 0;
sections.forEach((section, index) => { if (section.getBoundingClientRect().top <= window.innerHeight / 2) currentSection = index; });
dots.forEach((dot, index) => dot.classList.toggle('active', index === currentSection));
}
window.addEventListener('scroll', updateNavDots);
document.addEventListener('DOMContentLoaded', () => {
loadStats();
loadLeaderboard();
updateNavDots();
});
// ------- 主题切换按钮 -------
const themeBtn = document.getElementById('themeSwitchBtn');
themeBtn.addEventListener('click', () => {
document.body.classList.toggle('white-theme');
// 改变按钮文字
if (document.body.classList.contains('white-theme')) {
themeBtn.textContent = '🌙 切换深色风格';
} else {
themeBtn.textContent = '🌓 切换白色风格';
}
});
</script>
</body>
</html>