|
|
@@ -7,6 +7,7 @@ use App\Filament\Traits\HasUserRole;
|
|
|
use App\Models\Student;
|
|
|
use App\Models\Teacher;
|
|
|
use App\Services\KnowledgeMasteryService;
|
|
|
+use App\Services\LearningAnalyticsService;
|
|
|
use App\Services\MasteryCalculator;
|
|
|
use BackedEnum;
|
|
|
use Filament\Pages\Page;
|
|
|
@@ -23,9 +24,7 @@ use App\Services\MistakeBookService;
|
|
|
|
|
|
class StudentDashboard extends Page
|
|
|
{
|
|
|
- use HasUserRole, HandlesMindmapDetails;
|
|
|
-
|
|
|
- use \Filament\Pages\Concerns\InteractsWithFormActions;
|
|
|
+ use HasUserRole, HandlesMindmapDetails, \Filament\Pages\Concerns\InteractsWithFormActions;
|
|
|
|
|
|
protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-chart-bar';
|
|
|
|
|
|
@@ -240,10 +239,18 @@ class StudentDashboard extends Page
|
|
|
$recommendations = $service->recommendLearningPaths($this->studentId, 3);
|
|
|
|
|
|
// 组合数据
|
|
|
+ $masteryList = $service->getStudentMasteryList($this->studentId);
|
|
|
+
|
|
|
+ // 如果没有掌握度数据,从错题记录中生成基于错题的掌握度
|
|
|
+ if (empty($masteryList['data'] ?? [])) {
|
|
|
+ Log::info('未找到掌握度数据,从错题记录生成', ['student_id' => $this->studentId]);
|
|
|
+ $masteryList = $this->generateMasteryFromMistakes($this->studentId);
|
|
|
+ }
|
|
|
+
|
|
|
$this->dashboardData = [
|
|
|
'mastery' => [
|
|
|
'overview' => $masteryOverview,
|
|
|
- 'list' => $service->getStudentMasteryList($this->studentId),
|
|
|
+ 'list' => $masteryList,
|
|
|
],
|
|
|
'skill' => [
|
|
|
'proficiency' => $skillProficiency,
|
|
|
@@ -424,4 +431,160 @@ class StudentDashboard extends Page
|
|
|
$this->studentId = $studentId;
|
|
|
$this->loadDashboardData();
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从错题记录生成掌握度数据
|
|
|
+ */
|
|
|
+ private function generateMasteryFromMistakes(string $studentId): array
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ // 获取学生的错题记录
|
|
|
+ $mistakeRecords = \App\Models\MistakeRecord::forStudent($studentId)
|
|
|
+ ->get(['kp_ids', 'knowledge_point', 'is_corrected', 'review_status']);
|
|
|
+
|
|
|
+ // 统计每个知识点的错题数量
|
|
|
+ $kpStats = [];
|
|
|
+ foreach ($mistakeRecords as $record) {
|
|
|
+ $kpIds = $record->kp_ids ?? [];
|
|
|
+ if (is_string($kpIds)) {
|
|
|
+ $kpIds = json_decode($kpIds, true) ?? [];
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach ($kpIds as $kpCode) {
|
|
|
+ if (empty($kpCode)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!isset($kpStats[$kpCode])) {
|
|
|
+ $kpStats[$kpCode] = [
|
|
|
+ 'kp_code' => $kpCode,
|
|
|
+ 'kp_name' => $record->knowledge_point ?? $kpCode,
|
|
|
+ 'mistake_count' => 0,
|
|
|
+ 'corrected_count' => 0,
|
|
|
+ 'mastery_level' => 0.0,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ $kpStats[$kpCode]['mistake_count']++;
|
|
|
+ if ($record->is_corrected) {
|
|
|
+ $kpStats[$kpCode]['corrected_count']++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算掌握度(基于错题数量和纠正情况)
|
|
|
+ $masteryData = [];
|
|
|
+ foreach ($kpStats as $kpCode => $stats) {
|
|
|
+ $total = $stats['mistake_count'];
|
|
|
+ $corrected = $stats['corrected_count'];
|
|
|
+
|
|
|
+ // 掌握度计算:已纠正的题目比例 + 基础分数
|
|
|
+ // 如果全部纠正,掌握度较高;如果有未纠正的,掌握度较低
|
|
|
+ $masteryLevel = $total > 0
|
|
|
+ ? ($corrected / $total) * 0.7 + 0.1 // 基础分数0.1,最高0.8
|
|
|
+ : 0.5; // 默认中等掌握度
|
|
|
+
|
|
|
+ // 确保掌握度在合理范围内
|
|
|
+ $masteryLevel = max(0.1, min(0.9, $masteryLevel));
|
|
|
+
|
|
|
+ $masteryData[] = [
|
|
|
+ 'kp_code' => $kpCode,
|
|
|
+ 'kp_name' => $stats['kp_name'],
|
|
|
+ 'mastery_level' => round($masteryLevel, 2),
|
|
|
+ 'total_attempts' => $total,
|
|
|
+ 'correct_attempts' => $corrected,
|
|
|
+ 'accuracy_rate' => $total > 0 ? round($corrected / $total, 2) : 0,
|
|
|
+ 'trend' => $corrected >= ($total * 0.5) ? 'improving' : 'needs_attention',
|
|
|
+ 'last_attempt' => now()->toISOString(),
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ Log::info('从错题记录生成掌握度数据', [
|
|
|
+ 'student_id' => $studentId,
|
|
|
+ 'kp_count' => count($masteryData),
|
|
|
+ 'mastery_data' => $masteryData
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // 为生成的掌握度数据创建快照记录
|
|
|
+ $this->createMasterySnapshots($studentId, $masteryData);
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'student_id' => $studentId,
|
|
|
+ 'total_count' => count($masteryData),
|
|
|
+ 'data' => $masteryData,
|
|
|
+ ];
|
|
|
+
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ Log::error('从错题记录生成掌握度失败', [
|
|
|
+ 'student_id' => $studentId,
|
|
|
+ 'error' => $e->getMessage()
|
|
|
+ ]);
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'student_id' => $studentId,
|
|
|
+ 'total_count' => 0,
|
|
|
+ 'data' => [],
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建掌握度快照记录
|
|
|
+ */
|
|
|
+ private function createMasterySnapshots(string $studentId, array $masteryData): void
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ // 计算整体掌握度
|
|
|
+ $totalPoints = count($masteryData);
|
|
|
+ $averageMastery = $totalPoints > 0
|
|
|
+ ? array_sum(array_column($masteryData, 'mastery_level')) / $totalPoints
|
|
|
+ : 0;
|
|
|
+
|
|
|
+ // 统计强弱知识点数量
|
|
|
+ $weakCount = 0;
|
|
|
+ $strongCount = 0;
|
|
|
+ foreach ($masteryData as $data) {
|
|
|
+ $level = floatval($data['mastery_level']);
|
|
|
+ if ($level >= 0.7) {
|
|
|
+ $strongCount++;
|
|
|
+ } elseif ($level < 0.5) {
|
|
|
+ $weakCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 生成快照ID
|
|
|
+ $snapshotId = 'auto_' . $studentId . '_' . time();
|
|
|
+
|
|
|
+ // 创建快照记录
|
|
|
+ DB::table('knowledge_point_mastery_snapshots')->insert([
|
|
|
+ 'snapshot_id' => $snapshotId,
|
|
|
+ 'student_id' => $studentId,
|
|
|
+ 'paper_id' => null, // 自动生成,没有关联试卷
|
|
|
+ 'answer_record_id' => null,
|
|
|
+ 'mastery_data' => json_encode($masteryData),
|
|
|
+ 'overall_mastery' => round($averageMastery, 4),
|
|
|
+ 'weak_knowledge_points_count' => $weakCount,
|
|
|
+ 'strong_knowledge_points_count' => $strongCount,
|
|
|
+ 'snapshot_time' => now(),
|
|
|
+ 'analysis_id' => null,
|
|
|
+ 'created_at' => now(),
|
|
|
+ 'updated_at' => now(),
|
|
|
+ ]);
|
|
|
+
|
|
|
+ Log::info('创建掌握度快照', [
|
|
|
+ 'student_id' => $studentId,
|
|
|
+ 'snapshot_id' => $snapshotId,
|
|
|
+ 'total_knowledge_points' => $totalPoints,
|
|
|
+ 'average_mastery' => $averageMastery,
|
|
|
+ 'weak_count' => $weakCount,
|
|
|
+ 'strong_count' => $strongCount,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ Log::error('创建掌握度快照失败', [
|
|
|
+ 'student_id' => $studentId,
|
|
|
+ 'error' => $e->getMessage()
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|