| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- <?php
- namespace App\Filament\Pages;
- use App\Services\KnowledgeServiceApi;
- use BackedEnum;
- use Filament\Actions\Action;
- use Filament\Pages\Page;
- use Illuminate\Http\Request;
- use Illuminate\Support\Collection;
- use UnitEnum;
- class KnowledgePointDetail extends Page
- {
- protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-document-text';
- protected static ?int $navigationSort = 2;
- // 不在导航菜单中显示这个页面
- protected static bool $shouldRegisterNavigation = false;
- protected string $view = 'filament.pages.knowledge-point-detail';
- public ?string $kpCode = null;
- public ?string $phaseFilter = null;
- public ?array $knowledgePoint = null;
- public array $graphData = [
- 'nodes' => [],
- 'edges' => [],
- ];
- protected ?KnowledgeServiceApi $knowledgeService = null;
- protected function getKnowledgeService(): KnowledgeServiceApi
- {
- if (!$this->knowledgeService) {
- $this->knowledgeService = app(KnowledgeServiceApi::class);
- }
- return $this->knowledgeService;
- }
- public function mount(Request $request): void
- {
- $this->kpCode = $request->query('kp_code');
- $this->phaseFilter = $request->query('phase');
- if (!$this->kpCode) {
- abort(404, '知识点代码不能为空');
- }
- // 加载知识点详细信息
- $this->knowledgePoint = $this->getKnowledgeService()->getFullGraphData($this->kpCode);
- if (!$this->knowledgePoint) {
- abort(404, '知识点不存在');
- }
- $this->graphData = $this->buildGraphData($this->knowledgePoint);
- }
- public function getTitle(): string
- {
- return $this->knowledgePoint['cn_name'] ?? '知识点详情';
- }
- public function getBreadcrumb(): string
- {
- return '知识点详情';
- }
- public function getKnowledgePointProperty(): ?array
- {
- return $this->knowledgePoint;
- }
- public function getSkillsProperty(): Collection
- {
- return collect($this->knowledgePoint['skills'] ?? []);
- }
- public function getParentNodesProperty(): array
- {
- return $this->knowledgePoint['parent_details'] ?? [];
- }
- public function getChildNodesProperty(): array
- {
- return $this->knowledgePoint['child_details'] ?? [];
- }
- protected function getHeaderActions(): array
- {
- return [
- Action::make('back_to_list')
- ->label('返回列表')
- ->icon('heroicon-o-arrow-left')
- ->url(route('filament.admin.resources.knowledge-points.index'))
- ->color('gray'),
- ];
- }
- public function getKnowledgeStatsProperty(): array
- {
- $skills = $this->skills;
- $parents = collect($this->parentNodes);
- $children = collect($this->childNodes);
- return [
- 'skills_count' => $skills->count(),
- 'parents_count' => $parents->count(),
- 'children_count' => $children->count(),
- 'importance' => $this->knowledgePoint['importance'] ?? 0,
- 'category' => $this->knowledgePoint['category'] ?? '未分类',
- 'phase' => $this->knowledgePoint['phase'] ?? '未知学段',
- ];
- }
- protected function buildGraphData(?array $point): array
- {
- if (empty($point)) {
- return [
- 'nodes' => [],
- 'edges' => [],
- ];
- }
- $centerId = $point['kp_code'] ?? uniqid('kp_', true);
- $nodeMap = [
- $centerId => $this->formatGraphNode($point, 'current', 0),
- ];
- $edges = [];
- $nodeBuckets = [
- 'prerequisite' => $this->extractNodeList($point, [
- 'prerequisite_kps',
- 'child_nodes',
- 'children',
- ]),
- 'post' => $this->extractNodeList($point, [
- 'post_kps',
- 'parent_nodes'
- ]),
- 'related' => $this->extractNodeList($point, [
- 'related_kps',
- ]),
- ];
- foreach ($nodeBuckets as $type => $nodes) {
- foreach ($nodes as $index => $item) {
- $formatted = $this->formatGraphNode($item, $type, $index + 1);
- if (! $formatted) {
- continue;
- }
- $nodeMap[$formatted['id']] = $formatted;
- $edges[] = [
- 'source' => $type === 'prerequisite' ? $formatted['id'] : $centerId,
- 'target' => $type === 'prerequisite' ? $centerId : $formatted['id'],
- 'type' => $type,
- ];
- }
- }
- return [
- 'nodes' => array_values($nodeMap),
- 'edges' => $edges,
- ];
- }
- /**
- * @param array<string, mixed>|string $item
- */
- protected function formatGraphNode(array|string $item, string $type, int $index): ?array
- {
- if (is_array($item)) {
- $id = $item['kp_code'] ?? $item['id'] ?? $item['code'] ?? "{$type}-{$index}";
- $label = $item['cn_name'] ?? $item['label'] ?? $item['name'] ?? $id;
- } elseif (is_string($item)) {
- $id = $item;
- $label = $item;
- $item = [
- 'kp_code' => $id,
- 'cn_name' => $label,
- ];
- } else {
- return null;
- }
- return [
- 'id' => $id,
- 'label' => $label,
- 'type' => $type,
- 'distance' => $type === 'current' ? 0 : 1,
- 'meta' => $item,
- ];
- }
- protected function extractNodeList(array $point, array $keys): array
- {
- foreach ($keys as $key) {
- if (!empty($point[$key]) && is_array($point[$key])) {
- return $point[$key];
- }
- }
- return [];
- }
- }
|