This commit is contained in:
Evan
2026-09-07 09:55:36 +08:00
parent 9b6892f2ed
commit badbc11154
9098 changed files with 985321 additions and 0 deletions

View File

@@ -0,0 +1,327 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>001CODE-赛练平台</title>
<link rel="stylesheet" href="css/competition-v2.css?v=<%= htmlWebpackPlugin.options.version %>" media="screen">
<link rel="stylesheet" href="css/competition_sum-v2.css?v=<%= htmlWebpackPlugin.options.version %>" media="screen">
<script class="u-script" type="text/javascript" src="js/jquery.js?v=<%= htmlWebpackPlugin.options.version %>"
defer></script>
</head>
<body>
<div class="page">
<main class="content">
<!-- Left Column: Leaderboard -->
<div class="left-column" style="display:flex; flex-direction:column; gap:24px; min-width: 0; width: 100%;">
<section class="card ranking-card">
<header class="card-header">
<h1 class="title">
<svg class="trophy-icon" xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M6 9H4.5a2.5 2.5 0 0 1 0-5H6"></path>
<path d="M18 9h1.5a2.5 2.5 0 0 0 0-5H18"></path>
<path d="M4 22h16"></path>
<path d="M10 14.66V17c0 .55-.47.98-.97 1.21C7.85 18.75 7 20.24 7 22"></path>
<path d="M14 14.66V17c0 .55.47.98.97 1.21C16.15 18.75 17 20.24 17 22"></path>
<path d="M18 2H6v7a6 6 0 0 0 12 0V2Z"></path>
</svg>
排行榜
</h1>
<div class="refresh-info">
实时排行榜 <span id="refresh-countdown" class="refresh-timer">30s</span> <span id="time"
class="refresh-timer"></span>
</div>
</header>
<div class="table-container">
<table class="custom-table">
<thead>
<tr>
<th style="width: 60px; text-align: center;">排名</th>
<th>姓名</th>
<th>学校</th>
<th>完成数量</th>
<th>代码总数</th>
<th>角色总步数</th>
</tr>
</thead>
<tbody id="leaderboard-body">
<!-- JS will populate -->
<tr>
<td colspan="6" style="text-align:center; padding: 20px; color: #94a3b8;">正在加载排行榜数据...</td>
</tr>
</tbody>
</table>
</div>
<!-- Search & Pagination moved inside Leaderboard Card -->
<div class="table-footer">
<div class="search-form-inline">
<label for="input-search">搜索用户:</label>
<input type="text" id="input-search" name="fullname" class="form-input-small" placeholder="输入姓名">
<button type="button" id="btn-search" class="form-btn-small">搜索</button>
<input type="hidden" id="email-2132">
</div>
<div id="page_num" class="pagination-container">
<!-- JS populates this -->
</div>
</div>
</section>
<!-- User Rank Table -->
<section class="card ranking-card">
<div class="table-container">
<table class="custom-table">
<thead>
<tr>
<th style="width: 60px; text-align: center;">排名</th>
<th>姓名</th>
<th>学校</th>
<th>完成数量</th>
<th>代码总数</th>
<th>角色总步数</th>
</tr>
</thead>
<tbody id="user-rank-body">
<tr>
<td class="rank-cell">-</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
</tr>
</tbody>
</table>
</div>
</section>
</div>
<!-- Right Column: Sidebar -->
<div class="right-column" style="display:flex; flex-direction:column; gap:24px;">
<!-- Countdown & Actions -->
<section class="card">
<h2 class="widget-title" id="countdown-title">
剩余时间
<span class="timer-icon"></span>
</h2>
<div id="custom-countdown" class="countdown-container">
<div class="countdown-item"><span class="countdown-value" id="countdown-days">00</span><span
class="countdown-label">日</span></div>
<div class="countdown-separator">:</div>
<div class="countdown-item"><span class="countdown-value" id="countdown-hours">00</span><span
class="countdown-label">时</span></div>
<div class="countdown-separator">:</div>
<div class="countdown-item"><span class="countdown-value" id="countdown-minutes">00</span><span
class="countdown-label">分</span></div>
<div class="countdown-separator">:</div>
<div class="countdown-item"><span class="countdown-value" id="countdown-seconds">00</span><span
class="countdown-label">秒</span></div>
</div>
<div class="action-buttons">
<button id="btn-start" class="full-width-btn u-btn-3">开始活动</button>
<button id="btn-exit" class="full-width-btn secondary">退出平台</button>
</div>
</section>
<!-- Announcement -->
<section class="card">
<h2 class="widget-title">公告</h2>
<div class="announcement-box">
<a id="competition-announcement" style="text-decoration: none; color: inherit; display: block;"></a>
</div>
</section>
<!-- Camera -->
<section class="card" style="display: none;">
<div id="camera-container" class="camera-wrapper">
<div class="camera-placeholder">摄像头画面</div>
</div>
<button id="btn-camera" class="full-width-btn">开启摄像头</button>
<p
style="font-size: 12px; color: #64748b; margin-top: 10px; text-align: center; display: flex; align-items: center; justify-content: center; gap: 4px;">
<span>📷</span> 摄像头在考试过程中将全程监考
</p>
</section>
</div>
</main>
<!-- Footer -->
<footer>
<div class="footer-line"></div>
<p class="footer-text">ICP备案号<a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener" style="color:#478ac9 ;">沪ICP备2026042325号</a>
<!-- 公安备案号:<a href="https://beian.mps.gov.cn/" target="_blank" style="color:#478ac9 ;">川公网安备51011202000980号</a> -->
© 灵丌编程001CODE.COM</p>
</footer>
</div>
<!-- Floating Elements -->
<div id="back-to-main" class="floating-back-button">
<a href="/login.html" class="back-link">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="m12 19-7-7 7-7" />
<path d="M19 12H5" />
</svg>
<span>返回主站</span>
</a>
</div>
<div id="floating-user-name" class="floating-user-name">
<div class="user-chip">
<span id="current-user-name-text"></span>
</div>
</div>
<!-- Confirm Start Modal -->
<div id="start-competition-modal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h2>开始比赛确认</h2>
<span class="close-modal">×</span>
</div>
<div class="modal-body">
<!-- Content populated by JS or simple text -->
<p>确定要开始比赛吗?</p>
</div>
<div class="modal-footer">
<button id="confirm-start-competition" class="modal-btn confirm-btn">确认开始</button>
<button id="cancel-start-competition" class="modal-btn cancel-btn">取消</button>
</div>
</div>
</div>
<!-- Competition End / Alert Modal -->
<div id="competition-end-modal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h2>提示</h2>
<span class="close-modal" id="competition-end-close">×</span>
</div>
<div class="modal-body">
<p id="competition-end-message">提示信息</p>
</div>
<div class="modal-footer">
<button id="competition-end-ok" class="modal-btn confirm-btn close-modal">确定</button>
</div>
</div>
</div>
<script>
// Include drag logic for floating buttons (Adapted from original file)
document.addEventListener('DOMContentLoaded', function () {
// Logic for user name already in competition_sum.js?
// check competition_sum.js line 469. It sets 'current-user-name-text' content.
const floatingButton = document.getElementById('back-to-main');
setupDraggable(floatingButton);
const floatingUser = document.getElementById('floating-user-name');
setupDraggable(floatingUser);
function setupDraggable(element) {
if (!element) return;
let isDragging = false;
let startX, startY, startLeft, startTop;
element.addEventListener('mousedown', function (e) {
if (e.target.tagName === 'A' || e.target.closest('a')) return;
isDragging = true;
startX = e.clientX;
startY = e.clientY;
const rect = element.getBoundingClientRect();
startLeft = rect.left;
startTop = rect.top;
element.style.position = 'fixed';
element.style.left = startLeft + 'px';
element.style.top = startTop + 'px';
element.style.right = 'auto'; // Disable right positioning after drag starts
element.style.bottom = 'auto';
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
e.preventDefault();
});
function handleMouseMove(e) {
if (!isDragging) return;
const deltaX = e.clientX - startX;
const deltaY = e.clientY - startY;
let newLeft = startLeft + deltaX;
let newTop = startTop + deltaY;
const rect = element.getBoundingClientRect();
newLeft = Math.max(0, Math.min(newLeft, window.innerWidth - rect.width));
newTop = Math.max(0, Math.min(newTop, window.innerHeight - rect.height));
element.style.left = newLeft + 'px';
element.style.top = newTop + 'px';
}
function handleMouseUp() {
isDragging = false;
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
}
// Touch support (basic)
element.addEventListener('touchstart', function (e) {
if (e.target.tagName === 'A' || e.target.closest('a')) return;
isDragging = true;
const touch = e.touches[0];
startX = touch.clientX;
startY = touch.clientY;
const rect = element.getBoundingClientRect();
startLeft = rect.left;
startTop = rect.top;
element.style.position = 'fixed';
element.style.left = startLeft + 'px';
element.style.top = startTop + 'px';
element.style.right = 'auto';
element.style.bottom = 'auto';
e.preventDefault();
}, { passive: false });
element.addEventListener('touchmove', function (e) {
if (!isDragging) return;
const touch = e.touches[0];
const deltaX = touch.clientX - startX;
const deltaY = touch.clientY - startY;
let newLeft = startLeft + deltaX;
let newTop = startTop + deltaY;
element.style.left = newLeft + 'px';
element.style.top = newTop + 'px';
e.preventDefault();
}, { passive: false });
element.addEventListener('touchend', function () { isDragging = false; });
}
// Modal close logic (competition-v2 style)
document.querySelectorAll('.close-modal, .cancel-btn').forEach(btn => {
btn.addEventListener('click', function () {
const modal = this.closest('.modal');
if (modal) modal.style.display = 'none';
});
});
// Close modal on outside click
window.addEventListener('click', function (e) {
if (e.target.classList.contains('modal')) {
e.target.style.display = 'none';
}
});
});
</script>
</body>
</html>