Files
Web_BLV_OA_Exam_Prod/api/server.ts

140 lines
5.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import express from 'express';
import cors from 'cors';
import path from 'path';
import { initDatabase } from './database';
import {
UserController,
QuestionController,
QuizController,
AdminController,
BackupController,
QuestionCategoryController,
ExamSubjectController,
ExamTaskController,
AdminUserController
} from './controllers';
import {
upload,
errorHandler,
adminAuth,
requestLogger,
responseFormatter
} from './middlewares';
const app = express();
const PORT = process.env.PORT || 3000;
// 中间件
app.use(cors());
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
app.use(requestLogger);
app.use(responseFormatter);
// API路由
const apiRouter = express.Router();
// 用户相关
apiRouter.post('/users', UserController.createUser);
apiRouter.get('/users/:id', UserController.getUser);
apiRouter.post('/users/validate', UserController.validateUserInfo);
apiRouter.get('/users/name/:name', UserController.getUsersByName);
// 题库管理
apiRouter.get('/questions', QuestionController.getQuestions);
apiRouter.get('/questions/:id', QuestionController.getQuestion);
apiRouter.post('/questions', adminAuth, QuestionController.createQuestion);
apiRouter.put('/questions/:id', adminAuth, QuestionController.updateQuestion);
apiRouter.delete('/questions/:id', adminAuth, QuestionController.deleteQuestion);
apiRouter.post('/questions/import', adminAuth, upload.single('file'), QuestionController.importQuestions);
apiRouter.get('/questions/export', adminAuth, QuestionController.exportQuestions);
// 为了兼容前端可能的错误请求,添加一个不包含 /api 前缀的路由
app.get('/questions/export', adminAuth, QuestionController.exportQuestions);
// 题目类别
apiRouter.get('/question-categories', QuestionCategoryController.getCategories);
apiRouter.post('/admin/question-categories', adminAuth, QuestionCategoryController.createCategory);
apiRouter.put('/admin/question-categories/:id', adminAuth, QuestionCategoryController.updateCategory);
apiRouter.delete('/admin/question-categories/:id', adminAuth, QuestionCategoryController.deleteCategory);
// 考试科目
apiRouter.get('/exam-subjects', ExamSubjectController.getSubjects);
apiRouter.get('/admin/subjects', adminAuth, ExamSubjectController.getSubjects);
apiRouter.post('/admin/subjects', adminAuth, ExamSubjectController.createSubject);
apiRouter.put('/admin/subjects/:id', adminAuth, ExamSubjectController.updateSubject);
apiRouter.delete('/admin/subjects/:id', adminAuth, ExamSubjectController.deleteSubject);
// 考试任务
apiRouter.get('/exam-tasks', ExamTaskController.getTasks);
apiRouter.get('/admin/tasks', adminAuth, ExamTaskController.getTasks);
apiRouter.get('/admin/tasks/:id/users', adminAuth, ExamTaskController.getTaskUsers);
apiRouter.get('/exam-tasks/user/:userId', ExamTaskController.getUserTasks);
apiRouter.post('/admin/tasks', adminAuth, ExamTaskController.createTask);
apiRouter.put('/admin/tasks/:id', adminAuth, ExamTaskController.updateTask);
apiRouter.delete('/admin/tasks/:id', adminAuth, ExamTaskController.deleteTask);
apiRouter.get('/admin/tasks/:id/report', adminAuth, ExamTaskController.getTaskReport);
// 用户管理
apiRouter.get('/admin/users', adminAuth, AdminUserController.getUsers);
apiRouter.put('/admin/users/:id', adminAuth, AdminUserController.updateUser);
apiRouter.delete('/admin/users', adminAuth, AdminUserController.deleteUser);
apiRouter.get('/admin/users/export', adminAuth, AdminUserController.exportUsers);
apiRouter.post('/admin/users/import', adminAuth, upload.single('file'), AdminUserController.importUsers);
apiRouter.get('/admin/users/:userId/records', adminAuth, AdminUserController.getUserRecords);
apiRouter.get('/admin/quiz/records/detail/:recordId', adminAuth, AdminUserController.getRecordDetail);
// 答题相关
apiRouter.post('/quiz/generate', QuizController.generateQuiz);
apiRouter.post('/quiz/submit', QuizController.submitQuiz);
apiRouter.get('/quiz/records/:userId', QuizController.getUserRecords);
apiRouter.get('/quiz/records/detail/:recordId', QuizController.getRecordDetail);
apiRouter.get('/quiz/records', adminAuth, QuizController.getAllRecords);
// 管理员相关
apiRouter.post('/admin/login', AdminController.login);
apiRouter.get('/admin/statistics', adminAuth, AdminController.getStatistics);
apiRouter.get('/admin/active-tasks', adminAuth, AdminController.getActiveTasksStats);
apiRouter.put('/admin/config', adminAuth, AdminController.updateQuizConfig);
apiRouter.get('/admin/config', adminAuth, AdminController.getQuizConfig);
apiRouter.put('/admin/password', adminAuth, AdminController.updatePassword);
apiRouter.get('/admin/configs', adminAuth, AdminController.getAllConfigs);
// 数据备份和恢复
apiRouter.get('/admin/export/users', adminAuth, BackupController.exportUsers);
apiRouter.get('/admin/export/questions', adminAuth, BackupController.exportQuestions);
apiRouter.get('/admin/export/records', adminAuth, BackupController.exportRecords);
apiRouter.get('/admin/export/answers', adminAuth, BackupController.exportAnswers);
apiRouter.post('/admin/restore', adminAuth, BackupController.restoreData);
// 应用API路由
app.use('/api', apiRouter);
// 静态文件服务
app.use(express.static(path.join(process.cwd(), 'dist')));
// 前端路由SPA支持
app.get('*', (req, res) => {
res.sendFile(path.join(process.cwd(), 'dist', 'index.html'));
});
// 错误处理
app.use(errorHandler);
// 启动服务器
async function startServer() {
try {
await initDatabase();
console.log('数据库初始化完成');
app.listen(PORT, () => {
console.log(`服务器运行在端口 ${PORT}`);
console.log(`API文档: http://localhost:${PORT}/api`);
});
} catch (error) {
console.error('启动服务器失败:', error);
process.exit(1);
}
}
startServer();