TextbookTable.php 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. <?php
  2. namespace App\Livewire;
  3. use App\Services\TextbookApiService;
  4. use Filament\Tables;
  5. use Filament\Tables\Table;
  6. use Filament\Livewire\Concerns\InteractsWithTables;
  7. use Livewire\Component;
  8. use Illuminate\Database\Eloquent\Model;
  9. class TextbookTable extends Component implements Tables\Contracts\HasTable
  10. {
  11. use InteractsWithTables;
  12. public function render()
  13. {
  14. return view('livewire.textbook-table');
  15. }
  16. public function table(Table $table): Table
  17. {
  18. return $table
  19. ->query(function () {
  20. // 返回空查询,实际数据通过 getTableRecords 提供
  21. return \App\Models\Textbook::query()->whereRaw('1=0');
  22. })
  23. ->columns([
  24. Tables\Columns\TextColumn::make('id')
  25. ->label('ID')
  26. ->sortable(),
  27. Tables\Columns\TextColumn::make('series.name')
  28. ->label('系列')
  29. ->searchable(),
  30. Tables\Columns\TextColumn::make('official_title')
  31. ->label('官方书名')
  32. ->searchable()
  33. ->wrap(),
  34. Tables\Columns\TextColumn::make('stage')
  35. ->label('学段')
  36. ->formatStateUsing(function ($state): string {
  37. return match ($state) {
  38. 'primary' => '小学',
  39. 'junior' => '初中',
  40. 'senior' => '高中',
  41. default => $state,
  42. };
  43. })
  44. ->badge()
  45. ->color('info'),
  46. Tables\Columns\TextColumn::make('grade')
  47. ->label('年级')
  48. ->formatStateUsing(function ($state): string {
  49. return $state ? "{$state}年级" : '-';
  50. }),
  51. Tables\Columns\TextColumn::make('semester')
  52. ->label('学期')
  53. ->formatStateUsing(function ($state): string {
  54. return match ($state) {
  55. 1 => '上学期',
  56. 2 => '下学期',
  57. default => '-',
  58. };
  59. })
  60. ->badge()
  61. ->color('success'),
  62. Tables\Columns\TextColumn::make('naming_scheme')
  63. ->label('体系')
  64. ->formatStateUsing(function ($state): string {
  65. return match ($state) {
  66. 'new' => '新体系',
  67. 'old' => '旧体系',
  68. default => $state,
  69. };
  70. })
  71. ->badge(),
  72. Tables\Columns\TextColumn::make('status')
  73. ->label('状态')
  74. ->formatStateUsing(function ($state): string {
  75. return match ($state) {
  76. 'draft' => '草稿',
  77. 'published' => '已发布',
  78. 'archived' => '已归档',
  79. default => $state,
  80. };
  81. })
  82. ->badge()
  83. ->color(function ($state): string {
  84. return match ($state) {
  85. 'draft' => 'gray',
  86. 'published' => 'success',
  87. 'archived' => 'danger',
  88. default => 'gray',
  89. };
  90. }),
  91. Tables\Columns\TextColumn::make('created_at')
  92. ->label('创建时间')
  93. ->dateTime()
  94. ->sortable()
  95. ->toggleable(isToggledHiddenByDefault: true),
  96. Tables\Columns\TextColumn::make('updated_at')
  97. ->label('更新时间')
  98. ->dateTime()
  99. ->sortable()
  100. ->toggleable(isToggledHiddenByDefault: true),
  101. ])
  102. ->filters([
  103. Tables\Filters\SelectFilter::make('stage')
  104. ->label('学段')
  105. ->options([
  106. 'primary' => '小学',
  107. 'junior' => '初中',
  108. 'senior' => '高中',
  109. ]),
  110. Tables\Filters\SelectFilter::make('status')
  111. ->label('状态')
  112. ->options([
  113. 'draft' => '草稿',
  114. 'published' => '已发布',
  115. 'archived' => '已归档',
  116. ]),
  117. ])
  118. ->actions([
  119. Tables\Actions\EditAction::make()
  120. ->label('编辑'),
  121. Tables\Actions\Action::make('delete')
  122. ->label('删除')
  123. ->color('danger')
  124. ->icon('heroicon-o-trash')
  125. ->requiresConfirmation()
  126. ->modalHeading('删除教材')
  127. ->modalDescription('确定要删除这个教材吗?此操作无法撤销。')
  128. ->action(function (Model $record) {
  129. // 在Livewire组件中,模型正确传递
  130. \Log::info('Livewire delete triggered', [
  131. 'record_id' => $record->id,
  132. 'record_class' => get_class($record)
  133. ]);
  134. try {
  135. $apiService = app(TextbookApiService::class);
  136. $deleted = $apiService->deleteTextbook($record->id);
  137. \Log::info('Delete API result', [
  138. 'deleted' => $deleted,
  139. 'record_id' => $record->id
  140. ]);
  141. if ($deleted) {
  142. \Filament\Notifications\Notification::make()
  143. ->title('成功')
  144. ->body('教材删除成功。')
  145. ->success()
  146. ->send();
  147. } else {
  148. \Filament\Notifications\Notification::make()
  149. ->title('错误')
  150. ->body('删除失败,请重试。')
  151. ->danger()
  152. ->send();
  153. }
  154. } catch (\Exception $e) {
  155. \Log::error('Delete error', [
  156. 'error' => $e->getMessage(),
  157. 'record_id' => $record->id
  158. ]);
  159. \Filament\Notifications\Notification::make()
  160. ->title('错误')
  161. ->body('删除失败:' . $e->getMessage())
  162. ->danger()
  163. ->send();
  164. }
  165. }),
  166. Tables\Actions\Action::make('view_catalog')
  167. ->label('查看目录')
  168. ->icon('heroicon-o-list-bullet')
  169. ->url(fn(Model $record): string =>
  170. route('filament.admin.resources.textbook-catalogs.index', ['tableFilters[textbook_id][value]' => $record->id])
  171. ),
  172. ])
  173. ->bulkActions([
  174. Tables\Actions\BulkActionGroup::make([
  175. Tables\Actions\DeleteBulkAction::make()
  176. ->label('批量删除'),
  177. ]),
  178. ])
  179. ->defaultSort('sort_order')
  180. ->paginated([10, 25, 50, 100]);
  181. }
  182. public function getTableRecords(): array
  183. {
  184. // 从 API 获取数据
  185. $apiService = app(TextbookApiService::class);
  186. $result = $apiService->getTextbooks();
  187. $records = [];
  188. foreach ($result['data'] ?? [] as $item) {
  189. $model = new \App\Models\Textbook();
  190. // 使用 setAttribute 确保属性正确设置
  191. foreach ($item as $key => $value) {
  192. $model->setAttribute($key, $value);
  193. }
  194. $model->exists = true;
  195. $model->id = $item['id'];
  196. // 设置关联
  197. if (isset($item['series'])) {
  198. $seriesModel = new \App\Models\TextbookSeries();
  199. foreach ($item['series'] as $key => $value) {
  200. $seriesModel->setAttribute($key, $value);
  201. }
  202. $seriesModel->exists = true;
  203. $model->setRelation('series', $seriesModel);
  204. }
  205. $records[] = $model;
  206. }
  207. return $records;
  208. }
  209. }