feat(P2): 实现选课管理、考试监考、学情诊断三大功能模块
## 新增功能模块 ### 1. 选课管理(elective) - 新增表:electiveCourses、courseSelections - 新增权限:ELECTIVE_MANAGE/ELECTIVE_READ/ELECTIVE_SELECT - 支持先到先得 + 抽签两种选课模式 - admin/teacher/student 三端页面 ### 2. 考试监考(proctoring) - exams 表扩展:examMode/durationMinutes/antiCheatEnabled 等字段 - 新增表:examProctoringEvents - 新增权限:EXAM_PROCTOR/EXAM_PROCTOR_READ - 教师监考面板 + 学生端防作弊监控 - API:/api/proctoring/event 接收事件上报 ### 3. 学情诊断报告(diagnostic) - 新增表:knowledgePointMastery、learningDiagnosticReports - 新增权限:DIAGNOSTIC_MANAGE/DIAGNOSTIC_READ - 基于提交答案自动计算知识点掌握度 - 生成个人/班级诊断报告(强项/弱项/建议) - 雷达图可视化 ## 其他改动 - 项目规则:单文件行数限制从 300 行调整为企业级规范(组件≤500/Actions≤800/硬上限1000) - scripts/seed.ts:消除全部 any 类型,定义内部类型,0 lint 错误 - 架构文档 004/005 同步更新三个新模块 - 迁移文件 0001_heavy_sage.sql 生成 ## 验证 - npx tsc --noEmit:0 错误 - npm run lint:0 错误 0 警告
This commit is contained in:
115
drizzle/0001_heavy_sage.sql
Normal file
115
drizzle/0001_heavy_sage.sql
Normal file
@@ -0,0 +1,115 @@
|
||||
CREATE TABLE `course_selections` (
|
||||
`id` varchar(128) NOT NULL,
|
||||
`course_id` varchar(128) NOT NULL,
|
||||
`student_id` varchar(128) NOT NULL,
|
||||
`selection_status` enum('selected','enrolled','waitlist','dropped','rejected') NOT NULL DEFAULT 'selected',
|
||||
`priority` int DEFAULT 1,
|
||||
`selected_at` timestamp NOT NULL DEFAULT (now()),
|
||||
`enrolled_at` timestamp,
|
||||
`dropped_at` timestamp,
|
||||
`lottery_rank` int,
|
||||
`created_at` timestamp NOT NULL DEFAULT (now()),
|
||||
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
|
||||
CONSTRAINT `course_selections_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `elective_courses` (
|
||||
`id` varchar(128) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`subject_id` varchar(128),
|
||||
`teacher_id` varchar(128) NOT NULL,
|
||||
`grade_id` varchar(128),
|
||||
`description` text,
|
||||
`capacity` int NOT NULL DEFAULT 30,
|
||||
`enrolled_count` int NOT NULL DEFAULT 0,
|
||||
`classroom` varchar(100),
|
||||
`schedule` varchar(255),
|
||||
`start_date` date,
|
||||
`end_date` date,
|
||||
`selection_start_at` datetime,
|
||||
`selection_end_at` datetime,
|
||||
`status` enum('draft','open','closed','cancelled') NOT NULL DEFAULT 'draft',
|
||||
`selection_mode` enum('fcfs','lottery') NOT NULL DEFAULT 'fcfs',
|
||||
`credit` decimal(3,1) DEFAULT '1.0',
|
||||
`created_at` timestamp NOT NULL DEFAULT (now()),
|
||||
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
|
||||
CONSTRAINT `elective_courses_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `exam_proctoring_events` (
|
||||
`id` varchar(128) NOT NULL,
|
||||
`submission_id` varchar(128) NOT NULL,
|
||||
`student_id` varchar(128) NOT NULL,
|
||||
`exam_id` varchar(128) NOT NULL,
|
||||
`event_type` enum('tab_switch','window_blur','copy_attempt','paste_attempt','right_click','devtools_open','fullscreen_exit','idle_timeout') NOT NULL,
|
||||
`event_detail` text,
|
||||
`occurred_at` timestamp NOT NULL DEFAULT (now()),
|
||||
`created_at` timestamp NOT NULL DEFAULT (now()),
|
||||
CONSTRAINT `exam_proctoring_events_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `knowledge_point_mastery` (
|
||||
`id` varchar(128) NOT NULL,
|
||||
`student_id` varchar(128) NOT NULL,
|
||||
`knowledge_point_id` varchar(128) NOT NULL,
|
||||
`mastery_level` decimal(5,2) NOT NULL DEFAULT '0',
|
||||
`total_questions` int NOT NULL DEFAULT 0,
|
||||
`correct_questions` int NOT NULL DEFAULT 0,
|
||||
`last_assessed_at` timestamp NOT NULL DEFAULT (now()),
|
||||
`created_at` timestamp NOT NULL DEFAULT (now()),
|
||||
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
|
||||
CONSTRAINT `knowledge_point_mastery_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `learning_diagnostic_reports` (
|
||||
`id` varchar(128) NOT NULL,
|
||||
`student_id` varchar(128) NOT NULL,
|
||||
`generated_by` varchar(128),
|
||||
`report_type` enum('individual','class','grade') NOT NULL DEFAULT 'individual',
|
||||
`period` varchar(50),
|
||||
`summary` text,
|
||||
`strengths` json,
|
||||
`weaknesses` json,
|
||||
`recommendations` json,
|
||||
`overall_score` decimal(5,2),
|
||||
`report_status` enum('draft','published','archived') NOT NULL DEFAULT 'draft',
|
||||
`created_at` timestamp NOT NULL DEFAULT (now()),
|
||||
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
|
||||
CONSTRAINT `learning_diagnostic_reports_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `exams` ADD `exam_mode` enum('homework','timed','proctored') DEFAULT 'homework';--> statement-breakpoint
|
||||
ALTER TABLE `exams` ADD `duration_minutes` int;--> statement-breakpoint
|
||||
ALTER TABLE `exams` ADD `shuffle_questions` boolean DEFAULT false;--> statement-breakpoint
|
||||
ALTER TABLE `exams` ADD `allow_late_start` boolean DEFAULT false;--> statement-breakpoint
|
||||
ALTER TABLE `exams` ADD `late_start_grace_minutes` int DEFAULT 0;--> statement-breakpoint
|
||||
ALTER TABLE `exams` ADD `anti_cheat_enabled` boolean DEFAULT false;--> statement-breakpoint
|
||||
ALTER TABLE `course_selections` ADD CONSTRAINT `course_selections_course_id_elective_courses_id_fk` FOREIGN KEY (`course_id`) REFERENCES `elective_courses`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `course_selections` ADD CONSTRAINT `course_selections_student_id_users_id_fk` FOREIGN KEY (`student_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `elective_courses` ADD CONSTRAINT `elective_courses_subject_id_subjects_id_fk` FOREIGN KEY (`subject_id`) REFERENCES `subjects`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `elective_courses` ADD CONSTRAINT `elective_courses_teacher_id_users_id_fk` FOREIGN KEY (`teacher_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `elective_courses` ADD CONSTRAINT `elective_courses_grade_id_grades_id_fk` FOREIGN KEY (`grade_id`) REFERENCES `grades`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `exam_proctoring_events` ADD CONSTRAINT `exam_proctoring_events_submission_id_exam_submissions_id_fk` FOREIGN KEY (`submission_id`) REFERENCES `exam_submissions`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `exam_proctoring_events` ADD CONSTRAINT `exam_proctoring_events_student_id_users_id_fk` FOREIGN KEY (`student_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `exam_proctoring_events` ADD CONSTRAINT `exam_proctoring_events_exam_id_exams_id_fk` FOREIGN KEY (`exam_id`) REFERENCES `exams`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `knowledge_point_mastery` ADD CONSTRAINT `knowledge_point_mastery_student_id_users_id_fk` FOREIGN KEY (`student_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `knowledge_point_mastery` ADD CONSTRAINT `knowledge_point_mastery_knowledge_point_id_knowledge_points_id_fk` FOREIGN KEY (`knowledge_point_id`) REFERENCES `knowledge_points`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `learning_diagnostic_reports` ADD CONSTRAINT `learning_diagnostic_reports_student_id_users_id_fk` FOREIGN KEY (`student_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `learning_diagnostic_reports` ADD CONSTRAINT `learning_diagnostic_reports_generated_by_users_id_fk` FOREIGN KEY (`generated_by`) REFERENCES `users`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX `course_selections_course_idx` ON `course_selections` (`course_id`);--> statement-breakpoint
|
||||
CREATE INDEX `course_selections_student_idx` ON `course_selections` (`student_id`);--> statement-breakpoint
|
||||
CREATE INDEX `course_selections_status_idx` ON `course_selections` (`selection_status`);--> statement-breakpoint
|
||||
CREATE INDEX `elective_courses_teacher_idx` ON `elective_courses` (`teacher_id`);--> statement-breakpoint
|
||||
CREATE INDEX `elective_courses_subject_idx` ON `elective_courses` (`subject_id`);--> statement-breakpoint
|
||||
CREATE INDEX `elective_courses_grade_idx` ON `elective_courses` (`grade_id`);--> statement-breakpoint
|
||||
CREATE INDEX `elective_courses_status_idx` ON `elective_courses` (`status`);--> statement-breakpoint
|
||||
CREATE INDEX `proctoring_submission_idx` ON `exam_proctoring_events` (`submission_id`);--> statement-breakpoint
|
||||
CREATE INDEX `proctoring_student_idx` ON `exam_proctoring_events` (`student_id`);--> statement-breakpoint
|
||||
CREATE INDEX `proctoring_exam_idx` ON `exam_proctoring_events` (`exam_id`);--> statement-breakpoint
|
||||
CREATE INDEX `proctoring_event_type_idx` ON `exam_proctoring_events` (`event_type`);--> statement-breakpoint
|
||||
CREATE INDEX `mastery_student_idx` ON `knowledge_point_mastery` (`student_id`);--> statement-breakpoint
|
||||
CREATE INDEX `mastery_kp_idx` ON `knowledge_point_mastery` (`knowledge_point_id`);--> statement-breakpoint
|
||||
CREATE INDEX `diagnostic_student_idx` ON `learning_diagnostic_reports` (`student_id`);--> statement-breakpoint
|
||||
CREATE INDEX `diagnostic_generated_by_idx` ON `learning_diagnostic_reports` (`generated_by`);--> statement-breakpoint
|
||||
CREATE INDEX `diagnostic_status_idx` ON `learning_diagnostic_reports` (`report_status`);--> statement-breakpoint
|
||||
CREATE INDEX `diagnostic_report_type_idx` ON `learning_diagnostic_reports` (`report_type`);
|
||||
Reference in New Issue
Block a user