question-management-simple.blade.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. <x-filament-panels::page>
  2. <!-- 数学公式渲染组件 -->
  3. <x-math-render />
  4. <div class="space-y-6">
  5. @php
  6. $questionsData = $this->questions;
  7. $metaData = $this->meta;
  8. $statisticsData = $this->statistics;
  9. @endphp
  10. <div class="flex justify-end">
  11. <a
  12. href="{{ url('/admin/question-generation') }}"
  13. class="inline-flex items-center justify-center px-4 py-2 text-sm font-medium text-white bg-green-600 hover:bg-green-700 rounded-lg transition-colors"
  14. >
  15. <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  16. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
  17. </svg>
  18. 生成题目
  19. </a>
  20. </div>
  21. <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
  22. <div class="bg-white p-4 rounded-lg border">
  23. <div class="text-sm text-gray-500">题目总数</div>
  24. <div class="text-2xl font-bold text-primary-600">{{ $statisticsData['total'] ?? 0 }}</div>
  25. </div>
  26. <div class="bg-white p-4 rounded-lg border">
  27. <div class="text-sm text-gray-500">基础难度 (≤0.4)</div>
  28. <div class="text-2xl font-bold text-green-600">
  29. @php
  30. $basicCount = 0;
  31. foreach ($statisticsData['by_difficulty'] ?? [] as $key => $value) {
  32. if ((float)$key <= 0.4) {
  33. $basicCount += $value;
  34. }
  35. }
  36. echo $basicCount;
  37. @endphp
  38. </div>
  39. </div>
  40. <div class="bg-white p-4 rounded-lg border">
  41. <div class="text-sm text-gray-500">中等难度 (0.4-0.7)</div>
  42. <div class="text-2xl font-bold text-yellow-600">
  43. @php
  44. $mediumCount = 0;
  45. foreach ($statisticsData['by_difficulty'] ?? [] as $key => $value) {
  46. if ((float)$key > 0.4 && (float)$key <= 0.7) {
  47. $mediumCount += $value;
  48. }
  49. }
  50. echo $mediumCount;
  51. @endphp
  52. </div>
  53. </div>
  54. <div class="bg-white p-4 rounded-lg border">
  55. <div class="text-sm text-gray-500">拔高难度 (>0.7)</div>
  56. <div class="text-2xl font-bold text-red-600">
  57. @php
  58. $advancedCount = 0;
  59. foreach ($statisticsData['by_difficulty'] ?? [] as $key => $value) {
  60. if ((float)$key > 0.7) {
  61. $advancedCount += $value;
  62. }
  63. }
  64. echo $advancedCount;
  65. @endphp
  66. </div>
  67. </div>
  68. </div>
  69. <div class="bg-white p-4 rounded-lg border">
  70. <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
  71. <div>
  72. <label class="block text-sm font-medium text-gray-700 mb-2">搜索题目</label>
  73. <input type="text" wire:model.live.debounce.300ms="search" placeholder="输入关键词" class="w-full border rounded p-2">
  74. </div>
  75. <div>
  76. <label class="block text-sm font-medium text-gray-700 mb-2">知识点筛选</label>
  77. <input type="text" wire:model.live="selectedKpCode" placeholder="KP1001" class="w-full border rounded p-2">
  78. </div>
  79. <div>
  80. <label class="block text-sm font-medium text-gray-700 mb-2">难度筛选</label>
  81. <input type="text" wire:model.live="selectedDifficulty" placeholder="0.3/0.6/0.85" class="w-full border rounded p-2">
  82. </div>
  83. <div>
  84. <label class="block text-sm font-medium text-gray-700 mb-2">每页显示</label>
  85. <input type="number" wire:model.live="perPage" min="10" max="100" step="5" class="w-full border rounded p-2">
  86. </div>
  87. </div>
  88. </div>
  89. <div class="bg-white rounded-lg border overflow-hidden">
  90. <table class="min-w-full divide-y divide-gray-200">
  91. <thead class="bg-gray-50">
  92. <tr>
  93. <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">题目编号</th>
  94. <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">知识点</th>
  95. <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">创建时间</th>
  96. <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">题干</th>
  97. <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">难度</th>
  98. <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">操作</th>
  99. </tr>
  100. </thead>
  101. <tbody class="bg-white divide-y divide-gray-200">
  102. @forelse($questionsData as $question)
  103. <tr class="hover:bg-gray-50">
  104. <td class="px-6 py-4 whitespace-nowrap">{{ $question['question_code'] ?? 'N/A' }}</td>
  105. <td class="px-6 py-4 whitespace-nowrap">
  106. <div class="text-sm font-medium text-gray-900">{{ $question['kp_name'] ?? $question['kp_code'] ?? 'N/A' }}</div>
  107. @if(!empty($question['kp_code']))
  108. <div class="text-xs text-gray-500">{{ $question['kp_code'] }}</div>
  109. @endif
  110. </td>
  111. <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-600">
  112. @if(!empty($question['created_at']))
  113. {{ \Carbon\Carbon::parse($question['created_at'])->toDateTimeString() }}
  114. @else
  115. -
  116. @endif
  117. </td>
  118. <td class="px-6 py-4" style="word-wrap: break-word; white-space: normal; line-height: 1.8; max-width: 400px;">
  119. <span class="text-sm">
  120. @math($question['stem'] ?? 'N/A')
  121. </span>
  122. </td>
  123. <td class="px-6 py-4">
  124. @php
  125. $difficulty = $question['difficulty'] ?? null;
  126. $label = match (true) {
  127. !$difficulty => 'N/A',
  128. (float)$difficulty <= 0.4 => '基础',
  129. (float)$difficulty <= 0.7 => '中等',
  130. default => '拔高',
  131. };
  132. @endphp
  133. {{ $label }}
  134. @if(app()->environment('local'))
  135. <span class="text-xs text-gray-400">({{ $difficulty }})</span>
  136. @endif
  137. </td>
  138. <td class="px-6 py-4 whitespace-nowrap">
  139. <button wire:click="viewQuestion('{{ $question['question_code'] }}')" class="text-blue-600 hover:underline mr-3">详情</button>
  140. <button wire:click="deleteQuestion('{{ $question['question_code'] }}')" class="text-red-600 hover:underline">删除</button>
  141. </td>
  142. </tr>
  143. @empty
  144. <tr><td colspan="5" class="px-6 py-12 text-center">暂无数据</td></tr>
  145. @endforelse
  146. </tbody>
  147. </table>
  148. @if(!empty($metaData) && ($metaData['total'] ?? 0) > 0)
  149. <div class="px-4 py-3 border-t border-gray-200 flex items-center justify-between">
  150. <div class="text-sm text-gray-700">共 {{ $metaData['total'] ?? 0 }} 条记录</div>
  151. <div class="flex items-center gap-2">
  152. <button wire:click="previousPage" @disabled($currentPage <= 1) class="px-3 py-1 border rounded">上一页</button>
  153. @foreach($this->getPages() as $page)
  154. <button wire:click="gotoPage({{ $page }})" class="px-3 py-1 border rounded {{ $page === $currentPage ? 'bg-blue-50 text-blue-700' : '' }}">{{ $page }}</button>
  155. @endforeach
  156. <button wire:click="nextPage" @disabled($currentPage >= ($metaData['total_pages'] ?? 1)) class="px-3 py-1 border rounded">下一页</button>
  157. </div>
  158. </div>
  159. @endif
  160. </div>
  161. {{-- 详情侧边栏 --}}
  162. @if($showDetailModal)
  163. <div class="fixed inset-0 z-40 flex">
  164. <div class="flex-1 bg-black/40" wire:click="$set('showDetailModal', false)"></div>
  165. <div class="w-full max-w-3xl bg-white shadow-xl overflow-y-auto">
  166. <div class="p-6 border-b flex justify-between items-center">
  167. <div>
  168. <h3 class="text-lg font-semibold">{{ $editing['question_code'] ?? '题目详情' }}</h3>
  169. <p class="text-sm text-gray-500">
  170. {{ $editing['kp_name'] ?? ($editing['kp_code'] ?? '') }}
  171. @if(!empty($editing['kp_code'])) ({{ $editing['kp_code'] }}) @endif
  172. </p>
  173. </div>
  174. <button class="text-gray-500 hover:text-gray-700" wire:click="$set('showDetailModal', false)">&times;</button>
  175. </div>
  176. <div class="p-6 space-y-4">
  177. <div>
  178. <label class="text-sm font-medium text-gray-700">知识点代码</label>
  179. <input type="text" wire:model="editing.kp_code" class="w-full border rounded px-3 py-2 text-sm">
  180. </div>
  181. <div>
  182. <label class="text-sm font-medium text-gray-700">题干</label>
  183. <textarea wire:model="editing.stem" rows="4" class="w-full border rounded px-3 py-2 text-sm"></textarea>
  184. </div>
  185. <div>
  186. <label class="text-sm font-medium text-gray-700">答案</label>
  187. <textarea wire:model="editing.answer" rows="3" class="w-full border rounded px-3 py-2 text-sm"></textarea>
  188. </div>
  189. <div>
  190. <label class="text-sm font-medium text-gray-700">解析</label>
  191. <textarea wire:model="editing.solution" rows="4" class="w-full border rounded px-3 py-2 text-sm"></textarea>
  192. </div>
  193. <div class="grid grid-cols-2 gap-4 text-sm">
  194. <div>
  195. <label class="text-sm font-medium text-gray-700">难度 (0-1)</label>
  196. <input type="number" step="0.01" min="0" max="1" wire:model="editing.difficulty" class="w-full border rounded px-3 py-2 text-sm">
  197. </div>
  198. <div>
  199. <label class="text-sm font-medium text-gray-700">题型</label>
  200. <input type="text" wire:model="editing.question_type" class="w-full border rounded px-3 py-2 text-sm" placeholder="choice/fill/answer">
  201. </div>
  202. <div>
  203. <label class="text-sm font-medium text-gray-700">来源</label>
  204. <input type="text" wire:model="editing.source" class="w-full border rounded px-3 py-2 text-sm">
  205. </div>
  206. <div>
  207. <label class="text-sm font-medium text-gray-700">标签</label>
  208. <input type="text" wire:model="editing.tags" class="w-full border rounded px-3 py-2 text-sm">
  209. </div>
  210. <div class="col-span-2">
  211. <label class="text-sm font-medium text-gray-700">技能(逗号分隔)</label>
  212. <input type="text" wire:model="editing.skills_text" class="w-full border rounded px-3 py-2 text-sm">
  213. </div>
  214. <div><span class="font-medium">创建时间:</span>{{ $editing['created_at'] ?? '-' }}</div>
  215. <div><span class="font-medium">更新时间:</span>{{ $editing['updated_at'] ?? '-' }}</div>
  216. </div>
  217. </div>
  218. <div class="p-6 border-t flex justify-end gap-3">
  219. <button class="px-4 py-2 border rounded text-sm" wire:click="$set('showDetailModal', false)">取消</button>
  220. <button class="px-4 py-2 bg-blue-600 text-white rounded text-sm hover:bg-blue-700" wire:click="saveQuestion">保存</button>
  221. </div>
  222. </div>
  223. </div>
  224. @endif
  225. </div>
  226. </x-filament-panels::page>