Compare commits

..

36 Commits
前端 ... main

Author SHA1 Message Date
luoyonghuang d290f6744e Delete '前端'
10 months ago
luoyonghuang 82aa9e4ed3 ADD file via upload
10 months ago
luoyonghuang 971a2fcd0d Update README.md
10 months ago
luoyonghuang f4d5f0b802 Update README.md
10 months ago
luoyonghuang 095fe641df Update README.md
10 months ago
luoyonghuang 028c57a3f8 Update classManager.js
10 months ago
luoyonghuang 32e96d8b03 ADD file via upload
10 months ago
luoyonghuang 1c143b8e77 ADD file via upload
10 months ago
luoyonghuang 285bcf0f92 Update select.html
10 months ago
luoyonghuang 1fa4bf0c55 Update score_display.html
10 months ago
luoyonghuang a4cf04db29 Update scoreManager.js
10 months ago
luoyonghuang acb2e42f98 Update router.js
10 months ago
luoyonghuang 634077c7e9 Update ranking.js
10 months ago
luoyonghuang 2b465511d1 Update lottery.html
10 months ago
luoyonghuang d9960ef64c Update index.html
10 months ago
luoyonghuang 9a54ab08f0 Update dianming.html
10 months ago
luoyonghuang a10f391f85 Update choice.html
10 months ago
luoyonghuang 06e46f5383 Update answer.html
10 months ago
luoyonghuang f940e22722 Delete '111'
10 months ago
luoyonghuang 526bc16392 Delete 'services'
10 months ago
luoyonghuang 1b397ecc5e ADD file via upload
10 months ago
luoyonghuang a53a54d811 Delete 'pu'
10 months ago
luoyonghuang f6656d94d3 ADD file via upload
10 months ago
luoyonghuang fcc3bda958 Update randomSelect.js
10 months ago
pg7s85mrc 873b9a982d Merge pull request '合并' (#1) from 123 into main
10 months ago
luoyonghuang a1365dd77f Update db.js
10 months ago
luoyonghuang 77f39dc63d Update classManager.js
10 months ago
luoyonghuang d272070c75 Delete 'app.js'
10 months ago
luoyonghuang 979aab6fc1 ADD file via upload
10 months ago
luoyonghuang b3f4447d5c ADD file via upload
10 months ago
luoyonghuang 05932c3195 ADD file via upload
10 months ago
luoyonghuang 16a1e5ca41 ADD file via upload
10 months ago
luoyonghuang 6b67287b04 ADD file via upload
10 months ago
luoyonghuang c136816000 ADD file via upload
10 months ago
luoyonghuang 8d1ddb46c4 ADD file via upload
10 months ago
luoyonghuang 5adf8cf862 ADD file via upload
10 months ago

@ -1,2 +1,3 @@
# select_random ###html属于前端部分
###js属于后端部分

@ -47,40 +47,153 @@
<body> <body>
<div class="container"> <div class="container">
<div id="question">你需要回答问题 结果是:</div> <div id="question">请重复问题,选择正确或错误:</div>
<button id="correctButton">正确</button> <button id="repeatCorrectButton">准确重复</button>
<button id="wrongButton">错误</button> <button id="repeatWrongButton">未准确重复</button>
<div id="questionResult"></div> <!-- 显示重复问题的结果 -->
<div id="answerContainer" style="display:none;">
<p>现在回答问题:</p>
<button id="correctButton">回答正确</button>
<button id="partiallyCorrectButton">部分正确</button>
<button id="wrongButton">回答错误</button>
</div>
<button class="back-button" onclick="window.location.href='select.html'">返回点名页面</button> <button class="back-button" onclick="window.location.href='select.html'">返回点名页面</button>
<div id="result"></div> <div id="result"></div>
<div id="studentInfo"></div> <!-- 显示学生信息 -->
</div> </div>
<script> <script>
async function updateScore(student_id, points) {
try {
const response = await fetch('/api/update-score', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ student_id, points }),
});
if (!response.ok) {
throw new Error('网络响应不正常');
}
const data = await response.text(); // 使用 text() 解析纯数字响应
console.log('更新后的分数:', data); // data 是字符串形式的分数
return data; // 返回更新后的分数字符串
} catch (error) {
console.error('分数更新失败:', error);
return null;
}
}
const urlParams = new URLSearchParams(window.location.search); const urlParams = new URLSearchParams(window.location.search);
const name = urlParams.get('name'); const student_name = urlParams.get('student_name');
const student_id = urlParams.get('student_id');
const repeatCorrectButton = document.querySelector('#repeatCorrectButton');
const repeatWrongButton = document.querySelector('#repeatWrongButton');
const questionResultDisplay = document.querySelector('#questionResult');
const correctButton = document.querySelector('#correctButton'); const correctButton = document.querySelector('#correctButton');
const partiallyCorrectButton = document.querySelector('#partiallyCorrectButton');
const wrongButton = document.querySelector('#wrongButton'); const wrongButton = document.querySelector('#wrongButton');
const resultDisplay = document.querySelector('#result'); const resultDisplay = document.querySelector('#result');
const answerContainer = document.querySelector('#answerContainer');
const studentInfoDisplay = document.querySelector('#studentInfo');
// 显示学生姓名和学号
studentInfoDisplay.textContent = `学生: ${student_name} 学号: ${student_id}`;
// 正确重复问题处理 +0.5
repeatCorrectButton.addEventListener('click', () => {
updateScore(student_id, 0.5)
.then(newscore => {
if (newscore !== null) {
questionResultDisplay.textContent = `重复正确!${student_id} 的当前积分: ${newscore}`; // 直接使用字符串
answerContainer.style.display = 'block'; // 显示回答问题部分
} else {
console.error('更新分数失败');
questionResultDisplay.textContent = `更新分数失败,请重试。`;
}
})
.catch(error => {
console.error('请求失败:', error);
questionResultDisplay.textContent = `更新分数失败,请重试。`;
});
});
// 初始化积分 // 未准确重复问题处理 -1
let userPoints = parseInt(localStorage.getItem(name)); repeatWrongButton.addEventListener('click', () => {
updateScore(student_id, -1)
.then(newscore => {
if (newscore !== null) {
questionResultDisplay.textContent = `重复错误!${student_id} 的当前积分: ${newscore}`; // 直接使用字符串
answerContainer.style.display = 'block'; // 显示回答问题部分
} else {
console.error('更新分数失败');
questionResultDisplay.textContent = `更新分数失败,请重试。`;
}
})
.catch(error => {
console.error('请求失败:', error);
questionResultDisplay.textContent = `更新分数失败,请重试。`;
});
});
// 正确答案处理 // 回答问题的处理
correctButton.addEventListener('click', () => { correctButton.addEventListener('click', () => {
userPoints += 10; // 正确回答加 10 分 updateScore(student_id, 3)
localStorage.setItem(name, userPoints); // 保存更新后的积分 .then(newscore => {
resultDisplay.textContent = `正确!${name} 的当前积分: ${userPoints}`; if (newscore !== null) {
resultDisplay.textContent = `回答完全正确!${student_id} 的当前积分: ${newscore}`; // 直接使用字符串
} else {
console.error('更新分数失败');
resultDisplay.textContent = `更新分数失败,请重试。`;
}
})
.catch(error => {
console.error('请求失败:', error);
resultDisplay.textContent = `更新分数失败,请重试。`;
});
});
partiallyCorrectButton.addEventListener('click', () => {
updateScore(student_id, 1.5)
.then(newscore => {
if (newscore !== null) {
resultDisplay.textContent = `回答部分正确!${student_id} 的当前积分: ${newscore}`; // 直接使用字符串
} else {
console.error('更新分数失败');
resultDisplay.textContent = `更新分数失败,请重试。`;
}
})
.catch(error => {
console.error('请求失败:', error);
resultDisplay.textContent = `更新分数失败,请重试。`;
});
}); });
// 错误答案处理
wrongButton.addEventListener('click', () => {
userPoints -= 5;
localStorage.setItem(name, userPoints); // 保存更新后的积分
resultDisplay.textContent = `错误!${name} 的当前积分: ${userPoints}`;
wrongButton.addEventListener('click', () => {
updateScore(student_id, 0.5)
.then(newscore => {
if (newscore !== null) {
resultDisplay.textContent = `回答基本正确!${student_id} 的当前积分: ${newscore}`; // 直接使用字符串
} else {
console.error('更新分数失败');
resultDisplay.textContent = `更新分数失败,请重试。`;
}
})
.catch(error => {
console.error('请求失败:', error);
resultDisplay.textContent = `更新分数失败,请重试。`;
});
}); });
</script> </script>
</body> </body>
</html> </html>

