label('重试转换') ->icon('heroicon-o-arrow-path') ->color('warning') ->visible(fn (): bool => $this->record->conversion_status === 'failed') ->requiresConfirmation() ->modalHeading('重试文档转换') ->modalDescription(fn (): string => '确定要重新转换文档 "' . $this->record->title . '" 吗?' . ($this->record->conversion_error ? "\n\n上次失败原因:" . $this->record->conversion_error : '') ) ->modalSubmitActionLabel('确认重试') ->action(function () { try { app(\App\Services\DocumentConversionService::class) ->queueConversion($this->record); Notification::make() ->success() ->title('重试成功') ->body('文档转换任务已重新加入队列,请稍后查看转换结果。') ->send(); $this->refreshFormData([ 'conversion_status', 'conversion_error', ]); } catch (\Exception $e) { Notification::make() ->danger() ->title('重试失败') ->body('无法重新派发转换任务:' . $e->getMessage()) ->send(); } }), Actions\Action::make('preview') ->label('预览 Markdown') ->icon('heroicon-o-eye') ->color('info') ->visible(fn (): bool => $this->record->conversion_status === 'completed') ->url(fn (): string => route('documents.preview', $this->record)) ->openUrlInNewTab() ->tooltip(fn (): ?string => $this->record->conversion_status !== 'completed' ? '文档尚未完成转换' : null ), Actions\Action::make('download') ->label('下载文档') ->icon('heroicon-o-arrow-down-tray') ->color('success') ->action(function () { $documentService = app(DocumentService::class); $user = auth()->user(); try { // 记录下载日志 $documentService->logDownload($this->record, $user); // 返回文件下载响应 return $documentService->downloadDocument($this->record, $user); } catch (\Exception $e) { Notification::make() ->danger() ->title('下载失败') ->body($e->getMessage()) ->send(); return null; } }), Actions\EditAction::make() ->label('编辑'), Actions\DeleteAction::make() ->label('删除'), ]; } public function infolist(Infolist $infolist): Infolist { return $infolist ->schema([ Section::make('文档信息') ->schema([ TextEntry::make('title') ->label('文档标题') ->size(TextEntry\TextEntrySize::Large) ->weight('bold'), TextEntry::make('description') ->label('文档描述') ->placeholder('无描述') ->columnSpanFull(), TextEntry::make('knowledgeBase.name') ->label('所属知识库'), TextEntry::make('uploader.name') ->label('上传者'), TextEntry::make('display_file_name') ->label('文件名'), TextEntry::make('file_size') ->label('文件大小') ->formatStateUsing(fn ($state): string => DocumentResource::formatFileSize($state)), TextEntry::make('conversion_status') ->label('转换状态') ->badge() ->color(fn (?string $state): string => match ($state) { 'completed' => 'success', 'processing' => 'info', 'pending' => 'warning', 'failed' => 'danger', default => 'gray', }) ->formatStateUsing(fn (?string $state): string => match ($state) { 'completed' => '已完成', 'processing' => '转换中', 'pending' => '等待转换', 'failed' => '转换失败', default => '未知', }), TextEntry::make('created_at') ->label('上传时间') ->dateTime('Y年m月d日 H:i:s'), TextEntry::make('updated_at') ->label('更新时间') ->dateTime('Y年m月d日 H:i:s'), ]) ->columns(2), Section::make('转换错误信息') ->schema([ ViewEntry::make('conversion_error') ->label('') ->view('filament.resources.document.conversion-error-detail') ->viewData([ 'document' => $this->record, ]), ]) ->visible(fn ($record) => $record->conversion_status === 'failed' && !empty($record->conversion_error)) ->collapsible() ->collapsed(false), Section::make('文档预览') ->schema([ ViewEntry::make('preview') ->label('') ->view('filament.resources.document.preview') ->viewData([ 'document' => $this->record, ]), ]) ->collapsible() ->collapsed(false), ]); } }