SourcePaperResource.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. <?php
  2. namespace App\Filament\Resources;
  3. use App\Filament\Resources\SourcePaperResource\Pages;
  4. use App\Filament\Resources\SourcePaperResource\RelationManagers\PaperPartsRelationManager;
  5. use App\Models\SourcePaper;
  6. use Filament\Forms;
  7. use Filament\Resources\Resource;
  8. use Filament\Schemas\Schema;
  9. use Filament\Tables;
  10. use Filament\Tables\Table;
  11. use Filament\Actions\ViewAction;
  12. use Illuminate\Database\Eloquent\Model;
  13. use BackedEnum;
  14. use UnitEnum;
  15. use Filament\Tables\Enums\FiltersLayout;
  16. use Filament\Tables\Filters\SelectFilter;
  17. use Filament\Tables\Filters\Filter;
  18. use Filament\Forms\Components\TextInput;
  19. use Illuminate\Database\Eloquent\Builder;
  20. class SourcePaperResource extends Resource
  21. {
  22. protected static ?string $model = SourcePaper::class;
  23. protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-document-text';
  24. protected static UnitEnum|string|null $navigationGroup = '卷子导入流程';
  25. protected static ?string $navigationLabel = '源卷子列表';
  26. protected static ?int $navigationSort = 3;
  27. public static function canCreate(): bool
  28. {
  29. return false;
  30. }
  31. public static function canEdit(Model $record): bool
  32. {
  33. return false;
  34. }
  35. public static function form(Schema $schema): Schema
  36. {
  37. return $schema->schema([
  38. Forms\Components\TextInput::make('title')->label('标题')->disabled(),
  39. Forms\Components\TextInput::make('full_title')->label('完整标题')->disabled(),
  40. Forms\Components\TextInput::make('chapter')->label('章节')->disabled(),
  41. Forms\Components\TextInput::make('grade')->label('年级')->disabled(),
  42. Forms\Components\TextInput::make('term')->label('学期')->disabled(),
  43. Forms\Components\Textarea::make('raw_markdown')
  44. ->label('卷子原始 Markdown')
  45. ->rows(12)
  46. ->disabled(),
  47. ]);
  48. }
  49. public static function table(Table $table): Table
  50. {
  51. return $table
  52. ->columns([
  53. Tables\Columns\TextColumn::make('order')->label('顺序')->sortable(),
  54. Tables\Columns\TextColumn::make('title')->label('卷标题')->searchable(),
  55. Tables\Columns\TextColumn::make('file.original_filename')->label('来源文件')->toggleable(),
  56. Tables\Columns\TextColumn::make('grade')->label('年级'),
  57. Tables\Columns\TextColumn::make('term')->label('学期'),
  58. Tables\Columns\TextColumn::make('source_type')->label('类型'),
  59. Tables\Columns\TextColumn::make('parts_sum_question_count')
  60. ->label('题量')
  61. ->getStateUsing(fn (Model $record) => $record->parts_sum_question_count ?? 0)
  62. ->sortable(),
  63. Tables\Columns\TextColumn::make('parts_count')
  64. ->label('区块数')
  65. ->getStateUsing(fn (Model $record) => $record->parts_count ?? 0)
  66. ->sortable(),
  67. ])
  68. ->filters([
  69. SelectFilter::make('grade')
  70. ->label('年级')
  71. ->options(collect(range(1, 12))->mapWithKeys(fn ($grade) => [$grade => "{$grade}年级"])->all()),
  72. SelectFilter::make('term')
  73. ->label('学期')
  74. ->options([
  75. '上学期' => '上学期',
  76. '下学期' => '下学期',
  77. ]),
  78. SelectFilter::make('source_type')
  79. ->label('来源类型')
  80. ->options([
  81. 'textbook' => '教材',
  82. 'exam' => '考试',
  83. 'other' => '其他',
  84. ]),
  85. Filter::make('question_range')
  86. ->label('题量范围')
  87. ->form([
  88. TextInput::make('min')->placeholder('最小题量')->numeric(),
  89. TextInput::make('max')->placeholder('最大题量')->numeric(),
  90. ])
  91. ->query(function (Builder $query, array $data) {
  92. $min = $data['min'] ?? null;
  93. $max = $data['max'] ?? null;
  94. if ($min !== null && $min !== '') {
  95. $query->having('parts_sum_question_count', '>=', (int) $min);
  96. }
  97. if ($max !== null && $max !== '') {
  98. $query->having('parts_sum_question_count', '<=', (int) $max);
  99. }
  100. }),
  101. ], layout: FiltersLayout::AboveContentCollapsible)
  102. ->actions([
  103. ViewAction::make()
  104. ->icon('heroicon-o-eye')
  105. ->iconButton()
  106. ->tooltip('查看详情'),
  107. ])
  108. ->recordUrl(fn (Model $record): string => route('filament.admin.resources.source-papers.view', $record));
  109. }
  110. public static function getRelations(): array
  111. {
  112. return [
  113. PaperPartsRelationManager::class,
  114. ];
  115. }
  116. public static function getPages(): array
  117. {
  118. return [
  119. 'index' => Pages\ListSourcePapers::route('/'),
  120. 'view' => Pages\ViewSourcePaper::route('/{record}'),
  121. ];
  122. }
  123. public static function getEloquentQuery(): Builder
  124. {
  125. return parent::getEloquentQuery()
  126. ->with(['file'])
  127. ->withCount(['parts', 'candidates'])
  128. ->withSum('parts', 'question_count');
  129. }
  130. }