feat: 实现教师资料更新、操作日志和系统设置功能

新增教师资料更新功能,包括个人信息修改和密码更新
添加操作日志记录系统,记录用户关键操作
实现系统设置模块,支持动态配置系统参数
重构数据库模型,新增教师表和系统设置表
优化成绩录入逻辑,支持平时分、期中和期末成绩计算
添加数据导出功能,支持学生、教师和成绩数据导出
完善管理员后台,增加统计图表和操作日志查看
This commit is contained in:
祀梦
2025-12-22 23:30:01 +08:00
parent 16802c85e5
commit b1da021185
43 changed files with 7860 additions and 2835 deletions

View File

@@ -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;