@include('pdf.partials.kp-explain-styles')
数学知识点讲解
围绕目标知识点生成讲解与案例,帮助学生高效复习。
{{-- 知识点正文:与 pdf.exam-knowledge-explanation(知识点组卷前置梳理)同一套容器与数据(buildExplanations + normalizeKpExplanation) --}} @if(empty($knowledgePoints))
暂无知识点数据
@else
@foreach($knowledgePoints as $point)
{{ $loop->iteration }}、{{ $point['kp_name'] ?? ($point['kp_code'] ?? '未命名知识点') }}
@if(!empty($point['explanation'])) {!! $point['explanation'] !!} @endif
@if(!empty($point['cases'])) @php // 与卷子题干一致的小题号断行逻辑(仅在至少2个小题编号时生效) $formatStemLikePaper = function (?string $text): string { $stem = trim((string) $text); if ($stem === '') { return '—'; } preg_match_all('/[((][1-9][0-9]*[))]/u', $stem, $subQuestionMatches); $subQuestionCount = count($subQuestionMatches[0] ?? []); if ($subQuestionCount >= 2) { $stem = preg_replace('/^\s*([((][1-9][0-9]*[))])\s*/u', '$1 ', $stem) ?? $stem; // 断行后保留两个中文空格缩进 $stem = preg_replace('/([。;;!?!?::.])\s*([((][1-9][0-9]*[))])\s*/u', '$1
  $2 ', $stem) ?? $stem; $stem = preg_replace('/(?:(?:\\\\r\\\\n|\\\\n)|(?:\r?\n)|(?:)|\s)+\s*([((][1-9][0-9]*[))])\s*/u', '
  $1 ', $stem) ?? $stem; $stem = preg_replace('/(求出|求解|求|写出|计算|证明|判断|化简)\s*([((][1-9][0-9]*[))])\s*/u', '$1
  $2 ', $stem) ?? $stem; } return $stem; }; $markComplexDisplayMath = function (string $html): string { return preg_replace_callback( '/]*\bclass="[^"]*\bkatex-display\b[^"]*"[^>]*)>(.*?)<\/span>/isu', static function (array $matches): string { $attrs = $matches[1] ?? ''; $content = $matches[2] ?? ''; $isComplex = str_contains($content, 'mfrac') || str_contains($content, 'vlist'); if (!$isComplex || str_contains($attrs, 'complex-display-math')) { return $matches[0]; } $attrs = preg_replace('/\bclass="([^"]*)"/u', 'class="$1 complex-display-math"', $attrs, 1) ?? $attrs; return '' . $content . ''; }, $html ) ?? $html; }; // 解析:移除“讲解/解析”前缀,结构化分析/详解小标题,并保守处理步骤换行 $formatSolution = function (?string $text) use ($markComplexDisplayMath): string { $solution = trim((string) $text); if ($solution === '') { return '—'; } $solution = preg_replace('/^\s*[【\[]?\s*(讲解|解析)\s*[】\]]?\s*[::]\s*/u', '', $solution) ?? $solution; $solution = preg_replace('/\s*【\s*(分析|详解|点睛)\s*】\s*/u', '
$1
', $solution) ?? $solution; $solution = preg_replace('/\s*\[\s*(分析|详解|点睛)\s*\]\s*/u', '
$1
', $solution) ?? $solution; $solution = preg_replace('/\s*(步骤\s*[0-9一二三四五六七八九十百零两]+\s*[::]?)/u', '
$1', $solution) ?? $solution; $solution = preg_replace('/\s*(第\s*[0-9一二三四五六七八九十百零两]+\s*步\s*[::]?)/u', '
$1', $solution) ?? $solution; $plainLength = mb_strlen(strip_tags($solution), 'UTF-8'); if ($plainLength > 160) { $solution = preg_replace('/([。;])\s*/u', '$1
', $solution) ?? $solution; } $solution = preg_replace('/(<\/div>)\s*
\s*(步骤\s*[0-9一二三四五六七八九十百零两]+\s*[::]?)/u', '$1$2', $solution) ?? $solution; $solution = preg_replace('/(<\/div>)\s*
\s*(第\s*[0-9一二三四五六七八九十百零两]+\s*步\s*[::]?)/u', '$1$2', $solution) ?? $solution; $solution = preg_replace('/^(?:\s*\s*)+/iu', '', $solution) ?? $solution; $solution = preg_replace('/(?:
\s*){2,}/u', '
', $solution) ?? $solution; $solution = preg_replace('/(?:\s*
\s*)*(
)/u', '$1', $solution) ?? $solution; $solution = $markComplexDisplayMath($solution); // 将「分析/详解」转换为可分页语义块:标题 + 内容。 // 仅短小纯文本节绑定;含图/display 公式的节允许自然分页,减少整块推页空白。 $caseSectionClass = static function (string $body, bool $hasTitle = true): string { $plainLength = mb_strlen(trim(strip_tags($body)), 'UTF-8'); $containsImage = str_contains($body, '(.*?)<\/div>/u', $solution, -1, PREG_SPLIT_DELIM_CAPTURE); if (is_array($chunks) && count($chunks) > 1) { $sectionHtml = ''; $lead = trim((string) ($chunks[0] ?? '')); if ($lead !== '') { $leadClass = $caseSectionClass($lead, false); $sectionHtml .= '
' . $lead . '
'; } for ($i = 1; $i < count($chunks); $i += 2) { $title = trim((string) ($chunks[$i] ?? '')); $body = trim((string) ($chunks[$i + 1] ?? '')); if ($title === '' && $body === '') { continue; } $sectionClass = $caseSectionClass($body, true); $sectionHtml .= '
' . $title . '
' . $body . '
'; } if ($sectionHtml !== '') { $solution = $sectionHtml; } } else { $plainClass = $caseSectionClass($solution, false); $solution = '
' . $solution . '
'; } return $solution; }; @endphp

