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.
llll/class_backend/src/controllers/attendanceController.js

168 lines
6.0 KiB

import Attendance from '../models/attendanceModel.js';
import Student from '../models/studentModel.js';
import axios from 'axios';
// 教师发布考勤
export const createAttendance = async (req, res) => {
const { username, studentIds, duration, isRandom } = req.body;
try {
const attendance = new Attendance({
username,
studentIds,
duration,
rollcallTime: new Date(),
isRandom // 新增字段,表示是否为抽点
});
await attendance.save();
// 发送通知给学生
if (isRandom) {
// 抽点逻辑
const selectedStudent = await randomCall(studentIds);
if (selectedStudent && selectedStudent.openId) {
await sendTemplateMessage(selectedStudent.openId, attendance.rollcallTime);
}
} else {
// 全点逻辑,发送通知给所有学生
for (const studentId of studentIds) {
const student = await Student.findById(studentId);
if (student && student.openId) {
await sendTemplateMessage(student.openId, attendance.rollcallTime);
}
}
}
// 设置超时处理
setTimeout(async () => {
attendance.status = 'completed';
await attendance.save();
// 更新未签到学生的考勤记录
for (const studentId of studentIds) {
if (!attendance.results.some(result => result.studentId.equals(studentId))) {
attendance.results.push({ studentId, status: 'absent' });
await Student.findByIdAndUpdate(studentId, { $inc: { points: -1 } });
}
}
await attendance.save();
}, duration * 60 * 1000); // duration 转换为毫秒
res.status(201).json({ message: '考勤发布成功', attendance });
} catch (error) {
res.status(500).json({ message: '发布考勤失败', error: error.message });
}
};
// 随机点名逻辑
async function randomCall(studentIds) {
const students = await Student.find({ String: { $in: studentIds } });
// 计算总积分的概率
const totalPoints = students.reduce((acc, student) => acc + Math.max(0, 100 - student.points), 0);
const randomNum = Math.random() * totalPoints;
let cumulativePoints = 0;
let selectedStudent = null;
for (const student of students) {
cumulativePoints += Math.max(0, 100 - student.points);
if (randomNum <= cumulativePoints) {
selectedStudent = student;
break;
}
}
return selectedStudent; // 返回被抽中的学生
}
// 发送模板消息的函数
async function sendTemplateMessage(openId, rollcallTime) {
const accessToken = await getAccessToken(); // 获取 access_token
const templateMessage = {
touser: openId,
template_id: 'ca8117c1133660af421ad67eab9054e7', // 替换为您的模板 ID
data: {
keyword1: { value: '您有一条签到' },
keyword2: { value: rollcallTime.toISOString() }, // 或者格式化成需要的日期格式
}
};
try {
await axios.post(`https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=${accessToken}`, templateMessage);
} catch (error) {
console.error('发送模板消息失败:', error);
}
}
// 获取 access_token 的函数
async function getAccessToken() {
const appId = 'wx0874fe247e4282a3'; // 替换为您的微信小程序 appId
const appSecret = 'ca8117c1133660af421ad67eab9054e7'; // 替换为您的微信小程序 appSecret
try {
const response = await axios.get(`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appId}&secret=${appSecret}`);
return response.data.access_token; // 返回获取到的 access_token
} catch (error) {
console.error('获取 access_token 失败:', error);
throw new Error('获取 access_token 失败');
}
}
// 学生签到
export const studentCheckIn = async (req, res) => {
const { studentId } = req.body; // 从请求体中获取 studentId
const rollcallTime = new Date().toISOString(); // 自动获取当前时间
console.log('签到请求:', { studentId, rollcallTime });
try {
// 找到当天的考勤记录
const attendance = await Attendance.findOne({ rollcallTime });
if (!attendance) {
return res.status(404).json({ message: '考勤记录未找到' });
}
// 检查学生是否在考勤名单中
if (!attendance.studentIds.includes(studentId)) {
return res.status(403).json({ message: '您不在考勤名单中' });
}
// 检查学生是否已经签到
const existingResult = attendance.results.find(result => result.studentId.equals(studentId));
if (existingResult) {
return res.status(400).json({ message: '您已签到' });
}
// 签到成功
attendance.results.push({ studentId, status: 'present' });
await Student.findByIdAndUpdate(studentId, { $inc: { points: 1 } }); // 积分加1
await attendance.save();
res.json({ message: '签到成功' });
} catch (error) {
res.status(500).json({ message: '签到失败', error: error.message });
}
}
// 获取教师的考勤记录
export const getAttendanceRecords = async (req, res) => {
const { username } = req.params;
try {
const records = await Attendance.find({ username }).populate('studentIds').populate('results.studentId');
res.json(records);
} catch (error) {
res.status(500).json({ message: '获取考勤记录失败', error: error.message || error });
}
};
// 获取学生的考勤记录
export const getStudentAttendance = async (req, res) => {
const { studentId } = req.params;
try {
const records = await Attendance.find({ 'results.studentId': studentId }).populate('results.studentId');
res.json(records);
} catch (error) {
res.status(500).json({ message: '获取学生考勤记录失败', error: error.message || error });
}
};