263 lines
8.9 KiB
JavaScript
263 lines
8.9 KiB
JavaScript
// 将 CommonJS 导入改为 ES 模块导入(注意添加 .js 扩展名)
|
|
import { getSystemDbPath, getUserDbPath } from './path.js';
|
|
import { systemSchema, userSchema, defaultData } from './schema.js';
|
|
import { openDatabase, batchInsert } from './utils.js';
|
|
import * as argon2 from "argon2";
|
|
|
|
// 数据库连接池
|
|
const dbConnections = new Map();
|
|
|
|
// 获取数据库连接
|
|
async function getDbConnection(dbPath) {
|
|
if (dbConnections.has(dbPath)) {
|
|
console.log(`使用现有数据库连接: ${dbPath}`);
|
|
return dbConnections.get(dbPath);
|
|
}
|
|
|
|
const db = await openDatabase(dbPath);
|
|
dbConnections.set(dbPath, db);
|
|
return db;
|
|
}
|
|
|
|
// 关闭所有数据库连接
|
|
function closeAllConnections() {
|
|
dbConnections.forEach((db, path) => {
|
|
try {
|
|
db.close();
|
|
console.log(`关闭数据库连接: ${path}`);
|
|
} catch (error) {
|
|
console.error(`关闭数据库连接失败: ${path}`, error);
|
|
}
|
|
});
|
|
dbConnections.clear();
|
|
}
|
|
|
|
// 检查数据库是否已初始化
|
|
async function checkDatabaseInitialized() {
|
|
try {
|
|
console.log('开始检查数据库初始化状态...');
|
|
const systemDb = await getDbConnection(getSystemDbPath());
|
|
console.log('成功打开系统数据库');
|
|
|
|
const result = await systemDb.getAsync('SELECT value FROM config WHERE key = ?', ['initialized']);
|
|
console.log('查询初始化状态结果:', result);
|
|
|
|
const isInitialized = result && result.value === 'true';
|
|
console.log('数据库初始化状态:', isInitialized ? '已初始化' : '未初始化');
|
|
return isInitialized;
|
|
} catch (error) {
|
|
console.error('检查数据库初始化状态失败:', error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// 初始化系统数据库
|
|
async function initializeSystemDatabase() {
|
|
console.log('开始初始化系统数据库...');
|
|
const systemDbPath = getSystemDbPath();
|
|
const systemDb = await getDbConnection(systemDbPath);
|
|
|
|
try {
|
|
// 开始事务
|
|
await systemDb.runAsync('BEGIN TRANSACTION');
|
|
console.log('开始事务');
|
|
|
|
// 创建表结构
|
|
console.log('开始创建系统数据库表结构...');
|
|
await systemDb.execAsync(systemSchema.config.trim());
|
|
console.log('创建 config 表成功');
|
|
|
|
await systemDb.execAsync(systemSchema.dictTypes.trim());
|
|
console.log('创建 dict_types 表成功');
|
|
|
|
await systemDb.execAsync(systemSchema.dictItems.trim());
|
|
console.log('创建 dict_items 表成功');
|
|
|
|
await systemDb.execAsync(systemSchema.questions.trim());
|
|
console.log('创建 questions 表成功');
|
|
|
|
await systemDb.execAsync(systemSchema.questionDatasets.trim());
|
|
console.log('创建 question_datasets 表成功');
|
|
|
|
await systemDb.execAsync(systemSchema.questionImages.trim());
|
|
console.log('创建 question_images 表成功');
|
|
|
|
await systemDb.execAsync(systemSchema.questionFillTable.trim());
|
|
console.log('创建 question_fill_table 表成功');
|
|
|
|
await systemDb.execAsync(systemSchema.questionFillTableBlanks.trim());
|
|
console.log('创建 question_fill_table_blanks 表成功');
|
|
|
|
await systemDb.execAsync(systemSchema.questionChoices.trim());
|
|
console.log('创建 question_choices 表成功');
|
|
|
|
await systemDb.execAsync(systemSchema.questionFillBlanks.trim());
|
|
console.log('创建 question_fill_blanks 表成功');
|
|
|
|
await systemDb.execAsync(systemSchema.questionJudge.trim());
|
|
console.log('创建 question_judge 表成功');
|
|
|
|
await systemDb.execAsync(systemSchema.questionShort.trim());
|
|
console.log('创建 question_short 表成功');
|
|
|
|
await systemDb.execAsync(systemSchema.exam.trim());
|
|
console.log('创建 exam 表成功');
|
|
|
|
await systemDb.execAsync(systemSchema.examQuestionSet.trim());
|
|
console.log('创建 exam_question_set 表成功');
|
|
|
|
await systemDb.execAsync(systemSchema.examinee.trim());
|
|
console.log('创建 examinee 表成功');
|
|
|
|
// 插入默认数据
|
|
console.log('开始插入默认数据...');
|
|
const plainPassword = defaultData.config.find(item => item.key === 'admin_password').value;
|
|
const hashedPassword = await argon2.hash(plainPassword);
|
|
|
|
// 更新密码为哈希值
|
|
const configData = defaultData.config.map(item => {
|
|
if (item.key === 'admin_password') {
|
|
return { ...item, value: hashedPassword };
|
|
}
|
|
return item;
|
|
});
|
|
|
|
await batchInsert(systemDb, 'config', configData);
|
|
console.log('插入 config 表数据成功');
|
|
|
|
await batchInsert(systemDb, 'dict_types', defaultData.dictTypes);
|
|
console.log('插入 dict_types 表数据成功');
|
|
|
|
await batchInsert(systemDb, 'dict_items', defaultData.dictItems);
|
|
console.log('插入 dict_items 表数据成功');
|
|
|
|
// 提交事务
|
|
await systemDb.runAsync('COMMIT');
|
|
console.log('提交事务成功');
|
|
|
|
return true;
|
|
} catch (error) {
|
|
// 处理错误
|
|
await systemDb.runAsync('ROLLBACK');
|
|
console.error('回滚事务:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// 初始化用户数据库
|
|
async function initializeUserDatabase() {
|
|
console.log('开始初始化用户数据库...');
|
|
const userDbPath = getUserDbPath();
|
|
const userDb = await getDbConnection(userDbPath);
|
|
|
|
try {
|
|
// 开始事务
|
|
await userDb.runAsync('BEGIN TRANSACTION');
|
|
console.log('开始事务');
|
|
|
|
// 创建表结构
|
|
console.log('开始创建用户数据库表结构...');
|
|
await userDb.execAsync(userSchema.examineeLog.trim());
|
|
console.log('创建 examinee_log 表成功');
|
|
|
|
await userDb.execAsync(userSchema.examineeExam.trim());
|
|
console.log('创建 examinee_exam 表成功');
|
|
|
|
await userDb.execAsync(userSchema.examineePapers.trim());
|
|
console.log('创建 examinee_papers 表成功');
|
|
|
|
await userDb.execAsync(userSchema.paperQuestions.trim());
|
|
console.log('创建 paper_questions 表成功');
|
|
|
|
await userDb.execAsync(userSchema.paperQuestionChoices.trim());
|
|
console.log('创建 paper_question_choices 表成功');
|
|
|
|
await userDb.execAsync(userSchema.paperQuestionBlanks.trim());
|
|
console.log('创建 paper_question_blanks 表成功');
|
|
|
|
await userDb.execAsync(userSchema.paperQuestionJudge.trim());
|
|
console.log('创建 paper_question_judge 表成功');
|
|
|
|
await userDb.execAsync(userSchema.paperQuestionFillTable.trim());
|
|
console.log('创建 paper_question_fill_table 表成功');
|
|
|
|
await userDb.execAsync(userSchema.paperQuestionFillTableBlanks.trim());
|
|
console.log('创建 paper_question_fill_table_blanks 表成功');
|
|
|
|
await userDb.execAsync(userSchema.paperQuestionSubjective.trim());
|
|
console.log('创建 paper_question_subjective 表成功');
|
|
|
|
// 提交事务
|
|
await userDb.runAsync('COMMIT');
|
|
console.log('提交事务成功');
|
|
|
|
return true;
|
|
} catch (error) {
|
|
// 处理错误
|
|
await userDb.runAsync('ROLLBACK');
|
|
console.error('回滚事务:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// 初始化数据库
|
|
async function initializeDatabase() {
|
|
try {
|
|
console.log('开始初始化数据库...');
|
|
|
|
// 确保只有一个初始化请求在执行
|
|
if (global.isInitializing) {
|
|
console.log('数据库初始化已在进行中,等待完成...');
|
|
while (global.isInitializing) {
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
}
|
|
return global.initResult;
|
|
}
|
|
|
|
global.isInitializing = true;
|
|
global.initResult = false;
|
|
|
|
// 先初始化系统数据库
|
|
console.log('开始初始化系统数据库...');
|
|
const systemResult = await initializeSystemDatabase();
|
|
console.log('系统数据库初始化结果:', systemResult ? '成功' : '失败');
|
|
|
|
if (!systemResult) {
|
|
throw new Error('系统数据库初始化失败');
|
|
}
|
|
|
|
// 再初始化用户数据库
|
|
console.log('开始初始化用户数据库...');
|
|
const userResult = await initializeUserDatabase();
|
|
console.log('用户数据库初始化结果:', userResult ? '成功' : '失败');
|
|
|
|
if (!userResult) {
|
|
throw new Error('用户数据库初始化失败');
|
|
}
|
|
|
|
// 更新初始化状态
|
|
console.log('更新数据库初始化状态...');
|
|
const systemDb = await getDbConnection(getSystemDbPath());
|
|
await systemDb.runAsync('UPDATE config SET value = ? WHERE key = ?', ['true', 'initialized']);
|
|
console.log('数据库初始化状态更新成功');
|
|
|
|
console.log('数据库整体初始化成功');
|
|
global.initResult = true;
|
|
return true;
|
|
} catch (error) {
|
|
console.error('数据库初始化失败:', error);
|
|
global.initResult = false;
|
|
return false;
|
|
} finally {
|
|
global.isInitializing = false;
|
|
}
|
|
}
|
|
|
|
// 应用退出时关闭所有连接
|
|
process.on('exit', closeAllConnections);
|
|
|
|
// 替换module.exports为export
|
|
export {
|
|
initializeDatabase,
|
|
checkDatabaseInitialized,
|
|
}; |