TextbookTable.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <?php
  2. namespace App\Filament\Resources\TextbookResource\Tables;
  3. use App\Filament\Resources\TextbookResource;
  4. use Filament\Actions\EditAction;
  5. use Filament\Actions\Action;
  6. use Filament\Actions\BulkAction;
  7. use Filament\Tables;
  8. use Filament\Tables\Columns\TextColumn;
  9. use Filament\Tables\Filters\SelectFilter;
  10. use Filament\Tables\Table;
  11. use Illuminate\Database\Eloquent\Model;
  12. use Filament\Tables\Enums\FiltersLayout;
  13. use Filament\Tables\Filters\Filter;
  14. use Filament\Forms\Components\TextInput;
  15. class TextbookTable
  16. {
  17. public static function make(Table $table): Table
  18. {
  19. // 直接返回配置好的表格,不使用query()
  20. return $table
  21. ->defaultSort('id', 'asc')
  22. ->columns([
  23. TextColumn::make('id')->label('ID')->sortable(),
  24. TextColumn::make('official_title')->label('教材名称')->searchable()->wrap(),
  25. TextColumn::make('series_name')->label('教材系列')->sortable(),
  26. TextColumn::make('stage')
  27. ->label('学段')
  28. ->sortable()
  29. ->formatStateUsing(fn ($state) => match ($state) {
  30. 'primary' => '小学',
  31. 'junior' => '初中',
  32. 'senior' => '高中',
  33. default => $state ?: '未标注',
  34. }),
  35. TextColumn::make('grade')->label('年级')->sortable(),
  36. TextColumn::make('semester')->label('学期')->sortable(),
  37. TextColumn::make('isbn')->label('ISBN')->toggleable(isToggledHiddenByDefault: true),
  38. TextColumn::make('status')
  39. ->label('状态')
  40. ->sortable()
  41. ->formatStateUsing(fn ($state) => match ($state) {
  42. 'draft' => '草稿',
  43. 'published' => '已发布',
  44. 'archived' => '已归档',
  45. default => $state ?: '未知',
  46. }),
  47. TextColumn::make('created_at')
  48. ->label('创建时间')
  49. ->dateTime()
  50. ->sortable()
  51. ->toggleable(isToggledHiddenByDefault: true),
  52. TextColumn::make('updated_at')
  53. ->label('更新时间')
  54. ->dateTime()
  55. ->sortable()
  56. ->toggleable(isToggledHiddenByDefault: true),
  57. ])
  58. ->filters([
  59. SelectFilter::make('stage')
  60. ->label('学段')
  61. ->options([
  62. 'primary' => '小学',
  63. 'junior' => '初中',
  64. 'senior' => '高中',
  65. ]),
  66. SelectFilter::make('grade')
  67. ->label('年级')
  68. ->options(collect(range(1, 12))->mapWithKeys(fn ($grade) => [$grade => "{$grade}年级"])->all()),
  69. SelectFilter::make('semester')
  70. ->label('学期')
  71. ->options([
  72. 1 => '上学期',
  73. 2 => '下学期',
  74. ]),
  75. SelectFilter::make('status')
  76. ->label('发布状态')
  77. ->options([
  78. 'draft' => '草稿',
  79. 'published' => '已发布',
  80. 'archived' => '已归档',
  81. ]),
  82. Filter::make('keyword')
  83. ->label('关键词')
  84. ->form([
  85. TextInput::make('value')
  86. ->placeholder('教材名称 / ISBN / 系列'),
  87. ]),
  88. ], layout: FiltersLayout::AboveContentCollapsible)
  89. ->actions([
  90. EditAction::make()
  91. ->label('编辑')
  92. ->icon('heroicon-o-pencil-square')
  93. ->iconButton()
  94. ->tooltip('编辑'),
  95. Action::make('delete')
  96. ->label('删除')
  97. ->color('danger')
  98. ->icon('heroicon-o-trash')
  99. ->iconButton()
  100. ->tooltip('删除')
  101. ->requiresConfirmation()
  102. ->modalHeading('删除教材')
  103. ->modalDescription('确定要删除这个教材吗?此操作无法撤销。')
  104. ->action(function (Model $record) {
  105. // 添加调试日志
  106. \Log::info('Deleting textbook', ['id' => $record->id, 'record' => $record]);
  107. if (!$record || !$record->id) {
  108. \Filament\Notifications\Notification::make()
  109. ->title('错误')
  110. ->body('无效的教材记录。')
  111. ->danger()
  112. ->send();
  113. return;
  114. }
  115. $apiService = app(\App\Services\TextbookApiService::class);
  116. $deleted = $apiService->deleteTextbook($record->id);
  117. \Log::info('Delete result', ['deleted' => $deleted]);
  118. if ($deleted) {
  119. \Filament\Notifications\Notification::make()
  120. ->title('成功')
  121. ->body('教材删除成功。')
  122. ->success()
  123. ->send();
  124. } else {
  125. \Filament\Notifications\Notification::make()
  126. ->title('错误')
  127. ->body('删除失败,请重试。')
  128. ->danger()
  129. ->send();
  130. }
  131. }),
  132. Action::make('view_catalog')
  133. ->label('查看目录')
  134. ->icon('heroicon-o-list-bullet')
  135. ->iconButton()
  136. ->tooltip('查看目录')
  137. ->url(fn(Model $record): string =>
  138. route('filament.admin.resources.textbook-catalogs.index', ['tableFilters[textbook_id][value]' => $record->id])
  139. ),
  140. ])
  141. ->bulkActions([
  142. \Filament\Actions\BulkActionGroup::make([
  143. \Filament\Actions\DeleteBulkAction::make()
  144. ->label('批量删除'),
  145. BulkAction::make('archive')
  146. ->label('批量归档')
  147. ->color('warning')
  148. ->icon('heroicon-o-archive-box')
  149. ->requiresConfirmation()
  150. ->action(function ($records): void {
  151. $apiService = app(\App\Services\TextbookApiService::class);
  152. foreach ($records as $record) {
  153. $apiService->updateTextbook((int) $record->id, ['status' => 'archived']);
  154. }
  155. }),
  156. ]),
  157. ])
  158. ->recordUrl(fn (Model $record): string => route('filament.admin.resources.textbooks.view', $record))
  159. ->defaultSort('sort_order')
  160. ->paginated([10, 25, 50, 100]);
  161. }
  162. }