@ -55,24 +55,22 @@
<script> <script>
// 获取URL中的参数名字 // 获取URL中的参数名字
const urlParams = new URLSearchParams(window.location.search); const urlParams = new URLSearchParams(window.location.search);
const name = urlParams.get('name'); const name = urlParams.get('student_name');
const id = urlParams.get('student_id');
// 显示被抽中的名字 // 显示被抽中的名字
const nameDisplay = document.querySelector('#nameDisplay'); const nameDisplay = document.querySelector('#nameDisplay');
nameDisplay.textContent = ` ${name} 你的选择是:`; nameDisplay.textContent = ` ${name} 你的选择是:`;
// 初始化用户的积分
let userPoints = localStorage.getItem(name) ? parseInt(localStorage.getItem(name)) : 0;
if (!localStorage.getItem(name)) {
localStorage.setItem(name, 0); // 如果没有积分记录,初始化为 0
}
// 回答问题功能,跳转到回答问题页面 // 回答问题功能,跳转到回答问题页面
document.querySelector('#answerButton').addEventListener('click', () => { document.querySelector('#answerButton').addEventListener('click', () => {
window.location.href = `answer.html?name=${encodeURIComponent(name)}`; window.location.href = `answer.html?student_name=${encodeURIComponent(name)}&student_id=${encodeURIComponent(id)}`;
}); });
// 抽奖功能,跳转到抽奖页面 // 抽奖功能,跳转到抽奖页面
document.querySelector('#lotteryButton').addEventListener('click', () => { document.querySelector('#lotteryButton').addEventListener('click', () => {
window.location.href = `lottery.html?name=${encodeURIComponent(name)}`; window.location.href = `lottery.html?student_name=${encodeURIComponent(name)}&student_id=${encodeURIComponent(id)}`;
}); });
</script> </script>

