// 辅助函数:将db.run包装为Promise const runAsync = (db, sql, params = []) => { return new Promise((resolve, reject) => { db.run(sql, params, function(err) { if (err) reject(err); else resolve(this); }); }); }; export { runAsync }; // 系统数据库表结构 const systemSchema = { config: ` CREATE TABLE IF NOT EXISTS config ( id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT NOT NULL, value TEXT NOT NULL, protected INTEGER DEFAULT 0 ); `, dictTypes: ` CREATE TABLE IF NOT EXISTS dict_types ( id INTEGER PRIMARY KEY AUTOINCREMENT, type_code TEXT NOT NULL UNIQUE, type_name TEXT NOT NULL, description TEXT, created_at TEXT DEFAULT CURRENT_TIMESTAMP ); `, dictItems: ` CREATE TABLE IF NOT EXISTS dict_items ( id INTEGER PRIMARY KEY AUTOINCREMENT, type_code TEXT NOT NULL, item_code TEXT NOT NULL, item_name TEXT NOT NULL, item_value TEXT, parent_code TEXT, is_active BOOLEAN DEFAULT 1, created_at TEXT DEFAULT CURRENT_TIMESTAMP, UNIQUE(type_code, item_code), FOREIGN KEY (type_code) REFERENCES dict_types(type_code) ); `, questions: ` CREATE TABLE IF NOT EXISTS questions ( id INTEGER PRIMARY KEY AUTOINCREMENT, question_type TEXT NOT NULL, question_name TEXT NOT NULL DEFAULT '', question_description TEXT NOT NULL DEFAULT '', created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (question_type) REFERENCES dict_types(type_code) ); `, questionDatasets: ` CREATE TABLE IF NOT EXISTS question_datasets ( id INTEGER PRIMARY KEY AUTOINCREMENT, question_id INTEGER NOT NULL, dataset_name TEXT NOT NULL DEFAULT '', dataset_data TEXT NOT NULL, created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (question_id) REFERENCES questions(id) ); `, questionImages: ` CREATE TABLE IF NOT EXISTS question_images ( id INTEGER PRIMARY KEY AUTOINCREMENT, question_id INTEGER NOT NULL, image_name TEXT NOT NULL DEFAULT '', image_base64 TEXT NOT NULL, created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (question_id) REFERENCES questions(id) ); `, questionFillTable: ` CREATE TABLE IF NOT EXISTS question_fill_table ( id INTEGER PRIMARY KEY AUTOINCREMENT, question_id INTEGER NOT NULL, table_name TEXT NOT NULL DEFAULT '', table_data TEXT NOT NULL, table_description TEXT NOT NULL DEFAULT '', created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (question_id) REFERENCES questions(id) ); `, questionFillTableBlanks: ` CREATE TABLE IF NOT EXISTS question_fill_table_blanks ( id INTEGER PRIMARY KEY AUTOINCREMENT, question_id INTEGER NOT NULL, dataset_id INTEGER NOT NULL, cell_position TEXT NOT NULL, cell_type TEXT NOT NULL DEFAULT 'number', correct_answer TEXT NOT NULL DEFAULT '', created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (question_id) REFERENCES questions(id), FOREIGN KEY (dataset_id) REFERENCES question_datasets(id) ); `, questionChoices: ` CREATE TABLE IF NOT EXISTS question_choices ( id INTEGER PRIMARY KEY AUTOINCREMENT, question_id INTEGER NOT NULL, choice_description TEXT NOT NULL DEFAULT '', choice_type TEXT NOT NULL DEFAULT 'single', choice_options TEXT NOT NULL, correct_answers TEXT NOT NULL, created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (question_id) REFERENCES questions(id) ); `, questionFillBlanks: ` CREATE TABLE IF NOT EXISTS question_fill_blanks ( id INTEGER PRIMARY KEY AUTOINCREMENT, question_id INTEGER NOT NULL, blank_description TEXT NOT NULL DEFAULT '', blank_count INTEGER NOT NULL DEFAULT 0, correct_answers TEXT NOT NULL DEFAULT '', created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (question_id) REFERENCES questions(id) ); `, questionJudge: ` CREATE TABLE IF NOT EXISTS question_judge ( id INTEGER PRIMARY KEY AUTOINCREMENT, question_id INTEGER NOT NULL, judge_ask TEXT NOT NULL DEFAULT '', judge_answer INTEGER NOT NULL, created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (question_id) REFERENCES questions(id) ); `, questionShort: ` CREATE TABLE IF NOT EXISTS question_short ( id INTEGER PRIMARY KEY AUTOINCREMENT, question_id INTEGER NOT NULL, short_ask TEXT NOT NULL DEFAULT '', short_answer_ref TEXT NOT NULL DEFAULT '', created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (question_id) REFERENCES questions(id) ); `, exam: ` CREATE TABLE IF NOT EXISTS exam ( id INTEGER PRIMARY KEY AUTOINCREMENT, exam_name TEXT NOT NULL DEFAULT '', exam_description TEXT NOT NULL DEFAULT '', exam_examinee_type TEXT NOT NULL DEFAULT '', exam_notice TEXT NOT NULL DEFAULT '', exam_minutes INTEGER NOT NULL DEFAULT 0, created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP ); `, examQuestionSet: ` CREATE TABLE IF NOT EXISTS exam_question_set ( id INTEGER PRIMARY KEY AUTOINCREMENT, exam_id INTEGER NOT NULL, question_type TEXT NOT NULL, question_count INTEGER NOT NULL DEFAULT 0, question_score INTEGER NOT NULL DEFAULT 0, created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (exam_id) REFERENCES exam(id), FOREIGN KEY (question_type) REFERENCES dict_types(type_code) ); `, examinee: ` CREATE TABLE IF NOT EXISTS examinee ( id INTEGER PRIMARY KEY AUTOINCREMENT, examinee_type TEXT NOT NULL DEFAULT '', examinee_name TEXT NOT NULL DEFAULT '', examinee_account TEXT NOT NULL DEFAULT '', examinee_phone TEXT NOT NULL DEFAULT '', examinee_unit TEXT NOT NULL DEFAULT '', created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP ); ` }; // 用户数据库表结构 const userSchema = { examineeLog: ` CREATE TABLE IF NOT EXISTS examinee_log ( id INTEGER PRIMARY KEY AUTOINCREMENT, examinee_id INTEGER NOT NULL, operation TEXT NOT NULL DEFAULT '', operation_time TEXT NOT NULL, created_at TEXT DEFAULT CURRENT_TIMESTAMP ); `, examineeExam: ` CREATE TABLE IF NOT EXISTS examinee_exam ( id INTEGER PRIMARY KEY AUTOINCREMENT, examinee_id INTEGER NOT NULL, exam_name TEXT NOT NULL DEFAULT '', exam_description TEXT NOT NULL DEFAULT '', exam_examinee_type TEXT NOT NULL DEFAULT '', exam_notice TEXT NOT NULL DEFAULT '', exam_minutes INTEGER NOT NULL DEFAULT 0, start_time TEXT NOT NULL, latest_end_time TEXT NOT NULL, end_time TEXT NOT NULL, exam_duration INTEGER NOT NULL DEFAULT 0, created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP ); `, examineePapers: ` CREATE TABLE IF NOT EXISTS examinee_papers ( id INTEGER PRIMARY KEY AUTOINCREMENT, examinee_id INTEGER NOT NULL, exam_id INTEGER NOT NULL, paper_minutes INTEGER NOT NULL DEFAULT 0, paper_total_score INTEGER NOT NULL DEFAULT 0, created_at TEXT DEFAULT CURRENT_TIMESTAMP ); `, paperQuestions: ` CREATE TABLE IF NOT EXISTS paper_questions ( id INTEGER PRIMARY KEY AUTOINCREMENT, examinee_paper_id INTEGER NOT NULL, question_type TEXT NOT NULL, question_name TEXT NOT NULL DEFAULT '', question_description TEXT NOT NULL DEFAULT '', question_score INTEGER NOT NULL DEFAULT 0, created_at TEXT DEFAULT CURRENT_TIMESTAMP ); `, paperQuestionChoices: ` CREATE TABLE IF NOT EXISTS paper_question_choices ( id INTEGER PRIMARY KEY AUTOINCREMENT, paper_question_id INTEGER NOT NULL, choice_options TEXT NOT NULL, user_answers TEXT NOT NULL DEFAULT '', created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (paper_question_id) REFERENCES paper_questions(id) ); `, paperQuestionBlanks: ` CREATE TABLE IF NOT EXISTS paper_question_blanks ( id INTEGER PRIMARY KEY AUTOINCREMENT, paper_question_id INTEGER NOT NULL, blank_count INTEGER NOT NULL DEFAULT 0, user_answers TEXT NOT NULL DEFAULT '', created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (paper_question_id) REFERENCES paper_questions(id) ); `, paperQuestionJudge: ` CREATE TABLE IF NOT EXISTS paper_question_judge ( id INTEGER PRIMARY KEY AUTOINCREMENT, paper_question_id INTEGER NOT NULL, judge_ask TEXT NOT NULL DEFAULT '', user_answer INTEGER NOT NULL DEFAULT 0, created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (paper_question_id) REFERENCES paper_questions(id) ); `, paperQuestionFillTable: ` CREATE TABLE IF NOT EXISTS paper_question_fill_table ( id INTEGER PRIMARY KEY AUTOINCREMENT, paper_question_id INTEGER NOT NULL, table_name TEXT NOT NULL DEFAULT '', table_data TEXT NOT NULL, created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (paper_question_id) REFERENCES paper_questions(id) ); `, paperQuestionFillTableBlanks: ` CREATE TABLE IF NOT EXISTS paper_question_fill_table_blanks ( id INTEGER PRIMARY KEY AUTOINCREMENT, paper_question_fill_table_id INTEGER NOT NULL, cell_position TEXT NOT NULL, cell_type TEXT NOT NULL DEFAULT 'number', user_answer TEXT NOT NULL DEFAULT '', created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (paper_question_fill_table_id) REFERENCES paper_question_fill_table(id) ); `, paperQuestionSubjective: ` CREATE TABLE IF NOT EXISTS paper_question_subjective ( id INTEGER PRIMARY KEY AUTOINCREMENT, paper_question_id INTEGER NOT NULL, subjective_type TEXT NOT NULL, user_answer TEXT NOT NULL DEFAULT '', score INTEGER NOT NULL DEFAULT -1, scored_by TEXT NOT NULL DEFAULT '', scored_at TEXT DEFAULT CURRENT_TIMESTAMP, created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (paper_question_id) REFERENCES paper_questions(id) ); ` }; // 初始化默认数据 // 系统配置默认数据 const plainPassword = 't2t6a9'; // 明文密码变量定义 // 注意:在实际初始化数据库时,需要使用argon2对plainPassword进行哈希 // 这里只定义默认数据结构,哈希操作应在index.js中的初始化函数中完成 const defaultData = { config: [ { key: 'admin_password', value: plainPassword, protected: 1 }, { key: 'question_bank_version', value: '1', protected: 1 }, { key: 'exam_version', value: '1', protected: 1 }, { key: 'initialized', value: '1', protected: 1 } ], // 字典类型默认数据 dictTypes: [ { type_code: 'question_category', type_name: '题型分类', description: '用于区分客观题和主观题' }, { type_code: 'question_type', type_name: '题型', description: '存储所有题型(选择题、填空题等)' }, { type_code: 'user_role', type_name: '用户角色', description: '区分不同用户类型' } ], // 字典项默认数据 dictItems: [ // 题型分类 { type_code: 'question_category', item_code: 'objective', item_name: '客观题', item_value: '有固定答案,机器可自动评分', parent_code: null }, { type_code: 'question_category', item_code: 'subjective', item_name: '主观题', item_value: '需人工评分,答案不唯一', parent_code: null }, // 题型 { type_code: 'question_type', item_code: 'choice', item_name: '选择题', item_value: '包含单选和多选', parent_code: 'objective' }, { type_code: 'question_type', item_code: 'fill_blank', item_name: '填空题', item_value: '填写空白处的答案', parent_code: 'objective' }, { type_code: 'question_type', item_code: 'fill_table', item_name: '填表题', item_value: '填写表格内容', parent_code: 'objective' }, { type_code: 'question_type', item_code: 'true_false', item_name: '判断题', item_value: '判断对错', parent_code: 'objective' }, { type_code: 'question_type', item_code: 'short_answer', item_name: '问答题', item_value: '简短回答问题', parent_code: 'subjective' }, { type_code: 'question_type', item_code: 'analysis', item_name: '分析题', item_value: '需要分析问题', parent_code: 'subjective' }, { type_code: 'question_type', item_code: 'essay', item_name: '论述题', item_value: '详细论述', parent_code: 'subjective' }, // 用户角色 { type_code: 'user_role', item_code: 'admin', item_name: '管理员', item_value: '系统管理员', parent_code: null }, { type_code: 'user_role', item_code: 'student', item_name: '考生', item_value: '参加考试的用户', parent_code: null } ] }; // 导出对象 export { systemSchema, userSchema, defaultData };