detail-drawer.blade.php 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. @props([
  2. 'open' => false,
  3. 'details' => [],
  4. 'closeAction' => 'closeDrawer',
  5. 'selectAction' => 'openDrawer',
  6. 'panelTitle' => '知识点详情',
  7. ])
  8. @php
  9. $mastery = $details['mastery_level'] ?? 0;
  10. $errorRate = $details['error_rate'] ?? 0;
  11. $name = $details['name'] ?? '';
  12. $code = $details['code'] ?? '';
  13. @endphp
  14. <div
  15. x-cloak
  16. x-show="@js($open)"
  17. x-transition:enter="transition ease-out duration-300"
  18. x-transition:enter-start="translate-x-full opacity-50"
  19. x-transition:enter-end="translate-x-0 opacity-100"
  20. x-transition:leave="transition ease-in duration-200"
  21. x-transition:leave-start="translate-x-0 opacity-100"
  22. x-transition:leave-end="translate-x-full opacity-0"
  23. class="fixed inset-y-0 right-0 w-full max-w-xl z-50"
  24. aria-live="polite"
  25. >
  26. <div class="h-full bg-gradient-to-b from-white/95 to-slate-50/95 backdrop-blur border-l border-white/60 shadow-2xl overflow-y-auto">
  27. <div class="p-6 space-y-6">
  28. <div class="flex items-start justify-between">
  29. <div>
  30. <p class="text-xs uppercase tracking-[0.3em] text-slate-400">Mindmap Drawer</p>
  31. <h3 class="mt-1 text-2xl font-bold text-slate-900 leading-tight">{{ $panelTitle }}</h3>
  32. </div>
  33. <button
  34. wire:click="{{ $closeAction }}"
  35. type="button"
  36. class="p-2 rounded-full bg-white/80 border border-slate-200 text-slate-500 hover:text-slate-700 hover:shadow"
  37. aria-label="关闭"
  38. >
  39. <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  40. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
  41. </svg>
  42. </button>
  43. </div>
  44. <div class="rounded-2xl border border-white/60 bg-white/80 shadow-inner p-5 space-y-3">
  45. <div class="flex items-center justify-between">
  46. <div>
  47. <p class="text-sm text-slate-500">编号 {{ $code }}</p>
  48. <h4 class="text-xl font-semibold text-slate-900">{{ $name }}</h4>
  49. </div>
  50. <div class="px-3 py-1.5 rounded-full text-xs font-semibold bg-gradient-to-r from-emerald-50 to-amber-50 text-emerald-700 border border-emerald-100">
  51. 掌握度 {{ number_format($mastery * 100, 1) }}%
  52. </div>
  53. </div>
  54. <x-mindmap.mastery-meter :value="$mastery" :error-rate="$errorRate" />
  55. </div>
  56. @if(!empty($details['skills']))
  57. <div class="rounded-2xl border border-white/60 bg-white/80 shadow-sm p-4">
  58. <p class="text-sm font-semibold text-slate-800 mb-3">关联技能</p>
  59. <div class="flex flex-wrap gap-2">
  60. @foreach($details['skills'] as $skill)
  61. <span class="px-3 py-1 rounded-full text-xs bg-indigo-50 text-indigo-700 border border-indigo-100">
  62. {{ $skill }}
  63. </span>
  64. @endforeach
  65. </div>
  66. </div>
  67. @endif
  68. @if(!empty($details['prerequisites']))
  69. <div class="rounded-2xl border border-white/60 bg-white/80 shadow-sm p-4 space-y-3">
  70. <p class="text-sm font-semibold text-slate-800">前置知识</p>
  71. <div class="space-y-2">
  72. @foreach($details['prerequisites'] as $prereq)
  73. <button
  74. wire:click="$parent.openPrerequisiteDrawer('{{ $prereq['id'] }}')"
  75. type="button"
  76. class="w-full flex items-center justify-between px-3 py-2 rounded-lg border border-slate-200/70 bg-white/60 hover:border-indigo-200 hover:bg-indigo-50/80 transition"
  77. >
  78. <span class="text-sm text-slate-700">{{ $prereq['name'] }}</span>
  79. <span class="text-xs px-2 py-1 rounded-full {{ ($prereq['mastery'] ?? 0) >= 0.6 ? 'bg-emerald-50 text-emerald-700' : 'bg-rose-50 text-rose-700' }}">
  80. {{ number_format(($prereq['mastery'] ?? 0) * 100, 0) }}%
  81. </span>
  82. </button>
  83. @endforeach
  84. </div>
  85. </div>
  86. @endif
  87. @if(!empty($details['successors']))
  88. <div class="rounded-2xl border border-white/60 bg-white/80 shadow-sm p-4 space-y-3">
  89. <p class="text-sm font-semibold text-slate-800">后续知识</p>
  90. <div class="space-y-2">
  91. @foreach($details['successors'] as $succ)
  92. <button
  93. wire:click="$parent.openSuccessorDrawer('{{ $succ['id'] }}')"
  94. type="button"
  95. class="w-full flex items-center justify-between px-3 py-2 rounded-lg border border-slate-200/70 bg-white/60 hover:border-amber-200 hover:bg-amber-50/70 transition"
  96. >
  97. <span class="text-sm text-slate-700">{{ $succ['name'] }}</span>
  98. <span class="text-xs px-2 py-1 rounded-full {{ ($succ['mastery'] ?? 0) >= 0.6 ? 'bg-emerald-50 text-emerald-700' : 'bg-rose-50 text-rose-700' }}">
  99. {{ number_format(($succ['mastery'] ?? 0) * 100, 0) }}%
  100. </span>
  101. </button>
  102. @endforeach
  103. </div>
  104. </div>
  105. @endif
  106. @if(!empty($details['recommendations']))
  107. <div class="rounded-2xl border border-white/60 bg-white/80 shadow-sm p-4 space-y-3">
  108. <div class="flex items-center justify-between">
  109. <p class="text-sm font-semibold text-slate-800">推荐练习</p>
  110. <span class="text-[11px] text-slate-500">自动挑选的3道题</span>
  111. </div>
  112. <div class="space-y-3">
  113. @foreach($details['recommendations'] as $rec)
  114. <div class="p-3 rounded-lg border border-slate-200/70 bg-white/60 hover:border-indigo-200 hover:shadow-sm transition">
  115. <div class="flex items-start justify-between gap-2">
  116. <div class="text-sm font-medium text-slate-900">{{ $rec['title'] }}</div>
  117. <span class="text-xs px-2 py-0.5 rounded-full border border-indigo-100 text-indigo-700 bg-indigo-50">
  118. {{ $rec['difficulty'] ?? '中等' }}
  119. </span>
  120. </div>
  121. <p class="mt-1 text-xs text-slate-500">{{ $rec['type'] ?? '练习题' }}</p>
  122. </div>
  123. @endforeach
  124. </div>
  125. </div>
  126. @endif
  127. <div class="flex gap-3">
  128. <a
  129. href="{{ url('/admin/practice?kp=' . ($details['id'] ?? '')) }}"
  130. class="flex-1 inline-flex items-center justify-center gap-2 rounded-lg bg-indigo-600 text-white font-semibold py-3 shadow-lg shadow-indigo-200 hover:bg-indigo-700 transition"
  131. >
  132. <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  133. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6l4 2"/>
  134. </svg>
  135. 开始练习
  136. </a>
  137. <button
  138. wire:click="{{ $closeAction }}"
  139. type="button"
  140. class="px-4 py-3 rounded-lg border border-slate-200 bg-white/70 text-slate-700 hover:border-slate-300"
  141. >
  142. 收起
  143. </button>
  144. </div>
  145. </div>
  146. </div>
  147. </div>
  148. <div
  149. x-cloak
  150. x-show="@js($open)"
  151. @click="{{ $closeAction }}"
  152. x-transition:enter="transition ease-out duration-300"
  153. x-transition:enter-start="opacity-0"
  154. x-transition:enter-end="opacity-100"
  155. x-transition:leave="transition ease-in duration-200"
  156. x-transition:leave-start="opacity-100"
  157. x-transition:leave-end="opacity-0"
  158. class="fixed inset-0 bg-slate-900/40 backdrop-blur-sm z-40"
  159. ></div>