const express = require('express'); const cors = require('cors'); const session = require('express-session'); const MySQLStore = require('express-mysql-session')(session); const path = require('path'); require('dotenv').config(); // Config & Utils const db = require('./config/database'); const errorHandler = require('./middleware/errorHandler'); const { requireAuth, requireRole } = require('./middleware/auth'); // Routes const authRoutes = require('./routes/auth'); const studentRoutes = require('./routes/student'); const teacherRoutes = require('./routes/teacher'); const adminRoutes = require('./routes/admin'); const app = express(); const PORT = process.env.PORT || 3000; // Middleware app.use(cors({ origin: 'http://localhost:3000', credentials: true })); app.use(express.json()); app.use(express.urlencoded({ extended: true })); // Session const sessionStore = new MySQLStore({ expiration: 86400000, createDatabaseTable: true, schema: { tableName: 'sessions', columnNames: { session_id: 'session_id', expires: 'expires', data: 'data' } } }, db.pool); app.use(session({ key: 'session_cookie', secret: process.env.SESSION_SECRET || 'your-secret-key', store: sessionStore, resave: false, saveUninitialized: false, cookie: { maxAge: 86400000, httpOnly: true, secure: process.env.NODE_ENV === 'production' } })); // Static Files app.use('/public', express.static(path.join(__dirname, '../frontend/public'))); // View Routes (HTML Serving) // 为了简单起见,这里仍然直接 serve HTML,未来可以考虑使用模板引擎或分离前端部署 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('

403 Forbidden - 权限不足

返回首页'); } next(); }; }; // --- Page Routes --- 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'); } }); // Student Pages app.get('/student/dashboard', requirePageAuth, requirePageRole(['student']), (req, res) => { res.sendFile(path.join(__dirname, '../frontend/views/student/dashboard.html')); }); app.get('/student/profile', requirePageAuth, requirePageRole(['student']), (req, res) => { res.sendFile(path.join(__dirname, '../frontend/views/student/profile.html')); }); // Teacher Pages const teacherPageRouter = express.Router(); teacherPageRouter.use(requirePageAuth, requirePageRole(['teacher'])); teacherPageRouter.get('/dashboard', (req, res) => res.sendFile(path.join(__dirname, '../frontend/views/teacher/dashboard.html'))); teacherPageRouter.get('/grade_entry', (req, res) => res.sendFile(path.join(__dirname, '../frontend/views/teacher/grade_entry.html'))); teacherPageRouter.get('/grade_management', (req, res) => res.sendFile(path.join(__dirname, '../frontend/views/teacher/grade_management.html'))); app.use('/teacher', teacherPageRouter); // Admin Pages const adminPageRouter = express.Router(); adminPageRouter.use(requirePageAuth, requirePageRole(['admin'])); adminPageRouter.get('/dashboard', (req, res) => res.sendFile(path.join(__dirname, '../frontend/views/admin/dashboard.html'))); adminPageRouter.get('/student_management', (req, res) => res.sendFile(path.join(__dirname, '../frontend/views/admin/student_management.html'))); adminPageRouter.get('/user_management', (req, res) => res.sendFile(path.join(__dirname, '../frontend/views/admin/user_management.html'))); app.use('/admin', adminPageRouter); // --- API Routes --- app.use('/api/auth', authRoutes); app.use('/api/student', studentRoutes); app.use('/api/teacher', teacherRoutes); app.use('/api/admin', adminRoutes); // Error Handler app.use((req, res) => { res.status(404).json({ success: false, message: 'Not Found' }); }); app.use(errorHandler); // Start Server app.listen(PORT, async () => { console.log(`Server running on port ${PORT}`); console.log(`访问地址: http://localhost:${PORT}`); await db.testConnection(); });