Sfoglia il codice sorgente

fix(report): use hit-kp parent reverse mapping and align solution rendering

yemeishu 2 settimane fa
parent
commit
31905728c8

+ 7 - 5
app/Services/ExamPdfExportService.php

@@ -1039,11 +1039,13 @@ class ExamPdfExportService
             $questions
         ))));
 
-        // 父节点列表:只基于“本卷命中知识点”映射
-        $processedParentMastery = $this->processParentMasteryLevels($parentMasteryLevels, $kpNameMap, $examQuestionKpCodes, $masteryMap, $snapshotMasteryData);
-        if (empty($processedParentMastery) && !empty($examQuestionKpCodes)) {
-            $processedParentMastery = $this->buildParentMasteryFromHitCodes($examQuestionKpCodes, $kpNameMap, $masteryMap, $snapshotMasteryData);
-        }
+        // 父节点列表:直接按“本卷命中子知识点”反查父节点,避免历史全集/补齐口径带偏
+        $processedParentMastery = $this->buildParentMasteryFromHitCodes(
+            $examQuestionKpCodes,
+            $kpNameMap,
+            $masteryMap,
+            $snapshotMasteryData
+        );
 
         Log::info('ExamPdfExportService: 处理后的父节点掌握度', [
             'raw_count' => count($parentMasteryLevels),

+ 42 - 4
resources/views/exam-analysis/pdf-report.blade.php

@@ -241,6 +241,7 @@
             // 严格口径:顶部列表来自“本卷题目关联知识点”
             $hitCodes = array_values(array_unique(array_filter($exam_hit_kp_codes ?? [])));
             $masteryByCode = [];
+            $hitMasteryFromParents = [];
             $questionKpNameMap = [];
             foreach (($questions ?? []) as $q) {
                 $code = trim((string) ($q['knowledge_point'] ?? ''));
@@ -249,6 +250,20 @@
                     $questionKpNameMap[$code] = $name;
                 }
             }
+            // 优先使用父节点树里的命中子节点掌握度(与左侧树口径一致)
+            foreach (($parent_mastery_levels ?? []) as $parent) {
+                $childrenAll = $parent['children_all'] ?? [];
+                if (!is_array($childrenAll)) {
+                    continue;
+                }
+                foreach ($childrenAll as $child) {
+                    $cCode = trim((string) ($child['kp_code'] ?? ''));
+                    if ($cCode === '' || empty($child['is_hit'])) {
+                        continue;
+                    }
+                    $hitMasteryFromParents[$cCode] = floatval($child['mastery_level'] ?? 0);
+                }
+            }
             foreach (($mastery['items'] ?? []) as $item) {
                 $code = (string) ($item['kp_code'] ?? '');
                 if ($code !== '') {
@@ -262,11 +277,23 @@
                     continue;
                 }
                 $base = $masteryByCode[$kpCode] ?? null;
+                $levelFromParentTree = $hitMasteryFromParents[$kpCode] ?? null;
+                $resolvedLevel = $levelFromParentTree !== null
+                    ? floatval($levelFromParentTree)
+                    : floatval($base['mastery_level'] ?? 0);
+                $resolvedChange = $base['mastery_change'] ?? null;
+                // 当顶部使用了父节点树中的实时值且与旧值不一致时,避免显示旧变化值误导
+                if ($levelFromParentTree !== null && $base !== null) {
+                    $oldLevel = floatval($base['mastery_level'] ?? 0);
+                    if (abs($resolvedLevel - $oldLevel) > 0.0001) {
+                        $resolvedChange = null;
+                    }
+                }
                 $filteredMasteryItems[] = [
                     'kp_code' => $kpCode,
                     'kp_name' => $questionKpNameMap[$kpCode] ?? ($base['kp_name'] ?? $kpCode),
-                    'mastery_level' => floatval($base['mastery_level'] ?? 0),
-                    'mastery_change' => $base['mastery_change'] ?? null,
+                    'mastery_level' => $resolvedLevel,
+                    'mastery_change' => $resolvedChange,
                     'is_hit' => true,
                 ];
             }
@@ -665,6 +692,17 @@
                 $solution = $q['solution'] ?? null;
                 $solution = $formatSolutionLikeGrading($solution);
                 $analysis = $formatSolutionLikeGrading($analysis);
+                // 对齐判卷渲染口径:直接走 MathFormulaProcessor,保留图片与公式标签
+                $renderLikeGrading = function ($text) {
+                    if (is_array($text)) {
+                        $text = json_encode($text, JSON_UNESCAPED_UNICODE);
+                    }
+                    $text = is_string($text) ? trim($text) : '';
+                    if ($text === '') {
+                        return '';
+                    }
+                    return \App\Services\MathFormulaProcessor::processFormulas($text);
+                };
             @endphp
             <div class="question-card">
                 <div style="display:flex; justify-content:space-between; align-items:center; gap:8px; margin-bottom:4px;">
@@ -702,13 +740,13 @@
                     <div class="question-block" style="margin-top:6px; background:#eff6ff; border-left:3px solid #3b82f6;">
                         <div style="font-weight:600; font-size:12px; color:#111827; margin-bottom:4px;">解题思路</div>
                         <div class="math-content solution-content" style="color:#374151;">
-                            {!! nl2br(e(is_array($solution) ? json_encode($solution, JSON_UNESCAPED_UNICODE) : (string) $solution)) !!}
+                            {!! $renderLikeGrading($solution) !!}
                         </div>
                     </div>
                 @elseif(!empty($analysis) && $analysis !== '暂无解题思路记录')
                     <div class="question-block" style="margin-top:6px; background:#eff6ff; border-left:3px solid #3b82f6;">
                         <div style="font-weight:600; font-size:12px; color:#111827; margin-bottom:4px;">解题思路</div>
-                        <div class="math-content solution-content" style="color:#374151;">{!! nl2br(e((string) $analysis)) !!}</div>
+                        <div class="math-content solution-content" style="color:#374151;">{!! $renderLikeGrading($analysis) !!}</div>
                     </div>
                 @endif