智能随机点名系统
创作时间:
作者:
@小白创作中心
智能随机点名系统
引用
CSDN
1.
https://m.blog.csdn.net/weixin_47139678/article/details/145889919
在日常教学、会议签到、活动抽奖等场景中,随机点名系统是一个非常实用的工具。本文将介绍一个基于HTML、CSS和JavaScript实现的智能随机点名系统的代码实现,并详细描述其功能和应用场景。
一、系统功能概述
这个智能随机点名系统主要具备以下功能:
- 添加姓名:用户可以通过输入框手动输入姓名并添加到点名列表中。
- 导入Excel:支持从Excel文件(.csv或.xlsx格式)中批量导入姓名,方便快捷地录入大量数据。
- 随机点名:从已录入的姓名列表中随机抽取一个名字作为结果显示,同时提供了一个动画效果,增加趣味性。
- 删除姓名:可以单个删除指定的姓名,也支持批量删除已选中的姓名。
- 全选和取消全选:提供了全选和取消全选的功能,方便用户进行批量操作。
- 状态显示:实时显示当前点名列表中的人数,并且根据列表的状态动态更新操作按钮的可用性。
- 本地存储:系统使用本地存储(localStorage)来保存点名列表,确保数据在页面刷新或关闭后仍然存在。
二、代码结构分析
HTML结构:页面采用了简洁的布局,包含一个输入框、几个按钮、一个显示点名列表的无序列表、一个显示结果的区域以及一个状态显示条。通过不同的类名(如.container、.input-group、.name-list等)来组织和样式化各个元素。
CSS样式:使用了CSS变量(--primary-color、--secondary-color、--background)来定义主要的颜色,方便统一管理和修改。通过对不同类名的样式设置,实现了页面的美观和交互效果,如按钮的悬停效果、列表项的高亮效果等。
JavaScript逻辑:
- 初始化和数据存储:在页面加载时,从本地存储中读取已保存的姓名列表,并初始化页面显示。通过saveToStorage函数将更新后的列表保存到本地存储中。
- 添加和删除姓名:addName函数负责将新的姓名添加到列表中,deleteName函数用于删除指定的姓名。在添加或删除操作后,会更新列表显示、保存数据到本地存储,并根据列表状态更新按钮的可用性。
- 批量操作:toggleSelection函数用于处理复选框的选中和取消选中状态,selectAll函数实现全选和取消全选的功能,batchDelete函数用于批量删除已选中的姓名。
- Excel导入:handleFile函数通过FileReader和xlsx库读取Excel文件内容,并将其中的姓名添加到点名列表中。在导入过程中,会显示一个加载提示,导入完成后更新列表和相关状态。
- 随机点名:randomPick函数实现了随机点名的功能,通过一个动画效果在列表中快速切换姓名,最后随机抽取一个作为结果显示,并高亮显示选中的姓名。
三、应用场景
- 教学场景:教师可以使用该系统随机抽取学生回答问题,增加课堂互动性和公平性。
- 会议签到:在会议开始前,参会人员的姓名可以录入系统,会议过程中可以随机抽取参会人员进行发言或提问。
- 活动抽奖:在各种活动中,将参与者的姓名录入系统,通过随机点名来确定中奖者,增加活动的趣味性和公正性。
四、安装这个代码
- 新建一个.txt文件
- 然后复制下面全部代码到这个dm.txt中
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>智能随机点名系统</title>
<style>
:root {
--primary-color: #2196F3;
--secondary-color: #ff4081;
--background: #f5f5f5;
}
body {
font-family: 'Microsoft Yahei', Arial, sans-serif;
background: var(--background);
margin: 0;
padding: 20px;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
padding: 30px;
}
.header {
text-align: center;
margin-bottom: 30px;
}
.input-group {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
input[type="text"] {
flex: 1;
padding: 12px;
border: 2px solid #ddd;
border-radius: 6px;
transition: border-color 0.3s;
}
input[type="text"]:focus {
border-color: var(--primary-color);
outline: none;
}
button {
padding: 12px 24px;
border: none;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s;
background: var(--primary-color);
color: white;
}
button:hover {
opacity: 0.9;
transform: translateY(-1px);
}
button:disabled {
background: #ccc;
cursor: not-allowed;
}
.file-input {
position: relative;
display: inline-block;
}
.file-input input[type="file"] {
position: absolute;
left: 0;
top: 0;
opacity: 0;
width: 100%;
height: 100%;
cursor: pointer;
}
.name-list {
list-style: none;
padding: 0;
margin: 20px 0;
border: 2px solid #eee;
border-radius: 8px;
max-height: 300px;
overflow-y: auto;
}
.name-list li {
padding: 15px;
margin: 0;
border-bottom: 1px solid #eee;
display: flex;
justify-content: space-between;
align-items: center;
transition: all 0.3s;
}
.name-list li:last-child {
border-bottom: none;
}
.name-list li:hover {
background: #f8f9fa;
}
.name-list .name-content {
flex: 1;
margin-left: 10px;
}
.highlight {
background: #fff3e0 !important;
font-weight: bold;
}
.result-box {
text-align: center;
padding: 30px;
margin: 20px 0;
background: #f8f9fa;
border-radius: 8px;
min-height: 100px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
color: var(--primary-color);
transition: all 0.3s;
}
@keyframes spin {
0% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.2); opacity: 0.8; }
100% { transform: scale(1); opacity: 1; }
}
.spinning {
animation: spin 0.1s infinite;
color: var(--secondary-color);
}
.status-bar {
text-align: right;
color: #666;
font-size: 14px;
margin-top: 20px;
}
.delete-btn {
background: var(--secondary-color);
padding: 6px 12px;
font-size: 12px;
}
.loading {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(255, 255, 255, 0.8);
justify-content: center;
align-items: center;
z-index: 1000;
}
.loading.active {
display: flex;
}
.batch-actions {
display: flex;
gap: 10px;
margin-bottom: 10px;
}
.delete-all-btn {
background: var(--secondary-color);
}
.name-checkbox {
margin-right: 10px;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎉 智能随机点名系统</h1>
</div>
<div class="input-group">
<input type="text" id="nameInput" placeholder="请输入姓名...">
<button onclick="addName()">➕ 添加</button>
<div class="file-input">
<button>📁 导入Excel</button>
<input type="file" id="excelFile" accept=".csv,.xlsx" onchange="handleFile()">
</div>
<button onclick="randomPick()" id="pickBtn" disabled>🎮 开始点名</button>
</div>
<div class="batch-actions">
<button onclick="selectAll()" id="selectAllBtn">全选</button>
<button onclick="batchDelete()" class="delete-all-btn" id="batchDeleteBtn" disabled>批量删除</button>
</div>
<ul class="name-list" id="nameList"></ul>
<div class="result-box" id="result">
👇 点击上方按钮开始
</div>
<div class="status-bar">
当前人数: <span id="count">0</span>
</div>
</div>
<div class="loading" id="loading">
<div style="font-size: 24px; color: var(--primary-color)">⏳ 正在导入数据...</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.17.5/xlsx.full.min.js"></script>
<script>
// 初始化本地存储
let names = JSON.parse(localStorage.getItem('names')) || [];
let isSpinning = false;
let selectedNames = [];
// 页面加载时初始化列表
window.onload = () => {
renderList();
updateButtonState();
updateCount();
};
function saveToStorage() {
localStorage.setItem('names', JSON.stringify(names));
updateCount();
}
function updateCount() {
document.getElementById('count').textContent = names.length;
}
function updateButtonState() {
const pickBtn = document.getElementById('pickBtn');
pickBtn.disabled = names.length < 2;
const batchDeleteBtn = document.getElementById('batchDeleteBtn');
batchDeleteBtn.disabled = selectedNames.length === 0;
}
function renderList() {
const list = document.getElementById('nameList');
list.innerHTML = names.map(name => `
<li>
<input type="checkbox" class="name-checkbox" onchange="toggleSelection('${name}', this.checked)">
<span class="name-content">${name}</span>
<button class="delete-btn" onclick="deleteName('${name}')">删除</button>
</li>
`).join('');
selectedNames = [];
updateButtonState();
}
function addName(name) {
const nameToAdd = name || document.getElementById('nameInput').value.trim();
if (nameToAdd && !names.includes(nameToAdd)) {
names.push(nameToAdd);
renderList();
document.getElementById('nameInput').value = '';
saveToStorage();
updateButtonState();
}
}
function deleteName(name) {
names = names.filter(n => n !== name);
selectedNames = selectedNames.filter(n => n !== name);
renderList();
saveToStorage();
updateButtonState();
}
function toggleSelection(name, isChecked) {
if (isChecked) {
if (!selectedNames.includes(name)) {
selectedNames.push(name);
}
} else {
selectedNames = selectedNames.filter(n => n !== name);
}
updateButtonState();
}
function selectAll() {
const checkboxes = document.querySelectorAll('.name-checkbox');
const selectAllBtn = document.getElementById('selectAllBtn');
// 检查是否所有都已选中
const allSelected = selectedNames.length === names.length;
if (allSelected) {
// 如果全部已选中,则取消全选
checkboxes.forEach(cb => cb.checked = false);
selectedNames = [];
selectAllBtn.textContent = '全选';
} else {
// 否则全选
checkboxes.forEach(cb => cb.checked = true);
selectedNames = [...names];
selectAllBtn.textContent = '取消全选';
}
updateButtonState();
}
function batchDelete() {
if (selectedNames.length === 0) return;
if (confirm(`确定要删除选中的 ${selectedNames.length} 个名字吗?`)) {
names = names.filter(name => !selectedNames.includes(name));
selectedNames = [];
renderList();
saveToStorage();
updateButtonState();
}
}
async function handleFile() {
const file = document.getElementById('excelFile').files[0];
if (!file) return;
document.getElementById('loading').classList.add('active');
const reader = new FileReader();
reader.onload = async function(e) {
const data = new Uint8Array(e.target.result);
const workbook = XLSX.read(data, {type: 'array'});
const sheet = workbook.Sheets[workbook.SheetNames[0]];
const json = XLSX.utils.sheet_to_json(sheet);
json.forEach(row => {
const name = Object.values(row)[0]?.toString().trim();
if (name && !names.includes(name)) {
names.push(name);
}
});
renderList();
saveToStorage();
updateButtonState();
document.getElementById('loading').classList.remove('active');
};
reader.readAsArrayBuffer(file);
}
function randomPick() {
if (isSpinning || names.length < 2) return;
isSpinning = true;
const resultDiv = document.getElementById('result');
const btn = document.getElementById('pickBtn');
btn.disabled = true;
let currentIndex = 0;
let interval = 50;
let rounds = 15;
resultDiv.classList.add('spinning');
const animate = () => {
resultDiv.textContent = names[currentIndex];
currentIndex = (currentIndex + 1) % names.length;
if (rounds-- > 0) {
interval += 10;
setTimeout(animate, interval);
} else {
const winner = names[Math.floor(Math.random() * names.length)];
resultDiv.textContent = `🎉 中奖者: ${winner}`;
resultDiv.classList.remove('spinning');
btn.disabled = false;
isSpinning = false;
document.querySelectorAll('#nameList li').forEach(li => {
li.classList.toggle('highlight', li.querySelector('.name-content').textContent.includes(winner));
});
}
};
setTimeout(animate, interval);
}
</script>
</body>
</html>
然后将dm.txt修改为dm.html
然后双击运行这个html文件
5、就可以看到这个点名系统了
热门推荐
如何计算个人负债率?负债率在财务健康中有哪些评估和调整策略?
实例讲解CANoe报文解析使用方法
硇砂是什么中药?功效与使用方法全解析
教育技术:跨学科融合推动学习体验变革与提升的探索之路
为什么炫富是罪行:从法律视角解析其违法性和社会危害
化工企业废气治理:八大方案助力绿色发展
凸函数与凹函数:定义、判定方法及应用
Excel中求两条线交点的三种方法
《怪物猎人》系列发展史:传承与革新的辉煌篇章
INFP性格特质、优势与挑战、内心世界、成长路径、潜能及职业适配性
小麦2035:未来小麦基础研究与育种创新
如何查询并维护个人征信记录,确保信用健康与安全
四川中职学校五星学校评级标准详解
品味AK47 感受步枪之王的力量
突发 | Sarah Burton上任Givenchy创意总监
平面度测量方法有哪些?工业应用中的实用技巧
家用电梯常见故障解析与维护指南
光疗生物学效应+白癜风
2024-2025年中国虚拟现实产业发展及趋势分析报告
生理期运动指南:听从身体的感受
“DeepSeek接入潮” 带动国内算力需求急涨
有氧运动多长时间才有效果?
小米需要“铁大”,人形机器人需要小米吗?
诺如病毒和肠胃炎潜伏期多久会传染吗为什么
劳动合同签订:报到即开始生效
辩论会主题:正方VS反方,哪个观点更胜一筹?
跨境电商的主要模式有哪些?每种模式的特点是什么?
洼田饮水试验评定量表及操作流程
2024年最成功的四款75英寸电视,基础体验让人满意,价格并不昂贵
探讨胃脘不适的原因与应对策略