duidui_mini_program/pages/camp_task_objective_questions/modules/paper-service.js
2026-03-27 10:41:46 +08:00

139 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 客观题试卷服务模块
* 负责试卷数据获取和处理
*/
import { questionApi } from '../../../config/question_api.js';
/**
* 获取试卷详情
* @param {String} paperId - 试卷ID
* @param {String} taskId - 任务ID
* @returns {Promise} 处理后的试卷数据
*/
export function fetchQuestionPaper(paperId, taskId) {
return new Promise((resolve, reject) => {
if (!paperId) {
reject(new Error('试卷ID不能为空'));
return;
}
questionApi.getPaperDetail(paperId)
.then(res => {
let paperInfo = null;
if (res && res.code === 200 && res.data) {
paperInfo = res.data;
} else if (res && res.success === true && (res.paper || res.data)) {
paperInfo = res.paper || res.data;
}
if (paperInfo) {
if (!paperInfo.questions || !Array.isArray(paperInfo.questions)) {
reject(new Error('试卷数据格式错误'));
return;
}
const mapped = paperInfo.questions.map(q => {
// Fiber 后端返回的格式QuestionInfo
// { id, type (QuestionType: 1=主观题, 2=选择题, 3=判断题, 4=填空题), title, content, answer, explanation, options ([]string), tags }
// 兼容旧格式PHP后端
if (q && (q.question_id || q.question_content || q.question_type)) {
return {
...q,
id: q.question_id,
title: q.question_content,
type: q.question_type,
materials: q.materials || [],
options: (q.options || []).map(opt => ({
...opt,
id: opt.option_id,
content: opt.option_content,
label: opt.option_label
})),
user_answer: q.user_answer || null,
explanation: q.explanation || ''
};
} else {
// Fiber 后端格式
// type: 1=主观题, 2=选择题(单选), 3=判断题, 4=填空题
// 对于客观题type 应该是 2 (选择题)
const opts = Array.isArray(q.options) ? q.options.map((text, idx) => ({
id: idx + 1,
content: text,
label: String.fromCharCode(65 + idx) // A, B, C...
})) : [];
// 映射题目类型
// Fiber: 2=选择题 -> 前端: 'single_choice' 或 'multiple_choice'
// 这里默认是单选,如果需要判断多选,可能需要根据其他字段或答案格式
let mappedType = 'single_choice';
if (q.type === 2) {
// 选择题,根据答案是否包含逗号判断单选或多选
const answer = q.answer || '';
mappedType = answer.includes(',') ? 'multiple_choice' : 'single_choice';
} else if (q.type === 3) {
mappedType = 'true_false';
} else if (q.type === 4) {
mappedType = 'fill_blank';
}
return {
...q,
id: q.id,
title: q.title || q.content || '',
type: mappedType,
material_id: q.material_id || null, // 保留题目关联的材料ID
materials: q.materials || [], // Fiber 后端可能没有 materials 字段
options: opts,
user_answer: q.user_answer || null,
explanation: q.explanation || ''
};
}
});
const questions = mapped.filter(q => Array.isArray(q.options) && q.options.length > 0);
const answers = questions.map(question => {
const optionsLength = question.options.length;
const arr = new Array(optionsLength).fill(false);
if (question.user_answer) {
const userAnsArr = question.user_answer.split(',').map(s => s.trim()).filter(Boolean);
userAnsArr.forEach(ans => {
const idx = question.options.findIndex(opt => opt.label === ans);
if (idx !== -1) arr[idx] = true;
});
}
return arr;
});
// 确保 paperInfo 包含必要的字段
const finalPaperInfo = {
...paperInfo,
title: paperInfo.title || '',
description: paperInfo.description || '',
duration_minutes: paperInfo.duration_minutes || 0 // Fiber 后端可能没有此字段,默认为 0
};
// 材料列表:后端 /paper/detail 返回 paper.materials用于背景层左右滑动展示
const materials = Array.isArray(paperInfo.materials) ? paperInfo.materials : [];
resolve({
paperInfo: finalPaperInfo,
questions,
answers,
questionAnsweredStatus: answers.map(arr => arr.some(v => v)),
materials
});
} else {
reject(new Error((res && res.message) || (res && res.msg) || '获取试卷失败'));
}
})
.catch(err => {
console.error('API调用失败:', err);
reject(err);
});
});
}