فهرست منبع

修改一些问题

yemeishu 1 ماه پیش
والد
کامیت
68adf9ea7b

+ 2 - 2
app/Filament/Pages/StudentDashboard.php

@@ -51,9 +51,9 @@ class StudentDashboard extends Page
     public function mount(Request $request): void
     {
         // 从请求中获取老师ID
-        $this->teacherId = $request->input('teacher_id', '');
+        $this->teacherId = (string) ($request->input('teacher_id') ?? '');
         // 从请求中获取学生ID
-        $this->studentId = $request->input('student_id', '');
+        $this->studentId = (string) ($request->input('student_id') ?? '');
 
         if ($this->studentId && empty($this->teacherId)) {
             $student = StudentModel::find($this->studentId);

+ 43 - 71
app/Services/LearningAnalyticsService.php

@@ -212,7 +212,7 @@ class LearningAnalyticsService
             ]);
 
             $response = Http::timeout($this->timeout)
-                ->get($this->baseUrl . "/api/v1/learning-path/student/{$studentId}/recommend");
+                ->post($this->baseUrl . "/api/v1/learning-path/student/{$studentId}/recommend");
 
             Log::info('LearningAnalytics Response: Get Learning Recommendations', [
                 'status' => $response->status(),
@@ -718,11 +718,11 @@ class LearningAnalyticsService
     {
         try {
             Log::info('LearningAnalytics Request: Get Student Learning Paths', [
-                'url' => $this->baseUrl . "/api/v1/learning-path/student/{$studentId}?count={$count}"
+                'url' => $this->baseUrl . "/api/v1/learning-path/student/{$studentId}?limit={$count}"
             ]);
 
             $response = Http::timeout($this->timeout)
-                ->get($this->baseUrl . "/api/v1/learning-path/student/{$studentId}?count={$count}");
+                ->get($this->baseUrl . "/api/v1/learning-path/student/{$studentId}?limit={$count}");
 
             Log::info('LearningAnalytics Response: Get Student Learning Paths', [
                 'status' => $response->status(),
@@ -862,75 +862,47 @@ class LearningAnalyticsService
     {
         Log::info('开始调用快速预测API', ['student_id' => $studentId]);
 
-        try {
-            $response = Http::timeout($this->timeout)
-                ->post($this->baseUrl . "/api/v1/prediction/student/{$studentId}/quick-prediction", [
-                    'student_id' => $studentId
-                ]);
-
-            Log::info('快速预测API响应', [
-                'student_id' => $studentId,
-                'status' => $response->status(),
-                'body' => $response->body()
-            ]);
+        $response = Http::timeout($this->timeout)
+            ->post($this->baseUrl . "/api/v1/prediction/student/{$studentId}/quick-prediction");
 
-            if ($response->successful()) {
-                $data = $response->json();
-                Log::info('快速预测API返回数据', ['student_id' => $studentId, 'data' => $data]);
+        Log::info('快速预测API响应', [
+            'student_id' => $studentId,
+            'status' => $response->status(),
+            'body' => $response->body()
+        ]);
+
+        if (!$response->successful()) {
+            throw new \Exception(sprintf(
+                '快速预测接口失败: %s %s',
+                $response->status(),
+                $response->body()
+            ));
+        }
 
-                // API直接返回数据,没有嵌套在'data'键中
-                $quickPredictionData = $data['quick_prediction'] ?? [];
+        $data = $response->json();
+        Log::info('快速预测API返回数据', ['student_id' => $studentId, 'data' => $data]);
 
-                return [
-                    'quick_prediction' => [
-                        'current_score' => $quickPredictionData['current_score'] ?? 70,
-                        'predicted_score' => $quickPredictionData['predicted_score'] ?? 75,
-                        'improvement_potential' => $quickPredictionData['improvement_potential'] ?? 5,
-                        'estimated_study_hours' => $quickPredictionData['estimated_study_hours'] ?? 15,
-                        'confidence_level' => $quickPredictionData['confidence_level'] ?? 0.75,
-                        'priority_topics' => $quickPredictionData['priority_topics'] ?? [],
-                        'recommended_actions' => $quickPredictionData['recommended_actions'] ?? [],
-                        'weak_knowledge_points_count' => $quickPredictionData['weak_knowledge_points_count'] ?? 0,
-                        'total_knowledge_points' => $quickPredictionData['total_knowledge_points'] ?? 0
-                    ],
-                    'predicted_score' => $quickPredictionData['predicted_score'] ?? 75,
-                    'confidence' => $quickPredictionData['confidence_level'] ? $quickPredictionData['confidence_level'] * 100 : 75,
-                    'time_estimate' => $quickPredictionData['estimated_study_hours'] ?? 15
-                ];
-            }
+        // API 返回结构:{ student_id, current_assumption, target_assumption, quick_prediction, prediction_id, message }
+        $quickPredictionData = $data['quick_prediction'] ?? [];
 
-            Log::warning('快速预测API调用失败', [
-                'student_id' => $studentId,
-                'status' => $response->status(),
-                'response' => $response->body()
-            ]);
-
-            return [
-                'quick_prediction' => [
-                    'improvement_potential' => 0,
-                    'estimated_study_hours' => 0,
-                    'confidence_level' => 0
-                ],
-                'predicted_score' => 0,
-                'confidence' => 0,
-                'time_estimate' => 0
-            ];
-        } catch (\Exception $e) {
-            Log::error('Quick Score Prediction Error', [
-                'student_id' => $studentId,
-                'error' => $e->getMessage()
-            ]);
-            return [
-                'quick_prediction' => [
-                    'improvement_potential' => 0,
-                    'estimated_study_hours' => 0,
-                    'confidence_level' => 0
-                ],
-                'predicted_score' => 0,
-                'confidence' => 0,
-                'time_estimate' => 0
-            ];
-        }
+        return [
+            'quick_prediction' => [
+                'current_score' => $quickPredictionData['current_score'] ?? $data['current_assumption'] ?? 0,
+                'predicted_score' => $quickPredictionData['predicted_score'] ?? $data['target_assumption'] ?? 0,
+                'improvement_potential' => $quickPredictionData['improvement_potential'] ?? (($data['target_assumption'] ?? 0) - ($data['current_assumption'] ?? 0)),
+                'estimated_study_hours' => $quickPredictionData['estimated_study_hours'] ?? 0,
+                'confidence_level' => $quickPredictionData['confidence_level'] ?? 0,
+                'priority_topics' => $quickPredictionData['priority_topics'] ?? [],
+                'recommended_actions' => $quickPredictionData['recommended_actions'] ?? [],
+                'weak_knowledge_points_count' => $quickPredictionData['weak_knowledge_points_count'] ?? 0,
+                'total_knowledge_points' => $quickPredictionData['total_knowledge_points'] ?? 0
+            ],
+            'predicted_score' => $quickPredictionData['predicted_score'] ?? $data['target_assumption'] ?? 0,
+            'confidence' => isset($quickPredictionData['confidence_level']) ? $quickPredictionData['confidence_level'] * 100 : 0,
+            'time_estimate' => $quickPredictionData['estimated_study_hours'] ?? 0,
+            'prediction_id' => $data['prediction_id'] ?? null,
+            'message' => $data['message'] ?? null,
+        ];
     }
 
     /**
@@ -940,11 +912,11 @@ class LearningAnalyticsService
     {
         try {
             Log::info('LearningAnalytics Request: Recommend Learning Paths', [
-                'url' => $this->baseUrl . "/api/v1/learning-path/recommend/{$studentId}?count={$count}"
+                'url' => $this->baseUrl . "/api/v1/learning-path/student/{$studentId}/recommend?limit={$count}"
             ]);
 
             $response = Http::timeout($this->timeout)
-                ->get($this->baseUrl . "/api/v1/learning-path/recommend/{$studentId}?count={$count}");
+                ->post($this->baseUrl . "/api/v1/learning-path/student/{$studentId}/recommend?limit={$count}");
 
             Log::info('LearningAnalytics Response: Recommend Learning Paths', [
                 'status' => $response->status(),
@@ -952,7 +924,7 @@ class LearningAnalyticsService
             ]);
 
             if ($response->successful()) {
-                $data = $response->json()['data'] ?? [];
+                $data = $response->json()['recommendations'] ?? $response->json()['data'] ?? [];
                 return [
                     'recommendations' => $data
                 ];

+ 52 - 13
resources/js/knowledge-mindmap-graph.js

@@ -186,11 +186,16 @@ class KnowledgeMindmapGraph {
     normalizeEdges(rawEdges) {
         const seen = new Set();
         const normalized = [];
+        const neutral = {
+            stroke: '#cbd5e1',
+            lineWidth: 2,
+            lineDash: [6, 6],
+        };
         const styleMap = {
-            prerequisite: { stroke: '#60a5fa', lineDash: [10, 8], lineWidth: 3, label: '前置' },
-            successor: { stroke: '#7dd3fc', lineWidth: 3, label: '后继' },
-            crosslink: { stroke: '#fb923c', lineDash: [8, 6], lineWidth: 2.5, label: '跨联' },
-            sibling: { stroke: '#94a3b8', lineDash: [6, 6], lineWidth: 2.5, label: '同级' },
+            prerequisite: { ...neutral, label: '前置' },
+            successor: { ...neutral, label: '后继' },
+            crosslink: { ...neutral, label: '跨联' },
+            sibling: { ...neutral, label: '同级' },
         };
 
         (rawEdges || []).forEach((edge, index) => {
@@ -203,10 +208,7 @@ class KnowledgeMindmapGraph {
             const category = edge.type || 'successor';
             const renderType =
                 category === 'successor' ? 'cubic-horizontal' : 'quadratic';
-            const baseStyle = styleMap[category] || {
-                stroke: '#cbd5e1',
-                lineWidth: 2.5,
-            };
+            const baseStyle = styleMap[category] || neutral;
             const label = baseStyle.label || edge.label || category;
             const arrowStroke = baseStyle.stroke || '#cbd5e1';
             const style = {
@@ -318,6 +320,9 @@ class KnowledgeMindmapGraph {
         // 折叠/展开或重新布局后重新挂载关联线
         this.graph.on('afterlayout', () => {
             this.redrawRelationEdges();
+            this.repaintNodes();
+            this.applyNodeStates();
+            this.graph.paint();
         });
 
         this.setupFocusListener();
@@ -388,7 +393,15 @@ class KnowledgeMindmapGraph {
                 if (!resolved || !this.graph.findById(resolved)) return;
                 targetId = resolved;
             }
-            this.graph.addItem('edge', { ...edge, source: sourceId, target: targetId });
+            const added = this.graph.addItem('edge', { ...edge, source: sourceId, target: targetId });
+            const shape = added?.getKeyShape?.();
+            if (shape) {
+                shape.attr({
+                    lineDash: [6, 6],
+                    stroke: '#cbd5e1',
+                    lineWidth: 2,
+                });
+            }
         });
     }
 
@@ -500,6 +513,10 @@ class KnowledgeMindmapGraph {
             this.hideTooltip();
         });
 
+        this.graph.on('canvas:mouseleave', () => {
+            this.hideTooltip();
+        });
+
         this.graph.on('node:click', (evt) => this.handleNodeClick(evt));
 
         // 双击用于折叠/展开
@@ -515,6 +532,9 @@ class KnowledgeMindmapGraph {
                 this.graph.updateItem(evt.item, { collapsed: nextState });
                 this.graph.layout?.();
                 this.redrawRelationEdges();
+                this.repaintNodes();
+                this.applyNodeStates?.();
+                this.graph.paint();
             }
         });
 
@@ -665,13 +685,13 @@ class KnowledgeMindmapGraph {
     }
 
     focusOnLowestMastery() {
-        if (!this.graph) return;
+        if (!this.graph) return null;
 
         const entries = Object.entries(this.masteryData || {}).filter(
             ([, value]) =>
                 value && typeof value.mastery_level === 'number'
         );
-        if (!entries.length) return;
+        if (!entries.length) return null;
 
         let targetId = null;
         let minLevel = Infinity;
@@ -683,7 +703,7 @@ class KnowledgeMindmapGraph {
             }
         });
 
-        if (!targetId) return;
+        if (!targetId) return null;
 
         this.graph.getNodes().forEach((node) => {
             this.graph.clearItemStates(node);
@@ -696,7 +716,9 @@ class KnowledgeMindmapGraph {
                 duration: 500,
             });
             this.graph.setItemState(item, 'selected', true);
+            return item;
         }
+        return null;
     }
 
     refreshGraph() {
@@ -727,11 +749,27 @@ class KnowledgeMindmapGraph {
         this.drawRelationEdges();
         this.applyNodeStates();
         this.startEdgeFlows();
-        this.focusOnLowestMastery();
+        const focused = this.focusOnLowestMastery();
+        this.zoomAfterFocus(focused);
         this.graph.paint();
         this.setupFocusListener();
     }
 
+    zoomAfterFocus(focusedItem = null) {
+        if (!this.graph) return;
+        const hasMastery = Object.keys(this.masteryData || {}).length > 0;
+        if (!hasMastery) return;
+        const model = focusedItem?.getModel?.() || null;
+        const center = model?.x && model?.y
+            ? { x: model.x, y: model.y }
+            : {
+                  x: this.graph.get('width') / 2,
+                  y: this.graph.get('height') / 2,
+              };
+        const targetZoom = Math.min(2.0, Math.max(1.4, this.graph.getZoom() * 1.35));
+        this.graph.zoomTo(targetZoom, center);
+    }
+
     bindEdgeTooltip() {
         if (!this.graph) return;
         const tooltipEl = document.createElement('div');
@@ -773,6 +811,7 @@ class KnowledgeMindmapGraph {
         });
 
         this.graph.on('edge:mouseleave', () => hide());
+        this.graph.on('canvas:mouseleave', () => hide());
     }
 
     redrawRelationEdges() {

+ 129 - 279
resources/views/filament/pages/student-dashboard.blade.php

@@ -11,22 +11,22 @@
                         学生仪表板
                     </h1>
                     <p class="mt-2 text-sm text-gray-600 ml-11">
-                        全面展示学生的学习分析数据,包括掌握度、技能熟练度、提分预测和学习路径
+                        全面展示学生的学习分析数据,包括掌握度、技能熟练度、提效分析和学习路径
                     </p>
                 </div>
             </div>
 
             {{-- 选择器区域 --}}
             <div class="bg-gray-50 rounded-lg p-4 border border-gray-200">
-                <div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
+                <div class="flex flex-col gap-3 lg:flex-row lg:items-center">
                     {{-- 选择老师 --}}
-                    <div class="form-control w-full">
+                    <div class="form-control w-full lg:flex-1">
                         <label class="label">
                             <span class="label-text font-medium">选择老师</span>
                         </label>
                         <select
                             wire:model.live="teacherId"
-                            class="select select-bordered w-full"
+                            class="select select-bordered w-full h-11"
                         >
                             <option value="">请选择老师...</option>
                             @foreach($this->teachers as $teacher)
@@ -41,13 +41,13 @@
                     </div>
 
                     {{-- 选择学生 --}}
-                    <div class="form-control w-full">
+                    <div class="form-control w-full lg:flex-1">
                         <label class="label">
                             <span class="label-text font-medium">选择学生</span>
                         </label>
                         <select
                             wire:model.live="studentId"
-                            class="select select-bordered w-full"
+                            class="select select-bordered w-full h-11"
                             @if(empty($teacherId)) disabled @endif
                         >
                             <option value="">
@@ -67,21 +67,21 @@
                             <span class="label-text text-xs text-gray-500">选择要查看的学生</span>
                         </label>
                     </div>
-                </div>
-
-                <div class="mt-4 pb-0.5 flex space-x-2">
-                    <button
-                        wire:click="loadDashboardData"
-                        wire:loading.attr="disabled"
-                        class="inline-flex items-center px-6 py-2.5 border border-transparent text-sm font-medium rounded-lg shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors duration-200"
-                    >
-                        <svg wire:loading class="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
-                            <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
-                            <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
-                        </svg>
-                        刷新数据
-                    </button>
 
+                    {{-- 刷新按钮 --}}
+                    <div class="w-full lg:w-auto flex items-center lg:pt-6">
+                        <button
+                            wire:click="loadDashboardData"
+                            wire:loading.attr="disabled"
+                            class="inline-flex items-center justify-center w-full h-11 px-6 border border-transparent text-sm font-medium rounded-lg shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors duration-200"
+                        >
+                            <svg wire:loading class="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
+                                <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
+                                <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
+                            </svg>
+                            刷新数据
+                        </button>
+                    </div>
                 </div>
             </div>
         </div>
@@ -107,7 +107,7 @@
             <div
                 wire:ignore
                 id="student-mindmap"
-                class="knowledge-mindmap-canvas relative h-[64vh] min-h-[560px] w-full"
+                class="knowledge-mindmap-canvas relative h-[56vh] min-h-[460px] w-full"
             >
             </div>
         </div>
@@ -246,7 +246,7 @@
                 @endif
 
                 {{-- 技能熟练度概览 --}}
-                @if (isset($dashboardData['skill']['summary']))
+                @if (isset($dashboardData['skill']['summary']) && !empty($dashboardData['skill']['summary']['total_skills']))
                     <div class="bg-white overflow-hidden shadow-sm rounded-xl border border-gray-200 hover:shadow-md transition-shadow duration-200">
                         <div class="p-6">
                             <div class="flex items-center justify-between">
@@ -280,7 +280,7 @@
                     </div>
                 @endif
 
-                {{-- 提分潜力 --}}
+                {{-- 学习提效概览 --}}
                 @if (isset($dashboardData['prediction']['quick']))
                     <div class="bg-white overflow-hidden shadow-sm rounded-xl border border-gray-200 hover:shadow-md transition-shadow duration-200">
                         <div class="p-6">
@@ -294,7 +294,7 @@
                                         </div>
                                     </div>
                                     <div class="ml-4">
-                                        <p class="text-sm font-medium text-gray-600">预期提</p>
+                                    <p class="text-sm font-medium text-gray-600">预期提</p>
                                         <p class="text-2xl font-bold text-gray-900 mt-1">
                                             +{{ $dashboardData['prediction']['quick']['quick_prediction']['improvement_potential'] ?? 0 }}
                                             <span class="text-lg text-gray-500">分</span>
@@ -316,34 +316,6 @@
                     </div>
                 @endif
 
-                {{-- 专题测试 / 智能出卷入口 --}}
-                @if(!empty($studentId))
-                    <div class="bg-white overflow-hidden shadow-sm rounded-xl border border-gray-200 hover:shadow-md transition-shadow duration-200">
-                        <div class="p-6 flex items-center justify-between">
-                            <div class="flex items-center">
-                                <div class="flex-shrink-0">
-                                    <div class="w-12 h-12 bg-gradient-to-br from-indigo-500 to-indigo-600 rounded-xl flex items-center justify-center shadow-lg">
-                                        <svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-                                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.1 0-2 .9-2 2v8h4v-8c0-1.1-.9-2-2-2zm0 0V4m0 16h.01M6 12h.01M18 12h.01" />
-                                        </svg>
-                                    </div>
-                                </div>
-                                <div class="ml-4">
-                                    <p class="text-sm font-medium text-gray-600">专题测试</p>
-                                    <p class="text-lg font-semibold text-gray-900">智能出卷</p>
-                                    <p class="text-sm text-gray-500">携带学生ID直达出卷,题目偏向薄弱点</p>
-                                </div>
-                            </div>
-                            <a
-                                href="{{ url('/admin/intelligent-exam-generation') }}?student_id={{ $studentId }}"
-                                class="inline-flex items-center px-4 py-2 rounded-lg bg-indigo-600 text-white text-sm font-medium hover:bg-indigo-700"
-                            >
-                                前往出卷
-                            </a>
-                        </div>
-                    </div>
-                @endif
-
                 {{-- 学习路径 --}}
                 @if (isset($dashboardData['learning_path']['analytics']))
                     <div class="bg-white overflow-hidden shadow-sm rounded-xl border border-gray-200 hover:shadow-md transition-shadow duration-200">
@@ -381,11 +353,11 @@
             </div>
         </div>
 
-        {{-- 主要内容区域 --}}
+        {{-- 主要内容区域:统一流式网格 --}}
         <div class="mb-8">
-            <div class="grid grid-cols-1 gap-6 lg:grid-cols-2">
+            <div class="grid grid-cols-1 gap-6 xl:grid-cols-2 2xl:grid-cols-3 items-start">
                 {{-- 掌握度分析 --}}
-                <div class="bg-white shadow-sm rounded-xl border border-gray-200">
+                <div class="bg-white shadow-sm rounded-xl border border-gray-200 xl:col-span-2">
                     <div class="px-6 py-5 border-b border-gray-100 flex items-center justify-between">
                         <h3 class="text-lg font-semibold text-gray-900 flex items-center">
                             <svg class="w-5 h-5 mr-2 text-indigo-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -393,74 +365,73 @@
                             </svg>
                             知识点掌握度
                         </h3>
-                        <button
-                            wire:click="batchUpdateSkills"
-                            class="inline-flex items-center px-3 py-1.5 border border-transparent text-xs font-medium rounded-lg text-indigo-700 bg-indigo-100 hover:bg-indigo-200 transition-colors duration-150"
-                        >
-                            <svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
-                            </svg>
-                            刷新
-                        </button>
                     </div>
-                <div class="p-6">
-                    @if (isset($dashboardData['mastery']['overview']['total_knowledge_points']))
-                        <div class="space-y-4">
-                            <div class="flex items-center justify-between text-sm">
-                                <span class="text-gray-600">总知识点数</span>
-                                <span class="font-medium text-gray-900">{{ $dashboardData['mastery']['overview']['total_knowledge_points'] }}</span>
-                            </div>
-                            <div class="w-full bg-gray-200 rounded-full h-2">
-                                <div class="bg-indigo-600 h-2 rounded-full" style="width: {{ $dashboardData['mastery']['overview']['average_mastery_level'] * 100 }}%"></div>
-                            </div>
-                            <div class="grid grid-cols-3 gap-4 mt-4">
-                                <div class="text-center">
-                                    <div class="text-2xl font-semibold text-green-600">{{ $dashboardData['mastery']['overview']['mastered_knowledge_points'] }}</div>
-                                    <div class="text-xs text-gray-500">已掌握 (≥85%)</div>
+                    <div class="p-6">
+                        @if (isset($dashboardData['mastery']['overview']['total_knowledge_points']))
+                            <div class="space-y-4">
+                                <div class="flex items-center justify-between text-sm">
+                                    <span class="text-gray-600">总知识点数</span>
+                                    <span class="font-medium text-gray-900">{{ $dashboardData['mastery']['overview']['total_knowledge_points'] }}</span>
                                 </div>
-                                <div class="text-center">
-                                    <div class="text-2xl font-semibold text-blue-600">{{ $dashboardData['mastery']['overview']['good_knowledge_points'] }}</div>
-                                    <div class="text-xs text-gray-500">良好 (70-85%)</div>
+                                <div class="w-full bg-gray-200 rounded-full h-2">
+                                    <div class="bg-indigo-600 h-2 rounded-full" style="width: {{ $dashboardData['mastery']['overview']['average_mastery_level'] * 100 }}%"></div>
                                 </div>
-                                <div class="text-center">
-                                    <div class="text-2xl font-semibold text-red-600">{{ $dashboardData['mastery']['overview']['weak_knowledge_points'] }}</div>
-                                    <div class="text-xs text-gray-500">薄弱 (<50%)</div>
+                                <div class="grid grid-cols-3 gap-4 mt-4">
+                                    <div class="text-center">
+                                        <div class="text-2xl font-semibold text-green-600">{{ $dashboardData['mastery']['overview']['mastered_knowledge_points'] }}</div>
+                                        <div class="text-xs text-gray-500">已掌握 (≥85%)</div>
+                                    </div>
+                                    <div class="text-center">
+                                        <div class="text-2xl font-semibold text-blue-600">{{ $dashboardData['mastery']['overview']['good_knowledge_points'] }}</div>
+                                        <div class="text-xs text-gray-500">良好 (70-85%)</div>
+                                    </div>
+                                    <div class="text-center">
+                                        <div class="text-2xl font-semibold text-red-600">{{ $dashboardData['mastery']['overview']['weak_knowledge_points'] }}</div>
+                                        <div class="text-xs text-gray-500">薄弱 (<50%)</div>
+                                    </div>
                                 </div>
-                            </div>
-                            @if (!empty($dashboardData['mastery']['overview']['weak_knowledge_points_list']))
-                                <div class="mt-6">
-                                    <h4 class="text-sm font-medium text-gray-900 mb-3">薄弱知识点</h4>
-                                    <div class="space-y-2">
-                                        @foreach (array_slice($dashboardData['mastery']['overview']['weak_knowledge_points_list'], 0, 5) as $weak)
-                                            <div class="flex items-center justify-between p-3 bg-red-50 rounded-lg">
-                                                <div class="flex items-center">
-                                                    <div class="w-2 h-2 bg-red-500 rounded-full mr-3"></div>
-                                                    <span class="text-sm font-medium text-gray-900">{{ $weak['kp_code'] ?? $weak['knowledge_point_code'] ?? 'N/A' }}</span>
-                                                </div>
-                                                <div class="flex items-center space-x-3">
+                                @if (!empty($dashboardData['mastery']['overview']['weak_knowledge_points_list']))
+                                    <div class="mt-6">
+                                        <h4 class="text-sm font-medium text-gray-900 mb-3">薄弱知识点</h4>
+                                        <div class="space-y-2">
+                                            @foreach (array_slice($dashboardData['mastery']['overview']['weak_knowledge_points_list'], 0, 5) as $weak)
+                                                <div class="flex items-center justify-between p-3 bg-red-50 rounded-lg">
+                                                    <div class="flex items-center">
+                                                        <div class="w-2 h-2 bg-red-500 rounded-full mr-3"></div>
+                                                        <span class="text-sm font-medium text-gray-900">{{ $weak['kp_code'] ?? $weak['knowledge_point_code'] ?? 'N/A' }}</span>
+                                                    </div>
+                                                    <div class="flex items-center space-x-3">
                                                     <span class="text-sm text-gray-600">{{ number_format(($weak['mastery_level'] ?? $weak['mastery'] ?? 0) * 100, 1) }}%</span>
-                                                    <button
-                                                        wire:click="recalculateMastery('{{ $weak['kp_code'] ?? $weak['knowledge_point_code'] ?? '' }}')"
+                                                    <a
+                                                        href="{{ url('/admin/intelligent-exam-generation') }}?student_id={{ $studentId }}&kp_code={{ urlencode($weak['kp_code'] ?? $weak['knowledge_point_code'] ?? '') }}"
                                                         class="text-xs text-indigo-600 hover:text-indigo-800"
+                                                        target="_blank"
                                                     >
-                                                        重新计算
-                                                    </button>
+                                                        去做题
+                                                    </a>
                                                 </div>
                                             </div>
                                         @endforeach
                                     </div>
                                 </div>
-                            @endif
-                        </div>
-                    @else
-                        <div class="text-center py-8 text-gray-500">
-                            暂无掌握度数据
-                        </div>
-                    @endif
+                                @endif
+                            </div>
+                        @else
+                            <div class="text-center py-8 text-gray-500">
+                                暂无掌握度数据
+                            </div>
+                        @endif
+                    </div>
                 </div>
-            </div>
 
                 {{-- 技能熟练度 --}}
+                @php
+                    $skillData = $dashboardData['skill']['proficiency']['data'] ?? [];
+                    if (!is_array($skillData)) {
+                        $skillData = [];
+                    }
+                @endphp
+                @if (!empty($skillData))
                 <div class="bg-white shadow-sm rounded-xl border border-gray-200">
                     <div class="px-6 py-5 border-b border-gray-100 flex items-center justify-between">
                         <h3 class="text-lg font-semibold text-gray-900 flex items-center">
@@ -479,14 +450,7 @@
                             批量更新
                         </button>
                     </div>
-                <div class="p-6">
-                    @php
-                        $skillData = $dashboardData['skill']['proficiency']['data'] ?? [];
-                        if (!is_array($skillData)) {
-                            $skillData = [];
-                        }
-                    @endphp
-                    @if (!empty($skillData))
+                    <div class="p-6">
                         <div class="space-y-4">
                             @foreach (array_slice($skillData, 0, 5) as $skill)
                                 <div class="flex items-center justify-between">
@@ -506,90 +470,59 @@
                                 </div>
                             @endforeach
                         </div>
-                    @else
-                        <div class="text-center py-8 text-gray-500">
-                            暂无技能数据
-                        </div>
-                    @endif
-                </div>
-            </div>
-        </div>
-
-        {{-- 技能熟练度雷达图 - 已隐藏(功能已实现但暂时隐藏以简化界面) --}}
-        {{-- <div class="mb-8">
-            <div class="bg-white shadow-sm rounded-xl border border-gray-200">
-                <div class="px-6 py-5 border-b border-gray-100">
-                    <h3 class="text-lg font-semibold text-gray-900 flex items-center">
-                        <svg class="w-5 h-5 mr-2 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"></path>
-                        </svg>
-                        技能熟练度雷达图
-                    </h3>
-                </div>
-                <div class="p-6">
-                    <livewire:skill-proficiency-radar :student-id="$studentId" />
+                    </div>
                 </div>
-            </div>
-        </div> --}}
+                @endif
 
-        {{-- 提分预测和学习路径 - 已实现 --}}
-        <div class="mb-8">
-            <div class="grid grid-cols-1 gap-6 lg:grid-cols-2">
-                {{-- 提分预测 --}}
+                {{-- 学习提效 --}}
                 <div class="bg-white shadow-sm rounded-xl border border-gray-200">
                     <div class="px-6 py-5 border-b border-gray-100 flex items-center justify-between">
                         <h3 class="text-lg font-semibold text-gray-900 flex items-center">
                             <svg class="w-5 h-5 mr-2 text-yellow-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"></path>
                             </svg>
-                            提分预测
+                            学习提效
                         </h3>
-                        <button
-                            wire:click="generateQuickPrediction"
-                            class="inline-flex items-center px-3 py-1.5 border border-transparent text-xs font-medium rounded-lg text-yellow-700 bg-yellow-100 hover:bg-yellow-200 transition-colors duration-150"
-                        >
-                            <svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
-                            </svg>
-                            快速预测
-                        </button>
                     </div>
-                <div class="p-6">
-                    {{-- 快速预测结果 --}}
-                    @if (isset($dashboardData['prediction']['quick']) && !empty($dashboardData['prediction']['quick']['quick_prediction']))
-                        @php
-                            $quickPrediction = $dashboardData['prediction']['quick']['quick_prediction'];
-                        @endphp
-
-                        {{-- 主要预测信息卡片 --}}
-                        <div class="bg-gradient-to-r from-blue-50 to-indigo-50 rounded-lg p-6 mb-6 border border-blue-200">
-                            <div class="flex items-center justify-between mb-4">
-                                <div>
-                                    <h4 class="text-lg font-semibold text-gray-900">智能提分预测</h4>
-                                    <p class="text-sm text-gray-600 mt-1">基于当前学习数据的AI分析</p>
+                    <div class="p-6">
+                        {{-- 快速预测结果 --}}
+                        @if (isset($dashboardData['prediction']['quick']) && !empty($dashboardData['prediction']['quick']['quick_prediction']))
+                            @php
+                                $quickPrediction = $dashboardData['prediction']['quick']['quick_prediction'];
+                                $round05 = function($v) {
+                                    return number_format(round(((float) $v) * 2) / 2, 1);
+                                };
+                            @endphp
+
+                            {{-- 主要预测信息卡片 --}}
+                            <div class="bg-gradient-to-r from-blue-50 to-indigo-50 rounded-lg p-6 mb-6 border border-blue-200">
+                                <div class="flex items-center justify-between mb-4">
+                                    <div>
+                                    <h4 class="text-lg font-semibold text-gray-900">学习提效分析</h4>
+                                    <p class="text-sm text-gray-600 mt-1">基于当前学习数据的分析</p>
                                 </div>
                                 <div class="text-right">
                                     <div class="text-2xl font-bold text-green-600">
-                                        +{{ number_format($quickPrediction['improvement_potential'] ?? 0, 1) }}分
+                                        +{{ $round05($quickPrediction['improvement_potential'] ?? 0) }}
                                     </div>
-                                    <div class="text-sm text-gray-500">预期提</div>
+                                    <div class="text-sm text-gray-500">预期提</div>
                                 </div>
                             </div>
 
-                            <div class="grid grid-cols-3 gap-4 mb-4">
-                                <div class="text-center">
-                                    <div class="text-lg font-semibold text-gray-900">
-                                        {{ $quickPrediction['current_score'] ?? 0 }}分
+                                <div class="grid grid-cols-3 gap-4 mb-4">
+                                    <div class="text-center">
+                                        <div class="text-lg font-semibold text-gray-900">
+                                            {{ $round05($quickPrediction['current_score'] ?? 0) }}
+                                        </div>
+                                        <div class="text-xs text-gray-500">当前分值</div>
                                     </div>
-                                    <div class="text-xs text-gray-500">当前分数</div>
-                                </div>
-                                <div class="text-center">
-                                    <div class="text-lg font-semibold text-blue-600">
-                                        {{ $quickPrediction['predicted_score'] ?? 0 }}分
+                                    <div class="text-center">
+                                        <div class="text-lg font-semibold text-blue-600">
+                                            {{ $round05($quickPrediction['predicted_score'] ?? 0) }}
+                                        </div>
+                                        <div class="text-xs text-gray-500">预测分值</div>
                                     </div>
-                                    <div class="text-xs text-gray-500">预测分数</div>
-                                </div>
-                                <div class="text-center">
+                                    <div class="text-center">
                                     <div class="text-lg font-semibold text-purple-600">
                                         {{ $quickPrediction['estimated_study_hours'] ?? 0 }}h
                                     </div>
@@ -607,9 +540,6 @@
                                         <span class="text-sm font-medium text-gray-900">{{ number_format(($quickPrediction['confidence_level'] ?? 0) * 100, 0) }}%</span>
                                     </div>
                                 </div>
-                                <div class="text-xs text-gray-500">
-                                    {{ $quickPrediction['weak_knowledge_points_count'] ?? 0 }}个薄弱知识点
-                                </div>
                             </div>
                         </div>
 
@@ -675,6 +605,17 @@
                             </div>
                         @endif
 
+                        @if (!empty($studentId))
+                            <div class="mt-6">
+                                <a
+                                    href="{{ url('/admin/intelligent-exam-generation') }}?student_id={{ $studentId }}"
+                                    class="inline-flex items-center px-4 py-2 rounded-lg bg-indigo-600 text-white text-sm font-medium hover:bg-indigo-700"
+                                >
+                                    去做匹配的题目,降低无效的刷题时间,提高效率
+                                </a>
+                            </div>
+                        @endif
+
                     {{-- 历史预测记录 --}}
                     @elseif (!empty($dashboardData['prediction']['list']['predictions']))
                         @php
@@ -690,11 +631,11 @@
                                     </div>
                                     <div class="flex items-center justify-between">
                                         <div class="text-sm text-gray-600">
-                                            当前: {{ $prediction['current_score'] ?? 0 }}
-                                            <span class="font-semibold text-gray-900">{{ $prediction['predicted_score'] ?? 0 }}</span>
+                                            当前: {{ $prediction['current_score'] ?? 0 }} →
+                                            <span class="font-semibold text-gray-900">{{ $prediction['predicted_score'] ?? 0 }}</span>
                                         </div>
                                         <div class="text-sm font-semibold text-green-600">
-                                            +{{ number_format(($prediction['predicted_score'] ?? 0) - ($prediction['current_score'] ?? 0), 1) }}
+                                            +{{ number_format(($prediction['predicted_score'] ?? 0) - ($prediction['current_score'] ?? 0), 1) }}
                                         </div>
                                     </div>
                                 </div>
@@ -708,103 +649,12 @@
                                 </svg>
                             </div>
                             <p class="text-sm font-medium text-gray-900 mb-1">暂无预测数据</p>
-                            <p class="text-xs text-gray-500 mb-4">点击"快速预测"按钮生成AI预测分析</p>
-                            <button
-                                wire:click="generateQuickPrediction"
-                                class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-lg text-white bg-blue-600 hover:bg-blue-700 transition-colors duration-200"
-                            >
-                                <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
-                                </svg>
-                                生成快速预测
-                            </button>
+                            <p class="text-xs text-gray-500">等待分析数据刷新后再查看</p>
                         </div>
                     @endif
                 </div>
             </div>
-        </div>
-
-        {{-- 掌握度热力图 - 已隐藏(功能已实现但暂时隐藏以简化界面) --}}
-        {{-- <div class="mb-8">
-            <div class="bg-white shadow-sm rounded-xl border border-gray-200">
-                <div class="px-6 py-5 border-b border-gray-100">
-                    <h3 class="text-lg font-semibold text-gray-900 flex items-center">
-                        <svg class="w-5 h-5 mr-2 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z"></path>
-                        </svg>
-                        知识点掌握度热力图
-                    </h3>
-                </div>
-                <div class="p-6">
-                    <livewire:mastery-heatmap :student-id="$studentId" />
-                </div>
-            </div>
-        </div> --}}
-
-        {{-- 知识点依赖关系图 - 已隐藏(功能已实现但暂时隐藏以简化界面) --}}
-        {{-- <div class="mb-8">
-            <div class="bg-white shadow-sm rounded-xl border border-gray-200">
-                <div class="px-6 py-5 border-b border-gray-100">
-                    <h3 class="text-lg font-semibold text-gray-900 flex items-center">
-                        <svg class="w-5 h-5 mr-2 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"></path>
-                        </svg>
-                        知识点依赖关系图
-                    </h3>
-                </div>
-                <div class="p-6">
-                    <livewire:knowledge-dependency-graph :student-id="$studentId" />
-                </div>
             </div>
-        </div> --}}
-
-        {{-- 推荐学习路径 - 已隐藏(功能已实现但暂时隐藏以简化界面) --}}
-        {{-- @if (isset($dashboardData['learning_path']['recommendations']['recommendations']))
-            <div class="mb-8">
-                <div class="bg-white shadow-sm rounded-xl border border-gray-200">
-                    <div class="px-6 py-5 border-b border-gray-100">
-                        <h3 class="text-lg font-semibold text-gray-900 flex items-center">
-                            <svg class="w-5 h-5 mr-2 text-indigo-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"></path>
-                            </svg>
-                            推荐学习路径
-                        </h3>
-                    </div>
-                <div class="p-6">
-                    <div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
-                        @foreach ($dashboardData['learning_path']['recommendations']['recommendations'] as $recommendation)
-                            <div class="p-4 border border-gray-200 rounded-lg hover:border-indigo-300 transition-colors">
-                                <div class="flex items-center mb-3">
-                                    <div class="w-8 h-8 bg-indigo-100 rounded-full flex items-center justify-center mr-3">
-                                        <svg class="w-4 h-4 text-indigo-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-                                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
-                                        </svg>
-                                    </div>
-                                    <div class="flex-1">
-                                        <div class="text-sm font-medium text-gray-900">{{ $recommendation['target_kp_name'] }}</div>
-                                        <div class="text-xs text-gray-500">{{ $recommendation['target_kp_code'] }}</div>
-                                    </div>
-                                </div>
-                                <div class="mb-3">
-                                    <div class="flex items-center justify-between text-xs text-gray-600 mb-1">
-                                        <span>当前掌握度</span>
-                                        <span class="font-medium">{{ number_format($recommendation['current_mastery'] * 100, 1) }}%</span>
-                                    </div>
-                                    <div class="w-full bg-gray-200 rounded-full h-1.5">
-                                        <div class="bg-indigo-500 h-1.5 rounded-full" style="width: {{ $recommendation['current_mastery'] * 100 }}%"></div>
-                                    </div>
-                                </div>
-                                <p class="text-xs text-gray-600 mb-3">{{ $recommendation['reason'] }}</p>
-                                <button class="w-full text-xs bg-indigo-600 text-white py-2 px-3 rounded-md hover:bg-indigo-700 transition-colors">
-                                    生成学习路径
-                                </button>
-                            </div>
-                        @endforeach
-                    </div>
-                </div>
-            </div>
-        @endif --}}
-
     </div>
 </div>
 @endif