智能随机点名系统
创作时间:
作者:
@小白创作中心
智能随机点名系统
引用
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、就可以看到这个点名系统了
热门推荐
从杨贵妃的宫廷秘方到现代养生:泡脚养生的前世今生
薰衣草泡脚,助你一夜好眠
苦参:脚气治疗的天然良方
苦参土槿皮:脚气治疗的良药还是“救星”?
Nature Aging最新研究:更年期与健康衰老的科学新发现
河南拔智齿,搞笑文案大集合
全国根治欠薪平台:农民工讨薪的利器
红法官教你如何合法追讨欠薪
更年期中医养生指南:这些方法值得收藏!
“河南拔智齿”梗爆火,背后竟是这样?
“河南拔智齿”梗爆火,背后的心理学解读
财报季来了,教你读懂上市公司损益表
损益表优化:让企业运营更高效
企业财报季,掌握损益表编制秘籍
《肖申克的救赎》:那些触动人心的经典台词
郑大一附院口腔科:专业智齿拔除,舒适就医体验
《阿甘正传》台词挑战:让英语口语飞起来!
《卧虎藏龙》台词里的中国风
《肖申克的救赎》台词:写作灵感的最佳源泉
怀化“旅游金三角”旅游专线正式开通,串联三大人文景点
无痛微创拔牙技术,让你告别智齿烦恼
武汉大学口腔医院教你无痛拔智齿
博仁牙科部推荐:智齿拔除后护理秘籍
腊月二十五:做豆腐,寄寓新年富贵
闲鱼&转转理财防骗指南:教你识破诈骗套路
销售必备:提升沟通技巧,赢在每一次交流
顺德清晖园探秘,美食打卡不容错过!
董宇辉直播探秘顺德清晖园:一场美食与文化的盛宴
顺德清晖园:岭南园林打卡胜地
北京双鹭药业教你正确使用溶菌酶含片