| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- {{-- 访问计算属性触发懒加载 --}}
- @php
- $questionsData = $this->questions;
- $metaData = $this->meta;
- $statisticsData = $this->statistics;
- @endphp
- <div class="filament-page">
- <div class="filament-page-header">
- <div class="filament-page-header-actions">
- {{-- 头部操作按钮将在此处 --}}
- </div>
- </div>
- <div class="filament-page-content">
- {{-- 页面内容 --}}
- <x-filament::section>
- <div class="flex items-center justify-between mb-6">
- <div>
- <h2 class="text-xl font-bold tracking-tight">题库管理</h2>
- <p class="mt-1 text-sm text-gray-500">
- 管理和浏览题库中的所有题目
- </p>
- </div>
- <div class="flex gap-3">
- <button
- type="button"
- class="filament-button filament-button-size-sm filament-button-color-success filament-button-icon-start inline-flex items-center justify-center px-4 py-2 text-sm font-medium transition-colors border border-transparent rounded-lg focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"
- wire:click="$dispatch('ai-generate')"
- >
- <span class="filament-button-icon mr-2">
- <!-- heroicon -->
- </span>
- AI 生成题目
- </button>
- <button
- type="button"
- class="filament-button filament-button-size-sm filament-button-color-warning filament-button-icon-start inline-flex items-center justify-center px-4 py-2 text-sm font-medium transition-colors border border-transparent rounded-lg focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"
- wire:click="$dispatch('refresh-data')"
- >
- <span class="filament-button-icon mr-2">
- <!-- heroicon -->
- </span>
- 刷新
- </button>
- </div>
- </div>
- {{-- 统计信息卡片 --}}
- <div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-6">
- <div class="bg-white p-4 rounded-lg border">
- <div class="text-sm text-gray-500">题目总数</div>
- <div class="text-2xl font-bold text-primary-600">
- {{ $statisticsData['total'] ?? 0 }}
- </div>
- </div>
- <div class="bg-white p-4 rounded-lg border">
- <div class="text-sm text-gray-500">基础难度</div>
- <div class="text-2xl font-bold text-green-600">
- {{ $statisticsData['by_difficulty']['0.3'] ?? 0 }}
- </div>
- </div>
- <div class="bg-white p-4 rounded-lg border">
- <div class="text-sm text-gray-500">中等难度</div>
- <div class="text-2xl font-bold text-yellow-600">
- {{ $statisticsData['by_difficulty']['0.6'] ?? 0 }}
- </div>
- </div>
- <div class="bg-white p-4 rounded-lg border">
- <div class="text-sm text-gray-500">拔高难度</div>
- <div class="text-2xl font-bold text-red-600">
- {{ $statisticsData['by_difficulty']['0.85'] ?? 0 }}
- </div>
- </div>
- </div>
- {{-- 搜索和筛选 --}}
- <div class="bg-white p-4 rounded-lg border mb-6">
- <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
- <div>
- <label class="block text-sm font-medium text-gray-700 mb-2">
- 搜索题目
- </label>
- <input
- type="text"
- wire:model.live.debounce.300ms="search"
- placeholder="输入题目内容、答案或编号"
- class="filament-forms-input block w-full rounded-lg border-gray-300 shadow-sm focus:border-primary-500 focus:ring-primary-500 sm:text-sm"
- />
- </div>
- <div>
- <label class="block text-sm font-medium text-gray-700 mb-2">
- 知识点筛选
- </label>
- <input
- type="text"
- wire:model.live="selectedKpCode"
- placeholder="如:KP1001"
- class="filament-forms-input block w-full rounded-lg border-gray-300 shadow-sm focus:border-primary-500 focus:ring-primary-500 sm:text-sm"
- />
- </div>
- <div>
- <label class="block text-sm font-medium text-gray-700 mb-2">
- 难度筛选
- </label>
- <input
- type="text"
- wire:model.live="selectedDifficulty"
- placeholder="0.3/0.6/0.85"
- class="filament-forms-input block w-full rounded-lg border-gray-300 shadow-sm focus:border-primary-500 focus:ring-primary-500 sm:text-sm"
- />
- </div>
- <div>
- <label class="block text-sm font-medium text-gray-700 mb-2">
- 每页显示
- </label>
- <input
- type="number"
- wire:model.live="perPage"
- min="10"
- max="100"
- step="5"
- class="filament-forms-input block w-full rounded-lg border-gray-300 shadow-sm focus:border-primary-500 focus:ring-primary-500 sm:text-sm"
- />
- </div>
- </div>
- </div>
- {{-- 题目列表 --}}
- <div class="bg-white rounded-lg border overflow-hidden">
- <div class="overflow-x-auto" wire:loading.class="opacity-50">
- <table class="min-w-full divide-y divide-gray-200">
- <thead class="bg-gray-50">
- <tr>
- <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
- 题目编号
- </th>
- <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
- 知识点
- </th>
- <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
- 题干
- </th>
- <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
- 关联技能
- </th>
- <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
- 难度
- </th>
- <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
- 来源
- </th>
- <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
- 操作
- </th>
- </tr>
- </thead>
- <tbody class="bg-white divide-y divide-gray-200">
- @forelse($questionsData as $question)
- <tr class="hover:bg-gray-50">
- <td class="px-6 py-4 whitespace-nowrap">
- <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
- {{ $question['question_code'] ?? 'N/A' }}
- </span>
- </td>
- <td class="px-6 py-4 whitespace-nowrap">
- <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-indigo-100 text-indigo-800">
- {{ $question['kp_code'] ?? 'N/A' }}
- </span>
- </td>
- <td class="px-6 py-4">
- <div class="text-sm text-gray-900 max-w-xs">
- {{ \Illuminate\Support\Str::limit($question['stem'] ?? 'N/A', 80) }}
- </div>
- </td>
- <td class="px-6 py-4">
- @php
- $skills = $question['skills'] ?? [];
- if (is_string($skills)) {
- $skills = json_decode($skills, true) ?? [];
- }
- $skillNames = [];
- foreach ($skills as $skill) {
- $skillNames[] = $skill['skill_name'] ?? ($skill['skill_code'] ?? 'N/A');
- }
- $skillText = implode(', ', array_slice($skillNames, 0, 2));
- if (count($skillNames) > 2) {
- $skillText .= ' ...';
- }
- @endphp
- <div class="text-xs text-gray-600 max-w-xs">
- @if(!empty($skillText))
- <span class="inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium bg-purple-100 text-purple-800">
- {{ $skillText }}
- </span>
- @else
- <span class="text-gray-400">无关联技能</span>
- @endif
- </div>
- </td>
- <td class="px-6 py-4 whitespace-nowrap">
- @php
- $difficulty = $question['difficulty'] ?? null;
- $difficultyLabel = match (true) {
- !$difficulty => 'N/A',
- (float)$difficulty <= 0.4 => '基础',
- (float)$difficulty <= 0.7 => '中等',
- default => '拔高',
- };
- $difficultyColor = match (true) {
- !$difficulty => 'gray',
- (float)$difficulty <= 0.4 => 'success',
- (float)$difficulty <= 0.7 => 'warning',
- default => 'danger',
- };
- @endphp
- <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-{{ $difficultyColor }}-100 text-{{ $difficultyColor }}-800">
- {{ $difficultyLabel }}
- </span>
- </td>
- <td class="px-6 py-4 whitespace-nowrap">
- @php
- $source = $question['source'] ?? '';
- $sourceLabel = str_contains($source, 'ai::') ? 'AI 生成' : '手工录入';
- $sourceColor = str_contains($source, 'ai::') ? 'blue' : 'gray';
- @endphp
- <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-{{ $sourceColor }}-100 text-{{ $sourceColor }}-800">
- {{ $sourceLabel }}
- </span>
- </td>
- <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
- <button type="button" class="text-indigo-600 hover:text-indigo-900 mr-3">
- 查看
- </button>
- <button type="button" class="text-red-600 hover:text-red-900">
- 删除
- </button>
- </td>
- </tr>
- @empty
- <tr>
- <td colspan="7" class="px-6 py-12 text-center text-sm text-gray-500">
- <div class="flex flex-col items-center">
- <x-heroicon-m-document-magnifying-glass class="w-12 h-12 text-gray-400 mb-3" />
- 暂无题目数据
- <p class="mt-2 text-xs text-gray-400">
- 请尝试调整搜索条件或生成新题目
- </p>
- </div>
- </td>
- </tr>
- @endforelse
- </tbody>
- </table>
- </div>
- {{-- 分页信息 --}}
- @if(!empty($metaData) && ($metaData['total'] ?? 0) > 0)
- <div class="bg-white px-4 py-3 border-t border-gray-200 sm:px-6">
- <div class="flex items-center justify-between">
- <div class="text-sm text-gray-700">
- 显示第 {{ (($metaData['page'] ?? 1) - 1) * ($metaData['per_page'] ?? 25) + 1 }} 到
- {{ min(($metaData['page'] ?? 1) * ($metaData['per_page'] ?? 25), $metaData['total'] ?? 0) }} 条,
- 共 {{ $metaData['total'] ?? 0 }} 条记录
- </div>
- <div class="flex items-center gap-2">
- <button
- type="button"
- class="px-3 py-1 text-sm border rounded {{ $currentPage <= 1 ? 'opacity-50 cursor-not-allowed' : 'hover:bg-gray-50' }}"
- wire:click="previousPage"
- @disabled($currentPage <= 1)
- >
- 上一页
- </button>
- @foreach($this->getPages() as $page)
- <button
- type="button"
- class="px-3 py-1 text-sm border rounded {{ $page === $currentPage ? 'bg-primary-50 text-primary-700 border-primary-300' : 'hover:bg-gray-50' }}"
- wire:click="gotoPage({{ $page }})"
- >
- {{ $page }}
- </button>
- @endforeach
- <button
- type="button"
- class="px-3 py-1 text-sm border rounded {{ $currentPage >= ($metaData['total_pages'] ?? 1) ? 'opacity-50 cursor-not-allowed' : 'hover:bg-gray-50' }}"
- wire:click="nextPage"
- @disabled($currentPage >= ($metaData['total_pages'] ?? 1))
- >
- 下一页
- </button>
- </div>
- </div>
- </div>
- @endif
- </div>
- {{-- 加载指示器 --}}
- <div wire:loading class="fixed top-4 right-4 bg-primary-600 text-white px-4 py-2 rounded-lg shadow-lg flex items-center gap-2 z-50">
- <div class="animate-spin h-4 w-4 border-2 border-white border-t-transparent rounded-full"></div>
- <span>加载中...</span>
- </div>
- </x-filament::section>
- </div>
|