@ -0,0 +1,65 @@
const fs = require('fs');
const path = require('path');
const xlsx = require('xlsx');
const pool = require('../db');
const classManager = {
addClass: async (req, res) => {
// 创建students表的SQL语句
const createTableQuery = `
CREATE TABLE IF NOT EXISTS students (
student_id INT AUTO_INCREMENT PRIMARY KEY,
student_name VARCHAR(255) NOT NULL,
score DECIMAL(5, 2),
call_count INT DEFAULT 0
);
`;
try {
// 先创建表
await pool.query(createTableQuery);
const filePath = req.file.path;
// 读取并解析Excel文件
const workbook = xlsx.readFile(filePath);
const sheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[sheetName];
const students = xlsx.utils.sheet_to_json(worksheet);
// 定义所需的字段
const requiredFields = ['student_id','student_name'];
let hasError = false;
students.forEach(student => {
// 数据验证
const missingFields = requiredFields.filter(field =>!(field in student));
if (missingFields.length > 0) {
console.error(`Student data is missing fields: ${missingFields.join(', ')}`);
hasError = true;
return;
}
// 将学生数据插入数据库
const query = 'INSERT INTO students (student_id, student_name, score, call_count) VALUES (?,?, 0, 0)';
pool.query(query, [student.student_id, student.student_name], (error) => {
if (error) {
console.error(`Error inserting student: ${student.name}`, error);
hasError = true;
}
});
});
if (hasError) {
res.status(500).json({ message: 'Error adding class. Some students were not added successfully.' });
} else {
res.status(200).json({ message: 'Class added successfully!' });
}
} catch (err) {
console.error('Error creating students table:', err);
res.status(500).json({ message: 'Error creating table during class addition.' });
}
}
};
module.exports = classManager;

24
db.js

@ -0,0 +1,24 @@
const mysql = require('mysql2/promise');
// 创建连接池
const pool = mysql.createPool({
host: 'localhost', // 数据库地址
user: 'root', // 数据库用户名
password: '123456', // 数据库密码
database: 'class_k' ,// 使用的数据库
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
});
// 测试数据库连接
pool.getConnection((err, connection) => {
if (err) {
console.error('Error connecting to the database:', err);
} else {
console.log('Database connected successfully!');
connection.release(); // 释放连接
}
});
module.exports = pool;

@ -0,0 +1,22 @@
const pool = require('../db');
async function deleteTable(req, res) {
const { tableName } = req.body; // 从请求体中获取表名
let connection;
try {
connection = await pool.getConnection();
await connection.query(`DROP TABLE IF EXISTS ??`, [tableName]); // 删除表
connection.release();
res.json({ message: `${tableName} 已被成功删除` });
} catch (error) {
console.error('删除表失败:', error);
res.status(500).json({ error: '删除表失败' });
} finally {
if (connection) {
connection.release();
}
}
}
module.exports = { deleteTable };

