refactor(frontend): 重构前端目录结构并优化认证流程
将前端文件从html目录迁移到views目录,按功能模块组织 重构认证中间件和路由处理,简化页面权限控制 更新静态资源引用路径,统一使用/public前缀 添加学生仪表板页面,优化移动端显示 移除旧版html和js文件,更新样式和脚本
This commit is contained in:
@@ -52,65 +52,72 @@ app.use(session({
|
||||
}
|
||||
}));
|
||||
|
||||
// 静态文件服务
|
||||
app.use(express.static(path.join(__dirname, '../frontend')));
|
||||
// 静态文件服务 - 只公开 public 目录
|
||||
app.use('/public', express.static(path.join(__dirname, '../frontend/public')));
|
||||
|
||||
// 重定向旧路径 /frontend/html/* 到 /html/*
|
||||
app.get('/frontend/html/*', (req, res) => {
|
||||
const path = req.params[0];
|
||||
res.redirect(`/html/${path}`);
|
||||
// 页面认证中间件
|
||||
const requirePageAuth = (req, res, next) => {
|
||||
if (!req.session.user) {
|
||||
return res.redirect('/login');
|
||||
}
|
||||
next();
|
||||
};
|
||||
|
||||
const requirePageRole = (allowedRoles) => {
|
||||
return (req, res, next) => {
|
||||
if (!req.session.user) return res.redirect('/login');
|
||||
if (!allowedRoles.includes(req.session.user.role)) {
|
||||
return res.status(403).send('<h1>403 Forbidden - 权限不足</h1><a href="/dashboard">返回首页</a>');
|
||||
}
|
||||
next();
|
||||
};
|
||||
};
|
||||
|
||||
// 页面路由
|
||||
app.get('/', (req, res) => res.redirect('/login'));
|
||||
app.get('/login', (req, res) => {
|
||||
if (req.session.user) return res.redirect('/dashboard');
|
||||
res.sendFile(path.join(__dirname, '../frontend/views/auth/login.html'));
|
||||
});
|
||||
app.get('/register', (req, res) => res.sendFile(path.join(__dirname, '../frontend/views/auth/register.html')));
|
||||
|
||||
app.get('/dashboard', requirePageAuth, (req, res) => {
|
||||
const role = req.session.user?.role;
|
||||
switch (role) {
|
||||
case 'student': res.redirect('/student/dashboard'); break;
|
||||
case 'teacher': res.redirect('/teacher/dashboard'); break;
|
||||
case 'admin': res.redirect('/admin/dashboard'); break;
|
||||
default: res.redirect('/login');
|
||||
}
|
||||
});
|
||||
|
||||
// 路由
|
||||
// 学生页面
|
||||
app.get('/student/dashboard', requirePageAuth, requirePageRole(['student']), (req, res) => {
|
||||
res.sendFile(path.join(__dirname, '../frontend/views/student/dashboard.html'));
|
||||
});
|
||||
|
||||
// 教师页面
|
||||
const teacherRouter = express.Router();
|
||||
teacherRouter.use(requirePageAuth, requirePageRole(['teacher']));
|
||||
teacherRouter.get('/dashboard', (req, res) => res.sendFile(path.join(__dirname, '../frontend/views/teacher/dashboard.html')));
|
||||
teacherRouter.get('/grade_entry', (req, res) => res.sendFile(path.join(__dirname, '../frontend/views/teacher/grade_entry.html')));
|
||||
teacherRouter.get('/grade_management', (req, res) => res.sendFile(path.join(__dirname, '../frontend/views/teacher/grade_management.html')));
|
||||
app.use('/teacher', teacherRouter);
|
||||
|
||||
// 管理员页面
|
||||
const adminRouter = express.Router();
|
||||
adminRouter.use(requirePageAuth, requirePageRole(['admin']));
|
||||
adminRouter.get('/dashboard', (req, res) => res.sendFile(path.join(__dirname, '../frontend/views/admin/dashboard.html')));
|
||||
adminRouter.get('/student_management', (req, res) => res.sendFile(path.join(__dirname, '../frontend/views/admin/student_management.html')));
|
||||
adminRouter.get('/user_management', (req, res) => res.sendFile(path.join(__dirname, '../frontend/views/admin/user_management.html')));
|
||||
app.use('/admin', adminRouter);
|
||||
|
||||
// API 路由
|
||||
app.use('/api/auth', authRoutes);
|
||||
app.use('/api/student', studentRoutes);
|
||||
app.use('/api/teacher', teacherRoutes);
|
||||
app.use('/api/admin', adminRoutes);
|
||||
|
||||
// 认证中间件
|
||||
const { requireAuth, requireRole } = require('./middleware/auth');
|
||||
|
||||
// 页面路由
|
||||
app.get('/', (req, res) => {
|
||||
res.sendFile(path.join(__dirname, '../frontend/html/login.html'));
|
||||
});
|
||||
|
||||
app.get('/dashboard', requireAuth, (req, res) => {
|
||||
// 根据用户角色重定向到不同的仪表板
|
||||
const role = req.session.user?.role;
|
||||
|
||||
switch (role) {
|
||||
case 'student':
|
||||
res.redirect('/html/student_dashboard.html');
|
||||
break;
|
||||
case 'teacher':
|
||||
res.redirect('/html/teacher_dashboard.html');
|
||||
break;
|
||||
case 'admin':
|
||||
res.redirect('/html/admin_dashboard.html');
|
||||
break;
|
||||
default:
|
||||
// 如果没有角色信息,重定向到登录页面
|
||||
res.redirect('/');
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// 学生页面路由
|
||||
app.get('/student/*', requireAuth, requireRole(['student', 'admin', 'teacher']), (req, res, next) => {
|
||||
next();
|
||||
});
|
||||
|
||||
// 教师页面路由
|
||||
app.get('/teacher/*', requireAuth, requireRole(['teacher', 'admin']), (req, res, next) => {
|
||||
next();
|
||||
});
|
||||
|
||||
// 管理员页面路由
|
||||
app.get('/admin/*', requireAuth, requireRole(['admin']), (req, res, next) => {
|
||||
next();
|
||||
});
|
||||
|
||||
// 404处理
|
||||
app.use((req, res) => {
|
||||
res.status(404).json({ error: 'Not found' });
|
||||
|
||||
@@ -1,269 +0,0 @@
|
||||
class AuthManager {
|
||||
constructor() {
|
||||
// 动态设置API基础URL,支持file:///协议和localhost:3000访问
|
||||
this.apiBase = window.location.protocol === 'file:' ? 'http://localhost:3000/api' : '/api';
|
||||
this.initEventListeners();
|
||||
this.checkAuthStatus();
|
||||
}
|
||||
|
||||
async checkAuthStatus() {
|
||||
try {
|
||||
const response = await fetch(`${this.apiBase}/auth/me`);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success && data.user) {
|
||||
// 用户已登录,根据角色重定向到正确的仪表板
|
||||
const userRole = data.user.role;
|
||||
let redirectUrl = '/dashboard';
|
||||
|
||||
if (userRole === 'student') {
|
||||
redirectUrl = '/frontend/html/student_dashboard.html';
|
||||
} else if (userRole === 'teacher') {
|
||||
redirectUrl = '/frontend/html/teacher_dashboard.html';
|
||||
} else if (userRole === 'admin') {
|
||||
redirectUrl = '/frontend/html/admin_dashboard.html';
|
||||
}
|
||||
|
||||
// 如果当前页面是登录或注册页面,则重定向到仪表板
|
||||
const currentPath = window.location.pathname;
|
||||
if (currentPath.includes('login.html') || currentPath.includes('register.html')) {
|
||||
window.location.href = redirectUrl;
|
||||
}
|
||||
// 如果当前页面不是正确的仪表板页面,则重定向
|
||||
else if (!currentPath.includes(redirectUrl) &&
|
||||
currentPath !== '/' &&
|
||||
!currentPath.includes('index.html')) {
|
||||
window.location.href = redirectUrl;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('用户未登录');
|
||||
}
|
||||
}
|
||||
|
||||
initEventListeners() {
|
||||
// 登录表单提交
|
||||
const loginForm = document.getElementById('loginForm');
|
||||
if (loginForm) {
|
||||
loginForm.addEventListener('submit', (e) => this.handleLogin(e));
|
||||
}
|
||||
|
||||
// 注册表单提交
|
||||
const registerForm = document.getElementById('registerForm');
|
||||
if (registerForm) {
|
||||
registerForm.addEventListener('submit', (e) => this.handleRegister(e));
|
||||
}
|
||||
|
||||
// 登出按钮
|
||||
const logoutBtn = document.getElementById('logoutBtn');
|
||||
if (logoutBtn) {
|
||||
logoutBtn.addEventListener('click', (e) => this.handleLogout(e));
|
||||
}
|
||||
}
|
||||
|
||||
async handleLogin(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const form = e.target;
|
||||
const formData = new FormData(form);
|
||||
const data = Object.fromEntries(formData.entries());
|
||||
|
||||
const submitBtn = form.querySelector('button[type="submit"]');
|
||||
const originalText = submitBtn.innerHTML;
|
||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 登录中...';
|
||||
submitBtn.disabled = true;
|
||||
|
||||
try {
|
||||
const response = await fetch(`${this.apiBase}/auth/login`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
this.showNotification('登录成功!正在跳转...', 'success');
|
||||
|
||||
// 根据用户角色跳转到不同的仪表板
|
||||
const userRole = result.user?.role;
|
||||
let redirectUrl = '/dashboard';
|
||||
|
||||
if (userRole === 'student') {
|
||||
redirectUrl = '/frontend/html/student_dashboard.html';
|
||||
} else if (userRole === 'teacher') {
|
||||
redirectUrl = '/frontend/html/teacher_dashboard.html';
|
||||
} else if (userRole === 'admin') {
|
||||
redirectUrl = '/frontend/html/admin_dashboard.html';
|
||||
}
|
||||
|
||||
// 延迟跳转以显示通知
|
||||
setTimeout(() => {
|
||||
window.location.href = redirectUrl;
|
||||
}, 1500);
|
||||
} else {
|
||||
this.showNotification(result.message || '登录失败', 'error');
|
||||
submitBtn.innerHTML = originalText;
|
||||
submitBtn.disabled = false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('登录错误:', error);
|
||||
this.showNotification('网络错误,请重试', 'error');
|
||||
submitBtn.innerHTML = originalText;
|
||||
submitBtn.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
async handleRegister(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const form = e.target;
|
||||
const formData = new FormData(form);
|
||||
const data = Object.fromEntries(formData.entries());
|
||||
|
||||
// 验证密码
|
||||
if (data.password !== data.confirmPassword) {
|
||||
this.showNotification('两次输入的密码不一致', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const submitBtn = form.querySelector('button[type="submit"]');
|
||||
const originalText = submitBtn.innerHTML;
|
||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 注册中...';
|
||||
submitBtn.disabled = true;
|
||||
|
||||
try {
|
||||
const response = await fetch(`${this.apiBase}/auth/register`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
this.showNotification('注册成功!正在跳转到登录页面...', 'success');
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = '/html/login.html';
|
||||
}, 1500);
|
||||
} else {
|
||||
this.showNotification(result.message || '注册失败', 'error');
|
||||
submitBtn.innerHTML = originalText;
|
||||
submitBtn.disabled = false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('注册错误:', error);
|
||||
this.showNotification('网络错误,请重试', 'error');
|
||||
submitBtn.innerHTML = originalText;
|
||||
submitBtn.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
async handleLogout(e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (!confirm('确定要退出登录吗?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`${this.apiBase}/auth/logout`, {
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
this.showNotification('已成功退出登录', 'success');
|
||||
setTimeout(() => {
|
||||
window.location.href = '/';
|
||||
}, 1000);
|
||||
} else {
|
||||
this.showNotification('退出登录失败', 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('退出登录错误:', error);
|
||||
this.showNotification('网络错误,请重试', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
showNotification(message, type = 'info') {
|
||||
// 移除现有的通知
|
||||
const existingNotification = document.querySelector('.notification');
|
||||
if (existingNotification) {
|
||||
existingNotification.remove();
|
||||
}
|
||||
|
||||
// 创建新的通知
|
||||
const notification = document.createElement('div');
|
||||
notification.className = `notification notification-${type}`;
|
||||
notification.innerHTML = `
|
||||
<i class="fas fa-${type === 'success' ? 'check-circle' : 'exclamation-circle'}"></i>
|
||||
<span>${message}</span>
|
||||
`;
|
||||
|
||||
// 样式
|
||||
notification.style.cssText = `
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
background: ${type === 'success' ? '#10b981' : type === 'error' ? '#ef4444' : '#3b82f6'};
|
||||
color: white;
|
||||
padding: 15px 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
z-index: 1000;
|
||||
animation: slideIn 0.3s ease;
|
||||
`;
|
||||
|
||||
document.body.appendChild(notification);
|
||||
|
||||
// 3秒后自动移除
|
||||
setTimeout(() => {
|
||||
notification.style.animation = 'slideOut 0.3s ease';
|
||||
setTimeout(() => notification.remove(), 300);
|
||||
}, 3000);
|
||||
|
||||
// 添加动画关键帧
|
||||
if (!document.querySelector('#notification-styles')) {
|
||||
const style = document.createElement('style');
|
||||
style.id = 'notification-styles';
|
||||
style.textContent = `
|
||||
@keyframes slideIn {
|
||||
from {
|
||||
transform: translateX(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes slideOut {
|
||||
from {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
transform: translateX(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化认证管理器
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
window.authManager = new AuthManager();
|
||||
});
|
||||
47
frontend/public/css/notification.css
Normal file
47
frontend/public/css/notification.css
Normal file
@@ -0,0 +1,47 @@
|
||||
/* 通知消息样式 */
|
||||
.notification {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
padding: 15px 25px;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
z-index: 1000;
|
||||
transform: translateX(120%);
|
||||
transition: transform 0.3s ease;
|
||||
border-left: 4px solid #4e73df;
|
||||
max-width: 350px;
|
||||
}
|
||||
|
||||
.notification.show {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.notification.success {
|
||||
border-left-color: #2ecc71;
|
||||
}
|
||||
|
||||
.notification.error {
|
||||
border-left-color: #e74c3c;
|
||||
}
|
||||
|
||||
.notification i {
|
||||
margin-right: 10px;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.notification.success i {
|
||||
color: #2ecc71;
|
||||
}
|
||||
|
||||
.notification.error i {
|
||||
color: #e74c3c;
|
||||
}
|
||||
|
||||
.notification-content {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,9 +11,8 @@ class AdminDashboard {
|
||||
}
|
||||
|
||||
async init() {
|
||||
// 检查登录状态
|
||||
if (!await this.checkAuth()) {
|
||||
window.location.href = '/frontend/html/login.html';
|
||||
// 璉<EFBFBD><EFBFBD>亦蒈敶閧𠶖<EFBFBD>? if (!await this.checkAuth()) {
|
||||
window.location.href = '/login';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -32,8 +31,7 @@ class AdminDashboard {
|
||||
// 更新界面
|
||||
this.updateUI();
|
||||
|
||||
// 初始化图表
|
||||
this.initCharts();
|
||||
// <EFBFBD>嘥<EFBFBD><EFBFBD>硋㦛銵? this.initCharts();
|
||||
}
|
||||
|
||||
async checkAuth() {
|
||||
@@ -49,7 +47,7 @@ class AdminDashboard {
|
||||
const data = await response.json();
|
||||
return data.success && data.user.role === 'admin';
|
||||
} catch (error) {
|
||||
console.error('认证检查失败:', error);
|
||||
console.error('霈方<EFBFBD>璉<EFBFBD><EFBFBD>亙仃韐?', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -234,8 +232,7 @@ class AdminDashboard {
|
||||
}
|
||||
});
|
||||
|
||||
// 退出登录
|
||||
document.getElementById('logoutBtn')?.addEventListener('click', () => {
|
||||
// <EFBFBD><EFBFBD><EFBFBD>箇蒈敶? document.getElementById('logoutBtn')?.addEventListener('click', () => {
|
||||
this.handleLogout();
|
||||
});
|
||||
|
||||
@@ -247,23 +244,20 @@ class AdminDashboard {
|
||||
|
||||
async loadPage(page) {
|
||||
// 这里可以实现页面切换逻辑
|
||||
// 暂时使用简单跳转
|
||||
switch (page) {
|
||||
// <EFBFBD><EFBFBD>𧒄雿輻鍂蝞<EFBFBD><EFBFBD>閗歲頧? switch (page) {
|
||||
case 'users':
|
||||
window.location.href = '/frontend/html/user_management.html';
|
||||
window.location.href = '/admin/user_management';
|
||||
break;
|
||||
case 'students':
|
||||
window.location.href = '/frontend/html/student_management.html';
|
||||
window.location.href = '/admin/student_management';
|
||||
break;
|
||||
case 'teachers':
|
||||
// 可以跳转到教师管理页面
|
||||
break;
|
||||
// <EFBFBD>臭誑頝唾蓮<EFBFBD>唳<EFBFBD>撣<EFBFBD>恣<EFBFBD><EFBFBD>△<EFBFBD>? break;
|
||||
case 'grades':
|
||||
window.location.href = '/frontend/html/grade_management.html';
|
||||
window.location.href = '/teacher/grade_management';
|
||||
break;
|
||||
case 'settings':
|
||||
// 可以跳转到系统设置页面
|
||||
break;
|
||||
// <EFBFBD>臭誑頝唾蓮<EFBFBD>啁頂蝏蠘挽蝵桅△<EFBFBD>? break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,7 +268,7 @@ class AdminDashboard {
|
||||
const className = document.getElementById('classFilter')?.value || '';
|
||||
|
||||
// 这里可以实现搜索逻辑
|
||||
this.showNotification('搜索功能待实现', 'info');
|
||||
this.showNotification('<EFBFBD>𦦵揣<EFBFBD>蠘<EFBFBD>敺<EFBFBD><EFBFBD><EFBFBD>?, 'info');
|
||||
}
|
||||
|
||||
resetFilters() {
|
||||
@@ -291,10 +285,10 @@ class AdminDashboard {
|
||||
// 这里可以打开添加用户模态框
|
||||
const userData = {
|
||||
user_id: prompt('请输入用户ID:'),
|
||||
full_name: prompt('请输入姓名:'),
|
||||
role: prompt('请输入角色 (admin/teacher/student):'),
|
||||
email: prompt('请输入邮箱:'),
|
||||
class_name: prompt('请输入班级 (学生/教师可选):')
|
||||
full_name: prompt('霂瑁<EFBFBD><EFBFBD>亙<EFBFBD><EFBFBD>?'),
|
||||
role: prompt('霂瑁<EFBFBD><EFBFBD>亥<EFBFBD><EFBFBD>?(admin/teacher/student):'),
|
||||
email: prompt('霂瑁<EFBFBD><EFBFBD>仿<EFBFBD>蝞?'),
|
||||
class_name: prompt('霂瑁<EFBFBD><EFBFBD>亦号蝥?(摮衣<E691AE>/<2F>坔<EFBFBD><E59D94>舫<EFBFBD>?:')
|
||||
};
|
||||
|
||||
if (!userData.user_id || !userData.full_name || !userData.role) {
|
||||
@@ -353,7 +347,7 @@ class AdminDashboard {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!confirm(`确定要删除选中的 ${checkboxes.length} 个用户吗?`)) {
|
||||
if (!confirm(`蝖桀<EFBFBD>閬<EFBFBD><EFBFBD><EFBFBD>日<EFBFBD>劐葉<EFBFBD>?${checkboxes.length} 銝芰鍂<EFBFBD>瑕<EFBFBD>嚗鬮)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -385,10 +379,10 @@ class AdminDashboard {
|
||||
if (!user) return;
|
||||
|
||||
// 这里可以打开编辑模态框
|
||||
const newName = prompt('请输入新的姓名:', user.full_name);
|
||||
const newName = prompt('霂瑁<EFBFBD><EFBFBD>交鰵<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?', user.full_name);
|
||||
if (newName === null) return;
|
||||
|
||||
const newRole = prompt('请输入新的角色:', user.role);
|
||||
const newRole = prompt('霂瑁<EFBFBD><EFBFBD>交鰵<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?', user.role);
|
||||
if (newRole === null) return;
|
||||
|
||||
try {
|
||||
@@ -418,7 +412,7 @@ class AdminDashboard {
|
||||
}
|
||||
|
||||
async deleteUser(userId) {
|
||||
if (!confirm('确定要删除这个用户吗?')) {
|
||||
if (!confirm('蝖桀<EFBFBD>閬<EFBFBD><EFBFBD><EFBFBD>方<EFBFBD>銝芰鍂<EFBFBD>瑕<EFBFBD>嚗?)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -449,17 +443,17 @@ class AdminDashboard {
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
window.location.href = '/html/login.html';
|
||||
window.location.href = '/login';
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('退出登录失败:', error);
|
||||
console.error('<EFBFBD><EFBFBD><EFBFBD>箇蒈敶訫仃韐?', error);
|
||||
}
|
||||
}
|
||||
|
||||
async refreshData() {
|
||||
await this.loadStats();
|
||||
await this.loadUsers();
|
||||
this.showNotification('数据已刷新', 'success');
|
||||
this.showNotification('<EFBFBD>唳旿撌脣<EFBFBD><EFBFBD>?, 'success');
|
||||
}
|
||||
|
||||
updateUI() {
|
||||
@@ -473,11 +467,9 @@ class AdminDashboard {
|
||||
}
|
||||
|
||||
async initCharts() {
|
||||
// 加载Chart.js库
|
||||
await this.loadChartLibrary();
|
||||
// <EFBFBD>㰘蝸Chart.js摨? await this.loadChartLibrary();
|
||||
|
||||
// 初始化用户分布饼图
|
||||
this.initUserDistributionChart();
|
||||
// <EFBFBD>嘥<EFBFBD><EFBFBD>𣇉鍂<EFBFBD>瑕<EFBFBD>撣<EFBFBD>未<EFBFBD>? this.initUserDistributionChart();
|
||||
|
||||
// 初始化成绩分布柱状图
|
||||
this.initGradeDistributionChart();
|
||||
@@ -493,8 +485,7 @@ class AdminDashboard {
|
||||
<button class="notification-close">×</button>
|
||||
`;
|
||||
|
||||
// 添加到页面
|
||||
document.body.appendChild(notification);
|
||||
// 瘛餃<EFBFBD><EFBFBD>圈△<EFBFBD>? document.body.appendChild(notification);
|
||||
|
||||
// 添加关闭事件
|
||||
notification.querySelector('.notification-close').addEventListener('click', () => {
|
||||
@@ -527,7 +518,7 @@ class AdminDashboard {
|
||||
|
||||
// 模拟数据
|
||||
const data = {
|
||||
labels: ['学生', '教师', '管理员'],
|
||||
labels: ['摮衣<EFBFBD>', '<EFBFBD>坔<EFBFBD>', '蝞∠<EFBFBD><EFBFBD>?],
|
||||
datasets: [{
|
||||
data: [this.stats.totalStudents || 100, this.stats.totalTeachers || 20, 1],
|
||||
backgroundColor: [
|
||||
@@ -589,3 +580,4 @@ class AdminDashboard {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
287
frontend/public/js/auth.js
Normal file
287
frontend/public/js/auth.js
Normal file
@@ -0,0 +1,287 @@
|
||||
/**
|
||||
* 认证模块管理器
|
||||
* 处理登录、注册、注销及权限检查
|
||||
*/
|
||||
class AuthManager {
|
||||
constructor() {
|
||||
this.apiBase = '/api';
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.createNotificationContainer();
|
||||
this.initEventListeners();
|
||||
this.checkAuthStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建通知容器
|
||||
*/
|
||||
createNotificationContainer() {
|
||||
if (!document.getElementById('notification-container')) {
|
||||
const container = document.createElement('div');
|
||||
container.id = 'notification-container';
|
||||
container.style.cssText = `
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
`;
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户认证状态
|
||||
*/
|
||||
async checkAuthStatus() {
|
||||
// 如果当前是公共页面,可以选择不检查,或者检查后更新UI
|
||||
const currentPath = window.location.pathname;
|
||||
const isAuthPage = currentPath.includes('/login') || currentPath.includes('/register');
|
||||
|
||||
try {
|
||||
const response = await fetch(`${this.apiBase}/auth/me`);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success && data.user) {
|
||||
// 用户已登录
|
||||
const redirectUrl = this.getDashboardUrl(data.user.role);
|
||||
|
||||
// 如果在登录/注册页,跳转到仪表板
|
||||
if (isAuthPage || currentPath === '/') {
|
||||
window.location.href = redirectUrl;
|
||||
}
|
||||
} else {
|
||||
// 用户未登录,如果在受保护页面,跳转到登录页
|
||||
// 注意:后端通常已经处理了重定向,这里是前端的额外保障
|
||||
if (!isAuthPage && currentPath !== '/') {
|
||||
// 可以在这里添加逻辑,但通常交给后端控制
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Auth check failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
getDashboardUrl(role) {
|
||||
switch(role) {
|
||||
case 'student': return '/student/dashboard';
|
||||
case 'teacher': return '/teacher/dashboard';
|
||||
case 'admin': return '/admin/dashboard';
|
||||
default: return '/dashboard';
|
||||
}
|
||||
}
|
||||
|
||||
initEventListeners() {
|
||||
// 登录表单
|
||||
const loginForm = document.getElementById('loginForm');
|
||||
if (loginForm) {
|
||||
loginForm.addEventListener('submit', (e) => this.handleLogin(e));
|
||||
}
|
||||
|
||||
// 注册表单
|
||||
const registerForm = document.getElementById('registerForm');
|
||||
if (registerForm) {
|
||||
registerForm.addEventListener('submit', (e) => this.handleRegister(e));
|
||||
|
||||
// 角色选择联动
|
||||
const roleSelect = document.getElementById('role');
|
||||
if (roleSelect) {
|
||||
roleSelect.addEventListener('change', (e) => this.handleRoleChange(e));
|
||||
}
|
||||
}
|
||||
|
||||
// 注销按钮 (可能有多个,例如在导航栏)
|
||||
document.querySelectorAll('.btn-logout, #logoutBtn').forEach(btn => {
|
||||
btn.addEventListener('click', (e) => this.handleLogout(e));
|
||||
});
|
||||
}
|
||||
|
||||
handleRoleChange(e) {
|
||||
const role = e.target.value;
|
||||
const classField = document.getElementById('classField');
|
||||
const classInput = document.getElementById('class');
|
||||
|
||||
if (classField && classInput) {
|
||||
if (role === 'student' || role === 'teacher') {
|
||||
classField.style.display = 'block';
|
||||
classInput.required = true;
|
||||
} else {
|
||||
classField.style.display = 'none';
|
||||
classInput.required = false;
|
||||
classInput.value = ''; // 清空值
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async handleLogin(e) {
|
||||
e.preventDefault();
|
||||
const form = e.target;
|
||||
const submitBtn = form.querySelector('button[type="submit"]');
|
||||
|
||||
if (this.setLoading(submitBtn, true, '登录中...')) {
|
||||
try {
|
||||
const formData = new FormData(form);
|
||||
const data = Object.fromEntries(formData.entries());
|
||||
|
||||
const response = await fetch(`${this.apiBase}/auth/login`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
this.showNotification('登录成功,正在跳转...', 'success');
|
||||
setTimeout(() => {
|
||||
window.location.href = this.getDashboardUrl(result.user.role);
|
||||
}, 1000);
|
||||
} else {
|
||||
this.showNotification(result.message || '登录失败', 'error');
|
||||
this.setLoading(submitBtn, false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Login error:', error);
|
||||
this.showNotification('网络错误,请稍后重试', 'error');
|
||||
this.setLoading(submitBtn, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async handleRegister(e) {
|
||||
e.preventDefault();
|
||||
const form = e.target;
|
||||
const submitBtn = form.querySelector('button[type="submit"]');
|
||||
|
||||
// 获取数据
|
||||
const formData = new FormData(form);
|
||||
const data = Object.fromEntries(formData.entries());
|
||||
|
||||
// 简单验证
|
||||
if (data.password !== data.confirmPassword) {
|
||||
this.showNotification('两次输入的密码不一致', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.setLoading(submitBtn, true, '注册中...')) {
|
||||
try {
|
||||
const response = await fetch(`${this.apiBase}/auth/register`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
this.showNotification('注册成功,请登录', 'success');
|
||||
setTimeout(() => {
|
||||
window.location.href = '/login';
|
||||
}, 1500);
|
||||
} else {
|
||||
this.showNotification(result.message || '注册失败', 'error');
|
||||
this.setLoading(submitBtn, false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Register error:', error);
|
||||
this.showNotification('网络错误,请稍后重试', 'error');
|
||||
this.setLoading(submitBtn, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async handleLogout(e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (confirm('确定要退出登录吗?')) {
|
||||
try {
|
||||
const response = await fetch(`${this.apiBase}/auth/logout`, {
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
this.showNotification('已退出登录', 'success');
|
||||
setTimeout(() => {
|
||||
window.location.href = '/login';
|
||||
}, 1000);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Logout error:', error);
|
||||
// 即使出错也强制跳转到登录页
|
||||
window.location.href = '/login';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置按钮加载状态
|
||||
* @param {HTMLElement} btn 按钮元素
|
||||
* @param {boolean} isLoading 是否正在加载
|
||||
* @param {string} text 加载时的文本
|
||||
* @returns {boolean} true表示状态设置成功
|
||||
*/
|
||||
setLoading(btn, isLoading, text = '') {
|
||||
if (!btn) return false;
|
||||
|
||||
if (isLoading) {
|
||||
if (btn.dataset.loading) return false; // 防止重复提交
|
||||
btn.dataset.loading = 'true';
|
||||
btn.dataset.originalText = btn.innerHTML;
|
||||
btn.innerHTML = `<i class="fas fa-spinner fa-spin"></i> ${text}`;
|
||||
btn.disabled = true;
|
||||
} else {
|
||||
btn.innerHTML = btn.dataset.originalText || btn.innerHTML;
|
||||
delete btn.dataset.loading;
|
||||
btn.disabled = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示通知
|
||||
* @param {string} message 消息内容
|
||||
* @param {string} type 消息类型 'success' | 'error' | 'info'
|
||||
*/
|
||||
showNotification(message, type = 'info') {
|
||||
const container = document.getElementById('notification-container');
|
||||
if (!container) return;
|
||||
|
||||
const notification = document.createElement('div');
|
||||
notification.className = `notification ${type}`;
|
||||
|
||||
let icon = 'info-circle';
|
||||
if (type === 'success') icon = 'check-circle';
|
||||
if (type === 'error') icon = 'exclamation-circle';
|
||||
|
||||
notification.innerHTML = `
|
||||
<i class="fas fa-${icon}"></i>
|
||||
<span class="notification-content">${message}</span>
|
||||
`;
|
||||
|
||||
container.appendChild(notification);
|
||||
|
||||
// 动画显示
|
||||
requestAnimationFrame(() => {
|
||||
notification.classList.add('show');
|
||||
});
|
||||
|
||||
// 自动消失
|
||||
setTimeout(() => {
|
||||
notification.classList.remove('show');
|
||||
notification.addEventListener('transitionend', () => {
|
||||
notification.remove();
|
||||
});
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
window.authManager = new AuthManager();
|
||||
});
|
||||
@@ -7,8 +7,7 @@ class MainPage {
|
||||
}
|
||||
|
||||
init() {
|
||||
// 初始化所有功能
|
||||
this.initNavbar();
|
||||
// åˆ<EFBFBD>始化所有功èƒ? this.initNavbar();
|
||||
this.initScrollEffects();
|
||||
this.initSmoothScroll();
|
||||
this.initBackToTop();
|
||||
@@ -30,8 +29,7 @@ class MainPage {
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化当前页面高亮
|
||||
this.highlightCurrentPage();
|
||||
// åˆ<EFBFBD>始化当å‰<EFBFBD>页é<EFBFBD>¢é«˜äº? this.highlightCurrentPage();
|
||||
}
|
||||
|
||||
// 高亮当前页面导航链接
|
||||
@@ -47,9 +45,8 @@ class MainPage {
|
||||
});
|
||||
}
|
||||
|
||||
// 初始化滚动效果
|
||||
initScrollEffects() {
|
||||
// 滚动时显示/隐藏元素
|
||||
// åˆ<EFBFBD>始化滚动效æž? initScrollEffects() {
|
||||
// 滚动时显ç¤?éš<C3A9>è—<C3A8>å…ƒç´
|
||||
const observerOptions = {
|
||||
root: null,
|
||||
rootMargin: '0px',
|
||||
@@ -70,8 +67,7 @@ class MainPage {
|
||||
});
|
||||
}
|
||||
|
||||
// 初始化平滑滚动
|
||||
initSmoothScroll() {
|
||||
// åˆ<EFBFBD>始化平滑滚åŠ? initSmoothScroll() {
|
||||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||||
anchor.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
@@ -89,15 +85,14 @@ class MainPage {
|
||||
});
|
||||
}
|
||||
|
||||
// 初始化返回顶部按钮
|
||||
initBackToTop() {
|
||||
// åˆ<EFBFBD>始化返回顶部按é’? initBackToTop() {
|
||||
const backToTopBtn = document.createElement('button');
|
||||
backToTopBtn.id = 'backToTop';
|
||||
backToTopBtn.innerHTML = '<i class="fas fa-chevron-up"></i>';
|
||||
backToTopBtn.title = '返回顶部';
|
||||
document.body.appendChild(backToTopBtn);
|
||||
|
||||
// 滚动时显示/隐藏按钮
|
||||
// 滚动时显ç¤?éš<C3A9>è—<C3A8>按钮
|
||||
window.addEventListener('scroll', () => {
|
||||
if (window.scrollY > 300) {
|
||||
backToTopBtn.classList.add('show');
|
||||
@@ -136,8 +131,7 @@ class MainPage {
|
||||
});
|
||||
}
|
||||
|
||||
// 初始化认证按钮状态
|
||||
initAuthButtons() {
|
||||
// åˆ<EFBFBD>始化认è¯<EFBFBD>按钮状æ€? initAuthButtons() {
|
||||
// 检查用户是否已登录
|
||||
this.checkLoginStatus().then(user => {
|
||||
const loginBtn = document.getElementById('loginBtn');
|
||||
@@ -145,23 +139,22 @@ class MainPage {
|
||||
const heroLoginBtn = document.getElementById('heroLoginBtn');
|
||||
|
||||
if (user) {
|
||||
// 用户已登录,显示仪表板按钮
|
||||
// 根据用户角色设置正确的仪表板路径
|
||||
// 用户已登录,显示仪表æ<EFBFBD>¿æŒ‰é’? // æ ¹æ<C2B9>®ç”¨æˆ·è§’色设置æ£ç¡®çš„仪表æ<C2A8>¿è·¯å¾„
|
||||
let dashboardUrl = '/dashboard';
|
||||
if (user.role === 'student') {
|
||||
dashboardUrl = '/frontend/html/student_dashboard.html';
|
||||
dashboardUrl = '/student/dashboard';
|
||||
} else if (user.role === 'teacher') {
|
||||
dashboardUrl = '/frontend/html/teacher_dashboard.html';
|
||||
dashboardUrl = '/teacher/dashboard';
|
||||
} else if (user.role === 'admin') {
|
||||
dashboardUrl = '/frontend/html/admin_dashboard.html';
|
||||
dashboardUrl = '/admin/dashboard';
|
||||
}
|
||||
|
||||
if (loginBtn) {
|
||||
loginBtn.textContent = '进入仪表板';
|
||||
loginBtn.textContent = '进入仪表æ<EFBFBD>?;
|
||||
loginBtn.href = dashboardUrl;
|
||||
}
|
||||
if (heroLoginBtn) {
|
||||
heroLoginBtn.textContent = '进入仪表板';
|
||||
heroLoginBtn.textContent = '进入仪表æ<EFBFBD>?;
|
||||
heroLoginBtn.href = dashboardUrl;
|
||||
}
|
||||
if (registerBtn) {
|
||||
@@ -171,15 +164,14 @@ class MainPage {
|
||||
});
|
||||
}
|
||||
|
||||
// 检查登录状态
|
||||
async checkLoginStatus() {
|
||||
// 检查登录状� async checkLoginStatus() {
|
||||
try {
|
||||
const apiBase = window.location.protocol === 'file:' ? 'http://localhost:3000/api' : '/api';
|
||||
const response = await fetch(`${apiBase}/auth/me`);
|
||||
const data = await response.json();
|
||||
return data.success && data.user;
|
||||
} catch (error) {
|
||||
console.log('用户未登录');
|
||||
console.log('用户未登�);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -196,8 +188,7 @@ class MainPage {
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 添加到页面
|
||||
document.body.appendChild(notification);
|
||||
// æ·»åŠ åˆ°é¡µé<EFBFBD>? document.body.appendChild(notification);
|
||||
|
||||
// 显示通知
|
||||
setTimeout(() => {
|
||||
@@ -219,4 +210,4 @@ class MainPage {
|
||||
// 页面加载完成后初始化
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
new MainPage();
|
||||
});
|
||||
});
|
||||
@@ -19,10 +19,10 @@ class StudentManager {
|
||||
});
|
||||
|
||||
if (response.status === 401) {
|
||||
// 未登录,重定向到登录页
|
||||
// <EFBFBD>芰蒈敶𤏪<EFBFBD><EFBFBD>滚<EFBFBD><EFBFBD>穃<EFBFBD><EFBFBD>餃<EFBFBD>憿?
|
||||
this.showNotification('请先登录', 'error');
|
||||
setTimeout(() => {
|
||||
window.location.href = '/html/login.html';
|
||||
window.location.href = '/login';
|
||||
}, 1500);
|
||||
return;
|
||||
}
|
||||
@@ -113,14 +113,14 @@ class StudentManager {
|
||||
<i class="fas fa-star"></i>
|
||||
</div>
|
||||
<div class="stat-value">${statistics.totalCredits}</div>
|
||||
<div class="stat-label">总学分</div>
|
||||
<div class="stat-label"><EFBFBD>餃郎<EFBFBD>?/div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon grade">
|
||||
<i class="fas fa-chart-line"></i>
|
||||
</div>
|
||||
<div class="stat-value">${statistics.averageScore}</div>
|
||||
<div class="stat-label">平均分</div>
|
||||
<div class="stat-label">撟喳<EFBFBD><EFBFBD>?/div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon teacher">
|
||||
@@ -143,10 +143,10 @@ class StudentManager {
|
||||
});
|
||||
|
||||
if (response.status === 401) {
|
||||
// 未登录,重定向到登录页
|
||||
// <EFBFBD>芰蒈敶𤏪<EFBFBD><EFBFBD>滚<EFBFBD><EFBFBD>穃<EFBFBD><EFBFBD>餃<EFBFBD>憿?
|
||||
this.showNotification('请先登录', 'error');
|
||||
setTimeout(() => {
|
||||
window.location.href = '/html/login.html';
|
||||
window.location.href = '/login';
|
||||
}, 1500);
|
||||
return;
|
||||
}
|
||||
@@ -156,7 +156,7 @@ class StudentManager {
|
||||
if (data.success) {
|
||||
const profile = data.profile;
|
||||
|
||||
// 更新学生仪表板顶部信息
|
||||
// <EFBFBD>湔鰵摮衣<EFBFBD>隞芾”<EFBFBD>輸▲<EFBFBD>其縑<EFBFBD>?
|
||||
const userNameElement = document.getElementById('userName');
|
||||
const studentNameElement = document.getElementById('studentName');
|
||||
const studentClassElement = document.getElementById('studentClass');
|
||||
@@ -168,7 +168,7 @@ class StudentManager {
|
||||
studentNameElement.textContent = profile.full_name || profile.username;
|
||||
}
|
||||
if (studentClassElement) {
|
||||
studentClassElement.textContent = profile.class_name || '未设置';
|
||||
studentClassElement.textContent = profile.class_name || '<EFBFBD>芾挽蝵?;
|
||||
}
|
||||
|
||||
profileElement.innerHTML = `
|
||||
@@ -202,14 +202,14 @@ class StudentManager {
|
||||
<i class="fas fa-book"></i>
|
||||
<div>
|
||||
<h4>专业</h4>
|
||||
<p>${profile.major || '未设置'}</p>
|
||||
<p>${profile.major || '<EFBFBD>芾挽蝵?}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
<div>
|
||||
<h4>入学年份</h4>
|
||||
<p>${profile.enrollment_year || '未设置'}</p>
|
||||
<p>${profile.enrollment_year || '<EFBFBD>芾挽蝵?}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -258,14 +258,14 @@ class StudentManager {
|
||||
else if (grade.score >= 80) gradeDescription = '良好';
|
||||
else if (grade.score >= 70) gradeDescription = '中等';
|
||||
else if (grade.score >= 60) gradeDescription = '及格';
|
||||
else gradeDescription = '不及格';
|
||||
else gradeDescription = '銝滚<EFBFBD><EFBFBD>?;
|
||||
|
||||
container.innerHTML = `
|
||||
<div class="grade-detail-card">
|
||||
<div class="grade-header">
|
||||
<h2>${grade.course_name} (${grade.course_code})</h2>
|
||||
<div class="grade-score ${grade.score >= 60 ? 'score-pass' : 'score-fail'}">
|
||||
${grade.score} 分
|
||||
${grade.score} <EFBFBD>?
|
||||
<span class="grade-description">${gradeDescription}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -274,23 +274,23 @@ class StudentManager {
|
||||
<div class="detail-section">
|
||||
<h3><i class="fas fa-info-circle"></i> 基本信息</h3>
|
||||
<div class="detail-row">
|
||||
<span>学分:</span>
|
||||
<span>摮血<EFBFBD>嚗?/span>
|
||||
<strong>${grade.credit}</strong>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span>学期:</span>
|
||||
<span>摮行<EFBFBD>嚗?/span>
|
||||
<strong>${grade.semester}</strong>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span>考试日期:</span>
|
||||
<span><EFBFBD><EFBFBD><EFBFBD><EFBFBD>交<EFBFBD>嚗?/span>
|
||||
<strong>${new Date(grade.exam_date).toLocaleDateString()}</strong>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span>等级:</span>
|
||||
<span>蝑厩漣嚗?/span>
|
||||
<strong class="grade-level-${grade.grade_level}">${grade.grade_level || '-'}</strong>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span>绩点:</span>
|
||||
<span>蝏拍<EFBFBD>嚗?/span>
|
||||
<strong>${grade.grade_point || '-'}</strong>
|
||||
</div>
|
||||
</div>
|
||||
@@ -298,31 +298,31 @@ class StudentManager {
|
||||
<div class="detail-section">
|
||||
<h3><i class="fas fa-user-graduate"></i> 学生信息</h3>
|
||||
<div class="detail-row">
|
||||
<span>姓名:</span>
|
||||
<span>憪枏<EFBFBD>嚗?/span>
|
||||
<strong>${grade.full_name}</strong>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span>学号:</span>
|
||||
<span>摮血噡嚗?/span>
|
||||
<strong>${grade.student_number}</strong>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span>班级:</span>
|
||||
<span><EFBFBD>剔漣嚗?/span>
|
||||
<strong>${grade.class_name}</strong>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span>专业:</span>
|
||||
<strong>${grade.major || '未设置'}</strong>
|
||||
<span>銝㮖<EFBFBD>嚗?/span>
|
||||
<strong>${grade.major || '<EFBFBD>芾挽蝵?}</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<h3><i class="fas fa-chalkboard-teacher"></i> 教师信息</h3>
|
||||
<div class="detail-row">
|
||||
<span>任课教师:</span>
|
||||
<span>隞餉紋<EFBFBD>坔<EFBFBD>嚗?/span>
|
||||
<strong>${grade.teacher_name}</strong>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span>教师邮箱:</span>
|
||||
<span><EFBFBD>坔<EFBFBD><EFBFBD>桃拳嚗?/span>
|
||||
<strong>${grade.teacher_email}</strong>
|
||||
</div>
|
||||
</div>
|
||||
@@ -337,7 +337,7 @@ class StudentManager {
|
||||
|
||||
<div class="grade-actions">
|
||||
<button onclick="window.print()" class="btn btn-secondary">
|
||||
<i class="fas fa-print"></i> 打印成绩单
|
||||
<i class="fas fa-print"></i> <EFBFBD>枏㫲<EFBFBD>鞟貍<EFBFBD>?
|
||||
</button>
|
||||
<button onclick="window.history.back()" class="btn btn-primary">
|
||||
<i class="fas fa-arrow-left"></i> 返回
|
||||
@@ -352,7 +352,7 @@ class StudentManager {
|
||||
if (!ctx) return;
|
||||
|
||||
if (typeof Chart === 'undefined') {
|
||||
// 如果没有Chart.js,延迟加载
|
||||
// 憒<EFBFBD><EFBFBD>瘝⊥<EFBFBD>Chart.js嚗<EFBFBD>辣餈笔<EFBFBD>頧?
|
||||
this.loadChartLibrary().then(() => this.updateChart(grades));
|
||||
return;
|
||||
}
|
||||
@@ -360,7 +360,7 @@ class StudentManager {
|
||||
const courseNames = grades.map(g => g.course_name);
|
||||
const scores = grades.map(g => g.score);
|
||||
|
||||
// 销毁现有图表实例
|
||||
// <EFBFBD><EFBFBD>瘥<EFBFBD>緵<EFBFBD>匧㦛銵典<EFBFBD>靘?
|
||||
if (window.gradeChart instanceof Chart) {
|
||||
window.gradeChart.destroy();
|
||||
}
|
||||
@@ -421,7 +421,7 @@ class StudentManager {
|
||||
}
|
||||
|
||||
showNotification(message, type = 'info') {
|
||||
// 使用AuthManager的通知系统或自己实现
|
||||
// 雿輻鍂AuthManager<EFBFBD><EFBFBD><EFBFBD>𡁶䰻蝟餌<EFBFBD><EFBFBD>𤥁䌊撌勗<EFBFBD><EFBFBD>?
|
||||
if (window.authManager && window.authManager.showNotification) {
|
||||
window.authManager.showNotification(message, type);
|
||||
} else {
|
||||
@@ -435,4 +435,4 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
if (window.location.pathname.includes('/student/')) {
|
||||
window.studentManager = new StudentManager();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -9,9 +9,8 @@ class TeacherDashboard {
|
||||
}
|
||||
|
||||
async init() {
|
||||
// 检查登录状态
|
||||
if (!await this.checkAuth()) {
|
||||
window.location.href = '/frontend/html/login.html';
|
||||
// 璉<EFBFBD><EFBFBD>亦蒈敶閧𠶖<EFBFBD>? if (!await this.checkAuth()) {
|
||||
window.location.href = '/login';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -44,7 +43,7 @@ class TeacherDashboard {
|
||||
const data = await response.json();
|
||||
return data.success && data.user.role === 'teacher';
|
||||
} catch (error) {
|
||||
console.error('认证检查失败:', error);
|
||||
console.error('霈方<EFBFBD>璉<EFBFBD><EFBFBD>亙仃韐?', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -108,8 +107,7 @@ class TeacherDashboard {
|
||||
}
|
||||
|
||||
populateCourseSelectors() {
|
||||
// 填充课程选择器
|
||||
const courseSelectors = document.querySelectorAll('.course-selector');
|
||||
// 憛怠<EFBFBD>霂曄<EFBFBD><EFBFBD>㗇𥋘<EFBFBD>? const courseSelectors = document.querySelectorAll('.course-selector');
|
||||
courseSelectors.forEach(select => {
|
||||
select.innerHTML = '<option value="">请选择课程</option>';
|
||||
this.courses.forEach(course => {
|
||||
@@ -153,7 +151,7 @@ class TeacherDashboard {
|
||||
<span class="grade-score">${grade.score}</span>
|
||||
<span class="grade-level">${grade.grade_level}</span>
|
||||
</td>
|
||||
<td>${grade.exam_date ? new Date(grade.exam_date).toLocaleDateString() : '未设置'}</td>
|
||||
<td>${grade.exam_date ? new Date(grade.exam_date).toLocaleDateString() : '<EFBFBD>芾挽蝵?}</td>
|
||||
<td>
|
||||
<div class="action-buttons">
|
||||
<button class="btn-edit" data-id="${grade.id}">
|
||||
@@ -226,8 +224,7 @@ class TeacherDashboard {
|
||||
}
|
||||
});
|
||||
|
||||
// 退出登录
|
||||
document.getElementById('logoutBtn')?.addEventListener('click', () => {
|
||||
// <EFBFBD><EFBFBD><EFBFBD>箇蒈敶? document.getElementById('logoutBtn')?.addEventListener('click', () => {
|
||||
this.handleLogout();
|
||||
});
|
||||
}
|
||||
@@ -275,7 +272,7 @@ class TeacherDashboard {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!confirm(`确定要删除选中的 ${checkboxes.length} 条成绩记录吗?`)) {
|
||||
if (!confirm(`蝖桀<EFBFBD>閬<EFBFBD><EFBFBD><EFBFBD>日<EFBFBD>劐葉<EFBFBD>?${checkboxes.length} <EFBFBD>⊥<EFBFBD>蝏抵扇敶訫<EFBFBD>嚗鬮)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -308,12 +305,12 @@ class TeacherDashboard {
|
||||
|
||||
// 这里可以打开编辑模态框
|
||||
// 暂时使用简单提示框
|
||||
const newScore = prompt('请输入新的分数:', grade.score);
|
||||
const newScore = prompt('霂瑁<EFBFBD><EFBFBD>交鰵<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?', grade.score);
|
||||
if (newScore === null) return;
|
||||
|
||||
const numericScore = parseFloat(newScore);
|
||||
if (isNaN(numericScore) || numericScore < 0 || numericScore > 100) {
|
||||
this.showNotification('请输入0-100之间的有效分数', 'error');
|
||||
this.showNotification('霂瑁<EFBFBD><EFBFBD>?-100銋钅𡢿<E99285><F0A1A2BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -343,7 +340,7 @@ class TeacherDashboard {
|
||||
}
|
||||
|
||||
async deleteGrade(gradeId) {
|
||||
if (!confirm('确定要删除这条成绩记录吗?')) {
|
||||
if (!confirm('蝖桀<EFBFBD>閬<EFBFBD><EFBFBD><EFBFBD>方<EFBFBD><EFBFBD>⊥<EFBFBD>蝏抵扇敶訫<EFBFBD>嚗?)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -374,10 +371,10 @@ class TeacherDashboard {
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
window.location.href = '/frontend/html/login.html';
|
||||
window.location.href = '/login';
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('退出登录失败:', error);
|
||||
console.error('<EFBFBD><EFBFBD><EFBFBD>箇蒈敶訫仃韐?', error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,4 +403,4 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
if (window.location.pathname.includes('/teacher/')) {
|
||||
new TeacherDashboard();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -4,33 +4,32 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>学生成绩管理系统 - 管理员仪表板</title>
|
||||
<link rel="stylesheet" href="../css/style.css">
|
||||
<link rel="stylesheet" href="/public/css/style.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
</head>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 顶部导航栏 -->
|
||||
<!-- 憿園<EFBFBD>撖潸⏛<EFBFBD>?-->
|
||||
<nav class="navbar">
|
||||
<div class="navbar-brand">
|
||||
<i class="fas fa-graduation-cap"></i>
|
||||
<span>XX学校成绩管理系统</span>
|
||||
</div>
|
||||
<div class="navbar-menu">
|
||||
<a href="index.html" class="btn btn-secondary">
|
||||
<a href="/" class="btn btn-secondary">
|
||||
<i class="fas fa-home"></i> 主页
|
||||
</a>
|
||||
<div class="navbar-user">
|
||||
<span class="user-name" id="userName">管理员</span>
|
||||
<span class="user-name" id="userName">蝞∠<EFBFBD><EFBFBD>?/span>
|
||||
<button id="logoutBtn" class="btn btn-primary">
|
||||
<i class="fas fa-sign-out-alt"></i> 退出
|
||||
</button>
|
||||
<i class="fas fa-sign-out-alt"></i> <EFBFBD><EFBFBD><EFBFBD>? </button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- 仪表板容器 -->
|
||||
<!-- 隞芾”<EFBFBD>踹捆<EFBFBD>?-->
|
||||
<div class="dashboard-container">
|
||||
<!-- 左侧侧边栏 -->
|
||||
<!-- 撌虫儒靘扯器<EFBFBD>?-->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<div class="user-info">
|
||||
@@ -38,8 +37,8 @@
|
||||
<i class="fas fa-user-shield"></i>
|
||||
</div>
|
||||
<div class="user-details">
|
||||
<h3 id="adminName">管理员</h3>
|
||||
<p>系统管理员 | 权限:<span id="adminRole">超级管理员</span></p>
|
||||
<h3 id="adminName">蝞∠<EFBFBD><EFBFBD>?/h3>
|
||||
<p>蝟餌<EFBFBD>蝞∠<EFBFBD><EFBFBD>?| <20><><EFBFBD>嚗?span id="adminRole">頞<>漣蝞∠<E89D9E><E288A0>?/span></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -48,17 +47,17 @@
|
||||
<li>
|
||||
<a href="#" class="active">
|
||||
<i class="fas fa-tachometer-alt"></i>
|
||||
<span>仪表板</span>
|
||||
<span>隞芾”<EFBFBD>?/span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="user_management.html">
|
||||
<a href="/admin/user_management">
|
||||
<i class="fas fa-users"></i>
|
||||
<span>用户管理</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="student_management.html">
|
||||
<a href="/admin/student_management">
|
||||
<i class="fas fa-user-graduate"></i>
|
||||
<span>学生管理</span>
|
||||
</a>
|
||||
@@ -102,7 +101,7 @@
|
||||
<div>
|
||||
<h1 class="page-title">管理员仪表板</h1>
|
||||
<div class="breadcrumb">
|
||||
<a href="index.html">主页</a>
|
||||
<a href="/">銝駁△</a>
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
<span>管理员仪表板</span>
|
||||
</div>
|
||||
@@ -146,8 +145,7 @@
|
||||
<div class="stat-value" id="totalTeachers">128</div>
|
||||
<div class="stat-label">教师总数</div>
|
||||
<div class="stat-change">
|
||||
<i class="fas fa-minus"></i> 无变化
|
||||
</div>
|
||||
<i class="fas fa-minus"></i> <EFBFBD>惩<EFBFBD><EFBFBD>? </div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -173,8 +171,7 @@
|
||||
</div>
|
||||
<h3 class="function-title">用户管理</h3>
|
||||
<p class="function-description">
|
||||
管理所有用户账户,包括添加、编辑、删除用户,设置用户角色和权限。
|
||||
</p>
|
||||
蝞∠<EFBFBD><EFBFBD><EFBFBD><EFBFBD>厩鍂<EFBFBD>瑁揭<EFBFBD>瘀<EFBFBD><EFBFBD><EFBFBD>𡠺瘛餃<EFBFBD><EFBFBD><EFBFBD><EFBFBD>颲㻫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>斤鍂<EFBFBD>瘀<EFBFBD>霈曄蔭<EFBFBD>冽<EFBFBD>閫坿𠧧<EFBFBD>峕<EFBFBD><EFBFBD>僐<EFBFBD>? </p>
|
||||
<button class="btn btn-primary">进入管理</button>
|
||||
</div>
|
||||
|
||||
@@ -184,8 +181,7 @@
|
||||
</div>
|
||||
<h3 class="function-title">学生管理</h3>
|
||||
<p class="function-description">
|
||||
管理学生信息,包括学籍管理、班级分配、信息维护和批量导入导出。
|
||||
</p>
|
||||
蝞∠<EFBFBD>摮衣<EFBFBD>靽⊥<EFBFBD>嚗<EFBFBD><EFBFBD><EFBFBD>砍郎蝐滨恣<EFBFBD><EFBFBD><EFBFBD><EFBFBD>号蝥批<EFBFBD><EFBFBD>溻<EFBFBD><EFBFBD>縑<EFBFBD>舐輕<EFBFBD>文<EFBFBD><EFBFBD>寥<EFBFBD>撖澆<EFBFBD>撖澆枂<EFBFBD>? </p>
|
||||
<button class="btn btn-primary">进入管理</button>
|
||||
</div>
|
||||
|
||||
@@ -195,8 +191,7 @@
|
||||
</div>
|
||||
<h3 class="function-title">教师管理</h3>
|
||||
<p class="function-description">
|
||||
管理教师信息,包括教师分配、课程安排、权限设置和绩效考核。
|
||||
</p>
|
||||
蝞∠<EFBFBD><EFBFBD>坔<EFBFBD>靽⊥<EFBFBD>嚗<EFBFBD><EFBFBD><EFBFBD>祆<EFBFBD>撣<EFBFBD><EFBFBD><EFBFBD>溻<EFBFBD><EFBFBD>紋蝔见<EFBFBD><EFBFBD>鉝<EFBFBD><EFBFBD><EFBFBD><EFBFBD>鞱挽蝵桀<EFBFBD>蝏拇<EFBFBD><EFBFBD><EFBFBD>瓲<EFBFBD>? </p>
|
||||
<button class="btn btn-primary">进入管理</button>
|
||||
</div>
|
||||
|
||||
@@ -206,30 +201,28 @@
|
||||
</div>
|
||||
<h3 class="function-title">成绩统计</h3>
|
||||
<p class="function-description">
|
||||
查看全校成绩统计,生成分析报告,支持图表展示和数据导出。
|
||||
</p>
|
||||
<EFBFBD>亦<EFBFBD><EFBFBD>冽嵗<EFBFBD>鞟貍蝏蠘恣嚗𣬚<EFBFBD><EFBFBD>𣂼<EFBFBD><EFBFBD>鞉𥁒<EFBFBD>𠺪<EFBFBD><EFBFBD>舀<EFBFBD><EFBFBD>曇”撅閧內<EFBFBD>峕㺭<EFBFBD>桀紡<EFBFBD>箝<EFBFBD>? </p>
|
||||
<button class="btn btn-primary">查看统计</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 系统状态 -->
|
||||
<!-- 蝟餌<EFBFBD><EFBFBD>嗆<EFBFBD>?-->
|
||||
<div class="system-status">
|
||||
<h2 class="section-title">
|
||||
<i class="fas fa-server"></i>
|
||||
系统状态
|
||||
</h2>
|
||||
蝟餌<EFBFBD><EFBFBD>嗆<EFBFBD>? </h2>
|
||||
<div class="status-list">
|
||||
<div class="status-item">
|
||||
<div class="status-indicator online"></div>
|
||||
<div>
|
||||
<div class="status-label">数据库服务</div>
|
||||
<div class="status-label"><EFBFBD>唳旿摨𤘪<EFBFBD><EFBFBD>?/div>
|
||||
<div class="status-value">运行正常 | 响应时间: 12ms</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<div class="status-indicator online"></div>
|
||||
<div>
|
||||
<div class="status-label">Web服务器</div>
|
||||
<div class="status-label">Web<EFBFBD>滚𦛚<EFBFBD>?/div>
|
||||
<div class="status-value">运行正常 | 在线用户: 156</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -237,7 +230,7 @@
|
||||
<div class="status-indicator online"></div>
|
||||
<div>
|
||||
<div class="status-label">文件存储</div>
|
||||
<div class="status-value">使用率: 65% | 剩余: 35GB</div>
|
||||
<div class="status-value">雿輻鍂<EFBFBD>? 65% | <EFBFBD>拐<EFBFBD>: 35GB</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
@@ -250,12 +243,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 最近活动 -->
|
||||
<!-- <EFBFBD><EFBFBD>餈烐暑<EFBFBD>?-->
|
||||
<div class="recent-activities">
|
||||
<h2 class="section-title">
|
||||
<i class="fas fa-history"></i>
|
||||
最近活动
|
||||
</h2>
|
||||
<EFBFBD><EFBFBD>餈烐暑<EFBFBD>? </h2>
|
||||
<ul class="activity-list">
|
||||
<li class="activity-item">
|
||||
<div class="activity-icon">
|
||||
@@ -263,7 +255,7 @@
|
||||
</div>
|
||||
<div class="activity-content">
|
||||
<div class="activity-title">新增学生用户</div>
|
||||
<div class="activity-time">10分钟前 | 操作人: 管理员</div>
|
||||
<div class="activity-time">10<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?| <20>滢<EFBFBD>鈭? 蝞∠<E89D9E><E288A0>?/div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="activity-item">
|
||||
@@ -272,7 +264,7 @@
|
||||
</div>
|
||||
<div class="activity-content">
|
||||
<div class="activity-title">修改教师信息</div>
|
||||
<div class="activity-time">1小时前 | 操作人: 管理员</div>
|
||||
<div class="activity-time">1撠𤩺𧒄<EFBFBD>?| <20>滢<EFBFBD>鈭? 蝞∠<E89D9E><E288A0>?/div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="activity-item">
|
||||
@@ -281,7 +273,7 @@
|
||||
</div>
|
||||
<div class="activity-content">
|
||||
<div class="activity-title">生成成绩统计报告</div>
|
||||
<div class="activity-time">3小时前 | 操作人: 系统</div>
|
||||
<div class="activity-time">3撠𤩺𧒄<EFBFBD>?| <20>滢<EFBFBD>鈭? 蝟餌<E89D9F></div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="activity-item">
|
||||
@@ -290,7 +282,7 @@
|
||||
</div>
|
||||
<div class="activity-content">
|
||||
<div class="activity-title">导出用户数据</div>
|
||||
<div class="activity-time">5小时前 | 操作人: 管理员</div>
|
||||
<div class="activity-time">5撠𤩺𧒄<EFBFBD>?| <20>滢<EFBFBD>鈭? 蝞∠<E89D9E><E288A0>?/div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="activity-item">
|
||||
@@ -299,7 +291,7 @@
|
||||
</div>
|
||||
<div class="activity-content">
|
||||
<div class="activity-title">系统设置更新</div>
|
||||
<div class="activity-time">1天前 | 操作人: 管理员</div>
|
||||
<div class="activity-time">1憭拙<EFBFBD> | <20>滢<EFBFBD>鈭? 蝞∠<E89D9E><E288A0>?/div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -328,16 +320,13 @@
|
||||
updateCurrentTime();
|
||||
setInterval(updateCurrentTime, 1000);
|
||||
|
||||
// 退出登录
|
||||
document.getElementById('logoutBtn').addEventListener('click', function() {
|
||||
if (confirm('确定要退出登录吗?')) {
|
||||
// 清除登录状态
|
||||
localStorage.removeItem('token');
|
||||
// <EFBFBD><EFBFBD><EFBFBD>箇蒈敶? document.getElementById('logoutBtn').addEventListener('click', function() {
|
||||
if (confirm('蝖桀<E89D96>閬<EFBFBD><E996AC><EFBFBD><EFBFBD>箇蒈敶訫<E695B6>嚗?)) {
|
||||
// 皜<>膄<EFBFBD>餃<EFBFBD><E9A483>嗆<EFBFBD>? localStorage.removeItem('token');
|
||||
localStorage.removeItem('userRole');
|
||||
localStorage.removeItem('userInfo');
|
||||
|
||||
// 跳转到登录页面
|
||||
window.location.href = 'login.html';
|
||||
// 頝唾蓮<EFBFBD>啁蒈敶閖△<EFBFBD>? window.location.href = 'login.html';
|
||||
}
|
||||
});
|
||||
|
||||
@@ -350,4 +339,4 @@
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -4,55 +4,55 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>学生管理 - XX学校成绩管理系统</title>
|
||||
<link rel="stylesheet" href="../css/style.css">
|
||||
<link rel="stylesheet" href="/public/css/style.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- 导航栏 -->
|
||||
<!-- 撖潸⏛<EFBFBD>?-->
|
||||
<nav class="navbar">
|
||||
<div class="container">
|
||||
<div class="navbar-brand">
|
||||
<a href="index.html">
|
||||
<a href="/">
|
||||
<i class="fas fa-graduation-cap"></i>
|
||||
<span>XX学校成绩管理系统</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="navbar-menu">
|
||||
<a href="index.html" class="navbar-item">
|
||||
<a href="/" class="navbar-item">
|
||||
<i class="fas fa-home"></i>
|
||||
<span>主页</span>
|
||||
</a>
|
||||
<a href="admin_dashboard.html" class="navbar-item">
|
||||
<a href="/admin/dashboard" class="navbar-item">
|
||||
<i class="fas fa-tachometer-alt"></i>
|
||||
<span>控制面板</span>
|
||||
</a>
|
||||
<a href="student_management.html" class="navbar-item active">
|
||||
<a href="/admin/student_management" class="navbar-item active">
|
||||
<i class="fas fa-users"></i>
|
||||
<span>学生管理</span>
|
||||
</a>
|
||||
<a href="grade_management.html" class="navbar-item">
|
||||
<a href="/teacher/grade_management" class="navbar-item">
|
||||
<i class="fas fa-chart-bar"></i>
|
||||
<span>成绩管理</span>
|
||||
</a>
|
||||
<a href="user_management.html" class="navbar-item">
|
||||
<a href="/admin/user_management" class="navbar-item">
|
||||
<i class="fas fa-user-cog"></i>
|
||||
<span>用户管理</span>
|
||||
</a>
|
||||
<div class="navbar-user">
|
||||
<i class="fas fa-user-circle"></i>
|
||||
<span>管理员</span>
|
||||
<span>蝞∠<EFBFBD><EFBFBD>?/span>
|
||||
<div class="user-dropdown">
|
||||
<a href="#"><i class="fas fa-user"></i> 个人资料</a>
|
||||
<a href="#"><i class="fas fa-cog"></i> 设置</a>
|
||||
<a href="login.html"><i class="fas fa-sign-out-alt"></i> 退出登录</a>
|
||||
<a href="/login"><i class="fas fa-sign-out-alt"></i> <EFBFBD><EFBFBD><EFBFBD>箇蒈敶?/a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- 主要内容区 -->
|
||||
<!-- 銝餉<EFBFBD><EFBFBD><EFBFBD>捆<EFBFBD>?-->
|
||||
<main class="main-content">
|
||||
<div class="container">
|
||||
<div class="student-management">
|
||||
@@ -62,35 +62,35 @@
|
||||
<p>管理学生基本信息,支持添加、编辑、删除和查询学生信息</p>
|
||||
</div>
|
||||
|
||||
<!-- 筛选区域 -->
|
||||
<!-- 蝑偦<EFBFBD>匧躹<EFBFBD>?-->
|
||||
<div class="filter-section">
|
||||
<div class="filter-row">
|
||||
<div class="filter-group">
|
||||
<label for="student-id"><i class="fas fa-id-card"></i> 学号</label>
|
||||
<input type="text" id="student-id" placeholder="请输入学号">
|
||||
<input type="text" id="student-id" placeholder="霂瑁<EFBFBD><EFBFBD>亙郎<EFBFBD>?>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label for="student-name"><i class="fas fa-user"></i> 姓名</label>
|
||||
<input type="text" id="student-name" placeholder="请输入姓名">
|
||||
<input type="text" id="student-name" placeholder="霂瑁<EFBFBD><EFBFBD>亙<EFBFBD><EFBFBD>?>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label for="class-select"><i class="fas fa-school"></i> 班级</label>
|
||||
<select id="class-select">
|
||||
<option value="">全部班级</option>
|
||||
<option value="计算机科学与技术1班">计算机科学与技术1班</option>
|
||||
<option value="计算机科学与技术2班">计算机科学与技术2班</option>
|
||||
<option value="软件工程1班">软件工程1班</option>
|
||||
<option value="软件工程2班">软件工程2班</option>
|
||||
<option value="网络工程1班">网络工程1班</option>
|
||||
<option value="网络工程2班">网络工程2班</option>
|
||||
<option value="霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?>霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?/option>
|
||||
<option value="霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?>霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?/option>
|
||||
<option value="頧臭辣撌亦<EFBFBD>1<EFBFBD>?>頧臭辣撌亦<EFBFBD>1<EFBFBD>?/option>
|
||||
<option value="頧臭辣撌亦<EFBFBD>2<EFBFBD>?>頧臭辣撌亦<EFBFBD>2<EFBFBD>?/option>
|
||||
<option value="蝵𤑳<EFBFBD>撌亦<EFBFBD>1<EFBFBD>?>蝵𤑳<EFBFBD>撌亦<EFBFBD>1<EFBFBD>?/option>
|
||||
<option value="蝵𤑳<EFBFBD>撌亦<EFBFBD>2<EFBFBD>?>蝵𤑳<EFBFBD>撌亦<EFBFBD>2<EFBFBD>?/option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label for="gender-select"><i class="fas fa-venus-mars"></i> 性别</label>
|
||||
<select id="gender-select">
|
||||
<option value="">全部性别</option>
|
||||
<option value="男">男</option>
|
||||
<option value="女">女</option>
|
||||
<option value="<EFBFBD>?><EFBFBD>?/option>
|
||||
<option value="憟?>憟?/option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -131,7 +131,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="student-table-body">
|
||||
<!-- 数据将通过JavaScript动态加载 -->
|
||||
<!-- <EFBFBD>唳旿撠<EFBFBD><EFBFBD>朞<EFBFBD>JavaScript<EFBFBD>冽<EFBFBD><EFBFBD><EFBFBD>頧?-->
|
||||
<tr>
|
||||
<td colspan="8" class="loading">
|
||||
<i class="fas fa-spinner fa-spin"></i>
|
||||
@@ -146,14 +146,12 @@
|
||||
<div class="pagination" id="pagination">
|
||||
<button id="prev-btn" disabled>
|
||||
<i class="fas fa-chevron-left"></i>
|
||||
上一页
|
||||
</button>
|
||||
銝𠹺<EFBFBD>憿? </button>
|
||||
<button class="active">1</button>
|
||||
<button>2</button>
|
||||
<button>3</button>
|
||||
<button id="next-btn">
|
||||
下一页
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
銝衤<EFBFBD>憿? <i class="fas fa-chevron-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -163,8 +161,8 @@
|
||||
<!-- 页脚 -->
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<p>© 2023 XX学校成绩管理系统. 版权所有.</p>
|
||||
<p>技术支持: 计算机科学与技术学院</p>
|
||||
<p>穢 2023 XX摮行嵗<EFBFBD>鞟貍蝞∠<EFBFBD>蝟餌<EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?</p>
|
||||
<p><EFBFBD><EFBFBD><EFBFBD>舀𣈲<EFBFBD>? 霈∠<E99C88><E288A0>箇<EFBFBD>摮虫<E691AE><E899AB><EFBFBD><EFBFBD>臬郎<E887AC>?/p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -174,8 +172,8 @@
|
||||
{
|
||||
id: '20230001',
|
||||
name: '张三',
|
||||
gender: '男',
|
||||
class: '计算机科学与技术1班',
|
||||
gender: '<EFBFBD>?,
|
||||
class: '霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?,
|
||||
phone: '13800138001',
|
||||
email: 'zhangsan@example.com',
|
||||
enrollmentDate: '2023-09-01'
|
||||
@@ -183,8 +181,8 @@
|
||||
{
|
||||
id: '20230002',
|
||||
name: '李四',
|
||||
gender: '女',
|
||||
class: '计算机科学与技术1班',
|
||||
gender: '憟?,
|
||||
class: '霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?,
|
||||
phone: '13800138002',
|
||||
email: 'lisi@example.com',
|
||||
enrollmentDate: '2023-09-01'
|
||||
@@ -192,8 +190,8 @@
|
||||
{
|
||||
id: '20230003',
|
||||
name: '王五',
|
||||
gender: '男',
|
||||
class: '计算机科学与技术2班',
|
||||
gender: '<EFBFBD>?,
|
||||
class: '霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?,
|
||||
phone: '13800138003',
|
||||
email: 'wangwu@example.com',
|
||||
enrollmentDate: '2023-09-01'
|
||||
@@ -201,8 +199,8 @@
|
||||
{
|
||||
id: '20230004',
|
||||
name: '赵六',
|
||||
gender: '女',
|
||||
class: '软件工程1班',
|
||||
gender: '憟?,
|
||||
class: '頧臭辣撌亦<EFBFBD>1<EFBFBD>?,
|
||||
phone: '13800138004',
|
||||
email: 'zhaoliu@example.com',
|
||||
enrollmentDate: '2023-09-01'
|
||||
@@ -210,8 +208,8 @@
|
||||
{
|
||||
id: '20230005',
|
||||
name: '钱七',
|
||||
gender: '男',
|
||||
class: '软件工程2班',
|
||||
gender: '<EFBFBD>?,
|
||||
class: '頧臭辣撌亦<EFBFBD>2<EFBFBD>?,
|
||||
phone: '13800138005',
|
||||
email: 'qianqi@example.com',
|
||||
enrollmentDate: '2023-09-01'
|
||||
@@ -219,8 +217,8 @@
|
||||
{
|
||||
id: '20230006',
|
||||
name: '孙八',
|
||||
gender: '男',
|
||||
class: '网络工程1班',
|
||||
gender: '<EFBFBD>?,
|
||||
class: '蝵𤑳<EFBFBD>撌亦<EFBFBD>1<EFBFBD>?,
|
||||
phone: '13800138006',
|
||||
email: 'sunba@example.com',
|
||||
enrollmentDate: '2023-09-01'
|
||||
@@ -228,8 +226,8 @@
|
||||
{
|
||||
id: '20230007',
|
||||
name: '周九',
|
||||
gender: '女',
|
||||
class: '网络工程2班',
|
||||
gender: '憟?,
|
||||
class: '蝵𤑳<EFBFBD>撌亦<EFBFBD>2<EFBFBD>?,
|
||||
phone: '13800138007',
|
||||
email: 'zhoujiu@example.com',
|
||||
enrollmentDate: '2023-09-01'
|
||||
@@ -237,16 +235,15 @@
|
||||
{
|
||||
id: '20230008',
|
||||
name: '吴十',
|
||||
gender: '男',
|
||||
class: '计算机科学与技术1班',
|
||||
gender: '<EFBFBD>?,
|
||||
class: '霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?,
|
||||
phone: '13800138008',
|
||||
email: 'wushi@example.com',
|
||||
enrollmentDate: '2023-09-01'
|
||||
}
|
||||
];
|
||||
|
||||
// 当前页数据
|
||||
let currentPage = 1;
|
||||
// 敶枏<EFBFBD>憿菜㺭<EFBFBD>? let currentPage = 1;
|
||||
const pageSize = 5;
|
||||
let filteredStudents = [...mockStudents];
|
||||
|
||||
@@ -272,7 +269,7 @@
|
||||
<td colspan="8" class="no-results">
|
||||
<i class="fas fa-user-slash"></i>
|
||||
<h3>没有找到学生信息</h3>
|
||||
<p>请尝试调整筛选条件或添加新学生</p>
|
||||
<p>霂瑕<EFBFBD>霂閗<EFBFBD><EFBFBD>渡<EFBFBD><EFBFBD>㗇辺隞嗆<EFBFBD>瘛餃<EFBFBD><EFBFBD>啣郎<EFBFBD>?/p>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
@@ -325,13 +322,11 @@
|
||||
}
|
||||
});
|
||||
|
||||
// 更新上一页/下一页按钮状态
|
||||
prevBtn.disabled = currentPage === 1;
|
||||
// <EFBFBD>湔鰵銝𠹺<EFBFBD>憿?銝衤<E98A9D>憿菜<E686BF><E88F9C>桃𠶖<E6A183>? prevBtn.disabled = currentPage === 1;
|
||||
nextBtn.disabled = currentPage === totalPages || totalPages === 0;
|
||||
}
|
||||
|
||||
// 筛选学生
|
||||
function filterStudents() {
|
||||
// 蝑偦<EFBFBD>匧郎<EFBFBD>? function filterStudents() {
|
||||
const studentId = document.getElementById('student-id').value.trim();
|
||||
const studentName = document.getElementById('student-name').value.trim();
|
||||
const selectedClass = document.getElementById('class-select').value;
|
||||
@@ -351,8 +346,7 @@
|
||||
updatePagination();
|
||||
}
|
||||
|
||||
// 重置筛选条件
|
||||
function resetFilters() {
|
||||
// <EFBFBD>滨蔭蝑偦<EFBFBD>㗇辺隞? function resetFilters() {
|
||||
document.getElementById('student-id').value = '';
|
||||
document.getElementById('student-name').value = '';
|
||||
document.getElementById('class-select').value = '';
|
||||
@@ -366,15 +360,13 @@
|
||||
|
||||
// 添加学生
|
||||
function addStudent() {
|
||||
alert('添加学生功能将在后端API完成后实现');
|
||||
// 这里可以打开一个模态框来添加学生信息
|
||||
}
|
||||
alert('瘛餃<EFBFBD>摮衣<EFBFBD><EFBFBD>蠘<EFBFBD>撠<EFBFBD>銁<EFBFBD>𡒊垢API摰峕<EFBFBD><EFBFBD>𤾸<EFBFBD><EFBFBD>?);
|
||||
// 餈䠷<EFBFBD><EFBFBD>臭誑<EFBFBD>枏<EFBFBD>銝<EFBFBD>銝芣芋<EFBFBD><EFBFBD><EFBFBD><EFBFBD>交溶<EFBFBD>惩郎<EFBFBD>煺縑<EFBFBD>? }
|
||||
|
||||
// 编辑学生
|
||||
function editStudent(studentId) {
|
||||
alert(`编辑学生 ${studentId} 功能将在后端API完成后实现`);
|
||||
// 这里可以打开一个模态框来编辑学生信息
|
||||
}
|
||||
// 餈䠷<EFBFBD><EFBFBD>臭誑<EFBFBD>枏<EFBFBD>銝<EFBFBD>銝芣芋<EFBFBD><EFBFBD><EFBFBD><EFBFBD>亦<EFBFBD>颲穃郎<EFBFBD>煺縑<EFBFBD>? }
|
||||
|
||||
// 删除学生
|
||||
function deleteStudent(studentId) {
|
||||
@@ -386,7 +378,7 @@
|
||||
|
||||
// 导出数据
|
||||
function exportData() {
|
||||
alert('导出数据功能将在后端API完成后实现');
|
||||
alert('撖澆枂<EFBFBD>唳旿<EFBFBD>蠘<EFBFBD>撠<EFBFBD>銁<EFBFBD>𡒊垢API摰峕<EFBFBD><EFBFBD>𤾸<EFBFBD><EFBFBD>?);
|
||||
// 这里可以调用API导出Excel或CSV文件
|
||||
}
|
||||
|
||||
@@ -397,8 +389,7 @@
|
||||
updatePagination();
|
||||
}
|
||||
|
||||
// 初始化事件监听
|
||||
function initEventListeners() {
|
||||
// <EFBFBD>嘥<EFBFBD><EFBFBD>碶<EFBFBD>隞嗥<EFBFBD><EFBFBD>? function initEventListeners() {
|
||||
searchBtn.addEventListener('click', filterStudents);
|
||||
resetBtn.addEventListener('click', resetFilters);
|
||||
addBtn.addEventListener('click', addStudent);
|
||||
@@ -427,8 +418,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
// 输入框回车搜索
|
||||
document.getElementById('student-id').addEventListener('keypress', (e) => {
|
||||
// 颲枏<EFBFBD>獢<EFBFBD><EFBFBD>頧行<EFBFBD>蝝? document.getElementById('student-id').addEventListener('keypress', (e) => {
|
||||
if (e.key === 'Enter') filterStudents();
|
||||
});
|
||||
|
||||
@@ -448,4 +438,4 @@
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -4,35 +4,35 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>用户管理 - XX学校成绩管理系统</title>
|
||||
<link rel="stylesheet" href="../css/style.css">
|
||||
<link rel="stylesheet" href="/public/css/style.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- 导航栏 -->
|
||||
<!-- 撖潸⏛<EFBFBD>?-->
|
||||
<nav class="navbar">
|
||||
<div class="container">
|
||||
<div class="navbar-brand">
|
||||
<a href="index.html">
|
||||
<a href="/">
|
||||
<i class="fas fa-graduation-cap"></i>
|
||||
<span>XX学校成绩管理系统</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="navbar-menu">
|
||||
<div class="navbar-start">
|
||||
<a href="admin_dashboard.html" class="navbar-item">
|
||||
<a href="/admin/dashboard" class="navbar-item">
|
||||
<i class="fas fa-tachometer-alt"></i>
|
||||
<span>仪表板</span>
|
||||
<span>隞芾”<EFBFBD>?/span>
|
||||
</a>
|
||||
<a href="user_management.html" class="navbar-item active">
|
||||
<a href="/admin/user_management" class="navbar-item active">
|
||||
<i class="fas fa-users"></i>
|
||||
<span>用户管理</span>
|
||||
</a>
|
||||
<a href="student_management.html" class="navbar-item">
|
||||
<a href="/admin/student_management" class="navbar-item">
|
||||
<i class="fas fa-user-graduate"></i>
|
||||
<span>学生管理</span>
|
||||
</a>
|
||||
<a href="grade_management.html" class="navbar-item">
|
||||
<a href="/teacher/grade_management" class="navbar-item">
|
||||
<i class="fas fa-chart-bar"></i>
|
||||
<span>成绩统计</span>
|
||||
</a>
|
||||
@@ -40,25 +40,23 @@
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item user-info">
|
||||
<i class="fas fa-user-circle"></i>
|
||||
<span>管理员</span>
|
||||
<span>蝞∠<EFBFBD><EFBFBD>?/span>
|
||||
<div class="dropdown">
|
||||
<a href="#" class="dropdown-toggle">
|
||||
<i class="fas fa-caret-down"></i>
|
||||
</a>
|
||||
<div class="dropdown-menu">
|
||||
<a href="admin_dashboard.html" class="dropdown-item">
|
||||
<a href="/admin/dashboard" class="dropdown-item">
|
||||
<i class="fas fa-tachometer-alt"></i>
|
||||
仪表板
|
||||
</a>
|
||||
隞芾”<EFBFBD>? </a>
|
||||
<a href="#" class="dropdown-item">
|
||||
<i class="fas fa-cog"></i>
|
||||
系统设置
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="index.html" class="dropdown-item">
|
||||
<a href="/" class="dropdown-item">
|
||||
<i class="fas fa-sign-out-alt"></i>
|
||||
退出登录
|
||||
</a>
|
||||
<EFBFBD><EFBFBD><EFBFBD>箇蒈敶? </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -75,13 +73,13 @@
|
||||
<div class="page-header">
|
||||
<h1>用户管理</h1>
|
||||
<div class="breadcrumb">
|
||||
<a href="index.html">主页</a> >
|
||||
<a href="admin_dashboard.html">管理员仪表板</a> >
|
||||
<a href="/">銝駁△</a> >
|
||||
<a href="/admin/dashboard">蝞∠<EFBFBD><EFBFBD>䀝貌銵冽踎</a> >
|
||||
<span>用户管理</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 筛选区域 -->
|
||||
<!-- 蝑偦<EFBFBD>匧躹<EFBFBD>?-->
|
||||
<div class="filter-section">
|
||||
<form class="filter-form" id="filter-form">
|
||||
<div class="filter-group">
|
||||
@@ -90,13 +88,13 @@
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label for="user-name">姓名</label>
|
||||
<input type="text" id="user-name" placeholder="请输入姓名">
|
||||
<input type="text" id="user-name" placeholder="霂瑁<EFBFBD><EFBFBD>亙<EFBFBD><EFBFBD>?>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label for="role-select">角色</label>
|
||||
<select id="role-select">
|
||||
<option value="">全部角色</option>
|
||||
<option value="admin">管理员</option>
|
||||
<option value="admin">蝞∠<EFBFBD><EFBFBD>?/option>
|
||||
<option value="teacher">教师</option>
|
||||
<option value="student">学生</option>
|
||||
</select>
|
||||
@@ -105,12 +103,12 @@
|
||||
<label for="class-select">班级</label>
|
||||
<select id="class-select">
|
||||
<option value="">全部班级</option>
|
||||
<option value="计算机科学与技术1班">计算机科学与技术1班</option>
|
||||
<option value="计算机科学与技术2班">计算机科学与技术2班</option>
|
||||
<option value="软件工程1班">软件工程1班</option>
|
||||
<option value="软件工程2班">软件工程2班</option>
|
||||
<option value="网络工程1班">网络工程1班</option>
|
||||
<option value="网络工程2班">网络工程2班</option>
|
||||
<option value="霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?>霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?/option>
|
||||
<option value="霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?>霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?/option>
|
||||
<option value="頧臭辣撌亦<EFBFBD>1<EFBFBD>?>頧臭辣撌亦<EFBFBD>1<EFBFBD>?/option>
|
||||
<option value="頧臭辣撌亦<EFBFBD>2<EFBFBD>?>頧臭辣撌亦<EFBFBD>2<EFBFBD>?/option>
|
||||
<option value="蝵𤑳<EFBFBD>撌亦<EFBFBD>1<EFBFBD>?>蝵𤑳<EFBFBD>撌亦<EFBFBD>1<EFBFBD>?/option>
|
||||
<option value="蝵𤑳<EFBFBD>撌亦<EFBFBD>2<EFBFBD>?>蝵𤑳<EFBFBD>撌亦<EFBFBD>2<EFBFBD>?/option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-actions">
|
||||
@@ -150,7 +148,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="user-table-body">
|
||||
<!-- 数据将通过JavaScript动态加载 -->
|
||||
<!-- <EFBFBD>唳旿撠<EFBFBD><EFBFBD>朞<EFBFBD>JavaScript<EFBFBD>冽<EFBFBD><EFBFBD><EFBFBD>頧?-->
|
||||
<tr>
|
||||
<td colspan="8" class="loading">
|
||||
<i class="fas fa-spinner fa-spin"></i>
|
||||
@@ -165,16 +163,14 @@
|
||||
<div class="pagination" id="pagination">
|
||||
<button id="prev-btn" disabled>
|
||||
<i class="fas fa-chevron-left"></i>
|
||||
上一页
|
||||
</button>
|
||||
銝𠹺<EFBFBD>憿? </button>
|
||||
<div id="page-numbers">
|
||||
<button class="active">1</button>
|
||||
<button>2</button>
|
||||
<button>3</button>
|
||||
</div>
|
||||
<button id="next-btn">
|
||||
下一页
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
銝衤<EFBFBD>憿? <i class="fas fa-chevron-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -184,8 +180,8 @@
|
||||
<!-- 页脚 -->
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<p>© 2023 XX学校成绩管理系统. 版权所有.</p>
|
||||
<p>技术支持: 信息技术中心 | 联系电话: 010-12345678</p>
|
||||
<p>© 2023 XX摮行嵗<EFBFBD>鞟貍蝞∠<EFBFBD>蝟餌<EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?</p>
|
||||
<p><EFBFBD><EFBFBD><EFBFBD>舀𣈲<EFBFBD>? 靽⊥<E99DBD><E28AA5><EFBFBD><EFBFBD>臭葉敹?| <20>𠉛頂<F0A0899B>菔<EFBFBD>: 010-12345678</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -206,7 +202,7 @@
|
||||
id: 'teacher001',
|
||||
name: '李老师',
|
||||
role: 'teacher',
|
||||
className: '计算机科学与技术1班',
|
||||
className: '霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?,
|
||||
phone: '13800138002',
|
||||
email: 'li.teacher@xxschool.edu.cn',
|
||||
registerTime: '2023-02-10'
|
||||
@@ -215,7 +211,7 @@
|
||||
id: 'teacher002',
|
||||
name: '王老师',
|
||||
role: 'teacher',
|
||||
className: '软件工程1班',
|
||||
className: '頧臭辣撌亦<EFBFBD>1<EFBFBD>?,
|
||||
phone: '13800138003',
|
||||
email: 'wang.teacher@xxschool.edu.cn',
|
||||
registerTime: '2023-02-12'
|
||||
@@ -224,7 +220,7 @@
|
||||
id: 'student001',
|
||||
name: '张三',
|
||||
role: 'student',
|
||||
className: '计算机科学与技术1班',
|
||||
className: '霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?,
|
||||
phone: '13800138004',
|
||||
email: 'zhangsan@xxschool.edu.cn',
|
||||
registerTime: '2023-03-01'
|
||||
@@ -233,7 +229,7 @@
|
||||
id: 'student002',
|
||||
name: '李四',
|
||||
role: 'student',
|
||||
className: '计算机科学与技术1班',
|
||||
className: '霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?,
|
||||
phone: '13800138005',
|
||||
email: 'lisi@xxschool.edu.cn',
|
||||
registerTime: '2023-03-01'
|
||||
@@ -242,7 +238,7 @@
|
||||
id: 'student003',
|
||||
name: '王五',
|
||||
role: 'student',
|
||||
className: '软件工程1班',
|
||||
className: '頧臭辣撌亦<EFBFBD>1<EFBFBD>?,
|
||||
phone: '13800138006',
|
||||
email: 'wangwu@xxschool.edu.cn',
|
||||
registerTime: '2023-03-02'
|
||||
@@ -251,7 +247,7 @@
|
||||
id: 'student004',
|
||||
name: '赵六',
|
||||
role: 'student',
|
||||
className: '软件工程1班',
|
||||
className: '頧臭辣撌亦<EFBFBD>1<EFBFBD>?,
|
||||
phone: '13800138007',
|
||||
email: 'zhaoliu@xxschool.edu.cn',
|
||||
registerTime: '2023-03-02'
|
||||
@@ -260,7 +256,7 @@
|
||||
id: 'student005',
|
||||
name: '钱七',
|
||||
role: 'student',
|
||||
className: '网络工程1班',
|
||||
className: '蝵𤑳<EFBFBD>撌亦<EFBFBD>1<EFBFBD>?,
|
||||
phone: '13800138008',
|
||||
email: 'qianqi@xxschool.edu.cn',
|
||||
registerTime: '2023-03-03'
|
||||
@@ -269,7 +265,7 @@
|
||||
id: 'student006',
|
||||
name: '孙八',
|
||||
role: 'student',
|
||||
className: '网络工程2班',
|
||||
className: '蝵𤑳<EFBFBD>撌亦<EFBFBD>2<EFBFBD>?,
|
||||
phone: '13800138009',
|
||||
email: 'sunba@xxschool.edu.cn',
|
||||
registerTime: '2023-03-03'
|
||||
@@ -278,15 +274,14 @@
|
||||
id: 'student007',
|
||||
name: '周九',
|
||||
role: 'student',
|
||||
className: '计算机科学与技术2班',
|
||||
className: '霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?,
|
||||
phone: '13800138010',
|
||||
email: 'zhoujiu@xxschool.edu.cn',
|
||||
registerTime: '2023-03-04'
|
||||
}
|
||||
];
|
||||
|
||||
// 当前显示的用户数据
|
||||
let currentUsers = [...mockUsers];
|
||||
// 敶枏<EFBFBD><EFBFBD>曄內<EFBFBD><EFBFBD>鍂<EFBFBD>瑟㺭<EFBFBD>? let currentUsers = [...mockUsers];
|
||||
let currentPage = 1;
|
||||
const usersPerPage = 5;
|
||||
|
||||
@@ -305,15 +300,13 @@
|
||||
const roleSelect = document.getElementById('role-select');
|
||||
const classSelect = document.getElementById('class-select');
|
||||
|
||||
// 初始化
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// <EFBFBD>嘥<EFBFBD><EFBFBD>? document.addEventListener('DOMContentLoaded', function() {
|
||||
renderUserTable();
|
||||
setupEventListeners();
|
||||
updatePagination();
|
||||
});
|
||||
|
||||
// 设置事件监听器
|
||||
function setupEventListeners() {
|
||||
// 霈曄蔭鈭衤辣<EFBFBD>穃𨯬<EFBFBD>? function setupEventListeners() {
|
||||
searchBtn.addEventListener('click', handleSearch);
|
||||
resetBtn.addEventListener('click', handleReset);
|
||||
addBtn.addEventListener('click', handleAddUser);
|
||||
@@ -330,7 +323,7 @@
|
||||
<td colspan="8" class="no-results">
|
||||
<i class="fas fa-user-slash"></i>
|
||||
<h3>没有找到用户</h3>
|
||||
<p>请尝试其他筛选条件或添加新用户</p>
|
||||
<p>霂瑕<EFBFBD>霂訫<EFBFBD>隞𣇉<EFBFBD><EFBFBD>㗇辺隞嗆<EFBFBD>瘛餃<EFBFBD><EFBFBD>啁鍂<EFBFBD>?/p>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
@@ -347,7 +340,7 @@
|
||||
// 角色徽章
|
||||
let roleBadge = '';
|
||||
if (user.role === 'admin') {
|
||||
roleBadge = '<span class="role-badge role-admin">管理员</span>';
|
||||
roleBadge = '<span class="role-badge role-admin">蝞∠<EFBFBD><EFBFBD>?/span>';
|
||||
} else if (user.role === 'teacher') {
|
||||
roleBadge = '<span class="role-badge role-teacher">教师</span>';
|
||||
} else {
|
||||
@@ -359,7 +352,7 @@
|
||||
<td>${user.id}</td>
|
||||
<td>${user.name}</td>
|
||||
<td>${roleBadge}</td>
|
||||
<td>${user.className || '—'}</td>
|
||||
<td>${user.className || '<EFBFBD>?}</td>
|
||||
<td>${user.phone}</td>
|
||||
<td>${user.email}</td>
|
||||
<td>${user.registerTime}</td>
|
||||
@@ -386,15 +379,13 @@
|
||||
function updatePagination() {
|
||||
const totalPages = Math.ceil(currentUsers.length / usersPerPage);
|
||||
|
||||
// 更新按钮状态
|
||||
prevBtn.disabled = currentPage === 1;
|
||||
// <EFBFBD>湔鰵<EFBFBD>厰僼<EFBFBD>嗆<EFBFBD>? prevBtn.disabled = currentPage === 1;
|
||||
nextBtn.disabled = currentPage === totalPages || totalPages === 0;
|
||||
|
||||
// 更新页码按钮
|
||||
let pageButtonsHTML = '';
|
||||
for (let i = 1; i <= totalPages; i++) {
|
||||
if (i <= 5) { // 最多显示5个页码
|
||||
pageButtonsHTML += `<button class="${i === currentPage ? 'active' : ''}" onclick="goToPage(${i})">${i}</button>`;
|
||||
if (i <= 5) { // <EFBFBD><EFBFBD>憭𡁏遬蝷?銝芷△<E88AB7>? pageButtonsHTML += `<button class="${i === currentPage ? 'active' : ''}" onclick="goToPage(${i})">${i}</button>`;
|
||||
}
|
||||
}
|
||||
pageNumbers.innerHTML = pageButtonsHTML;
|
||||
@@ -408,23 +399,19 @@
|
||||
const className = classSelect.value;
|
||||
|
||||
currentUsers = mockUsers.filter(user => {
|
||||
// 用户ID筛选
|
||||
if (userId && !user.id.toLowerCase().includes(userId.toLowerCase())) {
|
||||
// <EFBFBD>冽<EFBFBD>ID蝑偦<EFBFBD>? if (userId && !user.id.toLowerCase().includes(userId.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 姓名筛选
|
||||
if (userName && !user.name.toLowerCase().includes(userName.toLowerCase())) {
|
||||
// 憪枏<EFBFBD>蝑偦<EFBFBD>? if (userName && !user.name.toLowerCase().includes(userName.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 角色筛选
|
||||
if (role && user.role !== role) {
|
||||
// 閫坿𠧧蝑偦<EFBFBD>? if (role && user.role !== role) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 班级筛选
|
||||
if (className && user.className !== className) {
|
||||
// <EFBFBD>剔漣蝑偦<EFBFBD>? if (className && user.className !== className) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -451,31 +438,29 @@
|
||||
|
||||
// 处理添加用户
|
||||
function handleAddUser() {
|
||||
alert('添加用户功能将在后端API完成后实现');
|
||||
alert('瘛餃<EFBFBD><EFBFBD>冽<EFBFBD><EFBFBD>蠘<EFBFBD>撠<EFBFBD>銁<EFBFBD>𡒊垢API摰峕<EFBFBD><EFBFBD>𤾸<EFBFBD><EFBFBD>?);
|
||||
// 这里可以打开一个模态框来添加新用户
|
||||
}
|
||||
|
||||
// 处理导出
|
||||
function handleExport() {
|
||||
alert('导出功能将在后端API完成后实现');
|
||||
alert('撖澆枂<EFBFBD>蠘<EFBFBD>撠<EFBFBD>銁<EFBFBD>𡒊垢API摰峕<EFBFBD><EFBFBD>𤾸<EFBFBD><EFBFBD>?);
|
||||
// 这里可以导出为Excel或CSV格式
|
||||
}
|
||||
|
||||
// 编辑用户
|
||||
function editUser(userId) {
|
||||
alert(`编辑用户 ${userId} - 功能将在后端API完成后实现`);
|
||||
// 这里可以打开一个模态框来编辑用户信息
|
||||
}
|
||||
// 餈䠷<EFBFBD><EFBFBD>臭誑<EFBFBD>枏<EFBFBD>銝<EFBFBD>銝芣芋<EFBFBD><EFBFBD><EFBFBD><EFBFBD>亦<EFBFBD>颲𤑳鍂<EFBFBD>瑚縑<EFBFBD>? }
|
||||
|
||||
// 删除用户
|
||||
function deleteUser(userId) {
|
||||
if (confirm(`确定要删除用户 ${userId} 吗?此操作不可撤销。`)) {
|
||||
if (confirm(`蝖桀<EFBFBD>閬<EFBFBD><EFBFBD><EFBFBD>斤鍂<EFBFBD>?${userId} <20>梹<EFBFBD>甇斗<E79487>雿靝<E99BBF><E99D9D>舀伃<E88880><E4BC83><EFBFBD><EFBFBD>)) {
|
||||
// 从模拟数据中删除
|
||||
const index = mockUsers.findIndex(user => user.id === userId);
|
||||
if (index !== -1) {
|
||||
mockUsers.splice(index, 1);
|
||||
// 更新当前显示的数据
|
||||
handleSearch();
|
||||
// <EFBFBD>湔鰵敶枏<EFBFBD><EFBFBD>曄內<EFBFBD><EFBFBD>㺭<EFBFBD>? handleSearch();
|
||||
alert('用户删除成功');
|
||||
}
|
||||
}
|
||||
@@ -506,4 +491,4 @@
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -4,43 +4,41 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>学生成绩管理系统</title>
|
||||
<link rel="stylesheet" href="../css/style.css">
|
||||
<link rel="stylesheet" href="../css/main.css">
|
||||
<link rel="stylesheet" href="/public/css/style.css">
|
||||
<link rel="stylesheet" href="/public/css/main.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- 导航栏 -->
|
||||
<!-- 撖潸⏛<EFBFBD>?-->
|
||||
<nav class="navbar">
|
||||
<div class="navbar-brand">
|
||||
<i class="fas fa-graduation-cap"></i>
|
||||
<span>XX学校成绩管理系统</span>
|
||||
</div>
|
||||
<div class="navbar-menu">
|
||||
<a href="index.html" class="btn btn-secondary">
|
||||
<a href="/" class="btn btn-secondary">
|
||||
<i class="fas fa-home"></i> 主页
|
||||
</a>
|
||||
<div class="navbar-user">
|
||||
<a href="login.html" class="btn btn-primary" id="loginBtn">
|
||||
<a href="/login" class="btn btn-primary" id="loginBtn">
|
||||
<i class="fas fa-sign-in-alt"></i> 登录
|
||||
</a>
|
||||
<a href="register.html" class="btn btn-secondary" id="registerBtn">
|
||||
<a href="/register" class="btn btn-secondary" id="registerBtn">
|
||||
<i class="fas fa-user-plus"></i> 注册
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- 主体内容区 -->
|
||||
<!-- 銝颱<EFBFBD><EFBFBD><EFBFBD>捆<EFBFBD>?-->
|
||||
<main>
|
||||
<!-- 英雄区域 -->
|
||||
<section class="hero-section">
|
||||
<div class="hero-content">
|
||||
<h1 class="hero-title">XX学校学生成绩管理系统</h1>
|
||||
<p class="hero-subtitle">
|
||||
高效、安全、智能的成绩管理平台,为学校师生提供全方位的成绩管理服务,
|
||||
实现成绩录入、查询、统计和分析的一体化解决方案。
|
||||
</p>
|
||||
擃䀹<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>具<EFBFBD><EFBFBD>惣<EFBFBD>賜<EFBFBD><EFBFBD>鞟貍蝞∠<EFBFBD>撟喳蝱嚗䔶蛹摮行嵗撣<EFBFBD><EFBFBD><EFBFBD>𣂷<EFBFBD><EFBFBD>冽䲮雿滨<EFBFBD><EFBFBD>鞟貍蝞∠<EFBFBD><EFBFBD>滚𦛚嚗? 摰䂿緵<E482BF>鞟貍敶訫<E695B6><E8A8AB><EFBFBD>䰻霂U<E99C82><EFBCB5><EFBFBD>霈∪<E99C88><E288AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>雿枏<E99BBF>閫<EFBFBD><E996AB><EFBFBD>寞<EFBFBD><E5AF9E>? </p>
|
||||
<div class="cta-buttons">
|
||||
<a href="login.html" class="btn btn-primary" id="heroLoginBtn">
|
||||
<a href="/login" class="btn btn-primary" id="heroLoginBtn">
|
||||
<i class="fas fa-sign-in-alt"></i> 立即登录
|
||||
</a>
|
||||
<a href="#features" class="btn btn-secondary">
|
||||
@@ -60,9 +58,7 @@
|
||||
</div>
|
||||
<h3 class="feature-title">学生成绩查询</h3>
|
||||
<p class="feature-description">
|
||||
学生可随时查看个人成绩,包括各科成绩、平均分、排名等信息,
|
||||
支持成绩趋势分析和历史记录查看。
|
||||
</p>
|
||||
摮衣<EFBFBD><EFBFBD>舫<EFBFBD><EFBFBD>嗆䰻<EFBFBD>衤葵鈭箸<EFBFBD>蝏抬<EFBFBD><EFBFBD><EFBFBD>𡠺<EFBFBD><EFBFBD><EFBFBD><EFBFBD>鞟貍<EFBFBD><EFBFBD>像<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>滨<EFBFBD>靽⊥<EFBFBD>嚗? <20>舀<EFBFBD><E88880>鞟貍頞见飵<E8A781><E9A3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>脰扇敶閙䰻<E99699>卝<EFBFBD>? </p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
@@ -72,19 +68,16 @@
|
||||
<h3 class="feature-title">教师成绩管理</h3>
|
||||
<p class="feature-description">
|
||||
教师可便捷录入、修改、查询学生成绩,支持批量操作和成绩统计分析,
|
||||
提供多种数据导出格式。
|
||||
</p>
|
||||
<EFBFBD>𣂷<EFBFBD>憭𡁶<EFBFBD><EFBFBD>唳旿撖澆枂<EFBFBD>澆<EFBFBD><EFBFBD>? </p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-user-shield"></i>
|
||||
</div>
|
||||
<h3 class="feature-title">管理员权限控制</h3>
|
||||
<h3 class="feature-title">蝞∠<EFBFBD><EFBFBD>䀹<EFBFBD><EFBFBD>鞉綉<EFBFBD>?/h3>
|
||||
<p class="feature-description">
|
||||
管理员可管理用户账户、学生信息,查看系统统计报表,
|
||||
设置权限和系统参数,确保数据安全。
|
||||
</p>
|
||||
蝞∠<EFBFBD><EFBFBD>睃虾蝞∠<EFBFBD><EFBFBD>冽<EFBFBD>韐行<EFBFBD><EFBFBD><EFBFBD>郎<EFBFBD>煺縑<EFBFBD>荔<EFBFBD><EFBFBD>亦<EFBFBD>蝟餌<EFBFBD>蝏蠘恣<EFBFBD>亥”嚗? 霈曄蔭<E69B84><E894AD><EFBFBD><EFBFBD>𣬚頂蝏笔<E89D8F><E7AC94>堆<EFBFBD>蝖桐<E89D96><E6A190>唳旿摰匧<E691B0><E58CA7>? </p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
@@ -93,9 +86,7 @@
|
||||
</div>
|
||||
<h3 class="feature-title">智能统计分析</h3>
|
||||
<p class="feature-description">
|
||||
提供丰富的图表统计功能,包括成绩分布、趋势分析、对比图表等,
|
||||
帮助学校进行教学评估和决策支持。
|
||||
</p>
|
||||
<EFBFBD>𣂷<EFBFBD>銝啣<EFBFBD><EFBFBD><EFBFBD>㦛銵函<EFBFBD>霈∪<EFBFBD><EFBFBD>踝<EFBFBD><EFBFBD><EFBFBD>𡠺<EFBFBD>鞟貍<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>踹<EFBFBD><EFBFBD>僐<EFBFBD><EFBFBD>笆瘥𥪜㦛銵函<EFBFBD>嚗? 撣桀𨭌摮行嵗餈𥡝<E9A488><F0A5A19D>坔郎霂<E9838E>摯<EFBFBD><E691AF><EFBFBD>蝑𡝗𣈲<F0A19D97><F0A388B2><EFBFBD>? </p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -104,12 +95,10 @@
|
||||
<section class="cta-section">
|
||||
<h2 class="cta-title">立即体验智能成绩管理</h2>
|
||||
<p style="font-size: 1.2rem; color: #666; margin-bottom: 40px; max-width: 600px; margin-left: auto; margin-right: auto;">
|
||||
加入XX学校成绩管理系统,体验高效、便捷的成绩管理服务。
|
||||
</p>
|
||||
<EFBFBD>惩<EFBFBD>XX摮行嵗<EFBFBD>鞟貍蝞∠<EFBFBD>蝟餌<EFBFBD>嚗䔶<EFBFBD>撉屸<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>噶<EFBFBD>瑞<EFBFBD><EFBFBD>鞟貍蝞∠<EFBFBD><EFBFBD>滚𦛚<EFBFBD>? </p>
|
||||
<div class="cta-buttons">
|
||||
<a href="login.html" class="btn btn-primary">
|
||||
<i class="fas fa-sign-in-alt"></i> 开始使用
|
||||
</a>
|
||||
<a href="/login" class="btn btn-primary">
|
||||
<i class="fas fa-sign-in-alt"></i> 撘<EFBFBD>憪衤蝙<EFBFBD>? </a>
|
||||
<a href="#" class="btn btn-secondary">
|
||||
<i class="fas fa-book"></i> 查看文档
|
||||
</a>
|
||||
@@ -122,8 +111,7 @@
|
||||
<div class="footer-content">
|
||||
<h3 style="margin-bottom: 20px;">XX学校学生成绩管理系统</h3>
|
||||
<p style="color: #ccc; margin-bottom: 20px; max-width: 600px; margin-left: auto; margin-right: auto;">
|
||||
致力于为学校提供专业、安全、高效的数字化成绩管理解决方案。
|
||||
</p>
|
||||
<EFBFBD>游<EFBFBD>鈭𦒘蛹摮行嵗<EFBFBD>𣂷<EFBFBD>銝㮖<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>具<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>啣<EFBFBD><EFBFBD>𡝗<EFBFBD>蝏拍恣<EFBFBD><EFBFBD>圾<EFBFBD>單䲮獢<EFBFBD><EFBFBD>? </p>
|
||||
<div class="footer-links">
|
||||
<a href="#"><i class="fas fa-info-circle"></i> 关于我们</a>
|
||||
<a href="#"><i class="fas fa-envelope"></i> 联系我们</a>
|
||||
@@ -131,12 +119,12 @@
|
||||
<a href="#"><i class="fas fa-file-contract"></i> 服务条款</a>
|
||||
</div>
|
||||
<div class="copyright">
|
||||
<p>© 2023 XX学校学生成绩管理系统 版权所有</p>
|
||||
<p>联系电话:010-12345678 | 邮箱:contact@school.edu.cn</p>
|
||||
<p>穢 2023 XX摮行嵗摮衣<EFBFBD><EFBFBD>鞟貍蝞∠<EFBFBD>蝟餌<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?/p>
|
||||
<p><EFBFBD>𠉛頂<EFBFBD>菔<EFBFBD>嚗?10-12345678 | <EFBFBD>桃拳嚗䬙ontact@school.edu.cn</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="../js/main.js"></script>
|
||||
<script src="/public/js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>学生成绩管理系统 - 登录</title>
|
||||
<link rel="stylesheet" href="../css/style.css">
|
||||
<link rel="stylesheet" href="/public/css/style.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
</head>
|
||||
<body>
|
||||
@@ -21,7 +21,7 @@
|
||||
<i class="fas fa-user"></i> 学号/工号
|
||||
</label>
|
||||
<input type="text" id="id" name="id" required
|
||||
placeholder="请输入学号/工号">
|
||||
placeholder="请输入学号/工号" autocomplete="username">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@@ -29,7 +29,7 @@
|
||||
<i class="fas fa-lock"></i> 密码
|
||||
</label>
|
||||
<input type="password" id="password" name="password" required
|
||||
placeholder="请输入密码">
|
||||
placeholder="请输入密码" autocomplete="current-password">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@@ -45,17 +45,18 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<button type="submit" class="btn btn-primary btn-block">
|
||||
<i class="fas fa-sign-in-alt"></i> 登录
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="auth-footer">
|
||||
<p>没有账户? <a href="register.html">立即注册</a></p>
|
||||
<p>没有账户? <a href="/register">立即注册</a></p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script src="../js/auth.js"></script>
|
||||
</div>
|
||||
|
||||
<script src="/public/js/auth.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>学生成绩管理系统 - 注册</title>
|
||||
<link rel="stylesheet" href="../css/style.css">
|
||||
<link rel="stylesheet" href="/public/css/style.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
</head>
|
||||
<body>
|
||||
@@ -21,7 +21,7 @@
|
||||
<i class="fas fa-id-card"></i> 学号/工号
|
||||
</label>
|
||||
<input type="text" id="id" name="id" required
|
||||
placeholder="请输入学号或工号">
|
||||
placeholder="请输入学号或工号" autocomplete="username">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@@ -37,7 +37,7 @@
|
||||
<i class="fas fa-lock"></i> 密码
|
||||
</label>
|
||||
<input type="password" id="password" name="password" required
|
||||
placeholder="请输入密码">
|
||||
placeholder="请输入密码" autocomplete="new-password">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@@ -45,7 +45,7 @@
|
||||
<i class="fas fa-lock"></i> 确认密码
|
||||
</label>
|
||||
<input type="password" id="confirmPassword" name="confirmPassword" required
|
||||
placeholder="请再次输入密码">
|
||||
placeholder="请再次输入密码" autocomplete="new-password">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@@ -69,38 +69,18 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<button type="submit" class="btn btn-primary btn-block">
|
||||
<i class="fas fa-user-plus"></i> 注册
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="auth-footer">
|
||||
<p>已有账户? <a href="login.html">立即登录</a></p>
|
||||
<p>已有账户? <a href="/login">立即登录</a></p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script src="../js/auth.js"></script>
|
||||
<script>
|
||||
// 显示/隐藏班级字段
|
||||
document.getElementById('role').addEventListener('change', function() {
|
||||
const role = this.value;
|
||||
const classField = document.getElementById('classField');
|
||||
const classInput = document.getElementById('class');
|
||||
|
||||
if (role === 'student' || role === 'teacher') {
|
||||
classField.style.display = 'block';
|
||||
classInput.required = true;
|
||||
} else {
|
||||
classField.style.display = 'none';
|
||||
classInput.required = false;
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化AuthManager
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
new AuthManager();
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
||||
<script src="/public/js/auth.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3,34 +3,33 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>学生成绩管理系统 - 学生仪表板</title>
|
||||
<link rel="stylesheet" href="../css/style.css">
|
||||
<title>摮衣<EFBFBD><EFBFBD>鞟貍蝞∠<EFBFBD>蝟餌<EFBFBD> - 摮衣<E691AE>隞芾”<E88ABE>?/title>
|
||||
<link rel="stylesheet" href="/public/css/style.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
</head>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 顶部导航栏 -->
|
||||
<!-- 憿園<EFBFBD>撖潸⏛<EFBFBD>?-->
|
||||
<nav class="navbar">
|
||||
<div class="navbar-brand">
|
||||
<i class="fas fa-graduation-cap"></i>
|
||||
<span>XX学校成绩管理系统</span>
|
||||
</div>
|
||||
<div class="navbar-menu">
|
||||
<a href="index.html" class="btn btn-secondary">
|
||||
<a href="/" class="btn btn-secondary">
|
||||
<i class="fas fa-home"></i> 主页
|
||||
</a>
|
||||
<div class="navbar-user">
|
||||
<span class="user-name" id="userName">加载中...</span>
|
||||
<span class="user-name" id="userName"><EFBFBD>㰘蝸銝?..</span>
|
||||
<button id="logoutBtn" class="btn btn-primary">
|
||||
<i class="fas fa-sign-out-alt"></i> 退出
|
||||
</button>
|
||||
<i class="fas fa-sign-out-alt"></i> <EFBFBD><EFBFBD><EFBFBD>? </button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- 仪表板容器 -->
|
||||
<!-- 隞芾”<EFBFBD>踹捆<EFBFBD>?-->
|
||||
<div class="dashboard-container">
|
||||
<!-- 左侧侧边栏 -->
|
||||
<!-- 撌虫儒靘扯器<EFBFBD>?-->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<div class="user-info">
|
||||
@@ -38,8 +37,8 @@
|
||||
<i class="fas fa-user-graduate"></i>
|
||||
</div>
|
||||
<div class="user-details">
|
||||
<h3 id="studentName">加载中...</h3>
|
||||
<p>学生 | 班级:<span id="studentClass">加载中...</span></p>
|
||||
<h3 id="studentName"><EFBFBD>㰘蝸銝?..</h3>
|
||||
<p>摮衣<EFBFBD> | <20>剔漣嚗?span id="studentClass"><3E>㰘蝸銝?..</span></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -48,7 +47,7 @@
|
||||
<li>
|
||||
<a href="#" class="active">
|
||||
<i class="fas fa-tachometer-alt"></i>
|
||||
<span>仪表板</span>
|
||||
<span>隞芾”<EFBFBD>?/span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
@@ -88,11 +87,11 @@
|
||||
<main class="main-content">
|
||||
<div class="content-header">
|
||||
<div>
|
||||
<h1 class="page-title">学生仪表板</h1>
|
||||
<h1 class="page-title">摮衣<EFBFBD>隞芾”<EFBFBD>?/h1>
|
||||
<div class="breadcrumb">
|
||||
<a href="index.html">主页</a>
|
||||
<a href="/">銝駁△</a>
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
<span>学生仪表板</span>
|
||||
<span>摮衣<EFBFBD>隞芾”<EFBFBD>?/span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="current-time" id="currentTime"></div>
|
||||
@@ -121,7 +120,7 @@
|
||||
<i class="fas fa-certificate"></i>
|
||||
</div>
|
||||
<div class="stat-value" id="creditTotal">24</div>
|
||||
<div class="stat-label">总学分</div>
|
||||
<div class="stat-label"><EFBFBD>餃郎<EFBFBD>?/div>
|
||||
</div>
|
||||
|
||||
<div class="stat-card">
|
||||
@@ -136,16 +135,15 @@
|
||||
<!-- 成绩表格 -->
|
||||
<div class="grades-table">
|
||||
<div class="table-header">
|
||||
<h2 class="table-title">本学期成绩</h2>
|
||||
<h2 class="table-title"><EFBFBD>砍郎<EFBFBD><EFBFBD><EFBFBD>蝏?/h2>
|
||||
<div class="table-actions">
|
||||
<select class="form-select" style="width: 150px;">
|
||||
<option value="all">所有学期</option>
|
||||
<option value="all"><EFBFBD><EFBFBD><EFBFBD>匧郎<EFBFBD>?/option>
|
||||
<option value="2023-2" selected>2023-2024学年第二学期</option>
|
||||
<option value="2023-1">2023-2024学年第一学期</option>
|
||||
</select>
|
||||
<button class="btn btn-primary">
|
||||
<i class="fas fa-download"></i> 导出成绩单
|
||||
</button>
|
||||
<i class="fas fa-download"></i> 撖澆枂<EFBFBD>鞟貍<EFBFBD>? </button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -158,13 +156,13 @@
|
||||
<th>学分</th>
|
||||
<th>平时成绩</th>
|
||||
<th>期末成绩</th>
|
||||
<th>总成绩</th>
|
||||
<th><EFBFBD>餅<EFBFBD>蝏?/th>
|
||||
<th>绩点</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="gradesTableBody">
|
||||
<!-- 成绩数据将通过JavaScript动态加载 -->
|
||||
<!-- <EFBFBD>鞟貍<EFBFBD>唳旿撠<EFBFBD><EFBFBD>朞<EFBFBD>JavaScript<EFBFBD>冽<EFBFBD><EFBFBD><EFBFBD>頧?-->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -172,8 +170,8 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="../js/student.js"></script>
|
||||
<script src="../js/auth.js"></script>
|
||||
<script src="/public/js/student.js"></script>
|
||||
<script src="/public/js/auth.js"></script>
|
||||
<script>
|
||||
// 更新当前时间
|
||||
function updateCurrentTime() {
|
||||
@@ -192,4 +190,4 @@
|
||||
updateCurrentTime();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>学生成绩管理系统 - 教师仪表板</title>
|
||||
<link rel="stylesheet" href="../css/style.css">
|
||||
<title>摮衣<EFBFBD><EFBFBD>鞟貍蝞∠<EFBFBD>蝟餌<EFBFBD> - <20>坔<EFBFBD>隞芾”<E88ABE>?/title>
|
||||
<link rel="stylesheet" href="/public/css/style.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
</head>
|
||||
/* 仪表板布局 */
|
||||
@@ -13,7 +13,7 @@
|
||||
min-height: calc(100vh - 80px);
|
||||
}
|
||||
|
||||
/* 侧边栏 */
|
||||
/* 靘扯器<EFBFBD>?*/
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
background: linear-gradient(180deg, #43e97b 0%, #38f9d7 100%);
|
||||
@@ -183,7 +183,7 @@
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* 快速操作 */
|
||||
/* 敹恍<EFBFBD><EFBFBD><EFBFBD>雿?*/
|
||||
.quick-actions {
|
||||
background: white;
|
||||
border-radius: 15px;
|
||||
@@ -230,7 +230,7 @@
|
||||
border-color: #43e97b;
|
||||
}
|
||||
|
||||
/* 最近活动 */
|
||||
/* <EFBFBD><EFBFBD>餈烐暑<EFBFBD>?*/
|
||||
.recent-activities {
|
||||
background: white;
|
||||
border-radius: 15px;
|
||||
@@ -282,7 +282,7 @@
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
/* <EFBFBD>滚<EFBFBD>撘讛挽霈?*/
|
||||
@media (max-width: 992px) {
|
||||
.dashboard-container {
|
||||
flex-direction: column;
|
||||
@@ -344,28 +344,27 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 顶部导航栏 -->
|
||||
<!-- 憿園<EFBFBD>撖潸⏛<EFBFBD>?-->
|
||||
<nav class="navbar">
|
||||
<div class="navbar-brand">
|
||||
<i class="fas fa-graduation-cap"></i>
|
||||
<span>XX学校成绩管理系统</span>
|
||||
</div>
|
||||
<div class="navbar-menu">
|
||||
<a href="index.html" class="btn btn-secondary">
|
||||
<a href="/" class="btn btn-secondary">
|
||||
<i class="fas fa-home"></i> 主页
|
||||
</a>
|
||||
<div class="navbar-user">
|
||||
<span class="user-name" id="userName">李老师</span>
|
||||
<button id="logoutBtn" class="btn btn-primary">
|
||||
<i class="fas fa-sign-out-alt"></i> 退出
|
||||
</button>
|
||||
<i class="fas fa-sign-out-alt"></i> <EFBFBD><EFBFBD><EFBFBD>? </button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- 仪表板容器 -->
|
||||
<!-- 隞芾”<EFBFBD>踹捆<EFBFBD>?-->
|
||||
<div class="dashboard-container">
|
||||
<!-- 左侧侧边栏 -->
|
||||
<!-- 撌虫儒靘扯器<EFBFBD>?-->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<div class="user-info">
|
||||
@@ -374,7 +373,7 @@
|
||||
</div>
|
||||
<div class="user-details">
|
||||
<h3 id="teacherName">李老师</h3>
|
||||
<p>教师 | 部门:<span id="teacherDept">计算机学院</span></p>
|
||||
<p><EFBFBD>坔<EFBFBD> | <20>券秄嚗?span id="teacherDept">霈∠<E99C88><E288A0>箏郎<E7AE8F>?/span></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -383,11 +382,11 @@
|
||||
<li>
|
||||
<a href="#" class="active">
|
||||
<i class="fas fa-tachometer-alt"></i>
|
||||
<span>仪表板</span>
|
||||
<span>隞芾”<EFBFBD>?/span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="grade_entry.html">
|
||||
<a href="/teacher/grade_entry">
|
||||
<i class="fas fa-edit"></i>
|
||||
<span>成绩录入</span>
|
||||
</a>
|
||||
@@ -429,11 +428,11 @@
|
||||
<main class="main-content">
|
||||
<div class="content-header">
|
||||
<div>
|
||||
<h1 class="page-title">教师仪表板</h1>
|
||||
<h1 class="page-title"><EFBFBD>坔<EFBFBD>隞芾”<EFBFBD>?/h1>
|
||||
<div class="breadcrumb">
|
||||
<a href="index.html">主页</a>
|
||||
<a href="/">銝駁△</a>
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
<span>教师仪表板</span>
|
||||
<span><EFBFBD>坔<EFBFBD>隞芾”<EFBFBD>?/span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="current-time" id="currentTime"></div>
|
||||
@@ -447,9 +446,8 @@
|
||||
</div>
|
||||
<h3 class="function-title">成绩录入</h3>
|
||||
<p class="function-description">
|
||||
为学生录入新的课程成绩,支持批量导入和单个录入。
|
||||
</p>
|
||||
<button class="btn btn-primary">开始录入</button>
|
||||
銝箏郎<EFBFBD>笔<EFBFBD><EFBFBD>交鰵<EFBFBD><EFBFBD>紋蝔𧢲<EFBFBD>蝏抬<EFBFBD><EFBFBD>舀<EFBFBD><EFBFBD>寥<EFBFBD>撖澆<EFBFBD><EFBFBD><EFBFBD><EFBFBD>銝芸<EFBFBD><EFBFBD>乓<EFBFBD>? </p>
|
||||
<button class="btn btn-primary">撘<EFBFBD>憪见<EFBFBD><EFBFBD>?/button>
|
||||
</div>
|
||||
|
||||
<div class="function-card" onclick="window.location.href='grade_query.html'">
|
||||
@@ -458,9 +456,8 @@
|
||||
</div>
|
||||
<h3 class="function-title">成绩查询</h3>
|
||||
<p class="function-description">
|
||||
查询学生成绩,支持按班级、课程、学期等多维度筛选。
|
||||
</p>
|
||||
<button class="btn btn-primary">开始查询</button>
|
||||
<EFBFBD>亥砭摮衣<EFBFBD><EFBFBD>鞟貍嚗峕𣈲<EFBFBD><EFBFBD><EFBFBD><EFBFBD>剔漣<EFBFBD><EFBFBD>紋蝔卝<EFBFBD><EFBFBD>郎<EFBFBD>毺<EFBFBD>憭𡁶輕摨衣<EFBFBD><EFBFBD>剹<EFBFBD>? </p>
|
||||
<button class="btn btn-primary">撘<EFBFBD>憪𧢲䰻霂?/button>
|
||||
</div>
|
||||
|
||||
<div class="function-card" onclick="window.location.href='grade_manage.html'">
|
||||
@@ -469,9 +466,8 @@
|
||||
</div>
|
||||
<h3 class="function-title">成绩管理</h3>
|
||||
<p class="function-description">
|
||||
修改或删除已录入的成绩,管理成绩记录和状态。
|
||||
</p>
|
||||
<button class="btn btn-primary">开始管理</button>
|
||||
靽格㺿<EFBFBD>硋<EFBFBD><EFBFBD>文歇敶訫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝏抬<EFBFBD>蝞∠<EFBFBD><EFBFBD>鞟貍霈啣<EFBFBD><EFBFBD>𣬚𠶖<EFBFBD><EFBFBD><EFBFBD>? </p>
|
||||
<button class="btn btn-primary">撘<EFBFBD>憪讠恣<EFBFBD>?/button>
|
||||
</div>
|
||||
|
||||
<div class="function-card" onclick="window.location.href='#'">
|
||||
@@ -480,31 +476,27 @@
|
||||
</div>
|
||||
<h3 class="function-title">统计分析</h3>
|
||||
<p class="function-description">
|
||||
查看成绩统计图表,分析教学效果和学生表现。
|
||||
</p>
|
||||
<EFBFBD>亦<EFBFBD><EFBFBD>鞟貍蝏蠘恣<EFBFBD>曇”嚗<EFBFBD><EFBFBD><EFBFBD>鞉<EFBFBD>摮行<EFBFBD><EFBFBD>𨅯<EFBFBD>摮衣<EFBFBD>銵函緵<EFBFBD>? </p>
|
||||
<button class="btn btn-primary">查看统计</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 快速操作 -->
|
||||
<!-- 敹恍<EFBFBD><EFBFBD><EFBFBD>雿?-->
|
||||
<div class="quick-actions">
|
||||
<h2 class="section-title">
|
||||
<i class="fas fa-bolt"></i>
|
||||
快速操作
|
||||
</h2>
|
||||
敹恍<EFBFBD><EFBFBD><EFBFBD>雿? </h2>
|
||||
<div class="action-buttons">
|
||||
<a href="grade_entry.html" class="action-btn">
|
||||
<a href="/teacher/grade_entry" class="action-btn">
|
||||
<i class="fas fa-plus"></i>
|
||||
录入新成绩
|
||||
</a>
|
||||
敶訫<EFBFBD><EFBFBD>唳<EFBFBD>蝏? </a>
|
||||
<a href="grade_query.html" class="action-btn">
|
||||
<i class="fas fa-search"></i>
|
||||
查询成绩
|
||||
</a>
|
||||
<a href="#" class="action-btn">
|
||||
<i class="fas fa-download"></i>
|
||||
导出成绩单
|
||||
</a>
|
||||
撖澆枂<EFBFBD>鞟貍<EFBFBD>? </a>
|
||||
<a href="#" class="action-btn">
|
||||
<i class="fas fa-chart-pie"></i>
|
||||
生成统计报告
|
||||
@@ -512,4 +504,4 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 最近活动
|
||||
<!-- <EFBFBD><EFBFBD>餈烐暑<EFBFBD>
|
||||
@@ -4,34 +4,34 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>成绩录入 - XX学校成绩管理系统</title>
|
||||
<link rel="stylesheet" href="../css/style.css">
|
||||
<link rel="stylesheet" href="/public/css/style.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- 导航栏 -->
|
||||
<!-- 撖潸⏛<EFBFBD>?-->
|
||||
<nav class="navbar">
|
||||
<div class="navbar-brand">
|
||||
<a href="index.html"><i class="fas fa-graduation-cap"></i> XX学校成绩管理系统</a>
|
||||
<a href="/"><i class="fas fa-graduation-cap"></i> XX摮行嵗<EFBFBD>鞟貍蝞∠<EFBFBD>蝟餌<EFBFBD></a>
|
||||
</div>
|
||||
<div class="navbar-menu">
|
||||
<a href="teacher_dashboard.html" class="navbar-item"><i class="fas fa-tachometer-alt"></i> 教师仪表板</a>
|
||||
<a href="grade_entry.html" class="navbar-item active"><i class="fas fa-edit"></i> 成绩录入</a>
|
||||
<a href="grade_management.html" class="navbar-item"><i class="fas fa-list"></i> 成绩管理</a>
|
||||
<a href="/teacher/dashboard" class="navbar-item"><i class="fas fa-tachometer-alt"></i> <EFBFBD>坔<EFBFBD>隞芾”<EFBFBD>?/a>
|
||||
<a href="/teacher/grade_entry" class="navbar-item active"><i class="fas fa-edit"></i> <EFBFBD>鞟貍敶訫<EFBFBD></a>
|
||||
<a href="/teacher/grade_management" class="navbar-item"><i class="fas fa-list"></i> <EFBFBD>鞟貍蝞∠<EFBFBD></a>
|
||||
<div class="user-info">
|
||||
<span class="user-name">李老师</span>
|
||||
<span class="user-role">教师</span>
|
||||
<a href="login.html" class="btn btn-outline btn-small"><i class="fas fa-sign-out-alt"></i> 退出</a>
|
||||
<a href="/login" class="btn btn-outline btn-small"><i class="fas fa-sign-out-alt"></i> <EFBFBD><EFBFBD><EFBFBD>?/a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- 面包屑导航 -->
|
||||
<!-- <EFBFBD>W<EFBFBD>撅穃紡<EFBFBD>?-->
|
||||
<div class="container">
|
||||
<div class="breadcrumb">
|
||||
<a href="index.html">主页</a>
|
||||
<a href="/">銝駁△</a>
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
<a href="teacher_dashboard.html">教师仪表板</a>
|
||||
<a href="/teacher/dashboard"><EFBFBD>坔<EFBFBD>隞芾”<EFBFBD>?/a>
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
<span>成绩录入</span>
|
||||
</div>
|
||||
@@ -41,7 +41,7 @@
|
||||
<div class="grade-entry-container">
|
||||
<div class="entry-header">
|
||||
<h1><i class="fas fa-edit"></i> 成绩录入</h1>
|
||||
<p>请选择班级和课程,然后为每个学生录入成绩</p>
|
||||
<p>霂琿<EFBFBD>㗇𥋘<EFBFBD>剔漣<EFBFBD>諹紋蝔页<EFBFBD><EFBFBD>嗅<EFBFBD>銝箸<EFBFBD>銝芸郎<EFBFBD>笔<EFBFBD><EFBFBD>交<EFBFBD>蝏?/p>
|
||||
</div>
|
||||
|
||||
<div class="entry-form">
|
||||
@@ -50,11 +50,11 @@
|
||||
<label for="class-select"><i class="fas fa-users"></i> 选择班级</label>
|
||||
<select id="class-select" class="form-control">
|
||||
<option value="">请选择班级</option>
|
||||
<option value="class1">计算机科学与技术2021级1班</option>
|
||||
<option value="class2">计算机科学与技术2021级2班</option>
|
||||
<option value="class3">软件工程2021级1班</option>
|
||||
<option value="class4">软件工程2021级2班</option>
|
||||
<option value="class5">网络工程2021级1班</option>
|
||||
<option value="class1">霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?021蝥?<3F>?/option>
|
||||
<option value="class2">霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?021蝥?<3F>?/option>
|
||||
<option value="class3">頧臭辣撌亦<EFBFBD>2021蝥?<3F>?/option>
|
||||
<option value="class4">頧臭辣撌亦<EFBFBD>2021蝥?<3F>?/option>
|
||||
<option value="class5">蝵𤑳<EFBFBD>撌亦<EFBFBD>2021蝥?<3F>?/option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -71,12 +71,12 @@
|
||||
|
||||
<div class="form-group">
|
||||
<label><i class="fas fa-info-circle"></i> 备注说明(可选)</label>
|
||||
<textarea id="remarks" rows="3" placeholder="可输入本次考试的说明信息,如:期中考试、期末考试等"></textarea>
|
||||
<textarea id="remarks" rows="3" placeholder="<EFBFBD>航<EFBFBD><EFBFBD>交𧋦甈∟<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>秩<EFBFBD>𦒘縑<EFBFBD>荔<EFBFBD>憒<EFBFBD><EFBFBD><EFBFBD>煺葉<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>怨<EFBFBD><EFBFBD><EFBFBD>蝑?></textarea>
|
||||
</div>
|
||||
|
||||
<div class="students-table-container">
|
||||
<h3><i class="fas fa-user-graduate"></i> 学生成绩录入</h3>
|
||||
<p class="text-muted">选择班级后,系统将自动加载该班级的学生列表</p>
|
||||
<p class="text-muted"><EFBFBD>㗇𥋘<EFBFBD>剔漣<EFBFBD>𠬍<EFBFBD>蝟餌<EFBFBD>撠<EFBFBD>䌊<EFBFBD>典<EFBFBD>頧質砲<EFBFBD>剔漣<EFBFBD><EFBFBD>郎<EFBFBD>笔<EFBFBD>銵?/p>
|
||||
|
||||
<div id="students-loading" class="loading" style="display: none;">
|
||||
<i class="fas fa-spinner"></i>
|
||||
@@ -100,7 +100,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="students-tbody">
|
||||
<!-- 学生数据将通过JavaScript动态加载 -->
|
||||
<!-- 摮衣<EFBFBD><EFBFBD>唳旿撠<EFBFBD><EFBFBD>朞<EFBFBD>JavaScript<EFBFBD>冽<EFBFBD><EFBFBD><EFBFBD>頧?-->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -118,11 +118,11 @@
|
||||
<div class="card">
|
||||
<h3><i class="fas fa-lightbulb"></i> 使用说明</h3>
|
||||
<ul class="text-muted">
|
||||
<li>首先选择要录入成绩的班级和课程</li>
|
||||
<li>系统会自动加载该班级的学生列表</li>
|
||||
<li>擐硋<EFBFBD><EFBFBD>㗇𥋘閬<EFBFBD><EFBFBD><EFBFBD>交<EFBFBD>蝏拍<EFBFBD><EFBFBD>剔漣<EFBFBD>諹紋蝔?/li>
|
||||
<li>蝟餌<EFBFBD>隡朞䌊<EFBFBD>典<EFBFBD>頧質砲<EFBFBD>剔漣<EFBFBD><EFBFBD>郎<EFBFBD>笔<EFBFBD>銵?/li>
|
||||
<li>为每个学生输入平时成绩、期中成绩和期末成绩</li>
|
||||
<li>总评成绩将根据权重自动计算(默认权重:平时20%,期中30%,期末50%)</li>
|
||||
<li>确认无误后点击“提交成绩”按钮保存数据</li>
|
||||
<li><EFBFBD>餉<EFBFBD><EFBFBD>鞟貍撠<EFBFBD>覔<EFBFBD>格<EFBFBD><EFBFBD>滩䌊<EFBFBD>刻恣蝞梹<EFBFBD>暺䁅恕<EFBFBD><EFBFBD><EFBFBD>嚗𡁜像<EFBFBD>?0%嚗峕<E59A97>銝?0%嚗峕<E59A97><E5B395>?0%嚗?/li>
|
||||
<li>蝖株恕<EFBFBD>㰘秤<EFBFBD>𡒊<EFBFBD><EFBFBD>領<EFBFBD>𨀣<EFBFBD>鈭斗<EFBFBD>蝏抽<EFBFBD>脲<EFBFBD><EFBFBD>桐<EFBFBD>摮䀹㺭<EFBFBD>?/li>
|
||||
<li>提交后可以在“成绩管理”页面查看和修改已录入的成绩</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -154,8 +154,7 @@
|
||||
const cancelBtn = document.getElementById('cancel-btn');
|
||||
const submitBtn = document.getElementById('submit-btn');
|
||||
|
||||
// 设置默认考试日期为今天
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
// 霈曄蔭暺䁅恕<EFBFBD><EFBFBD><EFBFBD><EFBFBD>交<EFBFBD>銝箔<EFBFBD>憭? const today = new Date().toISOString().split('T')[0];
|
||||
examDateInput.value = today;
|
||||
|
||||
// 班级选择变化事件
|
||||
@@ -168,8 +167,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// 显示加载状态
|
||||
showLoading();
|
||||
// <EFBFBD>曄內<EFBFBD>㰘蝸<EFBFBD>嗆<EFBFBD>? showLoading();
|
||||
|
||||
// 模拟API调用延迟
|
||||
setTimeout(() => {
|
||||
@@ -194,8 +192,7 @@
|
||||
// 清空表格
|
||||
studentsTbody.innerHTML = '';
|
||||
|
||||
// 添加学生行
|
||||
students.forEach((student, index) => {
|
||||
// 瘛餃<EFBFBD>摮衣<EFBFBD>銵? students.forEach((student, index) => {
|
||||
const row = document.createElement('tr');
|
||||
row.innerHTML = `
|
||||
<td>${student.id}</td>
|
||||
@@ -234,20 +231,17 @@
|
||||
addGradeInputListeners();
|
||||
}
|
||||
|
||||
// 显示加载状态
|
||||
function showLoading() {
|
||||
// <EFBFBD>曄內<EFBFBD>㰘蝸<EFBFBD>嗆<EFBFBD>? function showLoading() {
|
||||
studentsLoading.style.display = 'block';
|
||||
studentsTable.style.display = 'none';
|
||||
noStudents.style.display = 'none';
|
||||
}
|
||||
|
||||
// 隐藏加载状态
|
||||
function hideLoading() {
|
||||
// <EFBFBD>鞱<EFBFBD><EFBFBD>㰘蝸<EFBFBD>嗆<EFBFBD>? function hideLoading() {
|
||||
studentsLoading.style.display = 'none';
|
||||
}
|
||||
|
||||
// 显示无学生数据
|
||||
function showNoStudents() {
|
||||
// <EFBFBD>曄內<EFBFBD>惩郎<EFBFBD><EFBFBD>㺭<EFBFBD>? function showNoStudents() {
|
||||
hideLoading();
|
||||
studentsTable.style.display = 'none';
|
||||
noStudents.style.display = 'block';
|
||||
@@ -293,11 +287,9 @@
|
||||
const midterm = parseFloat(midtermInput.value) || 0;
|
||||
const final = parseFloat(finalInput.value) || 0;
|
||||
|
||||
// 计算总评成绩(权重:平时20%,期中30%,期末50%)
|
||||
const total = (usual * 0.2) + (midterm * 0.3) + (final * 0.5);
|
||||
// 霈∠<EFBFBD><EFBFBD>餉<EFBFBD><EFBFBD>鞟貍嚗<EFBFBD><EFBFBD><EFBFBD>㵪<EFBFBD>撟單𧒄20%嚗峕<E59A97>銝?0%嚗峕<E59A97><E5B395>?0%嚗? const total = (usual * 0.2) + (midterm * 0.3) + (final * 0.5);
|
||||
|
||||
// 显示总评成绩(四舍五入到整数)
|
||||
totalSpan.textContent = Math.round(total);
|
||||
// <EFBFBD>曄內<EFBFBD>餉<EFBFBD><EFBFBD>鞟貍嚗<EFBFBD><EFBFBD><EFBFBD>滢<EFBFBD><EFBFBD>亙<EFBFBD><EFBFBD>湔㺭嚗? totalSpan.textContent = Math.round(total);
|
||||
|
||||
// 根据成绩范围设置颜色
|
||||
if (total >= 90) {
|
||||
@@ -323,13 +315,12 @@
|
||||
}
|
||||
|
||||
if (!courseName) {
|
||||
alert('请输入课程名称');
|
||||
alert('霂瑁<EFBFBD><EFBFBD>亥紋蝔见<EFBFBD>蝘?);
|
||||
courseNameInput.focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否有学生成绩未填写
|
||||
const usualGrades = document.querySelectorAll('.usual-grade');
|
||||
// 璉<EFBFBD><EFBFBD>交糓<EFBFBD>行<EFBFBD>摮衣<EFBFBD><EFBFBD>鞟貍<EFBFBD>芸‵<EFBFBD>? const usualGrades = document.querySelectorAll('.usual-grade');
|
||||
const midtermGrades = document.querySelectorAll('.midterm-grade');
|
||||
const finalGrades = document.querySelectorAll('.final-grade');
|
||||
|
||||
@@ -350,7 +341,7 @@
|
||||
if (usualNum < 0 || usualNum > 100 ||
|
||||
midtermNum < 0 || midtermNum > 100 ||
|
||||
finalNum < 0 || finalNum > 100) {
|
||||
alert(`第${i + 1}行学生的成绩必须在0-100之间`);
|
||||
alert(`蝚?{i + 1}銵<EFBFBD>郎<EFBFBD>毺<EFBFBD><EFBFBD>鞟貍敹<EFBFBD>◆<EFBFBD>?-100銋钅𡢿`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -403,17 +394,15 @@
|
||||
|
||||
const formData = collectFormData();
|
||||
|
||||
// 显示提交中状态
|
||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 提交中...';
|
||||
// <EFBFBD>曄內<EFBFBD>𣂷漱銝剔𠶖<EFBFBD>? submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> <20>𣂷漱銝?..';
|
||||
submitBtn.disabled = true;
|
||||
|
||||
// 模拟API调用
|
||||
setTimeout(() => {
|
||||
// 模拟成功响应
|
||||
alert(`成绩提交成功!\n班级:${formData.className}\n课程:${formData.courseName}\n共录入${formData.grades.length}名学生成绩`);
|
||||
alert(`<EFBFBD>鞟貍<EFBFBD>𣂷漱<EFBFBD>𣂼<EFBFBD>嚗<EFBFBD>n<EFBFBD>剔漣嚗?{formData.className}\n霂曄<EFBFBD>嚗?{formData.courseName}\n<EFBFBD>勗<EFBFBD><EFBFBD>?{formData.grades.length}<EFBFBD>滚郎<EFBFBD><EFBFBD><EFBFBD>蝏奈);
|
||||
|
||||
// 重置按钮状态
|
||||
submitBtn.innerHTML = '<i class="fas fa-check"></i> 提交成绩';
|
||||
// <EFBFBD>滨蔭<EFBFBD>厰僼<EFBFBD>嗆<EFBFBD>? submitBtn.innerHTML = '<i class="fas fa-check"></i> <20>𣂷漱<F0A382B7>鞟貍';
|
||||
submitBtn.disabled = false;
|
||||
|
||||
// 重置表单
|
||||
@@ -439,7 +428,7 @@
|
||||
|
||||
// 取消按钮事件
|
||||
cancelBtn.addEventListener('click', function() {
|
||||
if (confirm('确定要取消吗?所有未保存的更改将会丢失。')) {
|
||||
if (confirm('蝖桀<EFBFBD>閬<EFBFBD><EFBFBD>瘨<EFBFBD><EFBFBD>嚗<EFBFBD><EFBFBD><EFBFBD>㗇𧊋靽嘥<EFBFBD><EFBFBD><EFBFBD>凒<EFBFBD>孵<EFBFBD>隡帋腺憭晞<EFBFBD>?)) {
|
||||
resetForm();
|
||||
}
|
||||
});
|
||||
@@ -449,11 +438,10 @@
|
||||
|
||||
// 页面加载时初始化
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// 检查是否有必要的数据
|
||||
if (!classSelect.value) {
|
||||
// 璉<EFBFBD><EFBFBD>交糓<EFBFBD>行<EFBFBD>敹<EFBFBD><EFBFBD><EFBFBD><EFBFBD>㺭<EFBFBD>? if (!classSelect.value) {
|
||||
submitBtn.disabled = true;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -4,30 +4,30 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>成绩查询/管理 - 学生成绩管理系统</title>
|
||||
<link rel="stylesheet" href="../css/style.css">
|
||||
<link rel="stylesheet" href="/public/css/style.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- 导航栏 -->
|
||||
<!-- 撖潸⏛<EFBFBD>?-->
|
||||
<nav class="navbar">
|
||||
<div class="nav-container">
|
||||
<div class="nav-brand">
|
||||
<a href="index.html">
|
||||
<a href="/">
|
||||
<i class="fas fa-graduation-cap"></i>
|
||||
<span>XX学校成绩管理系统</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="nav-menu">
|
||||
<a href="teacher_dashboard.html" class="nav-link">
|
||||
<a href="/teacher/dashboard" class="nav-link">
|
||||
<i class="fas fa-tachometer-alt"></i>
|
||||
<span>教师仪表板</span>
|
||||
<span><EFBFBD>坔<EFBFBD>隞芾”<EFBFBD>?/span>
|
||||
</a>
|
||||
<a href="grade_entry.html" class="nav-link">
|
||||
<a href="/teacher/grade_entry" class="nav-link">
|
||||
<i class="fas fa-edit"></i>
|
||||
<span>成绩录入</span>
|
||||
</a>
|
||||
<a href="grade_management.html" class="nav-link active">
|
||||
<a href="/teacher/grade_management" class="nav-link active">
|
||||
<i class="fas fa-search"></i>
|
||||
<span>成绩管理</span>
|
||||
</a>
|
||||
@@ -37,9 +37,9 @@
|
||||
<i class="fas fa-user-circle"></i>
|
||||
<span>张老师</span>
|
||||
</div>
|
||||
<a href="login.html" class="btn-logout">
|
||||
<a href="/login" class="btn-logout">
|
||||
<i class="fas fa-sign-out-alt"></i>
|
||||
<span>退出</span>
|
||||
<span><EFBFBD><EFBFBD><EFBFBD>?/span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -48,11 +48,11 @@
|
||||
<!-- 主内容区 -->
|
||||
<main class="main-content">
|
||||
<div class="container">
|
||||
<!-- 面包屑导航 -->
|
||||
<!-- <EFBFBD>W<EFBFBD>撅穃紡<EFBFBD>?-->
|
||||
<div class="breadcrumb">
|
||||
<a href="index.html">主页</a>
|
||||
<a href="/">銝駁△</a>
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
<a href="teacher_dashboard.html">教师仪表板</a>
|
||||
<a href="/teacher/dashboard"><EFBFBD>坔<EFBFBD>隞芾”<EFBFBD>?/a>
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
<span>成绩查询/管理</span>
|
||||
</div>
|
||||
@@ -63,22 +63,21 @@
|
||||
<p class="page-description">查询、修改和删除学生成绩记录</p>
|
||||
</div>
|
||||
|
||||
<!-- 筛选区域 -->
|
||||
<!-- 蝑偦<EFBFBD>匧躹<EFBFBD>?-->
|
||||
<div class="filter-section">
|
||||
<h2 class="filter-title">
|
||||
<i class="fas fa-filter"></i>
|
||||
筛选条件
|
||||
</h2>
|
||||
蝑偦<EFBFBD>㗇辺隞? </h2>
|
||||
<div class="filter-form">
|
||||
<div class="form-group">
|
||||
<label for="class-select">班级</label>
|
||||
<select id="class-select" class="form-control">
|
||||
<option value="">全部班级</option>
|
||||
<option value="class1">计算机科学与技术1班</option>
|
||||
<option value="class2">计算机科学与技术2班</option>
|
||||
<option value="class3">软件工程1班</option>
|
||||
<option value="class4">软件工程2班</option>
|
||||
<option value="class5">网络工程1班</option>
|
||||
<option value="class1">霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?/option>
|
||||
<option value="class2">霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?/option>
|
||||
<option value="class3">頧臭辣撌亦<EFBFBD>1<EFBFBD>?/option>
|
||||
<option value="class4">頧臭辣撌亦<EFBFBD>2<EFBFBD>?/option>
|
||||
<option value="class5">蝵𤑳<EFBFBD>撌亦<EFBFBD>1<EFBFBD>?/option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@@ -87,8 +86,8 @@
|
||||
<option value="">全部课程</option>
|
||||
<option value="course1">数据结构</option>
|
||||
<option value="course2">操作系统</option>
|
||||
<option value="course3">计算机网络</option>
|
||||
<option value="course4">数据库系统</option>
|
||||
<option value="course3">霈∠<EFBFBD><EFBFBD>箇<EFBFBD>蝏?/option>
|
||||
<option value="course4"><EFBFBD>唳旿摨梶頂蝏?/option>
|
||||
<option value="course5">软件工程</option>
|
||||
</select>
|
||||
</div>
|
||||
@@ -147,7 +146,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="grade-table-body">
|
||||
<!-- 数据将通过JavaScript动态加载 -->
|
||||
<!-- <EFBFBD>唳旿撠<EFBFBD><EFBFBD>朞<EFBFBD>JavaScript<EFBFBD>冽<EFBFBD><EFBFBD><EFBFBD>頧?-->
|
||||
<tr>
|
||||
<td colspan="11" class="loading">
|
||||
<i class="fas fa-spinner fa-spin"></i>
|
||||
@@ -160,11 +159,11 @@
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="pagination">
|
||||
<button id="prev-page" disabled>上一页</button>
|
||||
<button id="prev-page" disabled>銝𠹺<EFBFBD>憿?/button>
|
||||
<button class="active">1</button>
|
||||
<button>2</button>
|
||||
<button>3</button>
|
||||
<button id="next-page">下一页</button>
|
||||
<button id="next-page">銝衤<EFBFBD>憿?/button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -173,8 +172,8 @@
|
||||
<!-- 页脚 -->
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<p>© 2023 XX学校成绩管理系统. 版权所有.</p>
|
||||
<p>技术支持: 计算机科学与技术学院</p>
|
||||
<p>© 2023 XX摮行嵗<EFBFBD>鞟貍蝞∠<EFBFBD>蝟餌<EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?</p>
|
||||
<p><EFBFBD><EFBFBD><EFBFBD>舀𣈲<EFBFBD>? 霈∠<E99C88><E288A0>箇<EFBFBD>摮虫<E691AE><E899AB><EFBFBD><EFBFBD>臬郎<E887AC>?/p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -185,7 +184,7 @@
|
||||
id: 1,
|
||||
studentId: "20230001",
|
||||
studentName: "张三",
|
||||
className: "计算机科学与技术1班",
|
||||
className: "霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?,
|
||||
courseName: "数据结构",
|
||||
regularScore: 85,
|
||||
midtermScore: 88,
|
||||
@@ -197,7 +196,7 @@
|
||||
id: 2,
|
||||
studentId: "20230002",
|
||||
studentName: "李四",
|
||||
className: "计算机科学与技术1班",
|
||||
className: "霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?,
|
||||
courseName: "数据结构",
|
||||
regularScore: 78,
|
||||
midtermScore: 82,
|
||||
@@ -209,7 +208,7 @@
|
||||
id: 3,
|
||||
studentId: "20230003",
|
||||
studentName: "王五",
|
||||
className: "计算机科学与技术2班",
|
||||
className: "霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?,
|
||||
courseName: "操作系统",
|
||||
regularScore: 92,
|
||||
midtermScore: 88,
|
||||
@@ -221,7 +220,7 @@
|
||||
id: 4,
|
||||
studentId: "20230004",
|
||||
studentName: "赵六",
|
||||
className: "计算机科学与技术2班",
|
||||
className: "霈∠<EFBFBD><EFBFBD>箇<EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<3F>?,
|
||||
courseName: "操作系统",
|
||||
regularScore: 65,
|
||||
midtermScore: 70,
|
||||
@@ -233,8 +232,8 @@
|
||||
id: 5,
|
||||
studentId: "20230005",
|
||||
studentName: "钱七",
|
||||
className: "软件工程1班",
|
||||
courseName: "数据库系统",
|
||||
className: "頧臭辣撌亦<EFBFBD>1<EFBFBD>?,
|
||||
courseName: "<EFBFBD>唳旿摨梶頂蝏?,
|
||||
regularScore: 88,
|
||||
midtermScore: 85,
|
||||
finalScore: 90,
|
||||
@@ -245,8 +244,8 @@
|
||||
id: 6,
|
||||
studentId: "20230006",
|
||||
studentName: "孙八",
|
||||
className: "软件工程1班",
|
||||
courseName: "数据库系统",
|
||||
className: "頧臭辣撌亦<EFBFBD>1<EFBFBD>?,
|
||||
courseName: "<EFBFBD>唳旿摨梶頂蝏?,
|
||||
regularScore: 75,
|
||||
midtermScore: 78,
|
||||
finalScore: 80,
|
||||
@@ -257,7 +256,7 @@
|
||||
id: 7,
|
||||
studentId: "20230007",
|
||||
studentName: "周九",
|
||||
className: "软件工程2班",
|
||||
className: "頧臭辣撌亦<EFBFBD>2<EFBFBD>?,
|
||||
courseName: "软件工程",
|
||||
regularScore: 90,
|
||||
midtermScore: 92,
|
||||
@@ -269,7 +268,7 @@
|
||||
id: 8,
|
||||
studentId: "20230008",
|
||||
studentName: "吴十",
|
||||
className: "软件工程2班",
|
||||
className: "頧臭辣撌亦<EFBFBD>2<EFBFBD>?,
|
||||
courseName: "软件工程",
|
||||
regularScore: 82,
|
||||
midtermScore: 85,
|
||||
@@ -294,8 +293,7 @@
|
||||
// 当前选中的成绩ID
|
||||
let selectedGradeIds = new Set();
|
||||
|
||||
// 初始化页面
|
||||
function initPage() {
|
||||
// <EFBFBD>嘥<EFBFBD><EFBFBD>㚚△<EFBFBD>? function initPage() {
|
||||
renderGradeTable(mockGrades);
|
||||
setupEventListeners();
|
||||
updateSelectedCount();
|
||||
@@ -308,7 +306,7 @@
|
||||
<tr>
|
||||
<td colspan="11" class="no-results">
|
||||
<i class="fas fa-search"></i>
|
||||
<h3>未找到相关成绩记录</h3>
|
||||
<h3><EFBFBD>芣𪄳<EFBFBD>啁㮾<EFBFBD>單<EFBFBD>蝏抵扇敶?/h3>
|
||||
<p>请尝试调整筛选条件或添加新的成绩记录</p>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -319,8 +317,7 @@
|
||||
let tableHTML = '';
|
||||
|
||||
grades.forEach(grade => {
|
||||
// 根据成绩确定CSS类
|
||||
let gradeClass = 'grade-cell';
|
||||
// <EFBFBD>寞旿<EFBFBD>鞟貍蝖桀<EFBFBD>CSS蝐? let gradeClass = 'grade-cell';
|
||||
if (grade.totalScore >= 90) {
|
||||
gradeClass += ' grade-excellent';
|
||||
} else if (grade.totalScore >= 80) {
|
||||
@@ -377,8 +374,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
// 设置事件监听器
|
||||
function setupEventListeners() {
|
||||
// 霈曄蔭鈭衤辣<EFBFBD>穃𨯬<EFBFBD>? function setupEventListeners() {
|
||||
// 查询按钮
|
||||
searchBtn.addEventListener('click', function() {
|
||||
performSearch();
|
||||
@@ -404,11 +400,11 @@
|
||||
// 批量删除按钮
|
||||
batchDeleteBtn.addEventListener('click', function() {
|
||||
if (selectedGradeIds.size === 0) {
|
||||
alert('请先选择要删除的成绩记录!');
|
||||
alert('霂瑕<EFBFBD><EFBFBD>㗇𥋘閬<EFBFBD><EFBFBD><EFBFBD>斤<EFBFBD><EFBFBD>鞟貍霈啣<EFBFBD>嚗?);
|
||||
return;
|
||||
}
|
||||
|
||||
if (confirm(`确定要删除选中的 ${selectedGradeIds.size} 条成绩记录吗?此操作不可撤销。`)) {
|
||||
if (confirm(`蝖桀<EFBFBD>閬<EFBFBD><EFBFBD><EFBFBD>日<EFBFBD>劐葉<EFBFBD>?${selectedGradeIds.size} <EFBFBD>⊥<EFBFBD>蝏抵扇敶訫<EFBFBD>嚗<EFBFBD>迨<EFBFBD>滢<EFBFBD>銝滚虾<EFBFBD>日<EFBFBD><EFBFBD><EFBFBD>)) {
|
||||
batchDeleteGrades();
|
||||
}
|
||||
});
|
||||
@@ -445,8 +441,7 @@
|
||||
const studentId = studentIdInput.value.trim();
|
||||
const studentName = studentNameInput.value.trim();
|
||||
|
||||
// 显示加载状态
|
||||
gradeTableBody.innerHTML = `
|
||||
// <EFBFBD>曄內<EFBFBD>㰘蝸<EFBFBD>嗆<EFBFBD>? gradeTableBody.innerHTML = `
|
||||
<tr>
|
||||
<td colspan="11" class="loading">
|
||||
<i class="fas fa-spinner fa-spin"></i>
|
||||
@@ -458,23 +453,19 @@
|
||||
// 模拟API延迟
|
||||
setTimeout(() => {
|
||||
let filteredGrades = mockGrades.filter(grade => {
|
||||
// 班级筛选
|
||||
if (selectedClass && grade.className !== selectedClass) {
|
||||
// <EFBFBD>剔漣蝑偦<EFBFBD>? if (selectedClass && grade.className !== selectedClass) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 课程筛选
|
||||
if (selectedCourse && grade.courseName !== selectedCourse) {
|
||||
// 霂曄<EFBFBD>蝑偦<EFBFBD>? if (selectedCourse && grade.courseName !== selectedCourse) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 学号筛选
|
||||
if (studentId && !grade.studentId.includes(studentId)) {
|
||||
// 摮血噡蝑偦<EFBFBD>? if (studentId && !grade.studentId.includes(studentId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 姓名筛选
|
||||
if (studentName && !grade.studentName.includes(studentName)) {
|
||||
// 憪枏<EFBFBD>蝑偦<EFBFBD>? if (studentName && !grade.studentName.includes(studentName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -492,10 +483,10 @@
|
||||
function exportGrades() {
|
||||
// 这里应该调用后端API导出成绩
|
||||
// 暂时使用模拟导出
|
||||
alert('成绩导出功能正在开发中,将支持Excel和CSV格式导出。');
|
||||
alert('<EFBFBD>鞟貍撖澆枂<EFBFBD>蠘<EFBFBD>甇<EFBFBD>銁撘<EFBFBD><EFBFBD>睲葉嚗<EFBFBD><EFBFBD><EFBFBD>舀<EFBFBD>Excel<EFBFBD>龦SV<EFBFBD>澆<EFBFBD>撖澆枂<EFBFBD>?);
|
||||
|
||||
// 模拟导出过程
|
||||
exportBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 导出中...';
|
||||
exportBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 撖澆枂銝?..';
|
||||
exportBtn.disabled = true;
|
||||
|
||||
setTimeout(() => {
|
||||
@@ -504,7 +495,7 @@
|
||||
|
||||
// 在实际应用中,这里会触发文件下载
|
||||
// 暂时显示成功消息
|
||||
showNotification('成绩导出成功!文件已开始下载。', 'success');
|
||||
showNotification('<EFBFBD>鞟貍撖澆枂<EFBFBD>𣂼<EFBFBD>嚗<EFBFBD><EFBFBD>隞嗅歇撘<EFBFBD>憪衤<EFBFBD>頧賬<EFBFBD>?, 'success');
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
@@ -512,12 +503,11 @@
|
||||
function batchDeleteGrades() {
|
||||
// 这里应该调用后端API删除成绩
|
||||
// 暂时使用模拟删除
|
||||
batchDeleteBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 删除中...';
|
||||
batchDeleteBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> <EFBFBD>𣳇膄銝?..';
|
||||
batchDeleteBtn.disabled = true;
|
||||
|
||||
setTimeout(() => {
|
||||
// 从模拟数据中删除选中的成绩
|
||||
selectedGradeIds.forEach(id => {
|
||||
// 隞擧芋<EFBFBD><EFBFBD>㺭<EFBFBD>桐葉<EFBFBD>𣳇膄<EFBFBD>劐葉<EFBFBD><EFBFBD><EFBFBD>蝏? selectedGradeIds.forEach(id => {
|
||||
const index = mockGrades.findIndex(grade => grade.id === id);
|
||||
if (index !== -1) {
|
||||
mockGrades.splice(index, 1);
|
||||
@@ -546,7 +536,7 @@
|
||||
|
||||
// 删除单个成绩
|
||||
function deleteGrade(gradeId) {
|
||||
if (confirm('确定要删除这条成绩记录吗?此操作不可撤销。')) {
|
||||
if (confirm('蝖桀<EFBFBD>閬<EFBFBD><EFBFBD><EFBFBD>方<EFBFBD><EFBFBD>⊥<EFBFBD>蝏抵扇敶訫<EFBFBD>嚗<EFBFBD>迨<EFBFBD>滢<EFBFBD>銝滚虾<EFBFBD>日<EFBFBD><EFBFBD>?)) {
|
||||
// 这里应该调用后端API删除成绩
|
||||
// 暂时使用模拟删除
|
||||
const index = mockGrades.findIndex(grade => grade.id === gradeId);
|
||||
@@ -581,4 +571,4 @@
|
||||
document.addEventListener('DOMContentLoaded', initPage);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
Reference in New Issue
Block a user