mistake-book-panel.blade.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. @props(['data' => [], 'studentId' => '', 'teacherId' => ''])
  2. @php
  3. $stats = $data['stats'] ?? [];
  4. $recent = $data['recent'] ?? [];
  5. $weakSkills = $data['weak_skills'] ?? [];
  6. $weakKps = $data['weak_kps'] ?? [];
  7. $errorTypes = $data['error_types'] ?? [];
  8. @endphp
  9. <div class="bg-white shadow-sm rounded-xl border border-gray-200">
  10. <div class="px-6 py-5 border-b border-gray-100 flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
  11. <div>
  12. <p class="text-sm text-slate-500 mb-1">MistakeBook</p>
  13. <h3 class="text-xl font-semibold text-slate-900">错题本速览</h3>
  14. <p class="text-sm text-slate-500">最近错题 · 易错技能 · 薄弱知识点</p>
  15. </div>
  16. <div class="flex flex-wrap gap-2">
  17. <a
  18. href="{{ url('/admin/mistake-book') }}{{ $studentId ? ('?student_id=' . $studentId . ($teacherId ? '&teacher_id=' . $teacherId : '')) : '' }}{{ !$studentId && $teacherId ? ('?teacher_id=' . $teacherId) : '' }}"
  19. class="btn btn-primary btn-sm"
  20. target="_blank"
  21. >
  22. 打开错题本
  23. </a>
  24. </div>
  25. </div>
  26. <div class="px-6 py-5 space-y-4">
  27. <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3">
  28. <div class="stat bg-slate-50 rounded-lg border border-slate-200">
  29. <div class="stat-title text-slate-500">总错题</div>
  30. <div class="stat-value text-slate-900 text-2xl">{{ $stats['total'] ?? 0 }}</div>
  31. </div>
  32. <div class="stat bg-slate-50 rounded-lg border border-slate-200">
  33. <div class="stat-title text-slate-500">本周错题</div>
  34. <div class="stat-value text-amber-600 text-2xl">{{ $stats['this_week'] ?? 0 }}</div>
  35. </div>
  36. <div class="stat bg-slate-50 rounded-lg border border-slate-200">
  37. <div class="stat-title text-slate-500">待复习</div>
  38. <div class="stat-value text-indigo-600 text-2xl">{{ $stats['pending_review'] ?? 0 }}</div>
  39. </div>
  40. <div class="stat bg-slate-50 rounded-lg border border-slate-200">
  41. <div class="stat-title text-slate-500">掌握率</div>
  42. <div class="stat-value text-emerald-600 text-2xl">
  43. {{ isset($stats['mastery_rate']) ? number_format($stats['mastery_rate'] * 100, 1) . '%' : '--' }}
  44. </div>
  45. </div>
  46. </div>
  47. <div class="grid grid-cols-1 lg:grid-cols-3 gap-4">
  48. <div class="lg:col-span-1 bg-slate-50 border border-slate-200 rounded-lg p-4">
  49. <div class="flex items-center justify-between mb-3">
  50. <h4 class="font-semibold text-slate-800">最近错题</h4>
  51. <span class="badge badge-ghost">最新</span>
  52. </div>
  53. <div class="space-y-3">
  54. @forelse(array_slice($recent, 0, 4) as $item)
  55. <div class="p-3 bg-white rounded-lg border border-slate-200">
  56. <div class="flex items-center justify-between">
  57. <p class="text-xs text-slate-400">{{ $item['created_at'] ?? '' }}</p>
  58. @if(!empty($item['error_type']))
  59. <span class="badge badge-warning badge-outline">{{ $item['error_type'] }}</span>
  60. @endif
  61. </div>
  62. <p class="text-sm text-slate-800 mt-1">
  63. {{ \Illuminate\Support\Str::limit(strip_tags($item['question']['stem'] ?? $item['question']['content'] ?? '错题'), 80) }}
  64. </p>
  65. @if(!empty($item['kp_ids']))
  66. <div class="flex flex-wrap gap-1 mt-2">
  67. @foreach(array_slice($item['kp_ids'], 0, 2) as $kp)
  68. <span class="badge badge-ghost">KP {{ $kp }}</span>
  69. @endforeach
  70. </div>
  71. @endif
  72. </div>
  73. @empty
  74. <p class="text-sm text-slate-500">暂无错题记录</p>
  75. @endforelse
  76. </div>
  77. </div>
  78. <div class="bg-slate-50 border border-slate-200 rounded-lg p-4">
  79. <div class="flex items-center justify-between mb-3">
  80. <h4 class="font-semibold text-slate-800">本周易错技能</h4>
  81. <span class="badge badge-warning badge-outline">Top</span>
  82. </div>
  83. <div class="space-y-2">
  84. @forelse(array_slice($weakSkills, 0, 4) as $skill)
  85. @php
  86. $score = $skill['score'] ?? $skill['count'] ?? 0;
  87. $score = is_numeric($score) ? (float) $score : 0;
  88. @endphp
  89. <div>
  90. <div class="flex items-center justify-between text-sm text-slate-700">
  91. <span>{{ $skill['name'] ?? ($skill['skill'] ?? '技能') }}</span>
  92. <span class="text-xs text-slate-500">{{ $score }}</span>
  93. </div>
  94. <progress class="progress progress-warning w-full" value="{{ min(100, $score * 10) }}" max="100"></progress>
  95. </div>
  96. @empty
  97. <p class="text-sm text-slate-500">暂无技能数据</p>
  98. @endforelse
  99. </div>
  100. </div>
  101. <div class="bg-slate-50 border border-slate-200 rounded-lg p-4">
  102. <div class="flex items-center justify-between mb-3">
  103. <h4 class="font-semibold text-slate-800">薄弱知识点 Top 5</h4>
  104. <span class="badge badge-error badge-outline">KP</span>
  105. </div>
  106. <div class="space-y-2">
  107. @forelse(array_slice($weakKps, 0, 5) as $kp)
  108. @php
  109. $score = $kp['score'] ?? $kp['mistake_count'] ?? $kp['count'] ?? 0;
  110. $score = is_numeric($score) ? (float) $score : 0;
  111. @endphp
  112. <div class="flex items-center justify-between">
  113. <div>
  114. <p class="text-sm font-medium text-slate-800">{{ $kp['name'] ?? ($kp['kp'] ?? $kp['kp_code'] ?? '知识点') }}</p>
  115. <p class="text-xs text-slate-500">{{ $kp['kp_code'] ?? $kp['kp'] ?? '' }}</p>
  116. </div>
  117. <div class="text-right">
  118. <p class="text-sm text-slate-700">错误 {{ $kp['mistake_count'] ?? $kp['count'] ?? 0 }}</p>
  119. <div class="w-28 bg-slate-200 h-1.5 rounded-full mt-1">
  120. <div class="h-1.5 rounded-full bg-red-500" style="width: {{ min(100, (1 - min($score, 1)) * 100) }}%"></div>
  121. </div>
  122. </div>
  123. </div>
  124. @empty
  125. <p class="text-sm text-slate-500">暂无知识点数据</p>
  126. @endforelse
  127. </div>
  128. </div>
  129. </div>
  130. <div class="bg-slate-50 border border-slate-200 rounded-lg p-4">
  131. <div class="flex items-center justify-between">
  132. <h4 class="font-semibold text-slate-800">错误类型分布</h4>
  133. <span class="badge badge-ghost">AI</span>
  134. </div>
  135. <div class="flex flex-wrap gap-2 mt-3">
  136. @forelse($errorTypes as $error)
  137. <span class="badge badge-outline">
  138. {{ $error['name'] ?? $error['type'] ?? '错误' }} · {{ $error['count'] ?? $error['value'] ?? 0 }}
  139. </span>
  140. @empty
  141. <p class="text-sm text-slate-500">暂无错误类型数据</p>
  142. @endforelse
  143. </div>
  144. </div>
  145. </div>
  146. </div>