| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- <?php
- namespace App\Livewire;
- use App\Services\LearningAnalyticsService;
- use App\Services\KnowledgeServiceApi;
- use Livewire\Component;
- class KnowledgeDependencyGraph extends Component
- {
- public string $studentId = '';
- public array $graphData = [];
- public bool $isLoading = false;
- public string $errorMessage = '';
- public ?string $selectedNode = null;
- public function mount(string $studentId): void
- {
- $this->studentId = $studentId;
- $this->loadGraphData();
- }
- public function loadGraphData(): void
- {
- $this->isLoading = true;
- $this->errorMessage = '';
- try {
- // 获取掌握度数据
- $learningService = new LearningAnalyticsService();
- $masteryList = $learningService->getStudentMasteryList($this->studentId);
- // 获取知识点依赖关系
- $dependencies = $this->getKnowledgeDependencies();
- if ($masteryList && isset($masteryList['data']) && !empty($dependencies)) {
- $this->graphData = $this->processGraphData($masteryList['data'], $dependencies);
- } else {
- $this->graphData = [];
- }
- } catch (\Exception $e) {
- $this->errorMessage = '加载依赖关系图数据失败:' . $e->getMessage();
- $this->graphData = [];
- } finally {
- $this->isLoading = false;
- }
- }
- /**
- * 获取知识依赖关系
- */
- private function getKnowledgeDependencies(): array
- {
- try {
- // 使用现有的 KnowledgeServiceApi
- $knowledgeService = app(KnowledgeServiceApi::class);
- $allPoints = $knowledgeService->listKnowledgePoints();
- $dependencies = [];
- foreach ($allPoints as $point) {
- $kpCode = $point['kp_code'] ?? null;
- $parents = $point['parents'] ?? [];
- if ($kpCode && !empty($parents)) {
- foreach ($parents as $parentCode) {
- $dependencies[] = [
- 'prerequisite_kp_code' => $parentCode,
- 'dependent_kp_code' => $kpCode,
- 'influence_weight' => 1.0, // 默认权重
- 'dependency_type' => 'prerequisite',
- ];
- }
- }
- }
- return $dependencies;
- } catch (\Exception $e) {
- \Log::error('获取知识依赖关系失败: ' . $e->getMessage());
- return [];
- }
- }
- /**
- * 处理图数据
- */
- private function processGraphData(array $masteryList, array $dependencies): array
- {
- $nodes = [];
- $edges = [];
- $masteryMap = [];
- // 创建掌握度映射
- foreach ($masteryList as $mastery) {
- $masteryMap[$mastery['kp_code']] = $mastery['mastery_level'];
- }
- // 构建节点
- foreach ($dependencies as $dep) {
- $sourceCode = $dep['prerequisite_kp_code'];
- $targetCode = $dep['dependent_kp_code'];
- if (!isset($masteryMap[$sourceCode])) {
- $masteryMap[$sourceCode] = 0.0;
- }
- if (!isset($masteryMap[$targetCode])) {
- $masteryMap[$targetCode] = 0.0;
- }
- // 添加源节点
- if (!isset($nodes[$sourceCode])) {
- $nodes[$sourceCode] = [
- 'id' => $sourceCode,
- 'label' => $this->getKnowledgePointName($sourceCode),
- 'mastery' => $masteryMap[$sourceCode],
- 'color' => $this->getMasteryColor($masteryMap[$sourceCode]),
- 'size' => $this->getNodeSize($masteryMap[$sourceCode]),
- ];
- }
- // 添加目标节点
- if (!isset($nodes[$targetCode])) {
- $nodes[$targetCode] = [
- 'id' => $targetCode,
- 'label' => $this->getKnowledgePointName($targetCode),
- 'mastery' => $masteryMap[$targetCode],
- 'color' => $this->getMasteryColor($masteryMap[$targetCode]),
- 'size' => $this->getNodeSize($masteryMap[$targetCode]),
- ];
- }
- // 添加边
- $edges[] = [
- 'from' => $sourceCode,
- 'to' => $targetCode,
- 'width' => $dep['influence_weight'] * 3,
- 'color' => $this->getEdgeColor($masteryMap[$sourceCode], $masteryMap[$targetCode]),
- 'label' => '权重: ' . number_format($dep['influence_weight'], 2),
- ];
- }
- return [
- 'nodes' => array_values($nodes),
- 'edges' => array_values($edges),
- ];
- }
- /**
- * 获取知识点名称
- */
- private function getKnowledgePointName(string $kpCode): string
- {
- // 简单的名称映射,实际应从数据库获取
- $names = [
- 'KP1001' => '因式分解基础',
- 'KP1002' => '公因式提取',
- 'KP1003' => '分组分解法',
- 'KP1004' => '十字相乘法',
- 'KP1005' => '公式法',
- 'KP2001' => '完全平方公式',
- 'KP2002' => '平方差公式',
- 'default' => $kpCode,
- ];
- return $names[$kpCode] ?? $names['default'];
- }
- /**
- * 根据掌握度获取颜色
- */
- private function getMasteryColor(float $masteryLevel): string
- {
- if ($masteryLevel < 0.3) {
- return '#ef4444'; // 红色 - 薄弱
- } elseif ($masteryLevel < 0.5) {
- return '#f97316'; // 橙色 - 需要改进
- } elseif ($masteryLevel < 0.7) {
- return '#eab308'; // 黄色 - 一般
- } elseif ($masteryLevel < 0.85) {
- return '#22c55e'; // 绿色 - 良好
- } else {
- return '#3b82f6'; // 蓝色 - 掌握
- }
- }
- /**
- * 获取节点大小
- */
- private function getNodeSize(float $masteryLevel): int
- {
- return (int) (20 + $masteryLevel * 30); // 20-50像素
- }
- /**
- * 获取边的颜色
- */
- private function getEdgeColor(float $sourceMastery, float $targetMastery): string
- {
- // 根据源节点掌握度设置边的颜色
- if ($sourceMastery >= 0.7) {
- return '#22c55e'; // 绿色 - 源节点掌握良好
- } elseif ($sourceMastery >= 0.5) {
- return '#eab308'; // 黄色 - 源节点一般
- } else {
- return '#ef4444'; // 红色 - 源节点薄弱
- }
- }
- /**
- * 选择节点
- */
- public function selectNode(?string $nodeId): void
- {
- $this->selectedNode = $nodeId;
- }
- public function render()
- {
- return view('livewire.knowledge-dependency-graph');
- }
- }
|