defaultSort('id', 'asc')
->columns([
TextColumn::make('id')->label('ID')->sortable(),
TextColumn::make('official_title')
->label('教材名称')
->searchable()
->wrap()
// 副标题链接:不依赖单独「配图」列是否被横向滚动/列管理隐藏,用户一定能点到
->description(function (Model $record): HtmlString {
$href = TextbookResource::getUrl('covers', ['record' => $record->getKey()]);
return new HtmlString(
'管理配图'
);
}),
// 独立列:用 HTML 直链,避免 TextColumn::url() + icon/color 与 getUrl($stateItem) 组合导致链接丢失
TextColumn::make('covers_nav')
->label('配图')
->alignCenter()
->tooltip('上传、排序、删除多图(独立页面)')
->state(static fn (): string => "\u{00A0}")
->formatStateUsing(static function ($state, TextColumn $column): HtmlString {
$href = TextbookResource::getUrl('covers', ['record' => $column->getRecord()->getKey()]);
return new HtmlString(
'管理配图'
);
})
->html(),
TextColumn::make('series_name')->label('教材系列')->sortable(),
TextColumn::make('series_id')->label('系列ID')->sortable(),
TextColumn::make('stage')
->label('学段')
->sortable()
->formatStateUsing(fn ($state) => match ($state) {
'primary' => '小学',
'junior' => '初中',
'senior' => '高中',
default => $state ?: '未标注',
}),
TextColumn::make('grade')->label('年级')->sortable(),
TextColumn::make('semester')->label('学期')->sortable(),
TextColumn::make('isbn')->label('ISBN')->toggleable(isToggledHiddenByDefault: true),
TextColumn::make('status')
->label('状态')
->sortable()
->formatStateUsing(fn ($state) => match ($state) {
'draft' => '草稿',
'published' => '已发布',
'archived' => '已归档',
default => $state ?: '未知',
}),
TextColumn::make('created_at')
->label('创建时间')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
TextColumn::make('updated_at')
->label('更新时间')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
SelectFilter::make('series_id')
->label('教材系列')
->options(fn (): array => TextbookSeries::query()
->orderBy('sort_order')
->orderBy('id')
->pluck('name', 'id')
->toArray()),
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('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('covers')
->label('配图')
->icon('heroicon-o-photo')
->color('primary')
->tooltip('管理配图')
->url(fn (Model $record): string => TextbookResource::getUrl('covers', ['record' => $record->getKey()])),
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', ['filters[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]);
}
}