案例分析

@foreach($point['cases'] as $case) @php $sourceText = ''; if (!empty($case['child_kp_name'])) { // 只展示子知识点来源,不展示父知识点名称 $sourceText = trim((string) $case['child_kp_name']); $parentName = trim((string) ($point['kp_name'] ?? '')); if ($parentName !== '') { $escapedParent = preg_quote($parentName, '/'); $sourceText = preg_replace('/^' . $escapedParent . '\s*[-—-\/]\s*/u', '', $sourceText) ?? $sourceText; } if (preg_match('/[-—-\/]/u', $sourceText)) { $parts = preg_split('/\s*[-—-\/]\s*/u', $sourceText); if (is_array($parts) && !empty($parts)) { $sourceText = trim((string) end($parts)); } } } elseif (!empty($case['is_wrong_case'])) { $sourceText = '错题讲解'; } elseif (($case['source_type'] ?? '') === 'reviewed') { $sourceText = '已做题'; } elseif (($case['source_type'] ?? '') === 'fallback') { $sourceText = '补充题'; } @endphp
@php $stemLine = trim((string) ($case['stem'] ?? '')); if ($stemLine === '') { $renderedStemHtml = '—'; } else { [$renderedStemHtml] = \App\Support\BlankPlaceholderRenderer::replaceToBlankSpan($stemLine, null, true, false); $renderedStemHtml = \App\Support\BlankPlaceholderRenderer::normalizeTerminalPunctuation($renderedStemHtml, 'remove'); $renderedStemHtml = $formatStemLikePaper($renderedStemHtml); $renderedStemHtml = \App\Services\MathFormulaProcessor::processFormulas($renderedStemHtml); $renderedStemHtml = $markComplexDisplayMath($renderedStemHtml); } @endphp
例{{ $loop->iteration }}. @if($sourceText !== '') ({{ $sourceText }}) @endif {!! $renderedStemHtml !!}
@php $options = (array) ($case['options'] ?? []); @endphp @if(!empty($options)) @include('pdf.partials.exam-choice-options', [ 'options' => $options, 'gradingMode' => false, 'mathProcessed' => false, 'logQuestionNumber' => 'kp-' . ($case['question_id'] ?? $loop->iteration), 'showLeadSpacer' => false, ]) @endif
@php $layoutDeciderService = app(\App\Support\OptionLayoutDecider::class); $choiceAnswerRaw = $layoutDeciderService->normalizeCompactMathForDisplay(trim((string) ($case['answer'] ?? ''))); $solutionText = trim((string) ($case['solution'] ?? '')); $solutionText = preg_replace('/^【?\s*解题思路\s*】?\s*[::]?\s*/u', '', $solutionText) ?? $solutionText; $solutionProcessed = $solutionText === '' ? '' : \App\Services\MathFormulaProcessor::processFormulas($solutionText); $solutionHtml = $solutionProcessed === '' ? '(暂无解题思路)' : $formatSolution($solutionProcessed); $answerLineHtml = $choiceAnswerRaw === '' ? '—' : \App\Services\MathFormulaProcessor::processFormulas($choiceAnswerRaw); @endphp
正确答案:{!! $answerLineHtml !!}
解题思路:{!! $solutionHtml !!}
@endforeach
@endif
@endforeach
@endif