|
|
@@ -10,6 +10,50 @@ use Illuminate\Support\Facades\Log;
|
|
|
|
|
|
class ExamPdfController extends Controller
|
|
|
{
|
|
|
+ /**
|
|
|
+ * 标准化选项格式为数组值列表
|
|
|
+ * 支持格式:
|
|
|
+ * 1. {"A": "0", "B": "5", "C": "-3", "D": "12"} -> ["0", "5", "-3", "12"]
|
|
|
+ * 2. [["label": "A", "text": "选项A"], ...] -> ["选项A", "选项B", ...]
|
|
|
+ * 3. ["A", "B", "C", "D"] -> ["A", "B", "C", "D"]
|
|
|
+ */
|
|
|
+ private function normalizeOptions($options): array
|
|
|
+ {
|
|
|
+ if (empty($options)) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果是对象格式 {"A": "值1", "B": "值2", ...}
|
|
|
+ if (is_array($options) && !isset($options[0])) {
|
|
|
+ return array_values($options);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果是AI生成格式 [{"label": "A", "text": "选项A"}, ...]
|
|
|
+ if (is_array($options) && isset($options[0]) && is_array($options[0])) {
|
|
|
+ // 提取text字段,如果不存在则使用整个数组元素
|
|
|
+ $normalized = [];
|
|
|
+ foreach ($options as $opt) {
|
|
|
+ if (isset($opt['text'])) {
|
|
|
+ $normalized[] = $opt['text'];
|
|
|
+ } elseif (isset($opt['value'])) {
|
|
|
+ $normalized[] = $opt['value'];
|
|
|
+ } else {
|
|
|
+ // 如果既没有text也没有value,取数组的第一个值
|
|
|
+ $normalized[] = is_array($opt) ? (string) reset($opt) : (string) $opt;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return $normalized;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果已经是简单数组格式 ["A", "B", "C", "D"]
|
|
|
+ if (is_array($options)) {
|
|
|
+ return array_values($options);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 其他情况返回空数组
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 根据题目内容或类型字段判断题型
|
|
|
*/
|
|
|
@@ -436,10 +480,30 @@ class ExamPdfController extends Controller
|
|
|
list($stem, $extractedOptions) = $this->separateStemAndOptions($rawContent);
|
|
|
|
|
|
$q['stem'] = $stem;
|
|
|
+ $q['content'] = $stem; // 同时设置content字段
|
|
|
$q['answer'] = $apiData['answer'] ?? $q['answer'] ?? '';
|
|
|
$q['solution'] = $apiData['solution'] ?? $q['solution'] ?? '';
|
|
|
$q['tags'] = $apiData['tags'] ?? $q['tags'] ?? '';
|
|
|
- $q['options'] = $apiData['options'] ?? $extractedOptions; // 优先使用API选项,备选提取的选项
|
|
|
+
|
|
|
+ // 优先使用API选项,支持多种数据格式
|
|
|
+ $apiOptions = $apiData['options'] ?? null;
|
|
|
+
|
|
|
+ if (!empty($apiOptions)) {
|
|
|
+ // 标准化options格式为数组值列表
|
|
|
+ $q['options'] = $this->normalizeOptions($apiOptions);
|
|
|
+ Log::debug('使用标准化API options', [
|
|
|
+ 'question_id' => $q['id'],
|
|
|
+ 'raw_options' => $apiOptions,
|
|
|
+ 'normalized_options' => $q['options']
|
|
|
+ ]);
|
|
|
+ } else {
|
|
|
+ // 备选:从题干中提取的选项
|
|
|
+ $q['options'] = $extractedOptions;
|
|
|
+ Log::debug('使用提取的options', [
|
|
|
+ 'question_id' => $q['id'],
|
|
|
+ 'extracted_options' => $extractedOptions
|
|
|
+ ]);
|
|
|
+ }
|
|
|
}
|
|
|
return $q;
|
|
|
}, $questionsData);
|
|
|
@@ -525,10 +589,30 @@ class ExamPdfController extends Controller
|
|
|
|
|
|
// 合并数据,优先使用题库API的 stem、answer、solution、options
|
|
|
$q['stem'] = $stem;
|
|
|
+ $q['content'] = $stem; // 同时设置content字段
|
|
|
$q['answer'] = $apiData['answer'] ?? $q['answer'] ?? '';
|
|
|
$q['solution'] = $apiData['solution'] ?? $q['solution'] ?? '';
|
|
|
$q['tags'] = $apiData['tags'] ?? $q['tags'] ?? '';
|
|
|
- $q['options'] = $apiData['options'] ?? $extractedOptions; // 优先使用API选项,备选提取的选项
|
|
|
+
|
|
|
+ // 优先使用API选项,支持多种数据格式
|
|
|
+ $apiOptions = $apiData['options'] ?? null;
|
|
|
+
|
|
|
+ if (!empty($apiOptions)) {
|
|
|
+ // 标准化options格式为数组值列表
|
|
|
+ $q['options'] = $this->normalizeOptions($apiOptions);
|
|
|
+ Log::debug('使用标准化API options', [
|
|
|
+ 'question_id' => $q['id'],
|
|
|
+ 'raw_options' => $apiOptions,
|
|
|
+ 'normalized_options' => $q['options']
|
|
|
+ ]);
|
|
|
+ } else {
|
|
|
+ // 备选:从题干中提取的选项
|
|
|
+ $q['options'] = $extractedOptions;
|
|
|
+ Log::debug('使用提取的options', [
|
|
|
+ 'question_id' => $q['id'],
|
|
|
+ 'extracted_options' => $extractedOptions
|
|
|
+ ]);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// 从数据库 paper_questions 表中获取 question_type(已在前面设置,这里确保有值)
|
|
|
@@ -585,17 +669,26 @@ class ExamPdfController extends Controller
|
|
|
$type = 'answer';
|
|
|
}
|
|
|
|
|
|
- $qData = (object)[
|
|
|
+ // 统一处理数学公式和选项数据
|
|
|
+ $questionData = [
|
|
|
'id' => $q['id'] ?? $q['question_bank_id'] ?? null,
|
|
|
'content' => $content,
|
|
|
+ 'stem' => $content, // 同时提供stem字段
|
|
|
'answer' => $answer,
|
|
|
'solution' => $solution,
|
|
|
'difficulty' => $q['difficulty'] ?? 0.5,
|
|
|
'kp_code' => $q['kp_code'] ?? '',
|
|
|
'tags' => $q['tags'] ?? '',
|
|
|
'options' => $options, // 使用分离后的选项
|
|
|
- 'score' => $q['score'] ?? $this->getQuestionScore($type), // 优先使用生成时分配的分数
|
|
|
+ 'score' => $q['score'] ?? $this->getQuestionScore($type),
|
|
|
+ 'question_type' => $type,
|
|
|
];
|
|
|
+
|
|
|
+ // 统一处理数学公式 - 标记已处理,避免模板中重复处理
|
|
|
+ $questionData = \App\Services\MathFormulaProcessor::processQuestionData($questionData);
|
|
|
+ $questionData['math_processed'] = true; // 添加标记
|
|
|
+
|
|
|
+ $qData = (object) $questionData;
|
|
|
$questions[$type][] = $qData;
|
|
|
}
|
|
|
|
|
|
@@ -663,10 +756,30 @@ class ExamPdfController extends Controller
|
|
|
$rawContent = $apiData['stem'] ?? $q['stem'] ?? $q['content'] ?? '';
|
|
|
list($stem, $extractedOptions) = $this->separateStemAndOptions($rawContent);
|
|
|
$q['stem'] = $stem;
|
|
|
+ $q['content'] = $stem; // 同时设置content字段
|
|
|
$q['answer'] = $apiData['answer'] ?? $q['answer'] ?? '';
|
|
|
$q['solution'] = $apiData['solution'] ?? $q['solution'] ?? '';
|
|
|
$q['tags'] = $apiData['tags'] ?? $q['tags'] ?? '';
|
|
|
- $q['options'] = $apiData['options'] ?? $extractedOptions;
|
|
|
+
|
|
|
+ // 优先使用API选项,支持多种数据格式
|
|
|
+ $apiOptions = $apiData['options'] ?? null;
|
|
|
+
|
|
|
+ if (!empty($apiOptions)) {
|
|
|
+ // 标准化options格式为数组值列表
|
|
|
+ $q['options'] = $this->normalizeOptions($apiOptions);
|
|
|
+ Log::debug('使用标准化API options', [
|
|
|
+ 'question_id' => $q['id'],
|
|
|
+ 'raw_options' => $apiOptions,
|
|
|
+ 'normalized_options' => $q['options']
|
|
|
+ ]);
|
|
|
+ } else {
|
|
|
+ // 备选:从题干中提取的选项
|
|
|
+ $q['options'] = $extractedOptions;
|
|
|
+ Log::debug('使用提取的options', [
|
|
|
+ 'question_id' => $q['id'],
|
|
|
+ 'extracted_options' => $extractedOptions
|
|
|
+ ]);
|
|
|
+ }
|
|
|
}
|
|
|
return $q;
|
|
|
}, $questionsData);
|
|
|
@@ -710,10 +823,30 @@ class ExamPdfController extends Controller
|
|
|
$rawContent = $apiData['stem'] ?? $q['stem'] ?? '题目内容缺失';
|
|
|
list($stem, $extractedOptions) = $this->separateStemAndOptions($rawContent);
|
|
|
$q['stem'] = $stem;
|
|
|
+ $q['content'] = $stem; // 同时设置content字段
|
|
|
$q['answer'] = $apiData['answer'] ?? $q['answer'] ?? '';
|
|
|
$q['solution'] = $apiData['solution'] ?? $q['solution'] ?? '';
|
|
|
$q['tags'] = $apiData['tags'] ?? $q['tags'] ?? '';
|
|
|
- $q['options'] = $apiData['options'] ?? $extractedOptions;
|
|
|
+
|
|
|
+ // 优先使用API选项,支持多种数据格式
|
|
|
+ $apiOptions = $apiData['options'] ?? null;
|
|
|
+
|
|
|
+ if (!empty($apiOptions)) {
|
|
|
+ // 标准化options格式为数组值列表
|
|
|
+ $q['options'] = $this->normalizeOptions($apiOptions);
|
|
|
+ Log::debug('使用标准化API options', [
|
|
|
+ 'question_id' => $q['id'],
|
|
|
+ 'raw_options' => $apiOptions,
|
|
|
+ 'normalized_options' => $q['options']
|
|
|
+ ]);
|
|
|
+ } else {
|
|
|
+ // 备选:从题干中提取的选项
|
|
|
+ $q['options'] = $extractedOptions;
|
|
|
+ Log::debug('使用提取的options', [
|
|
|
+ 'question_id' => $q['id'],
|
|
|
+ 'extracted_options' => $extractedOptions
|
|
|
+ ]);
|
|
|
+ }
|
|
|
}
|
|
|
if (!isset($q['question_type']) || empty($q['question_type'])) {
|
|
|
$dbQuestion = $paperQuestions->firstWhere('question_bank_id', $q['id']);
|
|
|
@@ -740,9 +873,12 @@ class ExamPdfController extends Controller
|
|
|
if (!isset($questions[$type])) {
|
|
|
$type = 'answer';
|
|
|
}
|
|
|
- $qData = (object)[
|
|
|
+
|
|
|
+ // 统一处理数学公式和选项数据
|
|
|
+ $questionData = [
|
|
|
'id' => $q['id'] ?? $q['question_bank_id'] ?? null,
|
|
|
'content' => $content,
|
|
|
+ 'stem' => $content, // 同时提供stem字段
|
|
|
'answer' => $answer,
|
|
|
'solution' => $solution,
|
|
|
'difficulty' => $q['difficulty'] ?? 0.5,
|
|
|
@@ -750,7 +886,14 @@ class ExamPdfController extends Controller
|
|
|
'tags' => $q['tags'] ?? '',
|
|
|
'options' => $options,
|
|
|
'score' => $q['score'] ?? $this->getQuestionScore($type),
|
|
|
+ 'question_type' => $type,
|
|
|
];
|
|
|
+
|
|
|
+ // 统一处理数学公式 - 标记已处理,避免模板中重复处理
|
|
|
+ $questionData = \App\Services\MathFormulaProcessor::processQuestionData($questionData);
|
|
|
+ $questionData['math_processed'] = true; // 添加标记
|
|
|
+
|
|
|
+ $qData = (object) $questionData;
|
|
|
$questions[$type][] = $qData;
|
|
|
}
|
|
|
|