You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

205 lines
7.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-scale, initial-scale=1.0">
<title>学生点名系统</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
background: linear-gradient(to bottom right, #e0f7fa, #fce4ec); /* 柔和的渐变背景色 */
color: #333; /* 调整文本颜色以增加可读性 */
display: flex; /* 使用 flexbox */
flex-direction: column; /* 垂直排列 */
align-items: center; /* 水平居中 */
}
#students, #calledList { margin-top: 20px; }
#result { font-weight: bold; margin-top: 10px; }
.called-student { color: rgb(254, 2, 2); }
.btn {
padding: 10px 15px;
margin: 10px 0;
border: none;
border-radius: 5px;
background-color: #ffab40; /* 按钮背景颜色 */
color: white;
cursor: pointer;
transition: background-color 0.3s ease;
font-family: "kaiti";
font-size: 35px;
}
.btn:hover {
background-color: #ff9800; /* 悬停时的按钮背景颜色 */
}
@keyframes gradient-animation {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
h1 {
text-align: center;
font-weight: bolder;
font-size: 80px;
background: linear-gradient(45deg, #ff6b6b, #f7c24a);
background-size: 400% 400%;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
animation: gradient-animation 3s ease infinite;
background-clip: text; /* 标准属性 */
color: transparent; /* 标准属性 */
font-family: "kaiti";
}
.file-upload-container {
display: flex; /* 使用 flexbox */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
flex-direction: column; /* 垂直排列 */
margin: 20px 0; /* 添加间距 */
}
</style>
</head>
<body>
<h1>学生点名系统</h1>
<input type="file" id="fileInput" class="btn"/>
<button id="uploadBtn" class="btn">上传学生名单</button>
<div id="students"></div>
<button id="rollcallBtn" style="display: none;" class="btn">随机点名</button>
<button id="resetBtn" style="display: none;" class="btn">重置点名状态</button>
<button id="lotteryBtn" style="display: none;" class="btn">幸运抽奖</button>
<div id="result"></div>
<div id="calledList"></div>
<!-- 积分操作按钮 -->
<div id="scoreActions" style="display: none;">
<button id="arriveBtn" class="btn">抵达教室</button>
<button id="repeatCorrectBtn" class="btn">重复问题</button>
<button id="repeatWrongBtn" class="btn">重复错误</button>
<button id="accurateAnswerBtn" class="btn">准确回答</button>
</div>
<script>
let allStudents = []; // 存储所有学生
let calledStudents = []; // 存储已点名的学生 ID
let currentStudentId = null; // 当前被点名学生的 ID
document.getElementById('uploadBtn').onclick = async () => {
const fileInput = document.getElementById('fileInput');
const formData = new FormData();
formData.append('file', fileInput.files[0]);
const response = await fetch('http://localhost:3000/upload', {
method: 'POST',
body: formData,
});
const result = await response.json();
if (response.ok) {
allStudents = result.students;
calledStudents = [];
document.getElementById('rollcallBtn').style.display = 'block';
document.getElementById('resetBtn').style.display = 'block';
document.getElementById('lotteryBtn').style.display = 'block';
document.getElementById('calledList').innerHTML = ''; // 清空已点名列表
document.getElementById('scoreActions').style.display = 'none'; // 隐藏积分操作
} else {
alert(result.message);
}
};
document.getElementById('rollcallBtn').onclick = async () => {
if (calledStudents.length === allStudents.length) {
alert("所有学生都已被点名,请重置点名状态!");
return;
}
const response = await fetch('http://localhost:3000/rollcall');
const student = await response.json();
if (response.ok) {
currentStudentId = student.id;
document.getElementById('result').innerText = `被点到的学生: ${student.id} - ${student.name}`;
calledStudents.push(student.id);
const calledList = document.getElementById('calledList');
calledList.innerHTML += `<div class="called-student">${student.id} - ${student.name}</div>`;
document.getElementById('scoreActions').style.display = 'block'; // 显示积分操作按钮
} else {
alert(student.message);
}
};
document.getElementById('resetBtn').onclick = () => {
calledStudents = []; // 重置已点名数组
currentStudentId = null; // 清空当前点名学生 ID
document.getElementById('result').innerText = '';
document.getElementById('calledList').innerHTML = ''; // 清空已点名列表
document.getElementById('scoreActions').style.display = 'none'; // 隐藏积分操作
alert("已重置点名状态!");
};
// 积分操作
document.getElementById('arriveBtn').onclick = async () => {
await updateScore({ isInClass: true });
};
document.getElementById('repeatCorrectBtn').onclick = async () => {
await updateScore({ isQuestionCorrect: true });
};
document.getElementById('repeatWrongBtn').onclick = async () => {
await updateScore({ isQuestionCorrect: false });
};
document.getElementById('accurateAnswerBtn').onclick = async () => {
const score = prompt("请输入分数0.5 - 3:");
if (score !== null && !isNaN(score)) {
await updateScore({ isAnswerCorrect: true, score: parseFloat(score) });
}
};
document.getElementById('lotteryBtn').onclick = async () => {
const response = await fetch('http://localhost:3000/lottery', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ id: currentStudentId })
});
const result = await response.json();
if (response.ok) {
alert(`幸运抽奖结果: ${result.message}`);
} else {
alert(result.message);
}
};
async function updateScore(scoreData) {
const response = await fetch('http://localhost:3000/update-score', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: currentStudentId,
...scoreData
})
});
const result = await response.json();
if (response.ok) {
alert(`积分已更新: ${result.score}`);
} else {
alert(result.message);
}
}
</script>
</body>
</html>