selectedKpCode = $request->query('selected'); $this->page = (int) $request->query('page', 1); } public function getSelectedPointProperty(): ?array { if ($this->selectedPointData) { return $this->selectedPointData; } // If we have a specific kp code to load if ($this->selectedKpCode) { $this->selectedPointData = $this->getKnowledgeService()->getFullGraphData($this->selectedKpCode); return $this->selectedPointData; } // Get first point from paginated results $points = $this->paginatedPoints; if (!empty($points['data']) && count($points['data']) > 0) { $kpCode = $points['data'][0]['kp_code']; $this->selectedPointData = $this->getKnowledgeService()->getFullGraphData($kpCode); } return $this->selectedPointData; } public function getCurrentPhaseProperty(): ?string { return request()->query('phase'); } protected function getKnowledgeService(): KnowledgeServiceApi { if (!$this->knowledgeService) { $this->knowledgeService = app(KnowledgeServiceApi::class); } return $this->knowledgeService; } public function selectPoint(string $kpCode): void { $this->selectedPoint = $this->getKnowledgeService()->getKnowledgePointDetail($kpCode); } public function getStatsProperty(): array { $all = $this->getKnowledgeService()->listKnowledgePoints(); $phases = $all->groupBy('phase')->map->count()->sortDesc()->map(fn ($count, $phase) => "{$phase}·{$count}"); $categories = $all->groupBy('category')->map->count()->sortDesc()->take(3)->map(fn ($count, $category) => "{$category}·{$count}"); return [ ['label' => '知识点数量', 'value' => number_format($all->count()), 'hint' => '当前版本节点'], ['label' => '学段覆盖', 'value' => $phases->implode(' | ') ?: '未配置', 'hint' => 'phase 字段'], ['label' => 'Top 类别', 'value' => $categories->implode(' | ') ?: '未配置', 'hint' => 'category 字段'], ['label' => '平均重要度', 'value' => number_format($all->avg('importance') ?? 0, 1), 'hint' => 'importance'], ]; } public function getPhaseOptionsProperty(): array { return $this->getKnowledgeService() ->listKnowledgePoints() ->pluck('phase') ->filter() ->unique() ->sort() ->mapWithKeys(fn ($phase) => [$phase => $phase]) ->all(); } public function getCategoryOptionsProperty(): array { return $this->getKnowledgeService() ->listKnowledgePoints() ->pluck('category') ->filter() ->unique() ->sort() ->mapWithKeys(fn ($category) => [$category => $category]) ->all(); } public function getPaginatedPointsProperty(): array { // Get filters from URL $request = request(); $phaseFilter = $request->query('phase'); $categoryFilter = $request->query('category'); $searchTerm = trim((string) $request->query('search')); // Get all points $filters = array_filter([ 'phase' => $phaseFilter, 'category' => $categoryFilter, ]); $allPoints = $this->getKnowledgeService()->listKnowledgePoints( perPage: 200, filters: $filters ); // Apply search filter on the client side if ($searchTerm !== '') { $allPoints = $allPoints->filter(function (array $record) use ($searchTerm): bool { return Str::contains(Str::lower($record['cn_name'] ?? ''), Str::lower($searchTerm)) || Str::contains(Str::lower($record['kp_code'] ?? ''), Str::lower($searchTerm)) || Str::contains(Str::lower($record['description'] ?? ''), Str::lower($searchTerm)); }); } // Paginate the results $total = $allPoints->count(); $totalPages = (int) ceil($total / $this->perPage); $offset = ($this->page - 1) * $this->perPage; $records = $allPoints->slice($offset, $this->perPage)->values(); return [ 'data' => $records, 'total' => $total, 'page' => $this->page, 'total_pages' => $totalPages, 'has_prev' => $this->page > 1, 'has_next' => $this->page < $totalPages, ]; } public function getSelectedSkillsProperty(): Collection { $selectedPoint = $this->selectedPointData; return collect($selectedPoint['skills'] ?? []); } public function getRelatedNodesProperty(): array { $point = $this->selectedPointData; if (! $point) { return ['parents' => [], 'children' => []]; } $parents = collect($point['parents'] ?? []) ->map(fn ($name, $index) => [ 'id' => "parent-{$index}", 'label' => $name, 'relation' => 'parent', ])->values()->all(); $children = collect($point['children'] ?? []) ->map(fn ($name, $index) => [ 'id' => "child-{$index}", 'label' => $name, 'relation' => 'child', ])->values()->all(); return ['parents' => $parents, 'children' => $children]; } }