feat: 实现教师资料更新、操作日志和系统设置功能
新增教师资料更新功能,包括个人信息修改和密码更新 添加操作日志记录系统,记录用户关键操作 实现系统设置模块,支持动态配置系统参数 重构数据库模型,新增教师表和系统设置表 优化成绩录入逻辑,支持平时分、期中和期末成绩计算 添加数据导出功能,支持学生、教师和成绩数据导出 完善管理员后台,增加统计图表和操作日志查看
This commit is contained in:
@@ -2,28 +2,25 @@ const AdminService = require('../services/adminService');
|
||||
const { success, error } = require('../utils/response');
|
||||
|
||||
class AdminController {
|
||||
static async getStats(req, res) {
|
||||
try {
|
||||
const stats = await AdminService.getStats();
|
||||
success(res, stats, '获取统计信息成功');
|
||||
} catch (err) {
|
||||
console.error('Get Stats Error:', err);
|
||||
error(res, '服务器错误');
|
||||
}
|
||||
}
|
||||
|
||||
static async getUsers(req, res) {
|
||||
try {
|
||||
const result = await AdminService.getUsers(req.query);
|
||||
success(res, result.data, '获取成功');
|
||||
// 注意:原来的响应结构是 { success, data, pagination }
|
||||
// 现在的 success 工具函数结构是 { success, message, data }
|
||||
// 我们可以稍微调整 success 调用,或者让前端适应
|
||||
// 为了兼容性,这里手动返回
|
||||
/*
|
||||
res.json({
|
||||
success: true,
|
||||
message: '获取成功',
|
||||
data: result.data,
|
||||
pagination: result.pagination
|
||||
});
|
||||
*/
|
||||
// 或者修改 response.js 支持 extra 字段,这里简单处理:
|
||||
res.json({
|
||||
success: true,
|
||||
data: result.data,
|
||||
pagination: result.pagination
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.error('Get Users Error:', err);
|
||||
error(res, '服务器错误');
|
||||
@@ -38,7 +35,10 @@ class AdminController {
|
||||
return error(res, '请填写所有必填字段', 400);
|
||||
}
|
||||
|
||||
await AdminService.createUser(req.body);
|
||||
await AdminService.createUser(req.body, {
|
||||
user_id: req.session.user.id,
|
||||
ip: req.ip
|
||||
});
|
||||
success(res, null, '创建用户成功');
|
||||
} catch (err) {
|
||||
if (err.message === '用户ID已存在') {
|
||||
@@ -48,6 +48,287 @@ class AdminController {
|
||||
error(res, '服务器错误');
|
||||
}
|
||||
}
|
||||
|
||||
static async updateUser(req, res) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const updateData = req.body;
|
||||
|
||||
await AdminService.updateUser(id, updateData, {
|
||||
user_id: req.session.user.id,
|
||||
ip: req.ip
|
||||
});
|
||||
success(res, null, '更新用户成功');
|
||||
} catch (err) {
|
||||
console.error('Update User Error:', err);
|
||||
error(res, '服务器错误');
|
||||
}
|
||||
}
|
||||
|
||||
static async deleteUser(req, res) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
await AdminService.deleteUser(id, {
|
||||
user_id: req.session.user.id,
|
||||
ip: req.ip
|
||||
});
|
||||
success(res, null, '删除用户成功');
|
||||
} catch (err) {
|
||||
console.error('Delete User Error:', err);
|
||||
error(res, '服务器错误');
|
||||
}
|
||||
}
|
||||
|
||||
// Student Management
|
||||
static async getStudents(req, res) {
|
||||
try {
|
||||
const result = await AdminService.getStudents(req.query);
|
||||
res.json({
|
||||
success: true,
|
||||
message: '获取学生列表成功',
|
||||
data: result.data,
|
||||
pagination: result.pagination
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error(res, '服务器错误');
|
||||
}
|
||||
}
|
||||
|
||||
static async createStudent(req, res) {
|
||||
try {
|
||||
if (!req.body.id || !req.body.name) return error(res, 'ID和姓名必填', 400);
|
||||
await AdminService.createStudent(req.body, {
|
||||
user_id: req.session.user.id,
|
||||
ip: req.ip
|
||||
});
|
||||
success(res, null, '创建学生成功');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error(res, err.message || '创建失败', 400);
|
||||
}
|
||||
}
|
||||
|
||||
static async updateStudent(req, res) {
|
||||
try {
|
||||
await AdminService.updateStudent(req.params.id, req.body, {
|
||||
user_id: req.session.user.id,
|
||||
ip: req.ip
|
||||
});
|
||||
success(res, null, '更新学生成功');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error(res, '更新失败');
|
||||
}
|
||||
}
|
||||
|
||||
static async deleteStudent(req, res) {
|
||||
try {
|
||||
await AdminService.deleteStudent(req.params.id, {
|
||||
user_id: req.session.user.id,
|
||||
ip: req.ip
|
||||
});
|
||||
success(res, null, '删除学生成功');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error(res, '删除失败');
|
||||
}
|
||||
}
|
||||
|
||||
// Teacher Management
|
||||
static async getTeachers(req, res) {
|
||||
try {
|
||||
const result = await AdminService.getTeachers(req.query);
|
||||
res.json({
|
||||
success: true,
|
||||
message: '获取教师列表成功',
|
||||
data: result.data,
|
||||
pagination: result.pagination
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error(res, '服务器错误');
|
||||
}
|
||||
}
|
||||
|
||||
static async createTeacher(req, res) {
|
||||
try {
|
||||
if (!req.body.id || !req.body.name) return error(res, '工号和姓名必填', 400);
|
||||
await AdminService.createTeacher(req.body, {
|
||||
user_id: req.session.user.id,
|
||||
ip: req.ip
|
||||
});
|
||||
success(res, null, '创建教师成功');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error(res, err.message || '创建失败', 400);
|
||||
}
|
||||
}
|
||||
|
||||
static async updateTeacher(req, res) {
|
||||
try {
|
||||
await AdminService.updateTeacher(req.params.id, req.body, {
|
||||
user_id: req.session.user.id,
|
||||
ip: req.ip
|
||||
});
|
||||
success(res, null, '更新教师成功');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error(res, '更新失败');
|
||||
}
|
||||
}
|
||||
|
||||
static async deleteTeacher(req, res) {
|
||||
try {
|
||||
await AdminService.deleteTeacher(req.params.id, {
|
||||
user_id: req.session.user.id,
|
||||
ip: req.ip
|
||||
});
|
||||
success(res, null, '删除教师成功');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error(res, '删除失败');
|
||||
}
|
||||
}
|
||||
|
||||
// Grade Statistics
|
||||
static async getGradeStats(req, res) {
|
||||
try {
|
||||
const stats = await AdminService.getGradeStats();
|
||||
success(res, stats, '获取成绩统计成功');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error(res, '服务器错误');
|
||||
}
|
||||
}
|
||||
|
||||
// System Settings
|
||||
static async getSettings(req, res) {
|
||||
try {
|
||||
const settings = await AdminService.getSettings();
|
||||
success(res, settings);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error(res, '服务器错误');
|
||||
}
|
||||
}
|
||||
|
||||
static async saveSettings(req, res) {
|
||||
try {
|
||||
await AdminService.saveSettings(req.body, {
|
||||
user_id: req.session.user.id,
|
||||
ip: req.ip
|
||||
});
|
||||
success(res, null, '保存设置成功');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error(res, '保存失败');
|
||||
}
|
||||
}
|
||||
|
||||
// Data Maintenance
|
||||
static async backupDatabase(req, res) {
|
||||
try {
|
||||
const result = await AdminService.backupDatabase({
|
||||
user_id: req.session.user.id,
|
||||
ip: req.ip
|
||||
});
|
||||
success(res, result, '数据库备份成功');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error(res, '备份失败');
|
||||
}
|
||||
}
|
||||
|
||||
static async clearCache(req, res) {
|
||||
try {
|
||||
await AdminService.clearCache({
|
||||
user_id: req.session.user.id,
|
||||
ip: req.ip
|
||||
});
|
||||
success(res, null, '缓存已清理');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error(res, '清理失败');
|
||||
}
|
||||
}
|
||||
|
||||
static async resetStudentPasswords(req, res) {
|
||||
try {
|
||||
await AdminService.resetStudentPasswords({
|
||||
user_id: req.session.user.id,
|
||||
ip: req.ip
|
||||
});
|
||||
success(res, null, '所有学生密码已重置为 123456');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error(res, '重置失败');
|
||||
}
|
||||
}
|
||||
|
||||
// Operation Logs
|
||||
static async getOperationLogs(req, res) {
|
||||
try {
|
||||
const logs = await AdminService.getLogs(req.query);
|
||||
success(res, logs);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error(res, '获取日志失败');
|
||||
}
|
||||
}
|
||||
|
||||
// Data Export
|
||||
static async exportStudents(req, res) {
|
||||
try {
|
||||
const data = await AdminService.exportStudents();
|
||||
const csv = jsonToCsv(data, ['id', 'name', 'class', 'major', 'grade', 'contact_info']);
|
||||
res.setHeader('Content-Type', 'text/csv; charset=utf-8');
|
||||
res.setHeader('Content-Disposition', 'attachment; filename=students.csv');
|
||||
res.send(csv);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error(res, '导出失败');
|
||||
}
|
||||
}
|
||||
|
||||
static async exportTeachers(req, res) {
|
||||
try {
|
||||
const data = await AdminService.exportTeachers();
|
||||
const csv = jsonToCsv(data, ['id', 'name', 'department', 'title', 'contact_info', 'created_at']);
|
||||
res.setHeader('Content-Type', 'text/csv; charset=utf-8');
|
||||
res.setHeader('Content-Disposition', 'attachment; filename=teachers.csv');
|
||||
res.send(csv);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error(res, '导出失败');
|
||||
}
|
||||
}
|
||||
|
||||
static async exportGrades(req, res) {
|
||||
try {
|
||||
const data = await AdminService.exportGrades();
|
||||
const csv = jsonToCsv(data, ['student_id', 'student_name', 'course_code', 'course_name', 'total_score', 'grade_point', 'grade_level', 'teacher_name']);
|
||||
res.setHeader('Content-Type', 'text/csv; charset=utf-8');
|
||||
res.setHeader('Content-Disposition', 'attachment; filename=grades.csv');
|
||||
res.send(csv);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error(res, '导出失败');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function
|
||||
function jsonToCsv(data, fields) {
|
||||
if (!data || data.length === 0) return '';
|
||||
const header = fields.join(',') + '\n';
|
||||
const rows = data.map(row => {
|
||||
return fields.map(field => {
|
||||
const val = row[field] === null || row[field] === undefined ? '' : row[field];
|
||||
return `"${String(val).replace(/"/g, '""')}"`;
|
||||
}).join(',');
|
||||
}).join('\n');
|
||||
return '\ufeff' + header + rows; // Add BOM for Excel compatibility
|
||||
}
|
||||
|
||||
module.exports = AdminController;
|
||||
@@ -85,6 +85,26 @@ class AuthController {
|
||||
error(res, '服务器错误');
|
||||
}
|
||||
}
|
||||
|
||||
static async updateProfile(req, res) {
|
||||
try {
|
||||
const userId = req.session.user.id;
|
||||
const updateData = req.body;
|
||||
|
||||
const updatedUser = await AuthService.updateProfile(userId, updateData);
|
||||
|
||||
// 更新 Session 中的用户信息
|
||||
req.session.user = {
|
||||
...req.session.user,
|
||||
...updatedUser
|
||||
};
|
||||
|
||||
success(res, { user: req.session.user }, '资料更新成功');
|
||||
} catch (err) {
|
||||
console.error('Update Profile Error:', err);
|
||||
error(res, '服务器错误');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AuthController;
|
||||
@@ -18,6 +18,68 @@ class TeacherController {
|
||||
}
|
||||
}
|
||||
|
||||
static async getClasses(req, res) {
|
||||
try {
|
||||
const classes = await TeacherService.getClasses();
|
||||
success(res, { classes });
|
||||
} catch (err) {
|
||||
console.error('Get Classes Error:', err);
|
||||
error(res, '服务器错误');
|
||||
}
|
||||
}
|
||||
|
||||
static async getMyClasses(req, res) {
|
||||
try {
|
||||
const teacherId = req.session.user.id;
|
||||
const classes = await TeacherService.getTeacherClasses(teacherId);
|
||||
success(res, { classes });
|
||||
} catch (err) {
|
||||
console.error('Get My Classes Error:', err);
|
||||
error(res, '服务器错误');
|
||||
}
|
||||
}
|
||||
|
||||
static async createCourse(req, res) {
|
||||
try {
|
||||
const teacherId = req.session.user.id;
|
||||
const courseId = await TeacherService.createCourse(teacherId, req.body);
|
||||
success(res, { courseId }, '课程创建成功');
|
||||
} catch (err) {
|
||||
console.error('Create Course Error:', err);
|
||||
error(res, '服务器错误');
|
||||
}
|
||||
}
|
||||
|
||||
static async updateCourse(req, res) {
|
||||
try {
|
||||
const teacherId = req.session.user.id;
|
||||
const courseId = req.params.id;
|
||||
await TeacherService.updateCourse(teacherId, courseId, req.body);
|
||||
success(res, null, '课程更新成功');
|
||||
} catch (err) {
|
||||
if (err.message === '无权修改该课程或课程不存在') {
|
||||
return error(res, err.message, 403);
|
||||
}
|
||||
console.error('Update Course Error:', err);
|
||||
error(res, '服务器错误');
|
||||
}
|
||||
}
|
||||
|
||||
static async getGrades(req, res) {
|
||||
try {
|
||||
const teacherId = req.session.user.id;
|
||||
const filters = {
|
||||
courseId: req.query.courseId,
|
||||
studentName: req.query.studentName
|
||||
};
|
||||
const grades = await TeacherService.getGrades(teacherId, filters);
|
||||
success(res, { grades });
|
||||
} catch (err) {
|
||||
console.error('Get Grades Error:', err);
|
||||
error(res, '服务器错误');
|
||||
}
|
||||
}
|
||||
|
||||
static async addScore(req, res) {
|
||||
try {
|
||||
const teacherId = req.session.user.id;
|
||||
|
||||
Reference in New Issue
Block a user