mistake-book.blade.php.backup 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. <div class="min-h-screen bg-gray-50 p-8">
  2. {{-- 页面标题区域 --}}
  3. <div class="mb-8">
  4. <div class="bg-white rounded-xl shadow-sm p-6 border border-gray-200">
  5. <div class="flex items-center justify-between mb-6">
  6. <div>
  7. <h1 class="text-3xl font-bold text-gray-900 flex items-center">
  8. <svg class="w-8 h-8 mr-3 text-indigo-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  9. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path>
  10. </svg>
  11. 错题本
  12. </h1>
  13. <p class="mt-2 text-sm text-gray-600 ml-11">查看学生错题记录与AI分析,生成针对性练习</p>
  14. </div>
  15. </div>
  16. {{-- 选择器区域 --}}
  17. <div class="bg-gray-50 rounded-lg p-4 border border-gray-200">
  18. <div class="flex flex-col gap-3 lg:flex-row lg:items-center">
  19. @if(!$this->isTeacher)
  20. <div class="form-control w-full lg:flex-1">
  21. <label class="label"><span class="label-text font-medium">选择老师</span></label>
  22. <select wire:model.live="teacherId" class="select select-bordered w-full h-11">
  23. <option value="">请选择老师...</option>
  24. @foreach($this->teachers as $teacher)
  25. <option value="{{ $teacher->teacher_id }}">
  26. {{ trim($teacher->name ?? $teacher->teacher_id) . ($teacher->subject ? " ({$teacher->subject})" : '') }}
  27. </option>
  28. @endforeach
  29. </select>
  30. </div>
  31. @endif
  32. <div class="form-control w-full lg:flex-1">
  33. <label class="label"><span class="label-text font-medium">选择学生</span></label>
  34. <select wire:model.live="studentId" class="select select-bordered w-full h-11" @if(empty($teacherId)) disabled @endif>
  35. <option value="">{{ empty($teacherId) ? '请先选择老师' : '请选择学生...' }}</option>
  36. @foreach($this->students as $student)
  37. <option value="{{ $student->student_id }}">
  38. {{ trim($student->name ?? $student->student_id) . " ({$student->grade} - {$student->class_name})" }}
  39. </option>
  40. @endforeach
  41. </select>
  42. </div>
  43. <div class="w-full lg:w-auto flex items-center lg:pt-6">
  44. <button wire:click="loadMistakeData" wire:loading.attr="disabled"
  45. 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">
  46. <svg wire:loading class="animate-spin -ml-1 mr-2 h-4 w-4 text-white" fill="none" viewBox="0 0 24 24">
  47. <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
  48. <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>
  49. </svg>
  50. 刷新数据
  51. </button>
  52. </div>
  53. </div>
  54. </div>
  55. </div>
  56. </div>
  57. {{-- 错误提示 --}}
  58. @if ($errorMessage)
  59. <div class="mb-8">
  60. <div class="bg-red-50 border border-red-200 rounded-xl p-4">
  61. <div class="flex items-start">
  62. <svg class="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor">
  63. <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd" />
  64. </svg>
  65. <div class="ml-3">
  66. <h3 class="text-sm font-medium text-red-800">加载错误</h3>
  67. <p class="mt-1 text-sm text-red-700">{{ $errorMessage }}</p>
  68. </div>
  69. </div>
  70. </div>
  71. </div>
  72. @endif
  73. @if ($actionMessage)
  74. <div class="mb-8">
  75. <div class="bg-green-50 border border-green-200 rounded-xl p-4">
  76. <p class="text-sm text-green-700">{{ $actionMessage }}</p>
  77. </div>
  78. </div>
  79. @endif
  80. {{-- 学习状态概览 --}}
  81. <div class="mb-8">
  82. <div class="grid grid-cols-1 gap-6 lg:grid-cols-3">
  83. {{-- 今日必复习 --}}
  84. <div class="lg:col-span-2 bg-gradient-to-br from-indigo-500 to-purple-600 rounded-xl shadow-sm p-6 text-white">
  85. <div class="flex items-center justify-between mb-4">
  86. <h3 class="text-lg font-semibold">今日必复习</h3>
  87. <span class="bg-white/20 px-3 py-1 rounded-full text-sm">
  88. {{ count($mistakes) }} 道错题
  89. </span>
  90. </div>
  91. <div class="space-y-3">
  92. @php
  93. $urgentMistakes = collect($mistakes)->take(3);
  94. @endphp
  95. @if($urgentMistakes->isNotEmpty())
  96. @foreach($urgentMistakes as $mistake)
  97. @php
  98. $daysSince = $mistake['created_at'] ? \Carbon\Carbon::parse($mistake['created_at'])->diffInDays(now()) : 0;
  99. $urgency = $daysSince > 7 ? 'high' : ($daysSince > 3 ? 'medium' : 'low');
  100. @endphp
  101. <div class="bg-white/10 backdrop-blur rounded-lg p-4 hover:bg-white/20 transition-colors cursor-pointer">
  102. <!-- 题目标签 -->
  103. @php
  104. $hasValidInfo = false;
  105. $tags = [];
  106. @endphp
  107. @if(!empty($mistake['question']['question_number']))
  108. @php
  109. $hasValidInfo = true;
  110. $tags[] = '第' . $mistake['question']['question_number'] . '题';
  111. @endif
  112. @if(!empty($mistake['question']['kp_code']))
  113. @php
  114. $hasValidInfo = true;
  115. $kpName = $knowledgePointOptions[$mistake['question']['kp_code']] ?? $mistake['question']['kp_code'];
  116. if($kpName && $kpName !== $mistake['question']['kp_code']) {
  117. $tags[] = $kpName;
  118. }
  119. @endif
  120. @if(!empty($mistake['error_type']))
  121. @php
  122. $hasValidInfo = true;
  123. $tags[] = $mistake['error_type'];
  124. @endif
  125. @if($hasValidInfo && !empty($tags))
  126. <div class="flex flex-wrap gap-1.5 mb-2">
  127. @foreach($tags as $tag)
  128. <span class="text-xs bg-white/20 px-2 py-0.5 rounded">{{ $tag }}</span>
  129. @endforeach
  130. </div>
  131. @endif
  132. <!-- 完整题干 -->
  133. <div class="mb-3">
  134. <p class="text-sm leading-relaxed">
  135. {{ $mistake['question']['stem'] ?? '暂无题干' }}
  136. </p>
  137. </div>
  138. <!-- 底部按钮 -->
  139. <div class="flex justify-end">
  140. <button class="text-xs bg-white/20 hover:bg-white/30 px-3 py-1 rounded transition-colors">
  141. 查看详情
  142. </button>
  143. </div>
  144. </div>
  145. @endforeach
  146. @else
  147. <div class="text-center py-8 text-white/80">
  148. <svg class="w-16 h-16 mx-auto mb-4 text-white/50" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  149. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
  150. </svg>
  151. <p class="text-sm">暂无错题数据</p>
  152. <p class="text-xs mt-1 text-white/60">请先选择学生并刷新数据</p>
  153. </div>
  154. @endif
  155. </div>
  156. @if($urgentMistakes->isNotEmpty())
  157. <div class="mt-4 pt-4 border-t border-white/20">
  158. <button wire:click="startQuickReview"
  159. class="w-full bg-white text-indigo-600 px-4 py-2 rounded-lg text-sm font-medium hover:bg-gray-50 transition-colors">
  160. 开始快速复习 (前5题)
  161. </button>
  162. </div>
  163. @endif
  164. </div>
  165. {{-- 学习进度 --}}
  166. <div class="bg-white rounded-xl shadow-sm p-6 border border-gray-200">
  167. <h3 class="text-lg font-semibold text-gray-900 mb-4">学习进度</h3>
  168. <!-- 掌握度显示 -->
  169. <div class="mb-6">
  170. <div class="flex items-center justify-between mb-2">
  171. <span class="text-sm text-gray-600">整体掌握度</span>
  172. <span class="text-xs text-gray-500">基于所有知识点平均</span>
  173. </div>
  174. <div class="relative">
  175. <div class="w-full bg-gray-200 rounded-full h-3">
  176. @php
  177. $masteryRate = $summary['mastery_rate'] ?? 0;
  178. $masteryPercentage = $masteryRate * 100;
  179. @endphp
  180. <div class="bg-indigo-600 h-3 rounded-full transition-all duration-500"
  181. style="width: {{ $masteryPercentage }}%"></div>
  182. </div>
  183. <p class="text-2xl font-bold text-indigo-600 mt-2 text-center">
  184. {{ number_format($masteryPercentage, 0) }}%
  185. </p>
  186. </div>
  187. </div>
  188. <!-- 统计信息 -->
  189. <div class="space-y-3">
  190. <div class="flex items-center justify-between p-3 bg-orange-50 rounded-lg">
  191. <span class="text-sm text-gray-600">待复习知识点</span>
  192. <span class="text-xl font-bold text-orange-600">{{ $summary['pending_review'] ?? 0 }}</span>
  193. </div>
  194. <div class="flex items-center justify-between p-3 bg-red-50 rounded-lg">
  195. <span class="text-sm text-gray-600">总错题数</span>
  196. <span class="text-xl font-bold text-red-600">{{ $summary['total'] ?? 0 }}</span>
  197. </div>
  198. <div class="flex items-center justify-between p-3 bg-blue-50 rounded-lg">
  199. <span class="text-sm text-gray-600">本周新增</span>
  200. <span class="text-xl font-bold text-blue-600">{{ $summary['this_week'] ?? 0 }}</span>
  201. </div>
  202. </div>
  203. </div>
  204. </div>
  205. </div>
  206. {{-- 加载状态 --}}
  207. @if ($isLoading)
  208. <div class="mb-8">
  209. <div class="bg-white rounded-xl shadow-sm p-12 border border-gray-200">
  210. <div class="flex flex-col items-center justify-center">
  211. <svg class="animate-spin h-12 w-12 text-indigo-600" fill="none" viewBox="0 0 24 24">
  212. <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
  213. <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>
  214. </svg>
  215. <p class="mt-4 text-sm text-gray-600">正在加载数据,请稍候...</p>
  216. </div>
  217. </div>
  218. </div>
  219. @else
  220. {{-- 主内容区域 --}}
  221. <div class="grid grid-cols-1 gap-6 xl:grid-cols-4">
  222. {{-- 左侧筛选 --}}
  223. <div class="xl:col-span-1">
  224. <div class="bg-white shadow-sm rounded-xl border border-gray-200 sticky top-4">
  225. <div class="px-6 py-5 border-b border-gray-100">
  226. <div class="flex items-center justify-between">
  227. <h3 class="text-lg font-semibold text-gray-900">筛选条件</h3>
  228. @if(!empty($filters['error_types']) || !empty($filters['kp_ids']) || !empty($filters['skill_ids']))
  229. <button wire:click="clearFilters"
  230. class="text-sm text-indigo-600 hover:text-indigo-700 transition-colors">
  231. 清除全部
  232. </button>
  233. @endif
  234. </div>
  235. </div>
  236. <div class="p-6 space-y-6">
  237. {{-- 快速排序 --}}
  238. <div>
  239. <label class="text-sm font-medium text-gray-700 mb-3 block">快速排序</label>
  240. <select wire:model.live="filters.sort_by"
  241. class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
  242. <option value="created_at_desc">最近错题</option>
  243. <option value="urgency_desc">紧急优先</option>
  244. <option value="score_asc">得分最低</option>
  245. <option value="created_at_asc">最早错题</option>
  246. </select>
  247. </div>
  248. {{-- 正确与否筛选 --}}
  249. <div>
  250. <label class="text-sm font-medium text-gray-700 mb-3 block">正确情况</label>
  251. <div class="space-y-2">
  252. <label class="flex items-center gap-3 cursor-pointer p-2 rounded-lg hover:bg-gray-50">
  253. <input type="radio" name="correct_filter" value="all"
  254. wire:model="filters.correct_filter"
  255. class="w-4 h-4 border-gray-300 text-indigo-600 focus:ring-indigo-500">
  256. <span class="text-sm text-gray-700">全部题目</span>
  257. </label>
  258. <label class="flex items-center gap-3 cursor-pointer p-2 rounded-lg hover:bg-gray-50">
  259. <input type="radio" name="correct_filter" value="incorrect"
  260. wire:model="filters.correct_filter"
  261. class="w-4 h-4 border-gray-300 text-indigo-600 focus:ring-indigo-500">
  262. <span class="text-sm text-gray-700">仅错误题目</span>
  263. </label>
  264. <label class="flex items-center gap-3 cursor-pointer p-2 rounded-lg hover:bg-gray-50">
  265. <input type="radio" name="correct_filter" value="correct"
  266. wire:model="filters.correct_filter"
  267. class="w-4 h-4 border-gray-300 text-indigo-600 focus:ring-indigo-500">
  268. <span class="text-sm text-gray-700">仅正确题目</span>
  269. </label>
  270. </div>
  271. </div>
  272. {{-- 状态筛选 --}}
  273. <div>
  274. <label class="text-sm font-medium text-gray-700 mb-3 block">状态</label>
  275. <div class="flex gap-2">
  276. <button wire:click="toggleFilter('filter', 'unreviewed')"
  277. class="flex-1 px-3 py-2 text-xs font-medium rounded-lg transition-colors
  278. {{ in_array('unreviewed', $filters['filter'] ?? []) ? 'bg-orange-100 text-orange-700 ring-2 ring-orange-200' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' }}">
  279. 未复习
  280. </button>
  281. <button wire:click="toggleFilter('filter', 'favorite')"
  282. class="flex-1 px-3 py-2 text-xs font-medium rounded-lg transition-colors
  283. {{ in_array('favorite', $filters['filter'] ?? []) ? 'bg-yellow-100 text-yellow-700 ring-2 ring-yellow-200' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' }}">
  284. 已收藏
  285. </button>
  286. </div>
  287. </div>
  288. {{-- 时间范围 --}}
  289. <div>
  290. <label class="text-sm font-medium text-gray-700 mb-3 block">时间范围</label>
  291. <div class="grid grid-cols-3 gap-2">
  292. <button wire:click="$set('filters.time_range', 'last_7')"
  293. class="px-3 py-2 text-xs font-medium rounded-lg transition-colors {{ $filters['time_range'] === 'last_7' ? 'bg-indigo-600 text-white' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' }}">
  294. 7天
  295. </button>
  296. <button wire:click="$set('filters.time_range', 'last_30')"
  297. class="px-3 py-2 text-xs font-medium rounded-lg transition-colors {{ $filters['time_range'] === 'last_30' ? 'bg-indigo-600 text-white' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' }}">
  298. 30天
  299. </button>
  300. <button wire:click="$set('filters.time_range', 'all')"
  301. class="px-3 py-2 text-xs font-medium rounded-lg transition-colors {{ $filters['time_range'] === 'all' ? 'bg-indigo-600 text-white' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' }}">
  302. 全部
  303. </button>
  304. </div>
  305. </div>
  306. {{-- 错误类型 --}}
  307. <div>
  308. <label class="text-sm font-medium text-gray-700 mb-3 block">错误类型</label>
  309. <div class="space-y-2 max-h-48 overflow-y-auto">
  310. @foreach(['计算错误', '概念错误', '方法错误', '审题错误', '步骤缺失', '书写不规范'] as $type)
  311. <label class="flex items-center gap-3 cursor-pointer p-2 rounded-lg hover:bg-gray-50">
  312. <input type="checkbox" value="{{ $type }}" wire:model="filters.error_types"
  313. class="w-4 h-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500">
  314. <span class="text-sm text-gray-700">{{ $type }}</span>
  315. </label>
  316. @endforeach
  317. </div>
  318. </div>
  319. <!-- 应用筛选按钮 -->
  320. <div class="pt-4 border-t border-gray-100 space-y-2">
  321. <button wire:click="applyFilters"
  322. class="w-full px-4 py-2.5 bg-indigo-600 text-white text-sm font-medium rounded-lg hover:bg-indigo-700 transition-colors">
  323. 应用筛选
  324. </button>
  325. <button wire:click="resetFilters"
  326. class="w-full px-4 py-2 bg-gray-100 text-gray-700 text-sm font-medium rounded-lg hover:bg-gray-200 transition-colors">
  327. 重置
  328. </button>
  329. </div>
  330. </div>
  331. </div>
  332. </div>
  333. {{-- 右侧错题列表 --}}
  334. <div class="xl:col-span-3 space-y-6">
  335. {{-- 错题列表 --}}
  336. <div class="bg-white shadow-sm rounded-xl border border-gray-200">
  337. <div class="px-6 py-5 border-b border-gray-100 flex items-center justify-between">
  338. <h3 class="text-lg font-semibold text-gray-900 flex items-center">
  339. <svg class="w-5 h-5 mr-2 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  340. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path>
  341. </svg>
  342. 错题列表 ({{ $total }})
  343. </h3>
  344. <div class="flex items-center gap-3">
  345. @if(!empty($selectedMistakeIds))
  346. <div class="flex items-center gap-2">
  347. <button wire:click="generatePracticeFromSelection"
  348. class="inline-flex items-center px-4 py-2 bg-green-600 text-white text-sm font-medium rounded-lg hover:bg-green-700 transition-colors">
  349. 生成练习 ({{ count($selectedMistakeIds) }})
  350. </button>
  351. <button wire:click="batchMarkReviewed"
  352. class="inline-flex items-center px-4 py-2 bg-blue-600 text-white text-sm font-medium rounded-lg hover:bg-blue-700 transition-colors">
  353. 批量标记已复习
  354. </button>
  355. </div>
  356. @endif
  357. @if(!empty($mistakes) && empty($selectedMistakeIds))
  358. <button wire:click="startQuickReview"
  359. class="inline-flex items-center px-4 py-2 bg-indigo-600 text-white text-sm font-medium rounded-lg hover:bg-indigo-700 transition-colors">
  360. <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  361. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
  362. </svg>
  363. 快速复习 (前5题)
  364. </button>
  365. @endif
  366. </div>
  367. </div>
  368. <div class="p-6">
  369. @if(empty($mistakes))
  370. <div class="text-center py-12">
  371. <svg class="w-16 h-16 mx-auto text-gray-300 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  372. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
  373. </svg>
  374. <p class="text-sm font-medium text-gray-900 mb-1">暂无错题数据</p>
  375. <p class="text-xs text-gray-500">请先选择学生后刷新数据</p>
  376. </div>
  377. @else
  378. <div class="space-y-4">
  379. @foreach($mistakes as $mistake)
  380. @php
  381. $urgency = 'normal';
  382. if($mistake['created_at']) {
  383. $daysSince = \Carbon\Carbon::parse($mistake['created_at'])->diffInDays(now());
  384. $urgency = $daysSince > 7 ? 'high' : ($daysSince > 3 ? 'medium' : 'low');
  385. }
  386. @endphp
  387. <div class="group border {{ $urgency === 'high' ? 'border-red-200 bg-red-50/30' : ($urgency === 'medium' ? 'border-yellow-200 bg-yellow-50/20' : 'border-gray-200') }} rounded-xl hover:shadow-lg transition-all duration-200" wire:key="m-{{ $mistake['id'] ?? $loop->index }}">
  388. {{-- 错题卡片头部 - 紧凑布局 --}}
  389. <div class="p-4">
  390. <div class="flex items-start gap-3">
  391. {{-- 复选框和紧急度指示器 --}}
  392. <div class="flex items-center gap-2 pt-1">
  393. @if($urgency !== 'normal')
  394. <span class="w-2 h-2 rounded-full
  395. @if($urgency === 'high') bg-red-500
  396. @elseif($urgency === 'medium') bg-yellow-500
  397. @endif
  398. animate-pulse" title="{{ $urgency === 'high' ? '急需复习' : '建议复习' }}"></span>
  399. @endif
  400. <input type="checkbox"
  401. wire:click="toggleSelection('{{ $mistake['id'] ?? '' }}')"
  402. @checked(in_array($mistake['id'] ?? '', $selectedMistakeIds, true))
  403. class="w-4 h-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500">
  404. </div>
  405. {{-- 主要信息区域 --}}
  406. <div class="flex-1 min-w-0">
  407. <!-- 顶部信息行 -->
  408. <div class="flex items-center justify-between mb-2">
  409. <div class="flex items-center gap-2">
  410. <span class="text-xs font-mono text-gray-500">#{{ $mistake['id'] ?? '' }}</span>
  411. @if(!empty($mistake['question']['question_number']))
  412. <span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
  413. 第{{ $mistake['question']['question_number'] }}题
  414. </span>
  415. @endif
  416. <!-- 得分率已移除 -->
  417. </div>
  418. <div class="flex items-center gap-2">
  419. @php
  420. $createdAt = $mistake['created_at'] ?? null;
  421. if ($createdAt) {
  422. try {
  423. $date = \Carbon\Carbon::parse($createdAt);
  424. echo '<span class="text-xs text-gray-500">' . $date->diffForHumans() . '</span>';
  425. } catch (\Exception $e) {
  426. echo '<span class="text-xs text-gray-500">' . $createdAt . '</span>';
  427. }
  428. }
  429. @endphp
  430. <!-- 快速操作按钮 -->
  431. <div class="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
  432. <button wire:click="toggleFavorite('{{ $mistake['id'] ?? '' }}')"
  433. class="p-1.5 rounded hover:bg-gray-100 transition-colors"
  434. title="{{ !empty($mistake['favorite']) ? '取消收藏' : '收藏' }}">
  435. <svg class="w-4 h-4 {{ !empty($mistake['favorite']) ? 'text-yellow-500 fill-current' : 'text-gray-400' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  436. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"></path>
  437. </svg>
  438. </button>
  439. <button wire:click="markReviewed('{{ $mistake['id'] ?? '' }}')"
  440. class="p-1.5 rounded hover:bg-gray-100 transition-colors"
  441. title="{{ !empty($mistake['reviewed']) ? '取消复习标记' : '标记为已复习' }}">
  442. <svg class="w-4 h-4 {{ !empty($mistake['reviewed']) ? 'text-green-500 fill-current' : 'text-gray-400' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  443. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
  444. </svg>
  445. </button>
  446. </div>
  447. </div>
  448. </div>
  449. <!-- 题目预览 -->
  450. @if(!empty($mistake['question']['stem']))
  451. <div class="mb-3">
  452. <p class="text-sm text-gray-900 line-clamp-2 leading-relaxed">
  453. {{ \Illuminate\Support\Str::limit(strip_tags($mistake['question']['stem']), 150) }}
  454. </p>
  455. </div>
  456. @endif
  457. <!-- 标签行 -->
  458. <div class="flex flex-wrap items-center gap-1.5 mb-3">
  459. @if(!empty($mistake['question']['kp_code']))
  460. <a href="{{ url('/admin/knowledge-point-detail') }}?kp_code={{ urlencode($mistake['question']['kp_code']) }}"
  461. class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-indigo-100 text-indigo-700 hover:bg-indigo-200 transition-colors">
  462. {{ $knowledgePointOptions[$mistake['question']['kp_code']] ?? $mistake['question']['kp_code'] }}
  463. </a>
  464. @endif
  465. @if(!empty($mistake['error_type']))
  466. <span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-red-100 text-red-700">
  467. {{ $mistake['error_type'] }}
  468. </span>
  469. @endif
  470. @if(!empty($mistake['mistake_category']))
  471. <span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-orange-100 text-orange-700">
  472. {{ $mistake['mistake_category'] }}
  473. </span>
  474. @endif
  475. @php
  476. $skillIds = $mistake['skill_ids'] ?? [];
  477. if (is_array($skillIds) && !empty($skillIds)) {
  478. $validSkills = array_filter($skillIds, function($id) {
  479. return $id && $id !== '无' && $id !== 'none' && $id !== null;
  480. });
  481. if (!empty($validSkills)) {
  482. foreach(array_slice($validSkills, 0, 2) as $skillId):
  483. ?>
  484. <span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-teal-100 text-teal-700">
  485. {{ $skillId }}
  486. </span>
  487. @php
  488. endforeach;
  489. }
  490. }
  491. ?>
  492. </div>
  493. <!-- 作答对比 - 紧凑展示 -->
  494. <div class="grid grid-cols-2 gap-3 mb-3 text-sm">
  495. @if(!empty($mistake['student_answer']) && trim($mistake['student_answer']) !== '' && trim($mistake['student_answer']) !== '未作答')
  496. <div class="bg-red-50 rounded-lg p-3 border border-red-100">
  497. <p class="text-xs font-medium text-red-600 mb-1 flex items-center">
  498. <svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  499. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.728-.833-2.498 0L4.316 16.5c-.77.833.192 2.5 1.732 2.5z"></path>
  500. </svg>
  501. 你的答案
  502. </p>
  503. <p class="text-gray-900 line-clamp-2">{{ $mistake['student_answer'] }}</p>
  504. </div>
  505. @endif
  506. @if(!empty($mistake['question']['answer']))
  507. <div class="bg-green-50 rounded-lg p-3 border border-green-100">
  508. <p class="text-xs font-medium text-green-600 mb-1 flex items-center">
  509. <svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  510. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
  511. </svg>
  512. 正确答案
  513. </p>
  514. <p class="text-gray-900 line-clamp-2">{{ $mistake['question']['answer'] }}</p>
  515. </div>
  516. @endif
  517. </div>
  518. <!-- AI分析预览 -->
  519. @if(!empty($mistake['ai_analysis']['reason']))
  520. <div class="bg-amber-50 rounded-lg p-3 border border-amber-100">
  521. <p class="text-xs font-medium text-amber-700 mb-1">AI分析</p>
  522. <p class="text-sm text-gray-700 line-clamp-2">{{ $mistake['ai_analysis']['reason'] }}</p>
  523. </div>
  524. @endif
  525. </div>
  526. </div>
  527. </div>
  528. <!-- 展开区域 -->
  529. <details class="border-t border-gray-100">
  530. <summary class="px-4 py-2 text-sm text-gray-600 cursor-pointer hover:bg-gray-50 transition-colors">
  531. 查看详情与操作
  532. </summary>
  533. <div class="px-4 pb-4 space-y-4">
  534. <!-- 完整题干 -->
  535. @if(!empty($mistake['question']['stem']))
  536. <div>
  537. <p class="text-xs font-medium text-gray-500 mb-2">完整题干</p>
  538. <div class="bg-gray-50 rounded-lg p-3 border border-gray-100">
  539. <div class="prose prose-sm max-w-none text-gray-900">
  540. <x-math-render :content="$mistake['question']['stem']" />
  541. </div>
  542. </div>
  543. </div>
  544. @endif
  545. <!-- 解题步骤 -->
  546. @if(!empty($mistake['question']['solution']))
  547. <div>
  548. <p class="text-xs font-medium text-gray-500 mb-2">解题步骤</p>
  549. <div class="bg-blue-50 rounded-lg p-3 border border-blue-100">
  550. <div class="prose prose-sm max-w-none text-gray-900">
  551. {{ $mistake['question']['solution'] }}
  552. </div>
  553. </div>
  554. </div>
  555. @endif
  556. <!-- 完整AI分析 -->
  557. @if(!empty($mistake['ai_analysis']['solution']) || !empty($mistake['ai_analysis']['suggestions']))
  558. <div class="bg-amber-50 rounded-lg p-3 border border-amber-100">
  559. <p class="text-xs font-medium text-amber-700 mb-2">详细分析与建议</p>
  560. <div class="text-sm text-gray-700 space-y-2">
  561. @if(!empty($mistake['ai_analysis']['solution']))
  562. <div>
  563. <span class="font-medium">解法:</span>
  564. <p>{{ $mistake['ai_analysis']['solution'] }}</p>
  565. </div>
  566. @endif
  567. @if(!empty($mistake['ai_analysis']['suggestions']))
  568. <div>
  569. <span class="font-medium">建议:</span>
  570. <p>{{ $mistake['ai_analysis']['suggestions'] }}</p>
  571. </div>
  572. @endif
  573. </div>
  574. </div>
  575. @endif
  576. <!-- 操作按钮 -->
  577. <div class="flex flex-wrap gap-2 pt-3 border-t border-gray-100">
  578. <button wire:click="toggleFavorite('{{ $mistake['id'] ?? '' }}')"
  579. class="inline-flex items-center px-3 py-1.5 text-sm font-medium rounded-lg {{ !empty($mistake['favorite']) ? 'bg-yellow-100 text-yellow-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' }} transition-colors">
  580. {{ !empty($mistake['favorite']) ? '★ 已收藏' : '☆ 收藏此题' }}
  581. </button>
  582. <button wire:click="markReviewed('{{ $mistake['id'] ?? '' }}')"
  583. class="inline-flex items-center px-3 py-1.5 text-sm font-medium rounded-lg {{ !empty($mistake['reviewed']) ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' }} transition-colors">
  584. {{ !empty($mistake['reviewed']) ? '✓ 已复习' : '标记为已复习' }}
  585. </button>
  586. <button wire:click="loadRelatedQuestions('{{ $mistake['id'] ?? '' }}')"
  587. class="inline-flex items-center px-3 py-1.5 text-sm font-medium rounded-lg bg-indigo-100 text-indigo-700 hover:bg-indigo-200 transition-colors">
  588. 查找相似题
  589. </button>
  590. @if(!empty($mistake['answer_area_crop_path']))
  591. <a href="{{ $mistake['answer_area_crop_path'] }}" target="_blank"
  592. class="inline-flex items-center px-3 py-1.5 text-sm font-medium rounded-lg bg-gray-100 text-gray-700 hover:bg-gray-200 transition-colors">
  593. 查看原始图片
  594. </a>
  595. @endif
  596. </div>
  597. <!-- 关联题目 -->
  598. @if(!empty($relatedQuestions[$mistake['id'] ?? ''] ?? []))
  599. <div class="bg-gray-50 rounded-lg p-3 border border-gray-100">
  600. <p class="text-xs font-medium text-gray-500 mb-2">推荐练习</p>
  601. <div class="space-y-2">
  602. @foreach($relatedQuestions[$mistake['id']] as $related)
  603. <div class="text-sm p-3 bg-white rounded-lg border border-gray-200 hover:shadow-sm transition-shadow">
  604. <p class="text-gray-900 line-clamp-2">{{ $related['stem'] ?? '题目' }}</p>
  605. @if(!empty($related['difficulty']))
  606. <span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium
  607. @if($related['difficulty'] === 'easy') bg-green-100 text-green-700
  608. @elseif($related['difficulty'] === 'medium') bg-yellow-100 text-yellow-700
  609. @else bg-red-100 text-red-700
  610. @endif mt-2">
  611. {{ $related['difficulty'] === 'easy' ? '简单' : ($related['difficulty'] === 'medium' ? '中等' : '困难') }}
  612. </span>
  613. @endif
  614. </div>
  615. @endforeach
  616. </div>
  617. </div>
  618. @endif
  619. </div>
  620. </details>
  621. </div>
  622. @endforeach
  623. </div>
  624. {{-- 分页 --}}
  625. @php
  626. $maxPage = (int) ceil($total / $perPage);
  627. @endphp
  628. @if($maxPage > 1)
  629. <div class="mt-6 flex items-center justify-between border-t border-gray-100 pt-4">
  630. <div class="text-sm text-gray-500">
  631. 共 {{ $total }} 条,第 {{ $page }}/{{ $maxPage }} 页
  632. </div>
  633. <div class="flex items-center gap-2">
  634. <button wire:click="prevPage" @disabled($page <= 1)
  635. class="px-3 py-1.5 text-sm font-medium rounded-lg {{ $page <= 1 ? 'bg-gray-100 text-gray-400 cursor-not-allowed' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' }} transition-colors">
  636. 上一页
  637. </button>
  638. @for($i = max(1, $page - 2); $i <= min($maxPage, $page + 2); $i++)
  639. <button wire:click="gotoPage({{ $i }})"
  640. class="px-3 py-1.5 text-sm font-medium rounded-lg {{ $i === $page ? 'bg-indigo-600 text-white' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' }} transition-colors">
  641. {{ $i }}
  642. </button>
  643. @endfor
  644. <button wire:click="nextPage" @disabled($page >= $maxPage)
  645. class="px-3 py-1.5 text-sm font-medium rounded-lg {{ $page >= $maxPage ? 'bg-gray-100 text-gray-400 cursor-not-allowed' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' }} transition-colors">
  646. 下一页
  647. </button>
  648. </div>
  649. </div>
  650. @endif
  651. @endif
  652. </div>
  653. </div>
  654. {{-- 推荐练习题 --}}
  655. @if(!empty($recommendations))
  656. <div class="bg-white shadow-sm rounded-xl border border-gray-200">
  657. <div class="px-6 py-5 border-b border-gray-100">
  658. <h3 class="text-lg font-semibold text-gray-900 flex items-center">
  659. <svg class="w-5 h-5 mr-2 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  660. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
  661. </svg>
  662. 推荐练习题 ({{ count($recommendations) }})
  663. </h3>
  664. </div>
  665. <div class="p-6">
  666. <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
  667. @foreach($recommendations as $rec)
  668. <div class="p-4 border border-gray-200 rounded-lg bg-gray-50">
  669. <p class="text-sm text-gray-900 line-clamp-2">{{ $rec['stem'] ?? '推荐题目' }}</p>
  670. @if(!empty($rec['kp_codes']))
  671. <span class="inline-flex items-center mt-2 px-2 py-0.5 rounded text-xs font-medium bg-indigo-100 text-indigo-800">
  672. {{ is_array($rec['kp_codes']) ? implode(',', $rec['kp_codes']) : $rec['kp_codes'] }}
  673. </span>
  674. @endif
  675. </div>
  676. @endforeach
  677. </div>
  678. </div>
  679. </div>
  680. @endif
  681. {{-- 错误分析与学习建议 --}}
  682. @if(!empty($patterns['error_types']) || !empty($patterns['top_kps']))
  683. <div class="bg-white shadow-sm rounded-xl border border-gray-200">
  684. <div class="px-6 py-5 border-b border-gray-100">
  685. <h3 class="text-lg font-semibold text-gray-900 flex items-center">
  686. <svg class="w-5 h-5 mr-2 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  687. <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>
  688. </svg>
  689. 错误分析与学习建议
  690. </h3>
  691. </div>
  692. <div class="p-6">
  693. @if(!empty($patterns['error_types']) || !empty($patterns['top_kps']))
  694. <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
  695. @if(!empty($patterns['error_types']))
  696. <div>
  697. <p class="text-sm font-medium text-gray-900 mb-4 flex items-center">
  698. <svg class="w-4 h-4 mr-2 text-orange-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  699. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.728-.833-2.498 0L4.316 16.5c-.77.833.192 2.5 1.732 2.5z"></path>
  700. </svg>
  701. 错误类型分布
  702. </p>
  703. <div class="space-y-2">
  704. @php
  705. $totalErrors = collect($patterns['error_types'])->sum('count');
  706. @endphp
  707. @foreach($patterns['error_types'] as $et)
  708. @php
  709. $count = $et['count'] ?? 0;
  710. $percentage = $totalErrors > 0 ? ($count / $totalErrors * 100) : 0;
  711. @endphp
  712. <div class="bg-gray-50 rounded-lg p-3 hover:bg-gray-100 transition-colors">
  713. <div class="flex items-center justify-between mb-1">
  714. <span class="text-sm font-medium text-gray-700">{{ $et['type'] ?? '未知错误' }}</span>
  715. <span class="text-sm text-gray-500">{{ $count }}次 ({{ number_format($percentage, 0) }}%)</span>
  716. </div>
  717. <div class="w-full bg-gray-200 rounded-full h-2">
  718. <div class="bg-orange-500 h-2 rounded-full transition-all duration-500" style="width: {{ $percentage }}%"></div>
  719. </div>
  720. </div>
  721. @endforeach
  722. </div>
  723. </div>
  724. @endif
  725. @if(!empty($patterns['top_kps']))
  726. <div>
  727. <p class="text-sm font-medium text-gray-900 mb-4 flex items-center">
  728. <svg class="w-4 h-4 mr-2 text-red-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  729. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"></path>
  730. </svg>
  731. 薄弱知识点
  732. </p>
  733. <div class="space-y-2">
  734. @php
  735. $maxMistakes = collect($patterns['top_kps'])->max('mistake_count') ?: 1;
  736. @endphp
  737. @foreach($patterns['top_kps'] as $kp)
  738. @php
  739. $count = $kp['mistake_count'] ?? 0;
  740. $width = ($count / $maxMistakes) * 100;
  741. @endphp
  742. <div class="bg-red-50 rounded-lg p-3 hover:bg-red-100 transition-colors">
  743. <div class="flex items-center justify-between mb-1">
  744. <span class="text-sm font-medium text-gray-700">{{ $kp['name'] ?? $kp['kp_code'] ?? '知识点' }}</span>
  745. <span class="text-sm text-red-600">{{ $count }}题</span>
  746. </div>
  747. <div class="w-full bg-red-200 rounded-full h-2">
  748. <div class="bg-red-500 h-2 rounded-full transition-all duration-500" style="width: {{ $width }}%"></div>
  749. </div>
  750. </div>
  751. @endforeach
  752. </div>
  753. </div>
  754. @endif
  755. </div>
  756. @endif
  757. <!-- 学习建议卡片 -->
  758. <div class="bg-gradient-to-r from-blue-50 to-indigo-50 rounded-xl p-6 border border-blue-100">
  759. <h4 class="text-lg font-semibold text-gray-900 mb-4 flex items-center">
  760. <svg class="w-5 h-5 mr-2 text-indigo-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  761. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
  762. </svg>
  763. 学习建议
  764. </h4>
  765. <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
  766. <div class="flex items-start">
  767. <span class="flex-shrink-0 w-6 h-6 bg-green-100 text-green-600 rounded-full flex items-center justify-center text-xs font-medium mr-3">1</span>
  768. <div>
  769. <p class="text-sm font-medium text-gray-900">优先复习高错频知识点</p>
  770. <p class="text-xs text-gray-600 mt-1">集中练习错误次数最多的3个知识点</p>
  771. </div>
  772. </div>
  773. <div class="flex items-start">
  774. <span class="flex-shrink-0 w-6 h-6 bg-green-100 text-green-600 rounded-full flex items-center justify-center text-xs font-medium mr-3">2</span>
  775. <div>
  776. <p class="text-sm font-medium text-gray-900">制定复习计划</p>
  777. <p class="text-xs text-gray-600 mt-1">建议每天复习5-10道错题,形成规律</p>
  778. </div>
  779. </div>
  780. <div class="flex items-start">
  781. <span class="flex-shrink-0 w-6 h-6 bg-green-100 text-green-600 rounded-full flex items-center justify-center text-xs font-medium mr-3">3</span>
  782. <div>
  783. <p class="text-sm font-medium text-gray-900">重点突破错误类型</p>
  784. <p class="text-xs text-gray-600 mt-1">针对主要错误类型进行专项练习</p>
  785. </div>
  786. </div>
  787. <div class="flex items-start">
  788. <span class="flex-shrink-0 w-6 h-6 bg-green-100 text-green-600 rounded-full flex items-center justify-center text-xs font-medium mr-3">4</span>
  789. <div>
  790. <p class="text-sm font-medium text-gray-900">定期回顾与测试</p>
  791. <p class="text-xs text-gray-600 mt-1">每周回顾本周错题,检验掌握程度</p>
  792. </div>
  793. </div>
  794. </div>
  795. </div>
  796. </div>
  797. </div>
  798. @endif
  799. </div>
  800. </div>
  801. @endif
  802. </div>