feat(学生): 添加学生课程管理功能

- 新增我的课程页面及路由
- 实现课程列表和详情查看功能
- 更新导航链接指向新页面
- 添加成绩详情模态框
- 完善相关后端接口和服务
This commit is contained in:
祀梦
2025-12-22 19:48:38 +08:00
parent 6ae9a7ebee
commit 59501e514f
12 changed files with 624 additions and 8 deletions

View File

@@ -2,6 +2,34 @@ const StudentService = require('../services/studentService');
const { success, error } = require('../utils/response');
class StudentController {
static async getCourses(req, res) {
try {
const userId = req.session.user.id;
const data = await StudentService.getStudentCourses(userId);
success(res, data);
} catch (err) {
if (err.message === '学生信息不存在') {
return error(res, err.message, 404);
}
console.error('Get Courses Error:', err);
error(res, '服务器错误');
}
}
static async getCourseDetails(req, res) {
try {
const courseId = req.params.id;
const data = await StudentService.getCourseDetails(courseId);
success(res, data);
} catch (err) {
if (err.message === '课程不存在') {
return error(res, err.message, 404);
}
console.error('Get Course Details Error:', err);
error(res, '服务器错误');
}
}
static async getGrades(req, res) {
try {
const userId = req.session.user.id;

View File

@@ -12,6 +12,31 @@ class Course {
const rows = await db.query('SELECT * FROM courses WHERE id = ?', [id]);
return rows[0];
}
static async findDetailsById(id) {
const sql = `
SELECT c.*, u.name as teacher_name, cl.class_name
FROM courses c
JOIN users u ON c.teacher_id = u.id
JOIN classes cl ON c.class_id = cl.id
WHERE c.id = ?
`;
const rows = await db.query(sql, [id]);
return rows[0];
}
static async findByStudentId(studentId) {
const sql = `
SELECT c.*, u.name as teacher_name
FROM courses c
JOIN classes cl ON c.class_id = cl.id
JOIN students s ON cl.class_name = s.class
JOIN users u ON c.teacher_id = u.id
WHERE s.id = ?
ORDER BY c.course_code
`;
return await db.query(sql, [studentId]);
}
}
module.exports = Course;

View File

@@ -22,7 +22,7 @@ class Score {
s.usual_score, s.midterm_score, s.final_score, s.total_score as score,
s.grade_point, s.grade_level, s.created_at, s.remark,
c.course_code, c.course_name, c.credit, c.semester,
u.name as teacher_name, u.email as teacher_email,
u.name as teacher_name,
st.id as student_number, st.class as class_name
FROM grades s
JOIN courses c ON s.course_id = c.id

View File

@@ -3,6 +3,8 @@ const router = express.Router();
const StudentController = require('../controllers/studentController');
const { requireAuth, requireRole } = require('../middleware/auth');
router.get('/courses', requireAuth, requireRole(['student']), StudentController.getCourses);
router.get('/courses/:id', requireAuth, requireRole(['student']), StudentController.getCourseDetails);
router.get('/grades', requireAuth, requireRole(['student']), StudentController.getGrades);
router.get('/grades/:id', requireAuth, requireRole(['student']), StudentController.getGradeDetails);

View File

@@ -96,6 +96,9 @@ app.get('/dashboard', requirePageAuth, (req, res) => {
app.get('/student/dashboard', requirePageAuth, requirePageRole(['student']), (req, res) => {
res.sendFile(path.join(__dirname, '../frontend/views/student/dashboard.html'));
});
app.get('/student/my-courses', requirePageAuth, requirePageRole(['student']), (req, res) => {
res.sendFile(path.join(__dirname, '../frontend/views/student/my_courses.html'));
});
app.get('/student/profile', requirePageAuth, requirePageRole(['student']), (req, res) => {
res.sendFile(path.join(__dirname, '../frontend/views/student/profile.html'));
});

View File

@@ -1,7 +1,27 @@
const Score = require('../models/Score');
const Student = require('../models/Student');
const Course = require('../models/Course');
class StudentService {
static async getStudentCourses(userId) {
const student = await Student.findById(userId);
if (!student) {
throw new Error('学生信息不存在');
}
const courses = await Course.findByStudentId(userId);
return courses;
}
static async getCourseDetails(courseId) {
const course = await Course.findDetailsById(courseId);
if (!course) {
throw new Error('课程不存在');
}
return course;
}
static async getStudentGrades(userId) {
// 先通过 userId 获取 studentId
// 假设 users.id = students.id或者通过 user_id 关联