| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- <?php
- namespace App\Filament\Resources\TextbookResource\Tables;
- use App\Filament\Resources\TextbookResource;
- use Filament\Actions\EditAction;
- use Filament\Actions\Action;
- use Filament\Actions\BulkAction;
- use Filament\Tables;
- use Filament\Tables\Columns\TextColumn;
- use Filament\Tables\Filters\SelectFilter;
- use Filament\Tables\Table;
- use Illuminate\Database\Eloquent\Model;
- use Illuminate\Support\Facades\Storage;
- use Illuminate\Support\Str;
- use Filament\Tables\Enums\FiltersLayout;
- use Filament\Tables\Filters\Filter;
- use Filament\Forms\Components\TextInput;
- class TextbookTable
- {
- public static function make(Table $table): Table
- {
- // 直接返回配置好的表格,不使用query()
- return $table
- ->columns([
- TextColumn::make('official_title')
- ->label('教材信息')
- ->html()
- ->formatStateUsing(function ($state, Model $record): string {
- $cover = $record->cover_path ?? null;
- $coverUrl = null;
- if ($cover) {
- $coverUrl = Str::startsWith($cover, ['http://', 'https://', '/'])
- ? $cover
- : Storage::disk('public')->url($cover);
- }
- $seriesName = $record->series->name ?? '未归类系列';
- $stage = match ($record->stage) {
- 'primary' => '小学',
- 'junior' => '初中',
- 'senior' => '高中',
- default => $record->stage ?: '未标注',
- };
- $semester = match ($record->semester) {
- 1 => '上学期',
- 2 => '下学期',
- default => '未标注',
- };
- $naming = match ($record->naming_scheme) {
- 'new' => '新体系',
- 'old' => '旧体系',
- default => $record->naming_scheme ?: '未标注',
- };
- $status = match ($record->status) {
- 'draft' => '草稿',
- 'published' => '已发布',
- 'archived' => '已归档',
- default => $record->status ?: '未知',
- };
- $badgeTone = match ($record->status) {
- 'published' => 'text-emerald-600 bg-emerald-50 border-emerald-100',
- 'draft' => 'text-amber-600 bg-amber-50 border-amber-100',
- 'archived' => 'text-slate-500 bg-slate-100 border-slate-200',
- default => 'text-slate-500 bg-slate-100 border-slate-200',
- };
- $title = e($state ?: '未命名教材');
- $coverHtml = $coverUrl
- ? "<img src=\"{$coverUrl}\" alt=\"封面\" class=\"h-16 w-12 rounded-md border border-slate-200 object-cover\" />"
- : "<div class=\"flex h-16 w-12 items-center justify-center rounded-md border border-dashed border-slate-200 bg-slate-50 text-xs text-slate-400\">封面</div>";
- $gradeLabel = $record->grade ? "{$record->grade}年级" : '年级未标注';
- $isbnLabel = $record->isbn ?: '未填写';
- return <<<HTML
- <div class="flex items-start gap-4">
- {$coverHtml}
- <div class="min-w-0 flex-1">
- <div class="flex flex-wrap items-center gap-2">
- <div class="font-semibold text-slate-900">{$title}</div>
- <span class="inline-flex items-center rounded-full border px-2 py-0.5 text-xs {$badgeTone}">{$status}</span>
- </div>
- <div class="mt-1 text-xs text-slate-500">{$seriesName} · {$stage} · {$gradeLabel} · {$semester}</div>
- <div class="mt-2 flex flex-wrap gap-2 text-xs text-slate-500">
- <span class="ui-tag">体系:{$naming}</span>
- <span class="ui-tag">ISBN:{$isbnLabel}</span>
- <span class="ui-tag">ID:{$record->id}</span>
- </div>
- </div>
- </div>
- HTML;
- })
- ->wrap(),
- TextColumn::make('created_at')
- ->label('创建时间')
- ->dateTime()
- ->sortable()
- ->toggleable(isToggledHiddenByDefault: true),
- TextColumn::make('updated_at')
- ->label('更新时间')
- ->dateTime()
- ->sortable()
- ->toggleable(isToggledHiddenByDefault: true),
- ])
- ->filters([
- SelectFilter::make('stage')
- ->label('学段')
- ->options([
- 'primary' => '小学',
- 'junior' => '初中',
- 'senior' => '高中',
- ]),
- SelectFilter::make('grade')
- ->label('年级')
- ->options(collect(range(1, 12))->mapWithKeys(fn ($grade) => [$grade => "{$grade}年级"])->all()),
- SelectFilter::make('semester')
- ->label('学期')
- ->options([
- 1 => '上学期',
- 2 => '下学期',
- ]),
- SelectFilter::make('naming_scheme')
- ->label('教材体系')
- ->options([
- 'new' => '新体系',
- 'old' => '旧体系',
- ]),
- SelectFilter::make('status')
- ->label('发布状态')
- ->options([
- 'draft' => '草稿',
- 'published' => '已发布',
- 'archived' => '已归档',
- ]),
- Filter::make('keyword')
- ->label('关键词')
- ->form([
- TextInput::make('value')
- ->placeholder('教材名称 / ISBN / 系列'),
- ]),
- ], layout: FiltersLayout::AboveContentCollapsible)
- ->actions([
- EditAction::make()
- ->label('编辑')
- ->icon('heroicon-o-pencil-square')
- ->iconButton()
- ->tooltip('编辑'),
- Action::make('delete')
- ->label('删除')
- ->color('danger')
- ->icon('heroicon-o-trash')
- ->iconButton()
- ->tooltip('删除')
- ->requiresConfirmation()
- ->modalHeading('删除教材')
- ->modalDescription('确定要删除这个教材吗?此操作无法撤销。')
- ->action(function (Model $record) {
- // 添加调试日志
- \Log::info('Deleting textbook', ['id' => $record->id, 'record' => $record]);
- if (!$record || !$record->id) {
- \Filament\Notifications\Notification::make()
- ->title('错误')
- ->body('无效的教材记录。')
- ->danger()
- ->send();
- return;
- }
- $apiService = app(\App\Services\TextbookApiService::class);
- $deleted = $apiService->deleteTextbook($record->id);
- \Log::info('Delete result', ['deleted' => $deleted]);
- if ($deleted) {
- \Filament\Notifications\Notification::make()
- ->title('成功')
- ->body('教材删除成功。')
- ->success()
- ->send();
- } else {
- \Filament\Notifications\Notification::make()
- ->title('错误')
- ->body('删除失败,请重试。')
- ->danger()
- ->send();
- }
- }),
- Action::make('view_catalog')
- ->label('查看目录')
- ->icon('heroicon-o-list-bullet')
- ->iconButton()
- ->tooltip('查看目录')
- ->url(fn(Model $record): string =>
- route('filament.admin.resources.textbook-catalogs.index', ['tableFilters[textbook_id][value]' => $record->id])
- ),
- ])
- ->bulkActions([
- \Filament\Actions\BulkActionGroup::make([
- \Filament\Actions\DeleteBulkAction::make()
- ->label('批量删除'),
- BulkAction::make('archive')
- ->label('批量归档')
- ->color('warning')
- ->icon('heroicon-o-archive-box')
- ->requiresConfirmation()
- ->action(function ($records): void {
- $apiService = app(\App\Services\TextbookApiService::class);
- foreach ($records as $record) {
- $apiService->updateTextbook((int) $record->id, ['status' => 'archived']);
- }
- }),
- ]),
- ])
- ->recordUrl(fn (Model $record): string => route('filament.admin.resources.textbooks.view', $record))
- ->defaultSort('sort_order')
- ->paginated([10, 25, 50, 100]);
- }
- }
|