feat(admin): Complete tenant management and module access control system
Major Features: - Tenant management CRUD (list, create, edit, delete, module configuration) - Dynamic module management system (modules table with 8 modules) - Multi-tenant module permission merging (ModuleService) - Module access control middleware (requireModule) - User module permission API (GET /api/v1/auth/me/modules) - Frontend module permission filtering (HomePage + TopNavigation) Module Integration: - RVW module integrated with PromptService (editorial + methodology) - All modules (RVW/PKB/ASL/DC) added authenticate + requireModule middleware - Fixed ReviewTask foreign key constraint (cross-schema issue) - Removed all MOCK_USER_ID, unified to request.user?.userId Prompt Management Enhancements: - Module names displayed in Chinese (RVW -> 智能审稿) - Enhanced version history with view content and rollback features - List page shows both activeVersion and draftVersion columns Database Changes: - Added platform_schema.modules table - Modified tenant_modules table (added index and UUID) - Removed ReviewTask foreign key to public.users (cross-schema fix) - Seeded 8 modules: RVW, PKB, ASL, DC, IIT, AIA, SSA, ST Documentation Updates: - Updated ADMIN module development status - Updated TODO checklist (89% progress) - Updated Prompt management plan (Phase 3.5.5 completed) - Added module authentication specification Files Changed: 80+ Status: All features tested and verified locally Next: User management module development
This commit is contained in:
@@ -7,55 +7,56 @@ import * as projectController from '../controllers/projectController.js';
|
||||
import * as literatureController from '../controllers/literatureController.js';
|
||||
import * as screeningController from '../controllers/screeningController.js';
|
||||
import * as fulltextScreeningController from '../fulltext-screening/controllers/FulltextScreeningController.js';
|
||||
import { authenticate, requireModule } from '../../../common/auth/auth.middleware.js';
|
||||
|
||||
export async function aslRoutes(fastify: FastifyInstance) {
|
||||
// ==================== 筛选项目路由 ====================
|
||||
|
||||
// 创建筛选项目
|
||||
fastify.post('/projects', projectController.createProject);
|
||||
fastify.post('/projects', { preHandler: [authenticate, requireModule('ASL')] }, projectController.createProject);
|
||||
|
||||
// 获取用户的所有项目
|
||||
fastify.get('/projects', projectController.getProjects);
|
||||
fastify.get('/projects', { preHandler: [authenticate, requireModule('ASL')] }, projectController.getProjects);
|
||||
|
||||
// 获取单个项目详情
|
||||
fastify.get('/projects/:projectId', projectController.getProjectById);
|
||||
fastify.get('/projects/:projectId', { preHandler: [authenticate, requireModule('ASL')] }, projectController.getProjectById);
|
||||
|
||||
// 更新项目
|
||||
fastify.put('/projects/:projectId', projectController.updateProject);
|
||||
fastify.put('/projects/:projectId', { preHandler: [authenticate, requireModule('ASL')] }, projectController.updateProject);
|
||||
|
||||
// 删除项目
|
||||
fastify.delete('/projects/:projectId', projectController.deleteProject);
|
||||
fastify.delete('/projects/:projectId', { preHandler: [authenticate, requireModule('ASL')] }, projectController.deleteProject);
|
||||
|
||||
// ==================== 文献管理路由 ====================
|
||||
|
||||
// 导入文献(JSON)
|
||||
fastify.post('/literatures/import', literatureController.importLiteratures);
|
||||
fastify.post('/literatures/import', { preHandler: [authenticate, requireModule('ASL')] }, literatureController.importLiteratures);
|
||||
|
||||
// 导入文献(Excel上传)
|
||||
fastify.post('/literatures/import-excel', literatureController.importLiteraturesFromExcel);
|
||||
fastify.post('/literatures/import-excel', { preHandler: [authenticate, requireModule('ASL')] }, literatureController.importLiteraturesFromExcel);
|
||||
|
||||
// 获取项目的文献列表
|
||||
fastify.get('/projects/:projectId/literatures', literatureController.getLiteratures);
|
||||
fastify.get('/projects/:projectId/literatures', { preHandler: [authenticate, requireModule('ASL')] }, literatureController.getLiteratures);
|
||||
|
||||
// 删除文献
|
||||
fastify.delete('/literatures/:literatureId', literatureController.deleteLiterature);
|
||||
fastify.delete('/literatures/:literatureId', { preHandler: [authenticate, requireModule('ASL')] }, literatureController.deleteLiterature);
|
||||
|
||||
// ==================== 筛选任务路由 ====================
|
||||
|
||||
// 获取筛选任务进度
|
||||
fastify.get('/projects/:projectId/screening-task', screeningController.getScreeningTask);
|
||||
fastify.get('/projects/:projectId/screening-task', { preHandler: [authenticate, requireModule('ASL')] }, screeningController.getScreeningTask);
|
||||
|
||||
// 获取筛选结果列表(分页)
|
||||
fastify.get('/projects/:projectId/screening-results', screeningController.getScreeningResults);
|
||||
fastify.get('/projects/:projectId/screening-results', { preHandler: [authenticate, requireModule('ASL')] }, screeningController.getScreeningResults);
|
||||
|
||||
// 获取单个筛选结果详情
|
||||
fastify.get('/screening-results/:resultId', screeningController.getScreeningResultDetail);
|
||||
fastify.get('/screening-results/:resultId', { preHandler: [authenticate, requireModule('ASL')] }, screeningController.getScreeningResultDetail);
|
||||
|
||||
// 提交人工复核
|
||||
fastify.post('/screening-results/:resultId/review', screeningController.reviewScreeningResult);
|
||||
fastify.post('/screening-results/:resultId/review', { preHandler: [authenticate, requireModule('ASL')] }, screeningController.reviewScreeningResult);
|
||||
|
||||
// ⭐ 获取项目统计数据(Week 4 新增)
|
||||
fastify.get('/projects/:projectId/statistics', screeningController.getProjectStatistics);
|
||||
fastify.get('/projects/:projectId/statistics', { preHandler: [authenticate, requireModule('ASL')] }, screeningController.getProjectStatistics);
|
||||
|
||||
// TODO: 启动筛选任务(Week 2 Day 2 已实现为同步流程,异步版本待实现)
|
||||
// fastify.post('/projects/:projectId/screening/start', screeningController.startScreening);
|
||||
@@ -63,19 +64,19 @@ export async function aslRoutes(fastify: FastifyInstance) {
|
||||
// ==================== 全文复筛路由 (Day 5 新增) ====================
|
||||
|
||||
// 创建全文复筛任务
|
||||
fastify.post('/fulltext-screening/tasks', fulltextScreeningController.createTask);
|
||||
fastify.post('/fulltext-screening/tasks', { preHandler: [authenticate, requireModule('ASL')] }, fulltextScreeningController.createTask);
|
||||
|
||||
// 获取任务进度
|
||||
fastify.get('/fulltext-screening/tasks/:taskId', fulltextScreeningController.getTaskProgress);
|
||||
fastify.get('/fulltext-screening/tasks/:taskId', { preHandler: [authenticate, requireModule('ASL')] }, fulltextScreeningController.getTaskProgress);
|
||||
|
||||
// 获取任务结果(支持筛选和分页)
|
||||
fastify.get('/fulltext-screening/tasks/:taskId/results', fulltextScreeningController.getTaskResults);
|
||||
fastify.get('/fulltext-screening/tasks/:taskId/results', { preHandler: [authenticate, requireModule('ASL')] }, fulltextScreeningController.getTaskResults);
|
||||
|
||||
// 人工审核决策
|
||||
fastify.put('/fulltext-screening/results/:resultId/decision', fulltextScreeningController.updateDecision);
|
||||
fastify.put('/fulltext-screening/results/:resultId/decision', { preHandler: [authenticate, requireModule('ASL')] }, fulltextScreeningController.updateDecision);
|
||||
|
||||
// 导出Excel
|
||||
fastify.get('/fulltext-screening/tasks/:taskId/export', fulltextScreeningController.exportExcel);
|
||||
fastify.get('/fulltext-screening/tasks/:taskId/export', { preHandler: [authenticate, requireModule('ASL')] }, fulltextScreeningController.exportExcel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user