|
@@ -0,0 +1,195 @@
|
|
|
|
|
+@php
|
|
|
|
|
+ $choiceQuestions = $questions['choice'] ?? [];
|
|
|
|
|
+ $fillQuestions = $questions['fill'] ?? [];
|
|
|
|
|
+ $answerQuestions = $questions['answer'] ?? [];
|
|
|
|
|
+ $stepPattern = '(步骤\s*[0-9一二三四五六七八九十百零两]+\s*[::]?|第\s*[0-9一二三四五六七八九十百零两]+\s*步\s*[::]?)';
|
|
|
|
|
+
|
|
|
|
|
+ $allQuestions = collect()
|
|
|
|
|
+ ->concat(collect($choiceQuestions)->map(fn ($q) => ['q' => $q, 'detail_type' => 'choice']))
|
|
|
|
|
+ ->concat(collect($fillQuestions)->map(fn ($q) => ['q' => $q, 'detail_type' => 'fill']))
|
|
|
|
|
+ ->concat(collect($answerQuestions)->map(fn ($q) => ['q' => $q, 'detail_type' => 'answer']))
|
|
|
|
|
+ ->sortBy(fn ($item) => (int) (($item['q']->question_number ?? 0)))
|
|
|
|
|
+ ->values();
|
|
|
|
|
+
|
|
|
|
|
+ $normalizeAnswerText = function (?string $answer, bool $compact = false): string {
|
|
|
|
|
+ $answer = trim((string) $answer);
|
|
|
|
|
+ if ($answer === '') {
|
|
|
|
|
+ return '—';
|
|
|
|
|
+ }
|
|
|
|
|
+ $answer = preg_replace('/\s+/u', ' ', $answer) ?? $answer;
|
|
|
|
|
+ $answer = str_replace([';', ';'], [';<wbr>', ';<wbr>'], $answer);
|
|
|
|
|
+ if ($compact) {
|
|
|
|
|
+ $answer = preg_replace('/<br\s*\/?>/iu', ' ', $answer) ?? $answer;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return trim($answer);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ $quickAnswers = $allQuestions->map(function ($item) use ($normalizeAnswerText) {
|
|
|
|
|
+ $q = $item['q'];
|
|
|
|
|
+ $answerText = $normalizeAnswerText($q->answer ?? '', true);
|
|
|
|
|
+ $isLong = mb_strlen(strip_tags($answerText)) > 20
|
|
|
|
|
+ || str_contains($answerText, "\n")
|
|
|
|
|
+ || str_contains($answerText, "\r")
|
|
|
|
|
+ || str_contains($answerText, '{')
|
|
|
|
|
+ || str_contains($answerText, '\\frac')
|
|
|
|
|
+ || str_contains($answerText, '见解析');
|
|
|
|
|
+ $processedAnswer = \App\Services\MathFormulaProcessor::processFormulas($answerText);
|
|
|
|
|
+
|
|
|
|
|
+ return [
|
|
|
|
|
+ 'no' => (int) ($q->question_number ?? 0),
|
|
|
|
|
+ 'answer' => $processedAnswer,
|
|
|
|
|
+ 'long' => $isLong,
|
|
|
|
|
+ ];
|
|
|
|
|
+ })->values();
|
|
|
|
|
+
|
|
|
|
|
+ $normalizeDetailHtml = function (?string $text): string {
|
|
|
|
|
+ $text = trim((string) $text);
|
|
|
|
|
+ if ($text === '') {
|
|
|
|
|
+ return '';
|
|
|
|
|
+ }
|
|
|
|
|
+ $text = preg_replace('/<\s*image\b/iu', '<img', $text) ?? $text;
|
|
|
|
|
+ $text = preg_replace('/<\s*\/\s*image\s*>/iu', '', $text) ?? $text;
|
|
|
|
|
+ $text = preg_replace('/(^|[\s>])img\s+src\s*=\s*([\'"][^\'"]+[\'"])\s*\/?>/iu', '$1<img src=$2 />', $text) ?? $text;
|
|
|
|
|
+ $text = preg_replace('/font-size\s*:[^;"]+;?/iu', '', $text) ?? $text;
|
|
|
|
|
+ $text = preg_replace('/line-height\s*:[^;"]+;?/iu', '', $text) ?? $text;
|
|
|
|
|
+ $text = preg_replace('/style\s*=\s*([\'"])\s*\1/iu', '', $text) ?? $text;
|
|
|
|
|
+
|
|
|
|
|
+ return $text;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ $formatDetailForReadability = function (?string $text) use ($stepPattern): string {
|
|
|
|
|
+ $text = trim((string) $text);
|
|
|
|
|
+ if ($text === '') {
|
|
|
|
|
+ return '';
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $text = preg_replace('/\s*(' . $stepPattern . ')/u', '<br>$1', $text) ?? $text;
|
|
|
|
|
+ $text = str_replace([';', ';'], [';<wbr>', ';<wbr>'], $text);
|
|
|
|
|
+ $text = preg_replace('/,\s*(则|故|所以)/u', ',<br>$1', $text) ?? $text;
|
|
|
|
|
+ $text = preg_replace('/(?:<br>\s*){2,}/u', '<br>', $text) ?? $text;
|
|
|
|
|
+
|
|
|
|
|
+ return preg_replace('/^(?:\s*<br\s*\/?>\s*)+/iu', '', $text) ?? $text;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ $renderSolutionLikeGrading = function (string $solutionHtml, bool $withStepBoxes = false) use ($stepPattern): string {
|
|
|
|
|
+ $solution = trim($solutionHtml);
|
|
|
|
|
+ if ($solution === '' || $solution === '(无详解)') {
|
|
|
|
|
+ return $solutionHtml;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $solution = preg_replace('/(\s*\d+\s*分\s*)/u', '', $solution) ?? $solution;
|
|
|
|
|
+ $solution = preg_replace('/【(解题思路|详细解答|最终答案)】/u', "\n\n===SECTION_START===\n【$1】\n===SECTION_END===\n\n", $solution) ?? $solution;
|
|
|
|
|
+ $solution = preg_replace('/(解题过程\s*[^:\n]*:)/u', "\n\n===SECTION_START===\n【解题过程】\n===SECTION_END===\n\n", $solution) ?? $solution;
|
|
|
|
|
+
|
|
|
|
|
+ $sections = explode('===SECTION_START===', $solution);
|
|
|
|
|
+ $processedSections = [];
|
|
|
|
|
+ foreach ($sections as $section) {
|
|
|
|
|
+ if (trim((string) $section) === '') {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ $section = str_replace('===SECTION_END===', '', $section);
|
|
|
|
|
+
|
|
|
|
|
+ if (preg_match('/【(解题思路|详细解答|最终答案|解题过程)】/u', $section, $matches)) {
|
|
|
|
|
+ $sectionTitle = $matches[0];
|
|
|
|
|
+ $sectionContent = preg_replace('/【(解题思路|详细解答|最终答案|解题过程)】/u', '', $section) ?? $section;
|
|
|
|
|
+
|
|
|
|
|
+ if ($withStepBoxes) {
|
|
|
|
|
+ if (preg_match('/' . $stepPattern . '/u', $sectionContent)) {
|
|
|
|
|
+ $parts = preg_split('/(?=' . $stepPattern . ')/u', $sectionContent, -1, PREG_SPLIT_NO_EMPTY) ?: [];
|
|
|
|
|
+ $processed = '';
|
|
|
|
|
+ foreach ($parts as $index => $part) {
|
|
|
|
|
+ $stepText = trim((string) $part);
|
|
|
|
|
+ if ($stepText === '') {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ $prefix = $index > 0 ? '<br>' : '';
|
|
|
|
|
+ $isStep = preg_match('/^' . $stepPattern . '/u', $stepText);
|
|
|
|
|
+ if ($isStep) {
|
|
|
|
|
+ $processed .= $prefix
|
|
|
|
|
+ . '<span class="solution-step"><span class="step-box"><span class="detail-grade-box"></span></span><span class="step-label">'
|
|
|
|
|
+ . $stepText
|
|
|
|
|
+ . '</span></span>';
|
|
|
|
|
+ } else {
|
|
|
|
|
+ $processed .= $prefix . '<span class="step-label">' . $stepText . '</span>';
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ $sectionContent = $processed;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ $sectionContent = '<span class="solution-step"><span class="step-box"><span class="detail-grade-box"></span></span><span class="step-label"> </span></span> ' . trim((string) $sectionContent);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $processedSections[] = '<div class="solution-section"><strong>' . $sectionTitle . '</strong><br>' . $sectionContent . '</div>';
|
|
|
|
|
+ } else {
|
|
|
|
|
+ $processedSections[] = $section;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $solution = implode('', $processedSections);
|
|
|
|
|
+ $solution = preg_replace('/\n{3,}/u', "\n\n", $solution) ?? $solution;
|
|
|
|
|
+
|
|
|
|
|
+ return nl2br($solution);
|
|
|
|
|
+ };
|
|
|
|
|
+@endphp
|
|
|
|
|
+
|
|
|
|
|
+<div class="answer-detail-page">
|
|
|
|
|
+ <div class="answer-quick">
|
|
|
|
|
+ <div class="answer-quick-label">答案速查</div>
|
|
|
|
|
+ <div class="answer-quick-flow answer-quick-flow-ordered">
|
|
|
|
|
+ @foreach($quickAnswers as $item)
|
|
|
|
|
+ <span class="answer-quick-item {{ $item['long'] ? 'answer-quick-item-long' : 'answer-quick-item-compact' }}">
|
|
|
|
|
+ <strong>{{ $item['no'] }}. </strong>{!! $item['answer'] !!}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ @endforeach
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="answer-detail-two-cols">
|
|
|
|
|
+ @foreach($allQuestions as $item)
|
|
|
|
|
+ @php
|
|
|
|
|
+ $q = $item['q'];
|
|
|
|
|
+ $no = (int) ($q->question_number ?? 0);
|
|
|
|
|
+ $detailType = strtolower((string) ($item['detail_type'] ?? ''));
|
|
|
|
|
+ $isAnswerType = $detailType === 'answer';
|
|
|
|
|
+ $rawAnswer = trim((string) ($q->answer ?? ''));
|
|
|
|
|
+ $rawSolution = $normalizeDetailHtml($q->solution ?? '');
|
|
|
|
|
+ $isSeeSolutionAnswer = (bool) preg_match('/^见\s*解析[。\.]?$|^详见解析/u', $rawAnswer);
|
|
|
|
|
+ $hasImageLikeSolution = (bool) preg_match('/<\s*img\b|<\s*image\b|(^|[\s>])img\s+src\s*=/iu', $rawSolution);
|
|
|
|
|
+ $showAnswer = !$isSeeSolutionAnswer;
|
|
|
|
|
+
|
|
|
|
|
+ $renderAnswer = \App\Services\MathFormulaProcessor::processFormulas($normalizeAnswerText($rawAnswer, false));
|
|
|
|
|
+ if ($rawSolution === '') {
|
|
|
|
|
+ $renderSolution = '(无详解)';
|
|
|
|
|
+ } elseif ($hasImageLikeSolution) {
|
|
|
|
|
+ $renderSolution = $formatDetailForReadability($rawSolution);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ $renderSolution = \App\Services\MathFormulaProcessor::processFormulas($formatDetailForReadability($rawSolution));
|
|
|
|
|
+ }
|
|
|
|
|
+ $renderSolution = $renderSolutionLikeGrading($renderSolution, $isAnswerType);
|
|
|
|
|
+ $useSplitAnalysisLine = $isAnswerType && $showAnswer;
|
|
|
|
|
+ @endphp
|
|
|
|
|
+ <div class="answer-detail-item">
|
|
|
|
|
+ @if($useSplitAnalysisLine)
|
|
|
|
|
+ <div class="entry-line entry-answer-line">
|
|
|
|
|
+ <span class="qno">{{ $no }}.</span>
|
|
|
|
|
+ <span class="answer-only">【答案】{!! $renderAnswer !!}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="entry-line entry-analysis-line">
|
|
|
|
|
+ <span class="analysis-tag">【解析】</span>
|
|
|
|
|
+ <span class="solution-only">{!! $renderSolution !!}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ @else
|
|
|
|
|
+ <div class="entry-line entry-inline-line">
|
|
|
|
|
+ <span class="qno">{{ $no }}.</span>
|
|
|
|
|
+ @if($showAnswer)
|
|
|
|
|
+ <span class="answer-only">【答案】{!! $renderAnswer !!}</span>
|
|
|
|
|
+ @endif
|
|
|
|
|
+ <span class="analysis-tag">【解析】</span>
|
|
|
|
|
+ <span class="solution-only">{!! $renderSolution !!}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ @endif
|
|
|
|
|
+ </div>
|
|
|
|
|
+ @endforeach
|
|
|
|
|
+ </div>
|
|
|
|
|
+</div>
|