$this->selectedKpCode, 'difficulty' => $this->selectedDifficulty, 'type' => $this->selectedType, 'search' => $this->search, ], fn ($value) => filled($value)); $response = $service->listQuestions($this->currentPage, $this->perPage, $filters); return $response['data'] ?? []; } #[Computed(cache: false)] public function meta(): array { $service = app(QuestionServiceApi::class); $filters = array_filter([ 'kp_code' => $this->selectedKpCode, 'difficulty' => $this->selectedDifficulty, 'type' => $this->selectedType, 'search' => $this->search, ], fn ($value) => filled($value)); $response = $service->listQuestions($this->currentPage, $this->perPage, $filters); return $response['meta'] ?? ['page' => 1, 'per_page' => 25, 'total' => 0, 'total_pages' => 0]; } #[Computed(cache: false)] public function statistics(): array { $service = app(QuestionServiceApi::class); $filters = array_filter([ 'kp_code' => $this->selectedKpCode, 'difficulty' => $this->selectedDifficulty, 'type' => $this->selectedType, 'search' => $this->search, ], fn ($value) => filled($value)); return $service->getStatistics($filters); } #[Computed(cache: false)] public function knowledgePointOptions(): array { return app(QuestionServiceApi::class)->getKnowledgePointOptions(); } #[Computed(cache: false)] public function questionTypeOptions(): array { return [ 'CHOICE' => '单选题', 'MULTIPLE_CHOICE' => '多选题', 'FILL_IN_THE_BLANK' => '填空题', 'CALCULATION' => '简单题', 'WORD_PROBLEM' => '简单题', 'PROOF' => '简单题', ]; } #[Computed(cache: false)] public function questionTypeStatistics(): array { // 如果选择了特定知识点,获取该知识点的题型统计 if ($this->selectedKpCode) { try { $service = app(QuestionServiceApi::class); $filters = ['kp_code' => $this->selectedKpCode]; $response = $service->listQuestions(1, 1000, $filters); $questions = $response['data'] ?? []; $typeStats = []; // 直接使用 question_type 字段统计,而不是猜测 foreach ($questions as $question) { $type = $question['type'] ?? 'CALCULATION'; if (!isset($typeStats[$type])) { $typeStats[$type] = 0; } $typeStats[$type]++; } // 按数量排序 arsort($typeStats); return $typeStats; } catch (\Exception $e) { \Log::error('获取知识点题型统计失败', [ 'kp_code' => $this->selectedKpCode, 'error' => $e->getMessage() ]); return []; } } // 否则返回所有题目的题型统计(从统计数据中获取) try { $statistics = $this->statistics(); $typeStats = $statistics['by_type'] ?? []; // 转换为键值对格式 $result = []; foreach ($typeStats as $typeName => $count) { // 将中文类型名映射为英文类型名 $typeMapping = [ '选择题' => 'CHOICE', '填空题' => 'FILL_IN_THE_BLANK', '解答题' => 'CALCULATION', ]; $englishType = $typeMapping[$typeName] ?? 'CALCULATION'; $result[$englishType] = $count; } return $result; } catch (\Exception $e) { \Log::error('获取题型统计失败', ['error' => $e->getMessage()]); return []; } } // ✅ 检查待处理的回调任务(简化版) public function mount(): void { // 从 URL 参数初始化筛选条件 $this->selectedKpCode = request()->get('kp_code'); $this->selectedDifficulty = request()->get('difficulty'); $this->selectedType = request()->get('type'); $this->search = request()->get('search'); // 检查是否有从回调生成的通知 $notification = Session::get('notification'); if ($notification) { $color = $notification['color'] ?? 'info'; // 使用 persistent 确保通知持续显示 Notification::make() ->title($notification['title'] ?? '通知') ->body($notification['body'] ?? '') ->$color() ->persistent() ->send(); } } /** * 更新 URL 参数 */ public function updated($field): void { // 当筛选条件变化时,更新 URL 参数 if (in_array($field, ['selectedKpCode', 'selectedDifficulty', 'selectedType', 'search'])) { $params = array_filter([ 'kp_code' => $this->selectedKpCode, 'difficulty' => $this->selectedDifficulty, 'type' => $this->selectedType, 'search' => $this->search, ], fn($value) => filled($value)); // 重置到第一页 $this->currentPage = 1; // 更新 URL 参数(不刷新页面) $this->redirect(route('filament.admin.pages.question-management', $params), navigate: true); } } #[Computed(cache: false)] public function skillNameMapping(): array { $service = app(QuestionServiceApi::class); return $service->getSkillNameMapping($this->selectedKpCode); } public function deleteQuestion(string $questionCode): void { try { $service = app(\App\Services\QuestionBankService::class); $result = $service->deleteQuestion($questionCode); if ($result) { Notification::make()->title('删除成功')->body("题目 {$questionCode} 已删除")->success()->send(); // 清除所有缓存,确保页面刷新 Cache::flush(); // 重新加载页面数据 $this->dispatch('$refresh'); } else { Notification::make()->title('删除失败')->body("题目 {$questionCode} 不存在或已被删除")->warning()->send(); } } catch (\Exception $e) { Notification::make()->title('删除异常')->body($e->getMessage())->danger()->send(); } } public function updatedSearch(): void { $this->currentPage = 1; } public function updatedSelectedKpCode(): void { $this->currentPage = 1; } public function updatedSelectedDifficulty(): void { $this->currentPage = 1; } public function updatedSelectedType(): void { $this->currentPage = 1; } public function updatedPerPage(): void { $this->currentPage = 1; } public function viewQuestion(string $questionCode): void { $service = app(QuestionBankService::class); $detail = $service->getQuestion($questionCode); if (!$detail) { Notification::make() ->title('获取题目详情失败') ->danger() ->send(); return; } // 将技能数组转为逗号字符串便于编辑 if (isset($detail['skills']) && is_array($detail['skills'])) { $detail['skills_text'] = implode(',', $detail['skills']); } else { $detail['skills_text'] = (string)($detail['skills'] ?? ''); } $this->editing = $detail; $this->showDetailModal = true; } public function saveQuestion(): void { if (empty($this->editing['question_code'])) { Notification::make()->title('缺少题目编号').danger()->send(); return; } $payload = [ 'stem' => $this->editing['stem'] ?? '', 'answer' => $this->editing['answer'] ?? '', 'solution' => $this->editing['solution'] ?? '', 'difficulty' => $this->editing['difficulty'] ?? null, 'tags' => $this->editing['tags'] ?? null, 'question_type' => $this->editing['question_type'] ?? null, 'kp_code' => $this->editing['kp_code'] ?? null, ]; // skills 处理 $skillsText = $this->editing['skills_text'] ?? ''; $payload['skills'] = $skillsText; $service = app(QuestionBankService::class); $ok = $service->updateQuestion($this->editing['question_code'], array_filter( $payload, fn($v) => $v !== null )); if ($ok) { Notification::make()->title('保存成功')->success()->send(); $this->showDetailModal = false; $this->dispatch('$refresh'); $this->dispatch('math:render'); } else { Notification::make()->title('保存失败')->danger()->send(); } } public function gotoPage(int $page): void { $this->currentPage = $page; } public function previousPage(): void { if ($this->currentPage > 1) { $this->currentPage--; } } public function nextPage(): void { if ($this->currentPage < ($this->meta['total_pages'] ?? 1)) { $this->currentPage++; } } public function getPages(): array { $totalPages = $this->meta['total_pages'] ?? 1; $currentPage = $this->currentPage; $pages = []; $start = max(1, $currentPage - 2); $end = min($totalPages, $currentPage + 2); for ($i = $start; $i <= $end; $i++) { $pages[] = $i; } return $pages; } }