Files
TermiNexus f8d356f3ff chore(baseline): 注册 RollCall/Viper/Venom 子域与站点,补 rollcall 应用
Main.py:WHITE_HOSTS 增 rollcall/viper/venom 主机,STATIC_SITES 增 rollcall/venom 静态根,静态站点路由下 /API/ 前缀请求转交 Django 处理。

gvsds:settings.py 注册 gvsds.apps.rollcall,urls.py 挂载 API/RollCall/;新增 rollcall 应用(模型/视图/路由/迁移 + RollCallManager 数据访问层)与 TempLate/rollcall 前端站点。

.gitignore:排除 Viper/Venom 前端工程与部署产物、TempLate/FTP 二进制分发目录。
2026-09-14 12:30:06 +08:00

254 lines
11 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>课堂随机点名 · 同学点名</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700;900&family=Noto+Serif+SC:wght@600;700;900&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<!-- 顶部导航 -->
<header class="topbar">
<div class="brand">
<span class="brand-mark" aria-hidden="true">
<svg viewBox="0 0 32 32" width="28" height="28">
<rect x="3" y="6" width="26" height="20" rx="3" fill="#e8a838"/>
<rect x="3" y="6" width="26" height="6" rx="3" fill="#1a2238"/>
<circle cx="11" cy="19" r="3" fill="#f5f0e6"/>
<rect x="16" y="17" width="9" height="2" rx="1" fill="#1a2238"/>
<rect x="16" y="21" width="7" height="2" rx="1" fill="#1a2238"/>
</svg>
</span>
<h1 class="brand-title">同学点名</h1>
<span class="brand-sub">课堂随机抽取系统</span>
</div>
<nav class="tabs" role="tablist">
<button class="tab active" data-view="roll" role="tab">点名</button>
<button class="tab" data-view="settings" role="tab">设置</button>
</nav>
<div class="topbar-right">
<button class="btn btn-ghost btn-sm" id="refreshBtn" title="从服务器刷新学生名单与题库">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-3px;margin-right:4px;"><path d="M3 12a9 9 0 1 0 2.6-6.4"/><polyline points="3 4 3 10 9 10"/></svg>
刷新
</button>
<span class="count-badge" id="countBadge">0 人</span>
</div>
</header>
<main class="app">
<!-- ============ 点名视图 ============ -->
<section class="view view-roll active" id="view-roll">
<div class="roll-stage">
<!-- 抽取动画区 -->
<div class="roller" id="roller">
<div class="roller-card" id="rollerCard">
<div class="roller-avatar" id="rollerAvatar"></div>
<div class="roller-name" id="rollerName">准备就绪</div>
<div class="roller-tag" id="rollerTag">点击下方按钮开始点名</div>
</div>
</div>
<!-- 粒子层 -->
<canvas class="confetti" id="confetti" aria-hidden="true"></canvas>
<!-- 结果浮层 -->
<div class="result-toast" id="resultToast" hidden>
<div class="result-toast-inner">
<span class="result-label">本次抽中</span>
<span class="result-name" id="resultName"></span>
</div>
</div>
</div>
<!-- 多人抽取结果展示区(持久化) -->
<div class="multi-results" id="multiResults" hidden>
<div class="multi-results-head">
<span class="multi-results-title">本次抽取结果</span>
<span class="multi-results-count" id="multiResultsCount"></span>
</div>
<div class="multi-results-grid" id="multiResultsGrid"></div>
</div>
<!-- 题目结果展示区 -->
<div class="question-result" id="questionResult" hidden>
<div class="question-result-head">
<span class="qr-title">本次抽题</span>
</div>
<div class="question-display" id="questionDisplay">
<span class="question-placeholder">点击下方按钮开始抽题</span>
</div>
</div>
<!-- 模式开关 -->
<div class="mode-toggles">
<button class="mode-toggle active" data-toggle="person">
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
抽人
</button>
<button class="mode-toggle" data-toggle="question">
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg>
抽题
</button>
</div>
<!-- 控制栏 -->
<div class="controls">
<div class="person-controls" id="personControls">
<div class="mode-switch" id="modeSwitch">
<button class="mode-btn active" data-mode="single">单人抽取</button>
<button class="mode-btn" data-mode="multi">多人抽取</button>
<button class="mode-btn" data-mode="norepeat">不重复抽取</button>
</div>
<div class="group-filter">
<label class="group-label">分组</label>
<select class="group-select" id="groupSelect">
<option value="">全部学生</option>
</select>
</div>
</div>
<div class="question-controls" id="questionControls" hidden>
<select class="subject-select" id="subjectSelect">
<option value="">全部学科</option>
</select>
<label class="check-inline">
<input type="checkbox" id="questionNoRepeat" />
<span>不重复</span>
</label>
</div>
<button class="btn btn-primary btn-lg" id="rollBtn">
<span class="btn-icon">
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><polygon points="6 4 20 12 6 20 6 4"/></svg>
</span>
<span class="btn-text">开始</span>
</button>
<button class="btn btn-ghost" id="resetBtn" title="重置已抽中记录">
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 1 0 3-6.7"/><polyline points="3 4 3 10 9 10"/></svg>
重置
</button>
</div>
<!-- 多人抽取数量 -->
<div class="multi-config" id="multiConfig" hidden>
<label>抽取人数</label>
<div class="stepper">
<button class="step-btn" id="stepDown">−</button>
<span class="step-val" id="stepVal">3</span>
<button class="step-btn" id="stepUp">+</button>
</div>
</div>
<!-- 学生卡片墙 -->
<div class="wall-section">
<div class="section-head">
<h2 class="section-title">学生名单</h2>
<div class="wall-filter">
<button class="filter-btn active" data-filter="all">全部 <span id="cntAll">0</span></button>
<button class="filter-btn" data-filter="pending">待抽 <span id="cntPending">0</span></button>
<button class="filter-btn" data-filter="picked">已抽 <span id="cntPicked">0</span></button>
</div>
</div>
<div class="wall" id="wall"></div>
<div class="empty-state" id="wallEmpty" hidden>
<p>暂无学生数据</p>
<button class="btn btn-ghost" id="loadDemoBtn">加载示例数据</button>
</div>
</div>
<!-- 历史记录 -->
<div class="history-section" id="historySection">
<div class="section-head">
<h2 class="section-title">本次课堂记录</h2>
<button class="btn btn-ghost btn-sm" id="clearHistoryBtn">清空</button>
</div>
<div class="history-list" id="historyList"></div>
<div class="history-empty" id="historyEmpty">尚未抽取</div>
</div>
</section>
<!-- ============ 设置视图 ============ -->
<section class="view view-settings" id="view-settings">
<h2 class="section-title">设置</h2>
<div class="settings-card">
<h3 class="settings-group-title">抽取行为</h3>
<div class="setting-row">
<div class="setting-label">
<span class="setting-name">动画速度</span>
<span class="setting-desc">控制抽取动画的快慢</span>
</div>
<div class="setting-control">
<input type="range" id="speedRange" min="1" max="5" value="3" class="slider" />
<span class="setting-val" id="speedVal">标准</span>
</div>
</div>
<div class="setting-row">
<div class="setting-label">
<span class="setting-name">音效</span>
<span class="setting-desc">抽取时播放提示音</span>
</div>
<div class="setting-control">
<label class="switch">
<input type="checkbox" id="soundToggle" />
<span class="switch-track"><span class="switch-thumb"></span></span>
</label>
</div>
</div>
<div class="setting-row">
<div class="setting-label">
<span class="setting-name">自动记录历史</span>
<span class="setting-desc">将每次抽取结果记入课堂记录</span>
</div>
<div class="setting-control">
<label class="switch">
<input type="checkbox" id="historyToggle" checked />
<span class="switch-track"><span class="switch-thumb"></span></span>
</label>
</div>
</div>
</div>
<div class="settings-card">
<h3 class="settings-group-title">数据管理</h3>
<div class="setting-row">
<div class="setting-label">
<span class="setting-name">管理控制台</span>
<span class="setting-desc">学生与题目管理已迁移至管理员端</span>
</div>
<div class="setting-control">
<a class="btn btn-ghost btn-sm" href="./admin/" target="_blank" rel="noopener">前往管理端</a>
</div>
</div>
<div class="setting-row">
<div class="setting-label">
<span class="setting-name">示例数据</span>
<span class="setting-desc">加载一组示例学生用于体验</span>
</div>
<div class="setting-control">
<button class="btn btn-ghost btn-sm" id="loadDemoBtn2">加载示例</button>
</div>
</div>
<div class="setting-row">
<div class="setting-label">
<span class="setting-name">清空所有数据</span>
<span class="setting-desc">删除全部学生与课堂记录(不可恢复)</span>
</div>
<div class="setting-control">
<button class="btn btn-danger btn-sm" id="clearAllBtn">清空</button>
</div>
</div>
</div>
<p class="settings-foot">数据保存在浏览器本地 (localStorage),不会上传服务器。</p>
</section>
</main>
<!-- Toast 提示 -->
<div class="toast" id="toast" hidden></div>
<script src="script.js"></script>
</body>
</html>