| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- <?php
- namespace App\Livewire;
- use App\Services\LearningAnalyticsService;
- use Livewire\Component;
- class MasteryHeatmap extends Component
- {
- public string $studentId = '';
- public array $heatmapData = [];
- public bool $isLoading = false;
- public string $errorMessage = '';
- // 热力图配置
- public array $config = [
- 'cellSize' => 60,
- 'itemWidth' => 100,
- 'itemHeight' => 80,
- 'colorStops' => [
- ['offset' => 0, 'color' => '#ef4444', 'name' => '薄弱'],
- ['offset' => 0.5, 'color' => '#f59e0b', 'name' => '一般'],
- ['offset' => 0.7, 'color' => '#10b981', 'name' => '良好'],
- ['offset' => 1, 'color' => '#3b82f6', 'name' => '掌握'],
- ]
- ];
- public function mount(string $studentId): void
- {
- $this->studentId = $studentId;
- $this->loadHeatmapData();
- }
- public function loadHeatmapData(): void
- {
- $this->isLoading = true;
- $this->errorMessage = '';
- try {
- $service = new LearningAnalyticsService();
- $masteryList = $service->getStudentMasteryList($this->studentId);
- if ($masteryList && isset($masteryList['data'])) {
- $this->heatmapData = $this->processHeatmapData($masteryList['data']);
- } else {
- $this->heatmapData = [];
- }
- } catch (\Exception $e) {
- $this->errorMessage = '加载热力图数据失败:' . $e->getMessage();
- $this->heatmapData = [];
- } finally {
- $this->isLoading = false;
- }
- }
- /**
- * 处理热力图数据
- */
- private function processHeatmapData(array $masteryList): array
- {
- $processedData = [];
- $categories = []; // 知识分类
- foreach ($masteryList as $mastery) {
- $kpCode = $mastery['kp_code'];
- $masteryLevel = $mastery['mastery_level'];
- $trend = $mastery['mastery_trend'];
- // 根据知识点编码提取分类
- $category = $this->extractCategory($kpCode);
- if (!in_array($category, $categories)) {
- $categories[] = $category;
- }
- // 确定颜色
- $color = $this->getMasteryColor($masteryLevel);
- $borderColor = $this->getTrendColor($trend);
- $processedData[] = [
- 'kp_code' => $kpCode,
- 'category' => $category,
- 'mastery_level' => $masteryLevel,
- 'accuracy_rate' => $mastery['accuracy_rate'],
- 'total_attempts' => $mastery['total_attempts'],
- 'trend' => $trend,
- 'color' => $color,
- 'border_color' => $borderColor,
- 'text_color' => $masteryLevel > 0.5 ? '#ffffff' : '#000000',
- ];
- }
- // 按分类排序
- usort($categories, fn($a, $b) => $a <=> $b);
- return [
- 'data' => $processedData,
- 'categories' => $categories,
- ];
- }
- /**
- * 根据知识点编码提取分类
- */
- private function extractCategory(string $kpCode): string
- {
- // 简单的分类逻辑,实际应根据知识点体系进行分类
- if (strpos($kpCode, 'KP') === 0) {
- $number = (int) substr($kpCode, 2);
- if ($number >= 100 && $number < 200) {
- return '基础概念';
- } elseif ($number >= 200 && $number < 300) {
- return '基础技能';
- } elseif ($number >= 300 && $number < 400) {
- return '综合应用';
- } elseif ($number >= 400 && $number < 500) {
- return '高级技巧';
- } else {
- return '其他';
- }
- }
- return '未分类';
- }
- /**
- * 根据掌握度获取颜色
- */
- 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 getTrendColor(string $trend): string
- {
- return match ($trend) {
- 'improving' => '#10b981', // 绿色上升箭头
- 'stable' => '#6b7280', // 灰色横线
- 'declining' => '#ef4444', // 红色下降箭头
- 'insufficient' => '#d1d5db', // 灰色虚线
- default => '#9ca3af',
- };
- }
- /**
- * 获取掌握度等级名称
- */
- public function getMasteryLevelName(float $masteryLevel): string
- {
- if ($masteryLevel < 0.3) {
- return '薄弱';
- } elseif ($masteryLevel < 0.5) {
- return '入门';
- } elseif ($masteryLevel < 0.7) {
- return '进阶';
- } elseif ($masteryLevel < 0.85) {
- return '熟练';
- } else {
- return '精通';
- }
- }
- /**
- * 获取趋势图标
- */
- public function getTrendIcon(string $trend): string
- {
- return match ($trend) {
- 'improving' => '↗',
- 'stable' => '→',
- 'declining' => '↘',
- 'insufficient' => '⋯',
- default => '?',
- };
- }
- public function render()
- {
- return view('livewire.mastery-heatmap');
- }
- }
|