实现考试归档并永久锁定成绩流程

This commit is contained in:
2026-07-20 17:08:17 +08:00 Unverified
parent 6d22b41ce8
commit 1a87e06fc8
15 changed files with 265 additions and 39 deletions
+41 -1
View File
@@ -114,6 +114,8 @@ export const sqliteSchema = `
pass_policy TEXT NOT NULL DEFAULT 'rank_percent' CHECK (pass_policy IN ('fixed_score', 'score_ratio', 'rank_percent', 'subject_scores', 'none')),
pass_value REAL NOT NULL DEFAULT 60,
status TEXT NOT NULL CHECK (status IN ('draft', 'published', 'closed')),
archived_at TEXT,
archived_by TEXT REFERENCES users(id) ON DELETE RESTRICT,
created_at TEXT NOT NULL
) STRICT;
@@ -401,6 +403,7 @@ export const sqliteSchema = `
CREATE INDEX IF NOT EXISTS idx_profiles_status ON candidate_profiles(status);
CREATE INDEX IF NOT EXISTS idx_users_archive_scope ON users(role, school_id, class_id, archived_at);
CREATE INDEX IF NOT EXISTS idx_exams_archive ON exams(archived_at, exam_end);
CREATE INDEX IF NOT EXISTS idx_profiles_scope ON candidate_profiles(school_id, class_id, status);
CREATE INDEX IF NOT EXISTS idx_notices_status_publish ON notices(status, publish_at);
CREATE INDEX IF NOT EXISTS idx_exams_status_registration ON exams(status, registration_start, registration_end);
@@ -417,6 +420,39 @@ export const sqliteSchema = `
CREATE INDEX IF NOT EXISTS idx_account_batch_items ON candidate_account_batch_items(batch_id, class_id, position);
CREATE INDEX IF NOT EXISTS idx_results_registration ON results(registration_id, published);
CREATE INDEX IF NOT EXISTS idx_audit_created ON audit_logs(created_at);
CREATE TRIGGER IF NOT EXISTS trg_results_lock_archived_insert
BEFORE INSERT ON results
WHEN EXISTS (
SELECT 1 FROM registrations registration
JOIN exams exam ON exam.id = registration.exam_id
WHERE registration.id = NEW.registration_id AND exam.archived_at IS NOT NULL
)
BEGIN
SELECT RAISE(ABORT, '归档考试成绩已永久锁定');
END;
CREATE TRIGGER IF NOT EXISTS trg_results_lock_archived_update
BEFORE UPDATE ON results
WHEN EXISTS (
SELECT 1 FROM registrations registration
JOIN exams exam ON exam.id = registration.exam_id
WHERE registration.id IN (OLD.registration_id, NEW.registration_id) AND exam.archived_at IS NOT NULL
)
BEGIN
SELECT RAISE(ABORT, '归档考试成绩已永久锁定');
END;
CREATE TRIGGER IF NOT EXISTS trg_results_lock_archived_delete
BEFORE DELETE ON results
WHEN EXISTS (
SELECT 1 FROM registrations registration
JOIN exams exam ON exam.id = registration.exam_id
WHERE registration.id = OLD.registration_id AND exam.archived_at IS NOT NULL
)
BEGIN
SELECT RAISE(ABORT, '归档考试成绩已永久锁定');
END;
`;
export const mysqlSchema = [
@@ -553,10 +589,14 @@ export const mysqlSchema = [
pass_policy ENUM('fixed_score', 'score_ratio', 'rank_percent', 'subject_scores', 'none') NOT NULL DEFAULT 'rank_percent',
pass_value DOUBLE NOT NULL DEFAULT 60,
status ENUM('draft', 'published', 'closed') NOT NULL,
archived_at VARCHAR(35) NULL,
archived_by VARCHAR(64) NULL,
created_at VARCHAR(35) NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY uq_exams_code (code),
KEY idx_exams_status_registration (status, registration_start, registration_end)
KEY idx_exams_status_registration (status, registration_start, registration_end),
KEY idx_exams_archive (archived_at, exam_end),
CONSTRAINT fk_exams_archived_by FOREIGN KEY (archived_by) REFERENCES users(id) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci`,
`CREATE TABLE IF NOT EXISTS exam_subjects (
id VARCHAR(64) NOT NULL,