{{-- 与 components/exam/paper-body 选择题选项渲染完全一致(布局 + 公式预处理)。 参数: - $options: array 选项(数字下标或 A/B/C/D 键) - $gradingMode: bool 是否判卷上下文(影响 OptionLayoutDecider) - $mathProcessed: bool 题目是否已整体预处理公式 - $logQuestionNumber: string|int 仅用于日志标识 - $showLeadSpacer: bool 是否在选项前插入与 question-grid 对齐的隐形占位(嵌入案例行等非 grid 场景可设为 false) --}} @php /** @var array $options */ /** @var bool $gradingMode */ /** @var bool $mathProcessed */ /** @var string|int|null $logQuestionNumber */ /** @var bool $showLeadSpacer */ $showLeadSpacer = $showLeadSpacer ?? true; $layoutDeciderService = app(\App\Support\OptionLayoutDecider::class); $layoutMeta = $layoutDeciderService->decide( $options, $gradingMode ? 'grading' : 'exam' ); $optionsClass = $layoutMeta['class']; $layoutDesc = $layoutMeta['layout']; $hasImageOptionInQuestion = false; foreach ($options as $optRaw) { if (preg_match('/<(img|image|svg)\\b|data:image\\//i', (string) $optRaw) === 1) { $hasImageOptionInQuestion = true; break; } } if ($hasImageOptionInQuestion) { $optionsClass = 'options-grid-4'; $layoutDesc = '4列布局(图片选项固定)'; } \Illuminate\Support\Facades\Log::debug('选择题布局决策', [ 'question_number' => $logQuestionNumber ?? null, 'context' => $gradingMode ? 'grading' : 'exam', 'opt_count' => $layoutMeta['opt_count'], 'max_length' => $layoutMeta['max_length'], 'has_complex_formula' => $layoutMeta['has_complex_formula'], 'has_image_option' => $hasImageOptionInQuestion, 'selected_class' => $optionsClass, 'layout' => $layoutDesc, ]); @endphp @if($showLeadSpacer)
@endif
@foreach($options as $optIndex => $opt) @php // 兼容两种格式:数字索引 (0,1,2,3) 或字母键 (A,B,C,D) if (is_numeric($optIndex)) { $label = chr(65 + (int) $optIndex); } else { $label = strtoupper($optIndex); } // 【修复】根据是否已预处理决定处理方式 $normalizedOpt = (string) $opt; // 选项内优先使用行内分式,避免 \dfrac 导致单个选项视觉突兀 $normalizedOpt = str_replace('\\dfrac', '\\frac', $normalizedOpt); $normalizedOpt = str_replace('\\displaystyle', '', $normalizedOpt); $normalizedOpt = $layoutDeciderService->normalizeCompactMathForDisplay($normalizedOpt); // 清理来源HTML里可能携带的超大字号,避免单题选项异常放大 $normalizedOpt = preg_replace('/font-size\s*:[^;"]+;?/iu', '', $normalizedOpt); $normalizedOpt = preg_replace('/line-height\s*:[^;"]+;?/iu', '', $normalizedOpt); $normalizedOpt = preg_replace('/style\s*=\s*([\'"])\s*\1/iu', '', $normalizedOpt); if ($mathProcessed) { // 已预处理:数据已包含处理好的 和公式,直接使用 $renderedOpt = $normalizedOpt; } else { // 未预处理:先转义保护,processFormulas() 内部会解码并处理 $encodedOpt = htmlspecialchars($normalizedOpt, ENT_QUOTES | ENT_HTML5, 'UTF-8'); $renderedOpt = \App\Services\MathFormulaProcessor::processFormulas($encodedOpt); } // 仅针对“选项图片”覆盖公式处理器默认的题干尺寸,避免四列布局被 220px 宽图撑出边界 $renderedOpt = preg_replace('/max-width\s*:\s*220px\s*;?/iu', 'max-width:100%;', (string) $renderedOpt); $renderedOpt = preg_replace('/max-height\s*:\s*60mm\s*;?/iu', 'max-height:28mm;', (string) $renderedOpt); // 标记选项内图片,供 PDF 全局宽图放大逻辑识别并跳过 $renderedOpt = preg_replace('/]*\bdata-option-image=)/iu', ' 的场景,同样打标走选项专用规则 $renderedOpt = preg_replace('/]*\bdata-option-image=)/iu', ' {{ $label }}. {!! $renderedOpt !!}
@endforeach