运行必须源码:app/(controller/model/service/middleware/lib/utils/validate/router)、config/、database/(migrations/seeders/sql)、启动脚本、app/public/templates 模板。 已忽略运行非必须:node_modules/、logs/、run/、app/public 运行时上传数据、.env*、构建/缓存产物。
159 lines
7.9 KiB
JavaScript
159 lines
7.9 KiB
JavaScript
'use strict';
|
||
|
||
/**
|
||
* 路由配置 - Router
|
||
*
|
||
* 通信与导航应用技术创新赛 - 线上选拔赛网站后端路由定义
|
||
*
|
||
* 路由分组说明:
|
||
* - /api/auth/* : 认证相关(登录、激活、验证码等)
|
||
* - /api/news/* : 新闻通知(公开访问)
|
||
* - /api/carousel : 轮播图(公开访问)
|
||
* - /api/materials/* : 资料下载(需认证)
|
||
* - /api/exam/* : 比赛答题(需认证)
|
||
* - /api/upload/* : 文件上传(需认证)
|
||
* - /api/admin/* : 管理后台(需管理员认证)
|
||
* - /api/score/* : 成绩查询(需认证)
|
||
*/
|
||
|
||
module.exports = app => {
|
||
const { router, controller, middleware } = app;
|
||
|
||
// 获取 JWT 认证中间件实例
|
||
const auth = middleware.auth();
|
||
// 管理员认证中间件(需要 admin 角色)
|
||
const adminAuth = middleware.auth({ adminOnly: true });
|
||
// 登录限流中间件(防暴力破解):15 分钟内同一 IP+账号最多 10 次失败
|
||
const loginRateLimit = middleware.loginRateLimit({ windowMs: 15 * 60 * 1000, maxAttempts: 10 });
|
||
|
||
// ==================== 公开接口(无需认证) ====================
|
||
|
||
// 健康检查(容器探针 / 负载均衡探活,无需认证)
|
||
router.get('/api/health', controller.health.check);
|
||
|
||
// 认证相关 - 公开接口
|
||
router.post('/api/auth/captcha', controller.auth.captcha);
|
||
router.post('/api/auth/sms', controller.auth.sms);
|
||
router.post('/api/auth/activate', controller.auth.activate);
|
||
router.post('/api/auth/login', loginRateLimit, controller.auth.login);
|
||
router.post('/api/auth/admin-login', loginRateLimit, controller.auth.adminLogin);
|
||
router.post('/api/auth/forgot-password', controller.auth.forgotPassword);
|
||
router.post('/api/auth/reset-password', controller.auth.resetPassword);
|
||
|
||
// ==================== 选手认证接口(需要 JWT,不需要 admin 角色) ====================
|
||
|
||
// 认证相关 - 受保护接口
|
||
router.get('/api/auth/current-user', auth, controller.auth.currentUser);
|
||
router.post('/api/auth/logout', auth, controller.auth.logout);
|
||
// 静默刷新令牌(不挂 auth 中间件,因为携带的 token 可能已过期)
|
||
router.post('/api/auth/refresh', controller.auth.refresh);
|
||
|
||
// ==================== 公开内容接口 ====================
|
||
|
||
// 新闻通知
|
||
router.get('/api/news', controller.news.index);
|
||
router.get('/api/news/counts', controller.news.counts);
|
||
router.get('/api/news/:id', controller.news.show);
|
||
|
||
// 轮播图
|
||
router.get('/api/carousel', controller.carousel.index);
|
||
|
||
// ==================== 资料下载(需认证) ====================
|
||
|
||
router.get('/api/materials', auth, controller.materials.index);
|
||
router.get('/api/materials/:group/:fileName/download', auth, controller.materials.download);
|
||
|
||
// ==================== 比赛答题(需认证) ====================
|
||
|
||
router.get('/api/exam/:group/status', auth, controller.exam.status);
|
||
router.get('/api/exam/:group/questions', auth, controller.exam.questions);
|
||
router.get('/api/exam/:group/answers', auth, controller.exam.getAnswers);
|
||
router.get('/api/exam/:group/word-template', controller.exam.wordTemplate);
|
||
router.post('/api/exam/:group/submit-answers', auth, controller.exam.submitAnswers);
|
||
router.post('/api/exam/:group/upload-word', auth, controller.exam.uploadWord);
|
||
router.delete('/api/exam/:group/word', auth, controller.exam.deleteWord);
|
||
router.post('/api/exam/:group/submit-all', auth, controller.exam.submitAll);
|
||
|
||
// ==================== 文件上传(需认证) ====================
|
||
|
||
router.post('/api/upload/:group', auth, controller.upload.upload);
|
||
router.get('/api/upload/:group/status', auth, controller.upload.status);
|
||
router.get('/api/upload/:group/submissions', auth, controller.upload.submissions);
|
||
router.delete('/api/upload/:group/:id', auth, controller.upload.delete);
|
||
|
||
// 分片上传(需认证)
|
||
router.post('/api/upload/:group/chunk', auth, controller.upload.uploadChunk);
|
||
router.post('/api/upload/:group/merge', auth, controller.upload.mergeChunks);
|
||
router.get('/api/upload/:group/chunk-status', auth, controller.upload.chunkStatus);
|
||
|
||
// ==================== 管理后台(需管理员认证) ====================
|
||
|
||
// 数据统计
|
||
router.get('/api/admin/stats', adminAuth, controller.admin.stats);
|
||
|
||
// 账号管理
|
||
router.get('/api/admin/accounts', adminAuth, controller.admin.accounts);
|
||
router.post('/api/admin/import-excel', adminAuth, controller.admin.importExcel);
|
||
|
||
// 提交管理
|
||
router.get('/api/admin/submissions/:group', adminAuth, controller.admin.submissions);
|
||
router.get('/api/admin/submission-file/:group/:id', adminAuth, controller.admin.downloadSubmissionFile);
|
||
router.get('/api/admin/export-csv/:group', adminAuth, controller.admin.exportCsv);
|
||
router.get('/api/admin/batch-download/:group', adminAuth, controller.admin.batchDownload);
|
||
router.get('/api/admin/works/:group', adminAuth, controller.admin.works);
|
||
|
||
// 时间设置
|
||
router.get('/api/admin/times', adminAuth, controller.admin.getTimes);
|
||
router.put('/api/admin/times', adminAuth, controller.admin.setTimes);
|
||
|
||
// 分数管理
|
||
router.get('/api/admin/scores/:group', adminAuth, controller.admin.getScores);
|
||
router.put('/api/admin/scores/:group', adminAuth, controller.admin.setScores);
|
||
|
||
// 试题管理
|
||
router.get('/api/admin/exam/:group/questions', adminAuth, controller.admin.getQuestions);
|
||
router.put('/api/admin/exam/:group/questions', adminAuth, controller.admin.setQuestions);
|
||
router.post('/api/admin/exam/:group/questions/import-excel', adminAuth, controller.admin.importQuestionsExcel);
|
||
router.get('/api/admin/exam/:group/questions/template', adminAuth, controller.admin.downloadQuestionTemplate);
|
||
router.put('/api/admin/exam/:group/word-template', adminAuth, controller.admin.uploadWordTemplate);
|
||
router.get('/api/admin/exam/:group/word-template', adminAuth, controller.admin.getWordTemplate);
|
||
router.delete('/api/admin/exam/:group/word-template', adminAuth, controller.admin.deleteWordTemplate);
|
||
|
||
// 备赛资料管理
|
||
router.get('/api/admin/materials/:group', adminAuth, controller.admin.getMaterials);
|
||
router.post('/api/admin/materials/:group', adminAuth, controller.admin.uploadMaterial);
|
||
router.delete('/api/admin/materials/:group/:fileName', adminAuth, controller.admin.deleteMaterial);
|
||
|
||
// 成绩发布
|
||
router.put('/api/admin/publish-scores', adminAuth, controller.admin.publishScores);
|
||
router.get('/api/admin/publish-scores', adminAuth, controller.admin.getPublishStatus);
|
||
|
||
// 新闻管理
|
||
router.get('/api/admin/news', adminAuth, controller.admin.listNews);
|
||
router.post('/api/admin/news', adminAuth, controller.admin.createNews);
|
||
router.put('/api/admin/news/order', adminAuth, controller.admin.updateNewsOrder);
|
||
router.put('/api/admin/news/:id', adminAuth, controller.admin.updateNews);
|
||
router.delete('/api/admin/news/:id', adminAuth, controller.admin.deleteNews);
|
||
|
||
// 轮播图管理
|
||
router.get('/api/admin/carousel', adminAuth, controller.admin.listCarousel);
|
||
router.post('/api/admin/carousel', adminAuth, controller.admin.addCarousel);
|
||
router.put('/api/admin/carousel/:id', adminAuth, controller.admin.updateCarousel);
|
||
router.delete('/api/admin/carousel/:id', adminAuth, controller.admin.deleteCarousel);
|
||
router.put('/api/admin/carousel/order', adminAuth, controller.admin.updateCarouselOrder);
|
||
// 图片上传(轮播图等)
|
||
router.post('/api/admin/upload/image', adminAuth, controller.admin.uploadImage);
|
||
router.post('/api/admin/upload/news-image', adminAuth, controller.admin.uploadNewsImage);
|
||
|
||
// 下载考生答案 Word 文件
|
||
router.get('/api/admin/submissions/:group/:id/word', adminAuth, controller.admin.downloadWord);
|
||
|
||
// 测试数据标记与重置
|
||
router.post('/api/admin/toggle-test-flag', adminAuth, controller.admin.toggleTestFlag);
|
||
router.post('/api/admin/reset-test-data', adminAuth, controller.admin.resetTestData);
|
||
|
||
// ==================== 成绩查询(需认证) ====================
|
||
|
||
router.get('/api/score', auth, controller.score.index);
|
||
};
|