@ -99,8 +99,8 @@ startAttendanceButton.addEventListener('click', async () => {
const response = await fetch('http://localhost:3000/api/random-call'); const response = await fetch('http://localhost:3000/api/random-call');
const data = await response.json(); const data = await response.json();
if (data.student) { if (data.student_id && data.student_name) {
currentStudent = data.student; currentStudent = data;
studentNameDisplay.textContent = `当前学生: ${currentStudent.student_name}`; studentNameDisplay.textContent = `当前学生: ${currentStudent.student_name}`;
presentButton.style.display = 'inline-block'; presentButton.style.display = 'inline-block';
absentButton.style.display = 'inline-block'; absentButton.style.display = 'inline-block';
@ -117,8 +117,8 @@ startAttendanceButton.addEventListener('click', async () => {
// 到场按钮点击事件 // 到场按钮点击事件
presentButton.addEventListener('click', async () => { presentButton.addEventListener('click', async () => {
if (currentStudent) { if (currentStudent) {
await updatePoints(currentStudent.student_id, 1); // 到场加1 await updatePoints(currentStudent.student_id, 0.5); // 到场加0.5
alert(`${currentStudent.student_name} 已到,加1分`); alert(`${currentStudent.student_name} 已到,加0.5分`);
resetAttendance(); resetAttendance();
} }
}); });
@ -126,7 +126,7 @@ presentButton.addEventListener('click', async () => {
// 没到按钮点击事件 // 没到按钮点击事件
absentButton.addEventListener('click', async () => { absentButton.addEventListener('click', async () => {
if (currentStudent) { if (currentStudent) {
await updatePoints(currentStudent.student_id, -1); // 未到减2 await updatePoints(currentStudent.student_id, -1); // 未到减1
alert(`${currentStudent.student_name} 未到减1分`); alert(`${currentStudent.student_name} 未到减1分`);
resetAttendance(); resetAttendance();
} }

@ -65,8 +65,43 @@
<button onclick="window.location.href='dianming.html'">课堂点名</button> <button onclick="window.location.href='dianming.html'">课堂点名</button>
<button onclick="window.location.href='select.html'">随机提问</button> <button onclick="window.location.href='select.html'">随机提问</button>
<button onclick="window.location.href='score_display.html'">积分显示</button> <button onclick="window.location.href='score_display.html'">积分显示</button>
<button onclick="document.getElementById('fileInput').click()">导入学生名单</button>
<input type="file" id="fileInput" accept=".xlsx" style="display:none;" onchange="importStudents(event)">
</div> </div>
</div> </div>
<script>
async function importStudents() {
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0]; // 获取选中的文件
if (!file) {
alert('请选择一个文件');
return;
}
const formData = new FormData();
formData.append('file', file); // 将文件添加到FormData中键名为'file'
try {
const response = await fetch('/api/upload', { // 假设后端API的路径为/api/upload
method: 'POST',
body: formData
});
if (response.ok) {
const result = await response.json();
console.log('上传成功:', result);
alert('学生名单导入成功!');
} else {
console.error('上传失败:', response.statusText);
alert('导入失败,请重试。');
}
} catch (error) {
console.error('请求错误:', error);
alert('发生错误,请检查控制台了解详细信息。');
}
}
</script>
</body> </body>
</html> </html>

@ -64,12 +64,8 @@
<script> <script>
const urlParams = new URLSearchParams(window.location.search); const urlParams = new URLSearchParams(window.location.search);
let name = urlParams.get('name'); let student_name = urlParams.get('student_name');
let student_id = urlParams.get('student_id');
// 如果 URL 中没有 name 参数,尝试从 localStorage 获取
if (!name) {
name = localStorage.getItem('currentUserName');
}
const pointsDisplay = document.querySelector('#pointsDisplay'); const pointsDisplay = document.querySelector('#pointsDisplay');
const startLotteryButton = document.querySelector('#startLotteryButton'); const startLotteryButton = document.querySelector('#startLotteryButton');
@ -82,54 +78,123 @@
return new Promise(resolve => setTimeout(resolve, d)); return new Promise(resolve => setTimeout(resolve, d));
} }
// 获取该用户的积分 // 全局变量,用于存储用户积分
let userPoints = parseInt(localStorage.getItem(name)) || 0; let userPoints = null;
pointsDisplay.textContent = `${name} 的当前积分: ${userPoints}`;
// 获取该用户的分数
const fetchStudentScore = async (student_id) => {
try {
const response = await fetch('http://localhost:3000/api/get-score', {
method: 'POST', // 使用 POST 方法
headers: {
'Content-Type': 'application/json', // 设置请求体的内容类型
},
body: JSON.stringify({ student_id }), // 将 student_id 放入请求体
});
if (!response.ok) {
alert('分数获取失败');
return null; // 返回 null 表示获取失败
}
// 直接返回响应体中的数字
const data = await response.json(); // 直接解析为 JSON
const score = data.score;
return score; // 返回数字
} catch (error) {
alert('网络请求失败');
return null; // 返回 null 表示获取失败
}
};
// 更新用户分数
async function updateScore(student_id, points) {
try {
const response = await fetch('http://localhost:3000/api/update-score', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ student_id, points }),
});
if (!response.ok) {
throw new Error('网络响应不正常');
}
// 使用 text() 解析响应,得到字符串形式的分数
const data = await response.text();
let score = Number(data); // 转换为数字
return score; // 返回数字
} catch (error) {
console.error('分数更新失败:', error);
return null; // 返回 null 表示更新失败
}
}
// 初始化函数,用于设置用户积分
async function init() {
userPoints = await fetchStudentScore(student_id); // 获取分数并存储到全局变量
pointsDisplay.textContent = `${student_name} 的当前积分: ${userPoints}`;
}
// 执行初始化函数
init();
// 设置返回按钮的 URL // 设置返回按钮的 URL
backButton.onclick = () => { backButton.onclick = () => {
loadingIndicator.style.display = 'block'; // 显示加载提示 loadingIndicator.style.display = 'block'; // 显示加载提示
window.location.href = `choice.html?name=${encodeURIComponent(name)}`; window.location.href = `choice.html?student_name=${encodeURIComponent(student_name)}&student_id=${encodeURIComponent(student_id)}`;
}; };
// 抽奖逻辑 // 开始抽奖
startLotteryButton.addEventListener('click', async () => { startLotteryButton.addEventListener('click', async () => {
if (userPoints >= 20) { if (userPoints >= 2) {
userPoints -= 20; // 每次抽奖消耗 20 分 userPoints = await updateScore(student_id, -2); // 积分-2
localStorage.setItem(name, userPoints); // 保存更新后的积分
pointsDisplay.textContent = `${name} 的当前积分: ${userPoints}`; pointsDisplay.textContent = `${student_name} 的当前积分: ${userPoints}`;
// 随机选择奖品 // 随机选择奖品
const prizes = ["跳过权", "再来一次", "什么也没有发生", "加30积分且跳过"]; const prizes = ["跳过权", "再来一次", "什么也没有发生", "加3积分且跳过"];
const randomPrize = prizes[Math.floor(Math.random() * prizes.length)]; const randomPrize = prizes[Math.floor(Math.random() * prizes.length)];
resultDisplay.textContent = `你赢得了: ${randomPrize}`; resultDisplay.textContent = `你赢得了: ${randomPrize}`;
// 等待 2 秒以展示结果 // 等待 2 秒以展示结果
await sleep(2000); await new Promise(resolve => setTimeout(resolve, 2000));
loadingIndicator.style.display = 'block'; // 显示加载提示 loadingIndicator.style.display = 'block'; // 显示加载提示
if (randomPrize === '跳过权') { if (randomPrize === '跳过权') {
await sleep(1000); await sleep(2000);
window.location.href = `select.html?name=${encodeURIComponent(name)}`; window.location.href = `select.html?student_name=${encodeURIComponent(student_name)}&student_id=${encodeURIComponent(student_id)}`;
} else if (randomPrize === '再来一次') { }
userPoints += 20;
localStorage.setItem(name, userPoints); else if (randomPrize === '再来一次') {
} else if (randomPrize === '什么也没有发生') { userPoints = await updateScore(student_id, 2); // 积分返回2
await sleep(1000); await sleep(2000);
window.location.href = `answer.html?name=${encodeURIComponent(name)}`; window.location.href = `lottery.html?student_name=${encodeURIComponent(student_name)}&student_id=${encodeURIComponent(student_id)}`;
} else if (randomPrize === '加30积分且跳过') {
userPoints += 30;
localStorage.setItem(name, userPoints);
await sleep(1000);
window.location.href = `select.html?name=${encodeURIComponent(name)}`;
} }
else if (randomPrize === '什么也没有发生') {
await sleep(2000);
window.location.href = `answer.html?student_name=${encodeURIComponent(student_name)}&student_id=${encodeURIComponent(student_id)}`;
}
else if (randomPrize === '加3积分且跳过') {
userPoints = await updateScore(student_id, 3); // 积分+3
await sleep(2000);
window.location.href = `select.html?student_name=${encodeURIComponent(student_name)}&student_id=${encodeURIComponent(student_id)}`;
}
} else { } else {
resultDisplay.textContent = "积分不足,无法抽奖!"; resultDisplay.textContent = "积分不足,无法抽奖!返回回答问题";
loadingIndicator.style.display = 'block'; // 显示加载提示 loadingIndicator.style.display = 'block'; // 显示加载提示
await sleep(1000); await sleep(2000);
window.location.href = `answer.html?name=${encodeURIComponent(name)}`; window.location.href = `answer.html?student_name=${encodeURIComponent(student_name)}&student_id=${encodeURIComponent(student_id)}`;
} }
}); });
</script> </script>
</body> </body>
</html> </html>

@ -0,0 +1,9 @@
{
"dependencies": {
"body-parser": "^1.20.3",
"express": "^4.21.0",
"multer": "^1.4.5-lts.1",
"mysql2": "^3.11.3",
"xlsx": "^0.18.5"
}
}

@ -0,0 +1,47 @@
const pool = require('../db');
async function selectStudent(req, res) {
try {
const connection = await pool.getConnection();
// 从数据库查询学生
const [students] = await connection.query('SELECT * FROM students');
// 计算权重的总和(使用 softmax 权重计算)
const totalWeight = students.reduce((acc, student) => acc + Math.exp(-student.score), 0);
// 将每个学生的权重归一化
const weightedStudents = students.map(student => ({
student,
weight: Math.exp(-student.score) / totalWeight,
}));
// 生成随机数
const random = Math.random(); // 介于 0 和 1 之间
let sum = 0; // 用于累加权重
let selectedStudent = null;
// 遍历加权后的学生,累加权重,并判断随机数落在哪个学生的区间
for (let i = 0; i < weightedStudents.length; i++) {
sum += weightedStudents[i].weight; // 累加当前学生的权重
if (random <= sum) { // 如果随机数小于或等于当前的累积权重
selectedStudent = weightedStudents[i].student; // 选中该学生
break; // 找到后立即退出循环
}
}
if (selectedStudent) {
res.send({ student_name: selectedStudent.student_name,
student_id: selectedStudent.student_id
});
} else {
res.status(404).send({ message: '无学生数据' });
}
connection.release();
} catch (error) {
res.status(500).send({ error: '随机选择学生失败' });
}
}
module.exports = { selectStudent };

@ -0,0 +1,25 @@
const pool = require('../db');
async function get_descend_Ranking(req, res) {
try {
const connection = await pool.getConnection();
const [ranking] = await connection.query('SELECT student_name, student_id, score FROM students ORDER BY score DESC');
connection.release();
res.json(ranking);
} catch (error) {
res.status(500).send({ error: '无法获取排名' });
}
}
async function get_ascend_Ranking(req, res) {
try {
const connection = await pool.getConnection();
const [ranking] = await connection.query('SELECT student_name, student_id, score FROM students ORDER BY score ASC');
connection.release();
res.json(ranking);
} catch (error) {
res.status(500).send({ error: '无法获取排名' });
}
}
module.exports = { get_ascend_Ranking, get_descend_Ranking };

@ -0,0 +1,50 @@
const express = require('express');
const router = express.Router();
const multer = require('multer');
const randomSelect = require('./services/randomSelect');
const ranking = require('./services/ranking');
const classManager = require('./services/classManager');
const scoreManager = require('./services/scoreManager');
const TableManager = require('./services/delete-table');
const pool = require('./db');
// 文件上传配置
const upload = multer({ dest: 'uploads/' });
// 路由 - 添加班级
router.post('/upload', upload.single('file'), classManager.addClass);
// 路由 - 随机点名
router.get('/random-call', randomSelect.selectStudent);
// 路由 - 获取排名
router.get('/ascend_ranking', ranking.get_ascend_Ranking);
router.get('/descend_ranking', ranking.get_descend_Ranking);
// 路由 - 更新分数
router.post('/update-score', scoreManager.updateScore);
//路由 - 获取某个id的分数
router.post('/get-score', scoreManager.getStudentScore);
//路由 - 删除班级
router.post('/delete-table', TableManager.deleteTable);
// 获取全部学生名单
router.get('/get-students', async (req, res) => {
let connection; // 声明连接变量
try {
connection = await pool.getConnection(); // 从连接池获取连接
const [students] = await connection.query('SELECT student_name FROM students'); // 执行查询
const studentNames = students.map(student => ({ student_name: student.student_name })); // 只保留 student_name 字段
res.json(studentNames); // 返回只包含 student_name 的结果
} catch (error) {
console.error('Error fetching students:', error); // 记录错误信息
res.status(500).send({ error: 'Failed to fetch students' }); // 返回500错误响应
} finally {
if (connection) connection.release(); // 确保连接被释放
}
});
module.exports = router;

@ -0,0 +1,93 @@
const pool = require('../db');
async function updateScore(req, res) {
const { student_id, points } = req.body; //假设前端发送的数据是这两部分
const pool = require('../db');
async function updateScore(req, res) {
const { student_id, points } = req.body;
let connection; // 在try块外部声明connection
try {
connection = await pool.getConnection();
// 更新学生的积分并增加点名次数
const [result] = await connection.query(
'UPDATE students SET score = score + ?, call_count = call_count + 1 WHERE student_id = ?',
[points, student_id]
);
if (result.affectedRows > 0) {
// 查询更新后的分数
const [rows] = await connection.query(
'SELECT score FROM students WHERE student_id = ?',
[student_id]
);
if (rows.length > 0) {
const updatedScore = rows[0].score;
return res.send(String(updatedScore));
} else {
return res.status(404).send('学生不存在');
}
} else {
return res.status(404).send('学生不存在');
}
} catch (error) {
console.error('数据库操作失败:', error);
return res.status(500).send('更新积分失败');
} finally {
if (connection) {
connection.release(); // 只有在connection已被赋值时才调用release
}
}
}
async function getStudentScore(req, res) {
const { student_id } = req.body;
let connection;
try {
connection = await pool.getConnection();
// 查询指定学生的分数
const [rows] = await connection.query(
'SELECT score FROM students WHERE student_id =?',
[student_id]
);
if (rows.length > 0) {
const score = rows[0].score;
// 修改这里构建包含student_id和score的对象并返回
return res.json({ student_id, score });
} else {
return res.status(404).json({ message: '学生不存在' });
}
} catch (error) {
console.error('数据库操作失败:', error);
return res.status(500).json({ error: '获取分数失败' });
} finally {
if (connection) {
connection.release();
}
}
}
module.exports = { updateScore, getStudentScore };
try {
const connection = await pool.getConnection();
const [result] = await connection.query('UPDATE students SET score = score + ?, call_count = call_count + 1 WHERE student_id = ?', [points, student_id]);
if (result.affectedRows > 0) {
res.send({ message: '积分已更新' });
} else {
res.status(404).send({ message: '学生不存在' });
}
connection.release();
} catch (error) {
res.status(500).send({ error: '更新积分失败' });
}
}
module.exports = { updateScore };

@ -118,6 +118,7 @@
<thead> <thead>
<tr> <tr>
<th>姓名</th> <th>姓名</th>
<th>学号</th>
<th>积分</th> <th>积分</th>
</tr> </tr>
</thead> </thead>
@ -135,61 +136,112 @@
const studentList = document.getElementById('studentList'); const studentList = document.getElementById('studentList');
const sortButton = document.getElementById('sortButton'); const sortButton = document.getElementById('sortButton');
const clearButton = document.getElementById('clearButton'); const clearButton = document.getElementById('clearButton');
let ascending = false; // 默认降序 let ascend = false; // 默认降序
// 预定义学生名单
const predefinedStudents = [ //删除表
{ name: '张三', points: 0 }, async function deleteTable(tableName) {
{ name: '李四', points: 0 }, try {
{ name: '王五', points: 0 }, const response = await fetch('/api/delete-table', {
{ name: '赵六', points: 0 }, method: 'POST',
]; headers: {
'Content-Type': 'application/json',
// 获取所有学生,包括预定义名单 },
function getAllStudents() { body: JSON.stringify({ tableName }),
const students = predefinedStudents.map(student => {
const storedPoints = localStorage.getItem(student.name);
return {
name: student.name,
points: storedPoints !== null ? parseInt(storedPoints) : student.points
};
}); });
return students;
if (!response.ok) {
throw new Error('删除表失败');
}
const data = await response.json();
alert(data.message); // 成功后显示消息
} catch (error) {
console.error('删除表操作失败:', error);
alert('删除表失败');
}
}
// 获取按分数降序排列的学生排名
async function fetchDescendRanking() {
try {
const response = await fetch('/api/descend_ranking');
if (!response.ok) {
alert('无法获取降序排名');
return null;
}
const ranking = await response.json(); // 获取并解析为JSON数组
return ranking; // 返回排名数组
} catch (error) {
console.error('请求失败:', error);
return null;
}
}
// 获取按分数升序排列的学生排名
async function fetchAscendRanking() {
try {
const response = await fetch('/api/ascend_ranking');
if (!response.ok) {
alert('无法获取升序排名');
return null;
}
const ranking = await response.json(); // 获取并解析为JSON数组
return ranking; // 返回排名数组
} catch (error) {
console.error('请求失败:', error);
return null;
}
} }
// 显示学生积分 async function displayStudents() {
function displayStudents() { let ranking; // 声明 ranking 变量
const students = getAllStudents(); if (ascend) {
students.sort((a, b) => ascending ? a.points - b.points : b.points - a.points); ranking = await fetchAscendRanking(); // 获取升序排名
studentList.innerHTML = ''; } else {
students.forEach(student => { ranking = await fetchDescendRanking(); // 获取降序排名
}
// 检查 ranking 是否为空
if (!ranking) {
alert('空 ranking');
return; // 退出函数
}
studentList.innerHTML = ''; // 清空表格内容
// 只显示前五名学生
ranking.slice(0, 5).forEach(student => {
studentList.innerHTML += ` studentList.innerHTML += `
<tr> <tr>
<td>${student.name}</td> <td>${student.student_name}</td> <!-- 学生姓名 -->
<td>${student.points}</td> <td>${student.student_id}</td> <!-- 学生ID -->
<td>${student.score}</td> <!-- 学生分数 -->
</tr> </tr>
`; `;
}); });
} }
// 切换排序
sortButton.addEventListener('click', () => { sortButton.addEventListener('click', () => {
ascending = !ascending; ascend = !ascend;
sortButton.textContent = `切换排序 (${ascending ? '升序' : '降序'})`; sortButton.textContent = `切换排序 (${ascend ? '升序' : '降序'})`;
displayStudents(); displayStudents();
}); });
// 清除所有数据
clearButton.addEventListener('click', () => { clearButton.addEventListener('click', () => {
const confirmation = confirm("确定要清除所有学生数据吗?此操作无法撤销!"); const confirmation = confirm("确定要清除所有学生数据吗?此操作无法撤销!");
if (confirmation) { if (confirmation) {
localStorage.clear(); deleteTable('students');
alert("所有数据已清除!"); alert("所有信息已清除!");
displayStudents(); // 重新显示清空后的数据 displayStudents(); // 重新显示清空后的数据
} }
}); });
// 初次加载时显示学生积分
displayStudents(); displayStudents();
</script> </script>

@ -118,35 +118,35 @@
}); });
// 停止滚动并通过后端决定最终选择的学生 // 停止滚动并通过后端决定最终选择的学生
stopButton.addEventListener('click', () => { stopButton.addEventListener('click', async () => {
clearInterval(intervalId); clearInterval(intervalId);
startButton.disabled = false; startButton.disabled = false;
stopButton.disabled = true; stopButton.disabled = true;
// 调用后端接口获取最终选中的学生 try {
fetch('/api/random-call') const response = await fetch('/api/random-call');
.then(response => {
if (!response.ok) { if (!response.ok) {
throw new Error('Network response was not ok'); throw new Error('Network response was not ok');
} }
return response.json();
}) const data = await response.json();
.then(data => {
// 从后端返回的数据中获取学生名字 // 从后端返回的数据中获取学生名字
if (data.student && data.student.name) { const selectedName = data.student_name; // student_name 属性
const selectedName = data.student.name;
if (selectedName) {
// 更新显示选中的学生 // 更新显示选中的学生
updateNameDisplay(selectedName); updateNameDisplay(selectedName);
// 跳转到新页面并传递被选中的名字 // 跳转到新页面并传递被选中的名字
window.location.href = `choice.html?name=${encodeURIComponent(selectedName)}`; window.location.href = `choice.html?student_name=${encodeURIComponent(data.student_name)}&student_id=${encodeURIComponent(data.student_id)}`;
} else { } else {
console.error('未返回有效学生数据'); console.error('未返回有效学生数据');
} }
}) } catch (error) {
.catch(error => {
console.error('请求失败:', error); console.error('请求失败:', error);
}
}); });
});
</script> </script>
</body> </body>

@ -0,0 +1,26 @@
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const router = require('./router');
const app = express();
// 中间件
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// API 路由
app.use('/api', router);
// 静态文件
app.use(express.static(path.join(__dirname, 'public')));
// 处理 SPA 路由
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
// 启动服务器
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Loading…
Cancel
Save