QuestionDetailPage.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. <?php
  2. namespace App\Filament\Pages;
  3. use App\Services\QuestionBankService;
  4. use App\Services\KnowledgeGraphService;
  5. use App\Services\QuestionBankClient;
  6. use Filament\Pages\Page;
  7. use Illuminate\Support\Facades\Log;
  8. class QuestionDetailPage extends Page
  9. {
  10. protected string $view = 'filament.pages.question-detail';
  11. protected static ?string $slug = 'question-detail-legacy';
  12. protected static bool $shouldRegisterNavigation = false;
  13. public $questionId;
  14. public $mistakeId;
  15. public $questionData;
  16. public $mistakeData;
  17. public $sourceType; // 'bank' or 'mistake'
  18. public $studentId;
  19. public function mount(?string $questionId = null, ?string $mistakeId = null, ?string $studentId = null)
  20. {
  21. $this->questionId = $questionId;
  22. $this->mistakeId = $mistakeId;
  23. $this->studentId = $studentId;
  24. if ($mistakeId && $studentId) {
  25. $this->sourceType = 'mistake';
  26. $this->loadMistakeData();
  27. } elseif ($questionId) {
  28. $this->sourceType = 'bank';
  29. $this->loadQuestionData();
  30. }
  31. }
  32. protected function loadQuestionData(): void
  33. {
  34. try {
  35. $client = app(QuestionBankClient::class);
  36. $question = $client->getQuestion($this->questionId);
  37. if ($question) {
  38. $this->questionData = $question;
  39. // 获取相似题目
  40. $similarQuestions = $client->getSimilarQuestions($this->questionId, 5);
  41. $this->relatedQuestions = $similarQuestions['questions'] ?? [];
  42. }
  43. } catch (\Throwable $e) {
  44. Log::error('Failed to load question data', [
  45. 'question_id' => $this->questionId,
  46. 'error' => $e->getMessage()
  47. ]);
  48. $this->questionData = null;
  49. }
  50. }
  51. protected function loadMistakeData(): void
  52. {
  53. try {
  54. // 本地化:从MySQL获取错题详情,不再调用外部API
  55. $mistakeData = \Illuminate\Support\Facades\DB::table('student_mistakes')
  56. ->where('id', $this->mistakeId)
  57. ->where('student_id', $this->studentId)
  58. ->first();
  59. if ($mistakeData) {
  60. $this->mistakeData = (array) $mistakeData;
  61. // 如果有question_id,同时获取题库中的题目详情
  62. if (!empty($this->mistakeData['question_id'])) {
  63. $client = app(QuestionBankClient::class);
  64. $bankQuestion = $client->getQuestion($this->mistakeData['question_id']);
  65. if ($bankQuestion) {
  66. // 合并题库数据和错题数据
  67. $this->questionData = array_merge($bankQuestion, [
  68. 'mistake_info' => [
  69. 'student_answer' => $this->mistakeData['student_answer'] ?? '',
  70. 'correct' => $this->mistakeData['correct'] ?? false,
  71. 'score' => $this->mistakeData['score'] ?? 0,
  72. 'full_score' => $this->mistakeData['full_score'] ?? 0,
  73. 'partial_score_ratio' => $this->mistakeData['partial_score_ratio'] ?? 0,
  74. 'error_type' => $this->mistakeData['error_type'] ?? '',
  75. 'mistake_category' => $this->mistakeData['mistake_category'] ?? '',
  76. 'ai_analysis' => json_decode($this->mistakeData['ai_analysis'] ?? '[]', true),
  77. 'created_at' => $this->mistakeData['created_at'] ?? '',
  78. ]
  79. ]);
  80. }
  81. }
  82. }
  83. } catch (\Throwable $e) {
  84. Log::error('Failed to load mistake data', [
  85. 'mistake_id' => $this->mistakeId,
  86. 'student_id' => $this->studentId,
  87. 'error' => $e->getMessage()
  88. ]);
  89. }
  90. }
  91. public function getTitle(): string
  92. {
  93. $title = '题目详情';
  94. if ($this->sourceType === 'mistake') {
  95. $title = '错题分析 - ' . ($this->mistakeData['question']['question_number'] ?? '#' . $this->mistakeId);
  96. } elseif ($this->sourceType === 'bank' && $this->questionData) {
  97. $title = '题库详情 - ' . substr($this->questionData['stem'], 0, 30) . '...';
  98. }
  99. return $title;
  100. }
  101. public function getBreadcrumbs(): array
  102. {
  103. $breadcrumbs = [];
  104. $breadcrumbs[] = [
  105. 'url' => url('/admin'),
  106. 'name' => '首页',
  107. ];
  108. if ($this->sourceType === 'mistake') {
  109. $breadcrumbs[] = [
  110. 'url' => url('/admin/mistake-book'),
  111. 'name' => '错题本',
  112. ];
  113. } else {
  114. $breadcrumbs[] = [
  115. 'url' => url('/admin/question-management'),
  116. 'name' => '题库管理',
  117. ];
  118. }
  119. $breadcrumbs[] = [
  120. 'url' => '',
  121. 'name' => $this->getTitle(),
  122. ];
  123. return $breadcrumbs;
  124. }
  125. public function getKnowledgePointName(): string
  126. {
  127. $kpCode = '';
  128. if ($this->questionData && !empty($this->questionData['kp_code'])) {
  129. $kpCode = $this->questionData['kp_code'];
  130. } elseif ($this->mistakeData && !empty($this->mistakeData['question']['kp_code'])) {
  131. $kpCode = $this->mistakeData['question']['kp_code'];
  132. }
  133. if (!$kpCode) {
  134. return '未知知识点';
  135. }
  136. // 尝试从缓存获取知识点名称
  137. static $knowledgePoints = null;
  138. if ($knowledgePoints === null) {
  139. try {
  140. $service = app(KnowledgeGraphService::class);
  141. $kps = $service->listKnowledgePoints(1, 1000);
  142. $knowledgePoints = [];
  143. foreach ($kps['data'] ?? [] as $kp) {
  144. $code = $kp['kp_code'] ?? $kp['id'];
  145. $name = $kp['cn_name'] ?? $kp['name'] ?? $code;
  146. $knowledgePoints[$code] = $name;
  147. }
  148. } catch (\Throwable $e) {
  149. Log::error('Failed to load knowledge points');
  150. }
  151. }
  152. return $knowledgePoints[$kpCode] ?? $kpCode;
  153. }
  154. public function getDifficultyColor(): string
  155. {
  156. $difficulty = 0.5;
  157. if ($this->questionData && isset($this->questionData['difficulty'])) {
  158. $difficulty = floatval($this->questionData['difficulty']);
  159. }
  160. if ($difficulty < 0.4) {
  161. return 'bg-green-100 text-green-700';
  162. } elseif ($difficulty < 0.7) {
  163. return 'bg-yellow-100 text-yellow-700';
  164. } else {
  165. return 'bg-red-100 text-red-700';
  166. }
  167. }
  168. public function getDifficultyLabel(): string
  169. {
  170. $difficulty = 0.5;
  171. if ($this->questionData && isset($this->questionData['difficulty'])) {
  172. $difficulty = floatval($this->questionData['difficulty']);
  173. }
  174. if ($difficulty < 0.4) {
  175. return '简单';
  176. } elseif ($difficulty < 0.7) {
  177. return '中等';
  178. } else {
  179. return '困难';
  180. }
  181. }
  182. }