class StudentManager {
constructor() {
// 动态设置API基础URL,支持file:///协议和localhost:3000访问
this.apiBase = window.location.protocol === 'file:' ? 'http://localhost:3000/api' : '/api';
this.initDashboard();
this.initGradeDetails();
this.loadProfile();
}
async initDashboard() {
const gradeList = document.getElementById('gradeList');
const statisticsElement = document.getElementById('statistics');
if (!gradeList) return;
try {
const response = await fetch(`${this.apiBase}/student/grades`, {
credentials: 'include'
});
if (response.status === 401) {
// 未登录,重定向到登录页
this.showNotification('请先登录', 'error');
setTimeout(() => {
window.location.href = '/html/login.html';
}, 1500);
return;
}
const data = await response.json();
if (data.success) {
this.renderGrades(data.grades);
this.renderStatistics(data.statistics);
this.updateChart(data.grades);
} else {
this.showNotification(data.message || '获取成绩失败', 'error');
}
} catch (error) {
console.error('获取成绩错误:', error);
this.showNotification('网络错误,请重试', 'error');
}
}
renderGrades(grades) {
const gradeList = document.getElementById('gradeList');
const gradeTable = document.getElementById('gradeTable');
if (!gradeTable) return;
if (grades.length === 0) {
gradeList.innerHTML = `
`;
return;
}
const tbody = gradeTable.querySelector('tbody');
tbody.innerHTML = '';
grades.forEach(grade => {
const row = document.createElement('tr');
// 根据分数设置颜色
let scoreClass = '';
if (grade.score >= 90) scoreClass = 'grade-excellent';
else if (grade.score >= 80) scoreClass = 'grade-good';
else if (grade.score >= 60) scoreClass = 'grade-pass';
else scoreClass = 'grade-fail';
row.innerHTML = `
${grade.course_code} |
${grade.course_name} |
${grade.credit} |
${grade.score}
|
${grade.grade_level || '-'} |
${grade.grade_point || '-'} |
${grade.teacher_name} |
${new Date(grade.exam_date).toLocaleDateString()} |
查看
|
`;
tbody.appendChild(row);
});
}
renderStatistics(statistics) {
const element = document.getElementById('statistics');
if (!element) return;
element.innerHTML = `
${statistics.totalCourses}
总课程数
${statistics.totalCredits}
总学分
${statistics.averageScore}
平均分
`;
}
async loadProfile() {
const profileElement = document.getElementById('profileInfo');
if (!profileElement) return;
try {
const response = await fetch(`${this.apiBase}/student/profile`, {
credentials: 'include'
});
if (response.status === 401) {
// 未登录,重定向到登录页
this.showNotification('请先登录', 'error');
setTimeout(() => {
window.location.href = '/html/login.html';
}, 1500);
return;
}
const data = await response.json();
if (data.success) {
const profile = data.profile;
// 更新学生仪表板顶部信息
const userNameElement = document.getElementById('userName');
const studentNameElement = document.getElementById('studentName');
const studentClassElement = document.getElementById('studentClass');
if (userNameElement) {
userNameElement.textContent = profile.full_name || profile.username;
}
if (studentNameElement) {
studentNameElement.textContent = profile.full_name || profile.username;
}
if (studentClassElement) {
studentClassElement.textContent = profile.class_name || '未设置';
}
profileElement.innerHTML = `
专业
${profile.major || '未设置'}
入学年份
${profile.enrollment_year || '未设置'}
`;
} else {
// API返回失败
this.showNotification(data.message || '获取个人信息失败', 'error');
}
} catch (error) {
console.error('加载个人信息错误:', error);
this.showNotification('网络错误,请重试', 'error');
}
}
async initGradeDetails() {
const urlParams = new URLSearchParams(window.location.search);
const gradeId = urlParams.get('id');
if (!gradeId) return;
try {
const response = await fetch(`${this.apiBase}/student/grades/${gradeId}`, {
credentials: 'include'
});
const data = await response.json();
if (data.success) {
this.renderGradeDetails(data.grade);
} else {
this.showNotification('获取成绩详情失败', 'error');
setTimeout(() => window.history.back(), 1500);
}
} catch (error) {
console.error('获取成绩详情错误:', error);
this.showNotification('网络错误,请重试', 'error');
}
}
renderGradeDetails(grade) {
const container = document.getElementById('gradeDetails');
if (!container) return;
// 计算绩点描述
let gradeDescription = '';
if (grade.score >= 90) gradeDescription = '优秀';
else if (grade.score >= 80) gradeDescription = '良好';
else if (grade.score >= 70) gradeDescription = '中等';
else if (grade.score >= 60) gradeDescription = '及格';
else gradeDescription = '不及格';
container.innerHTML = `
基本信息
学分:
${grade.credit}
学期:
${grade.semester}
考试日期:
${new Date(grade.exam_date).toLocaleDateString()}
等级:
${grade.grade_level || '-'}
绩点:
${grade.grade_point || '-'}
学生信息
姓名:
${grade.full_name}
学号:
${grade.student_number}
班级:
${grade.class_name}
专业:
${grade.major || '未设置'}
教师信息
任课教师:
${grade.teacher_name}
教师邮箱:
${grade.teacher_email}
${grade.remark ? `
` : ''}
`;
}
updateChart(grades) {
const ctx = document.getElementById('gradeChart');
if (!ctx) return;
if (typeof Chart === 'undefined') {
// 如果没有Chart.js,延迟加载
this.loadChartLibrary().then(() => this.updateChart(grades));
return;
}
const courseNames = grades.map(g => g.course_name);
const scores = grades.map(g => g.score);
// 销毁现有图表实例
if (window.gradeChart instanceof Chart) {
window.gradeChart.destroy();
}
window.gradeChart = new Chart(ctx, {
type: 'bar',
data: {
labels: courseNames,
datasets: [{
label: '分数',
data: scores,
backgroundColor: scores.map(score => {
if (score >= 90) return 'rgba(75, 192, 192, 0.7)';
if (score >= 80) return 'rgba(54, 162, 235, 0.7)';
if (score >= 60) return 'rgba(255, 206, 86, 0.7)';
return 'rgba(255, 99, 132, 0.7)';
}),
borderColor: scores.map(score => {
if (score >= 90) return 'rgb(75, 192, 192)';
if (score >= 80) return 'rgb(54, 162, 235)';
if (score >= 60) return 'rgb(255, 206, 86)';
return 'rgb(255, 99, 132)';
}),
borderWidth: 1
}]
},
options: {
responsive: true,
plugins: {
title: {
display: true,
text: '各科成绩分布'
}
},
scales: {
y: {
beginAtZero: true,
max: 100
}
}
}
});
}
async loadChartLibrary() {
return new Promise((resolve, reject) => {
if (typeof Chart !== 'undefined') {
resolve();
return;
}
const script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/chart.js';
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
}
showNotification(message, type = 'info') {
// 使用AuthManager的通知系统或自己实现
if (window.authManager && window.authManager.showNotification) {
window.authManager.showNotification(message, type);
} else {
alert(message);
}
}
}
// 初始化学生管理器
document.addEventListener('DOMContentLoaded', () => {
if (window.location.pathname.includes('/student/')) {
window.studentManager = new StudentManager();
}
});