|
@@ -374,8 +374,24 @@ class ExamTypeStrategy
|
|
|
'question_ids' => array_slice($paperQuestionIds, 0, 10) // 只记录前10个
|
|
'question_ids' => array_slice($paperQuestionIds, 0, 10) // 只记录前10个
|
|
|
]);
|
|
]);
|
|
|
|
|
|
|
|
- // 获取卷子题目知识点(直接从 paper_questions.knowledge_point)
|
|
|
|
|
- $paperKnowledgePoints = $this->getKnowledgePointsFromPaperQuestions($paperIds);
|
|
|
|
|
|
|
+ // 优先从错题记录获取知识点;若无错题则回退到卷子题目知识点
|
|
|
|
|
+ $paperKnowledgePoints = $this->getMistakeKnowledgePointsFromPapers($studentId, $paperIds);
|
|
|
|
|
+ $useMistakeKnowledgePoints = ! empty($paperKnowledgePoints);
|
|
|
|
|
+ if (! $useMistakeKnowledgePoints) {
|
|
|
|
|
+ // 获取卷子题目知识点(直接从 paper_questions.knowledge_point)
|
|
|
|
|
+ $paperKnowledgePoints = $this->getKnowledgePointsFromPaperQuestions($paperIds);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 排除错题本已有题目,避免重复出现
|
|
|
|
|
+ $excludeQuestionIds = $this->getMistakeQuestionIdsFromPapers($studentId, $paperIds);
|
|
|
|
|
+
|
|
|
|
|
+ Log::info('ExamTypeStrategy: 追练知识点来源', [
|
|
|
|
|
+ 'student_id' => $studentId,
|
|
|
|
|
+ 'paper_ids' => $paperIds,
|
|
|
|
|
+ 'use_mistake_kp' => $useMistakeKnowledgePoints,
|
|
|
|
|
+ 'kp_count' => count($paperKnowledgePoints),
|
|
|
|
|
+ 'exclude_count' => count($excludeQuestionIds),
|
|
|
|
|
+ ]);
|
|
|
|
|
|
|
|
if (empty($paperKnowledgePoints)) {
|
|
if (empty($paperKnowledgePoints)) {
|
|
|
Log::warning('ExamTypeStrategy: 卷子题目未找到知识点,无法生成错题本', [
|
|
Log::warning('ExamTypeStrategy: 卷子题目未找到知识点,无法生成错题本', [
|
|
@@ -416,6 +432,8 @@ class ExamTypeStrategy
|
|
|
'difficulty_category' => $difficultyCategory,
|
|
'difficulty_category' => $difficultyCategory,
|
|
|
'is_mistake_exam' => true,
|
|
'is_mistake_exam' => true,
|
|
|
'is_paper_based_mistake' => true, // 标记是基于卷子的错题本
|
|
'is_paper_based_mistake' => true, // 标记是基于卷子的错题本
|
|
|
|
|
+ 'mistake_kp_source' => $useMistakeKnowledgePoints,
|
|
|
|
|
+ 'exclude_question_ids' => $excludeQuestionIds,
|
|
|
'source_paper_question_count' => $questionCount,
|
|
'source_paper_question_count' => $questionCount,
|
|
|
'knowledge_points_count' => count($paperKnowledgePoints),
|
|
'knowledge_points_count' => count($paperKnowledgePoints),
|
|
|
'max_questions_limit' => $maxQuestions,
|
|
'max_questions_limit' => $maxQuestions,
|
|
@@ -441,6 +459,83 @@ class ExamTypeStrategy
|
|
|
return $this->buildKnowledgePointAssembleParams($enhanced);
|
|
return $this->buildKnowledgePointAssembleParams($enhanced);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 从错题记录中获取知识点列表(按学生+卷子)
|
|
|
|
|
+ */
|
|
|
|
|
+ private function getMistakeKnowledgePointsFromPapers(?string $studentId, array $paperIds): array
|
|
|
|
|
+ {
|
|
|
|
|
+ if (empty($studentId) || empty($paperIds)) {
|
|
|
|
|
+ return [];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ $records = \App\Models\MistakeRecord::query()
|
|
|
|
|
+ ->where('student_id', $studentId)
|
|
|
|
|
+ ->whereIn('paper_id', $paperIds)
|
|
|
|
|
+ ->get(['kp_ids']);
|
|
|
|
|
+
|
|
|
|
|
+ $kpCodes = [];
|
|
|
|
|
+ foreach ($records as $record) {
|
|
|
|
|
+ $kpIds = $record->kp_ids;
|
|
|
|
|
+ if (empty($kpIds)) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (is_string($kpIds)) {
|
|
|
|
|
+ $decoded = json_decode($kpIds, true);
|
|
|
|
|
+ if (is_array($decoded)) {
|
|
|
|
|
+ $kpIds = $decoded;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (is_array($kpIds)) {
|
|
|
|
|
+ foreach ($kpIds as $kpId) {
|
|
|
|
|
+ if (! empty($kpId)) {
|
|
|
|
|
+ $kpCodes[$kpId] = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return array_values(array_keys($kpCodes));
|
|
|
|
|
+ } catch (\Exception $e) {
|
|
|
|
|
+ Log::warning('ExamTypeStrategy: 获取错题知识点失败,回退旧逻辑', [
|
|
|
|
|
+ 'student_id' => $studentId,
|
|
|
|
|
+ 'paper_ids' => $paperIds,
|
|
|
|
|
+ 'error' => $e->getMessage(),
|
|
|
|
|
+ ]);
|
|
|
|
|
+ return [];
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 从错题记录中获取题目ID列表(用于排除已出现的错题)
|
|
|
|
|
+ */
|
|
|
|
|
+ private function getMistakeQuestionIdsFromPapers(?string $studentId, array $paperIds): array
|
|
|
|
|
+ {
|
|
|
|
|
+ if (empty($studentId) || empty($paperIds)) {
|
|
|
|
|
+ return [];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ return \App\Models\MistakeRecord::query()
|
|
|
|
|
+ ->where('student_id', $studentId)
|
|
|
|
|
+ ->whereIn('paper_id', $paperIds)
|
|
|
|
|
+ ->pluck('question_id')
|
|
|
|
|
+ ->filter()
|
|
|
|
|
+ ->unique()
|
|
|
|
|
+ ->values()
|
|
|
|
|
+ ->toArray();
|
|
|
|
|
+ } catch (\Exception $e) {
|
|
|
|
|
+ Log::warning('ExamTypeStrategy: 获取错题题目ID失败,忽略排除', [
|
|
|
|
|
+ 'student_id' => $studentId,
|
|
|
|
|
+ 'paper_ids' => $paperIds,
|
|
|
|
|
+ 'error' => $e->getMessage(),
|
|
|
|
|
+ ]);
|
|
|
|
|
+ return [];
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 专项练习:针对特定技能或知识点练习
|
|
* 专项练习:针对特定技能或知识点练习
|
|
|
*/
|
|
*/
|