schema([ Forms\Components\TextInput::make('title')->label('标题')->disabled(), Forms\Components\TextInput::make('full_title')->label('完整标题')->disabled(), Forms\Components\TextInput::make('chapter')->label('章节')->disabled(), Forms\Components\TextInput::make('grade')->label('年级')->disabled(), Forms\Components\TextInput::make('term')->label('学期')->disabled(), Forms\Components\Textarea::make('raw_markdown') ->label('卷子原始 Markdown') ->rows(12) ->disabled(), ]); } public static function table(Table $table): Table { return $table ->columns([ Tables\Columns\TextColumn::make('id')->label('ID')->sortable(), Tables\Columns\TextColumn::make('title')->label('卷标题')->searchable(), Tables\Columns\TextColumn::make('grade')->label('年级'), Tables\Columns\TextColumn::make('term')->label('学期'), Tables\Columns\TextColumn::make('source_type')->label('类型'), Tables\Columns\TextColumn::make('parts_sum_question_count') ->label('题量') ->getStateUsing(fn (Model $record) => $record->parts_sum_question_count ?? 0) ->sortable(), Tables\Columns\TextColumn::make('parts_count') ->label('区块数') ->getStateUsing(fn (Model $record) => $record->parts_count ?? 0) ->sortable(), Tables\Columns\TextColumn::make('file.original_filename')->label('来源文件')->toggleable(), ]) ->filters([ SelectFilter::make('grade') ->label('年级') ->options(collect(range(1, 12))->mapWithKeys(fn ($grade) => [$grade => "{$grade}年级"])->all()), SelectFilter::make('term') ->label('学期') ->options([ '上学期' => '上学期', '下学期' => '下学期', ]), SelectFilter::make('source_type') ->label('来源类型') ->options([ 'textbook' => '教材', 'exam' => '考试', 'other' => '其他', ]), Filter::make('question_range') ->label('题量范围') ->form([ TextInput::make('min')->placeholder('最小题量')->numeric(), TextInput::make('max')->placeholder('最大题量')->numeric(), ]) ->query(function (Builder $query, array $data) { $min = $data['min'] ?? null; $max = $data['max'] ?? null; if ($min !== null && $min !== '') { $query->having('parts_sum_question_count', '>=', (int) $min); } if ($max !== null && $max !== '') { $query->having('parts_sum_question_count', '<=', (int) $max); } }), ], layout: FiltersLayout::AboveContentCollapsible) ->actions([ ViewAction::make() ->icon('heroicon-o-eye') ->iconButton() ->tooltip('查看详情'), Action::make('generate_questions') ->label('入库题库') ->icon('heroicon-o-sparkles') ->requiresConfirmation() ->action(function (SourcePaper $record) { $taskId = app(TaskManager::class)->createTask( TaskManager::TASK_TYPE_ANALYSIS, ['type' => 'source_paper_import', 'paper_ids' => [$record->id]] ); PromoteSourcePapersJob::dispatch($taskId, [$record->id]); Notification::make() ->title("已加入队列,任务号:{$taskId}") ->success() ->send(); }), ]) ->bulkActions([ BulkActionGroup::make([ GenerateQuestionsBulkAction::make(), ]), ]) ->recordUrl(fn (Model $record): string => route('filament.admin.resources.source-papers.view', $record)); } public static function getRelations(): array { return [ PaperPartsRelationManager::class, PreQuestionCandidatesRelationManager::class, ]; } public static function getPages(): array { return [ 'index' => Pages\ListSourcePapers::route('/'), 'view' => Pages\ViewSourcePaper::route('/{record}'), ]; } public static function getEloquentQuery(): Builder { return parent::getEloquentQuery() ->with(['file']) ->withCount(['parts', 'candidates']) ->withSum('parts', 'question_count'); } }