electron-vue-exam-single/electron/db/question.js

286 lines
9.6 KiB
JavaScript

import { getSystemDbPath } from './path.js';
import { executeWithRetry } from './utils.js';
import { getDbConnection } from './index.js';
/**
* 添加新题干及相关数据
* @param {Object} questionData - 题干数据
* @param {string} questionData.question_type - 题型代码
* @param {string} questionData.question_description - 题干描述
* @param {Array} questionData.images - 图片数据数组
* @param {Array} questionData.datasets - 数据集数据数组
* @returns {Promise<number>} 新创建的题干ID
*/
async function addQuestion(questionData) {
const { question_type, question_description, images = [], datasets = [] } = questionData;
const db = await getDbConnection(getSystemDbPath());
return executeWithRetry(db, async () => {
// 开始事务
await db.runAsync('BEGIN TRANSACTION');
try {
// 1. 插入题干基本信息
const questionResult = await db.runAsync(
'INSERT INTO questions (question_type, question_name, question_description, created_at, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)',
[question_type, '', question_description]
);
const questionId = questionResult.lastID;
// 2. 插入图片数据
if (images.length > 0) {
for (const image of images) {
await db.runAsync(
'INSERT INTO question_images (question_id, image_name, image_base64, created_at, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)',
[questionId, image.image || 'image', image.base64]
);
}
}
// 3. 插入数据集数据
if (datasets.length > 0) {
for (const dataset of datasets) {
await db.runAsync(
'INSERT INTO question_datasets (question_id, dataset_name, dataset_data, created_at, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)',
[questionId, dataset.name || 'dataset',dataset.content]
);
}
}
// 提交事务
await db.runAsync('COMMIT');
return questionId;
} catch (error) {
// 回滚事务
await db.runAsync('ROLLBACK');
throw error;
}
});
}
/**
* 获取所有题干
* @returns {Promise<Array>} 题干列表
*/
async function getAllQuestions() {
const db = await getDbConnection(getSystemDbPath());
return executeWithRetry(db, async () => {
return await db.allAsync('SELECT * FROM questions ORDER BY id DESC');
});
}
/**
* 根据ID获取题干详情
* @param {number} id - 题干ID
* @returns {Promise<Object>} 题干详情
*/
async function getQuestionById(id) {
const db = await getDbConnection(getSystemDbPath());
return executeWithRetry(db, async () => {
return await db.getAsync('SELECT * FROM questions WHERE id = ?', [id]);
});
}
/**
* 更新题干信息
* @param {number} id - 题干ID
* @param {Object} questionData - 题干数据
* @returns {Promise<boolean>} 是否更新成功
*/
async function updateQuestion(id, questionData) {
const { question_type, question_description } = questionData;
const db = await getDbConnection(getSystemDbPath());
return executeWithRetry(db, async () => {
const result = await db.runAsync(
'UPDATE questions SET question_type = ?, question_description = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?',
[question_type, question_description, id]
);
return result.changes > 0;
});
}
/**
* 删除题干
* @param {number} id - 题干ID
* @returns {Promise<boolean>} 是否删除成功
*/
async function deleteQuestion(id) {
const db = await getDbConnection(getSystemDbPath());
return executeWithRetry(db, async () => {
// 开始事务
await db.runAsync('BEGIN TRANSACTION');
try {
// 先删除关联数据
await db.runAsync('DELETE FROM question_images WHERE question_id = ?', [id]);
await db.runAsync('DELETE FROM question_datasets WHERE question_id = ?', [id]);
// 删除关联的试题数据
await db.runAsync('DELETE FROM question_choices WHERE question_id = ?', [id]);
await db.runAsync('DELETE FROM question_fill_blanks WHERE question_id = ?', [id]);
await db.runAsync('DELETE FROM question_fill_table WHERE question_id = ?', [id]);
await db.runAsync('DELETE FROM question_fill_table_blanks WHERE question_id = ?', [id]);
await db.runAsync('DELETE FROM question_judge WHERE question_id = ?', [id]);
await db.runAsync('DELETE FROM question_short WHERE question_id = ?', [id]);
// 再删除题干
const result = await db.runAsync('DELETE FROM questions WHERE id = ?', [id]);
// 提交事务
await db.runAsync('COMMIT');
return result.changes > 0;
} catch (error) {
// 回滚事务
await db.runAsync('ROLLBACK');
throw error;
}
});
}
/**
* 获取所有题干及其关联信息
* @returns {Promise<Array>} 包含关联信息的题干列表
*/
async function getAllQuestionsWithRelations() {
const db = await getDbConnection(getSystemDbPath());
return executeWithRetry(db, async () => {
// 1. 查询所有题干基本信息及关联的题型名称
const questions = await db.allAsync(`
SELECT q.*, di.item_name as question_type_name
FROM questions q
LEFT JOIN dict_items di ON q.question_type = di.item_code AND di.type_code = 'question_type'
ORDER BY q.id DESC
`);
// 2. 为每个题干查询关联的图片、数据集和特定类型的问题数据
for (const question of questions) {
// 查询关联的图片
const images = await db.allAsync(
'SELECT * FROM question_images WHERE question_id = ?',
[question.id]
);
question.images = images;
// 查询关联的数据集
const datasets = await db.allAsync(
'SELECT * FROM question_datasets WHERE question_id = ?',
[question.id]
);
datasets.forEach(dataset => {
try {
dataset.dataset_data = JSON.parse(dataset.dataset_data);
} catch (e) {
console.error('解析数据集失败:', e);
dataset.dataset_data = null;
}
});
question.datasets = datasets;
// 根据question_type关联不同的问题表
switch (question.question_type) {
case 'choice':
// 关联选择题表
question.choices = await db.allAsync(
'SELECT * FROM question_choices WHERE question_id = ?',
[question.id]
);
break;
case 'fill_blank':
// 关联填空题表
question.fillBlanks = await db.allAsync(
'SELECT * FROM question_fill_blanks WHERE question_id = ?',
[question.id]
);
break;
case 'fill_table':
// 关联表格填空题表和表格填空项表
question.fillTables = await db.allAsync(
'SELECT * FROM question_fill_table WHERE question_id = ?',
[question.id]
);
// 对每个表格查询其填空项
for (let table of question.fillTables) {
table.blanks = await db.allAsync(
'SELECT * FROM question_fill_table_blanks WHERE table_id = ?',
[table.id]
);
}
break;
case 'true_false':
// 关联判断题表
question.judges = await db.allAsync(
'SELECT * FROM question_judge WHERE question_id = ?',
[question.id]
);
break;
case 'short_answer':
case 'analysis':
case 'essay':
// 关联简答题表
question.shorts = await db.allAsync(
'SELECT * FROM question_short WHERE question_id = ?',
[question.id]
);
break;
default:
// 未知题型,不关联任何表
break;
}
}
return questions;
});
}
/**
* 更新题干描述
* @param {number} id - 题干ID
* @param {string} questionDescription - 新的题干描述
* @returns {Promise<boolean>} 是否更新成功
*/
async function updateQuestionDescription(id, questionDescription) {
const db = await getDbConnection(getSystemDbPath());
return executeWithRetry(db, async () => {
const result = await db.runAsync(
'UPDATE questions SET question_description = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?',
[questionDescription, id]
);
return result.changes > 0;
});
}
/**
* 添加选择题问题
* @param {Object} choiceData - 选择题数据
* @param {number} choiceData.question_id - 题干ID
* @param {string} choiceData.choice_description - 问题描述
* @param {string} choiceData.choice_type - 题型(single/multiple)
* @param {Array} choiceData.choice_options - 候选项数组
* @param {Array} choiceData.correct_answers - 正确答案序号数组
* @returns {Promise<number>} 新创建的选择题ID
*/
async function addChoiceQuestion(choiceData) {
const { question_id, choice_description, choice_type, choice_options, correct_answers } = choiceData;
const db = await getDbConnection(getSystemDbPath());
return executeWithRetry(db, async () => {
const result = await db.runAsync(
'INSERT INTO question_choices (question_id, choice_description, choice_type, choice_options, correct_answers, created_at, updated_at) VALUES (?, ?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)',
[question_id, choice_description, choice_type, JSON.stringify(choice_options), JSON.stringify(correct_answers)]
);
return result.lastID;
});
}
export {
addQuestion,
getAllQuestions,
getQuestionById,
updateQuestion,
deleteQuestion,
getAllQuestionsWithRelations,
updateQuestionDescription,
addChoiceQuestion // 添加新函数导出
};