356 lines
15 KiB
JavaScript
356 lines
15 KiB
JavaScript
|
||
// 辅助函数:将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
|
||
}; |