|
|
@@ -1157,12 +1157,27 @@ class IntelligentExamController extends Controller
|
|
|
return (int) $textbook->id;
|
|
|
}
|
|
|
|
|
|
- Log::warning('未找到匹配的教材', [
|
|
|
+ Log::warning('未找到匹配的教材,尝试从同系列中寻找其他教材', [
|
|
|
'series_id' => $seriesId,
|
|
|
'semester_code' => $semesterCode,
|
|
|
'grade' => $grade,
|
|
|
]);
|
|
|
|
|
|
+ // Fallback:从同系列中按 grade 倒序、semester 倒序选一个有章节的教材
|
|
|
+ $fallbackTextbook = $this->findFallbackTextbookInSeries($seriesId, $grade, $semesterCode);
|
|
|
+ if ($fallbackTextbook) {
|
|
|
+ Log::info('成功从同系列中找到fallback教材', [
|
|
|
+ 'original_series_id' => $seriesId,
|
|
|
+ 'original_semester_code' => $semesterCode,
|
|
|
+ 'original_grade' => $grade,
|
|
|
+ 'fallback_textbook_id' => $fallbackTextbook->id,
|
|
|
+ 'fallback_grade' => $fallbackTextbook->grade,
|
|
|
+ 'fallback_semester' => $fallbackTextbook->semester,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ return (int) $fallbackTextbook->id;
|
|
|
+ }
|
|
|
+
|
|
|
return null;
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
@@ -1176,4 +1191,70 @@ class IntelligentExamController extends Controller
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从同系列中查找一个有章节的教材
|
|
|
+ * 优先选择与目标最接近的教材:grade 倒序,semester 倒序
|
|
|
+ * 用于教材找不到时的 fallback
|
|
|
+ */
|
|
|
+ private function findFallbackTextbookInSeries(int $seriesId, ?int $targetGrade = null, ?int $targetSemester = null): ?\stdClass
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ // 找出同系列下有章节的教材
|
|
|
+ // 筛选 grade <= 目标年级(确保不选择比目标更高的年级)
|
|
|
+ // 按 grade 降序、semester 降序排列
|
|
|
+ // 这样当目标教材不存在时,会选择最接近的"上一个年级/学期"的教材
|
|
|
+ // 例如:找 8年级下 -> 筛选 <=8年级 -> 7年级下 > 7年级上 > 6年级下 > 6年级上
|
|
|
+ $query = DB::connection('mysql')
|
|
|
+ ->table('textbooks as t')
|
|
|
+ ->leftJoin('textbook_catalog_nodes as c', 't.id', '=', 'c.textbook_id')
|
|
|
+ ->where('t.series_id', $seriesId)
|
|
|
+ ->where('c.node_type', 'chapter')
|
|
|
+ ->whereNotNull('c.id');
|
|
|
+
|
|
|
+ if ($targetGrade !== null) {
|
|
|
+ $query->where('t.grade', '<=', $targetGrade);
|
|
|
+ }
|
|
|
+
|
|
|
+ $textbooksWithChapters = $query
|
|
|
+ ->select('t.id', 't.grade', 't.semester')
|
|
|
+ ->groupBy('t.id', 't.grade', 't.semester')
|
|
|
+ ->orderByDesc('t.grade')
|
|
|
+ ->orderByDesc('t.semester')
|
|
|
+ ->get();
|
|
|
+
|
|
|
+ if ($textbooksWithChapters->isEmpty()) {
|
|
|
+ Log::warning('同系列中没有任何教材有章节', [
|
|
|
+ 'series_id' => $seriesId,
|
|
|
+ ]);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 选择第一个有章节的教材(已按 grade 倒序、semester 倒序排列)
|
|
|
+ $selected = $textbooksWithChapters->first();
|
|
|
+
|
|
|
+ Log::info('按倒序选择fallback教材', [
|
|
|
+ 'series_id' => $seriesId,
|
|
|
+ 'target_grade' => $targetGrade,
|
|
|
+ 'target_semester' => $targetSemester,
|
|
|
+ 'selected_textbook_id' => $selected->id,
|
|
|
+ 'selected_grade' => $selected->grade,
|
|
|
+ 'selected_semester' => $selected->semester,
|
|
|
+ 'available_count' => $textbooksWithChapters->count(),
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // 返回完整的教材对象
|
|
|
+ return DB::connection('mysql')
|
|
|
+ ->table('textbooks')
|
|
|
+ ->where('id', $selected->id)
|
|
|
+ ->first();
|
|
|
+
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ Log::error('查找fallback教材失败', [
|
|
|
+ 'series_id' => $seriesId,
|
|
|
+ 'error' => $e->getMessage(),
|
|
|
+ ]);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|