feat(文档): 增加转换失败报错提醒和重试功能
- 在文档列表添加「重试转换」和「查看错误」操作按钮 - 在文档详情页添加「重试转换」功能和转换错误信息展示 - 创建错误详情视图,提供友好的错误信息和解决方案 - 重试功能会重置文档状态并重新派发转换任务 - 优化用户体验,提供清晰的错误提示和操作指引
This commit is contained in:
@@ -222,6 +222,57 @@ class DocumentResource extends Resource
|
||||
->placeholder('全部状态'),
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\Action::make('retry_conversion')
|
||||
->label('重试转换')
|
||||
->icon('heroicon-o-arrow-path')
|
||||
->color('warning')
|
||||
->visible(fn (Document $record): bool => $record->conversion_status === 'failed')
|
||||
->requiresConfirmation()
|
||||
->modalHeading('重试文档转换')
|
||||
->modalDescription(fn (Document $record): string =>
|
||||
'确定要重新转换文档 "' . $record->title . '" 吗?' .
|
||||
($record->conversion_error ? "\n\n上次失败原因:" . $record->conversion_error : '')
|
||||
)
|
||||
->modalSubmitActionLabel('确认重试')
|
||||
->action(function (Document $record) {
|
||||
try {
|
||||
// 重置转换状态
|
||||
$record->conversion_status = 'pending';
|
||||
$record->conversion_error = null;
|
||||
$record->save();
|
||||
|
||||
// 重新派发转换任务
|
||||
\App\Jobs\ConvertDocumentToMarkdown::dispatch($record);
|
||||
|
||||
\Filament\Notifications\Notification::make()
|
||||
->success()
|
||||
->title('重试成功')
|
||||
->body('文档转换任务已重新加入队列,请稍后查看转换结果。')
|
||||
->send();
|
||||
} catch (\Exception $e) {
|
||||
\Filament\Notifications\Notification::make()
|
||||
->danger()
|
||||
->title('重试失败')
|
||||
->body('无法重新派发转换任务:' . $e->getMessage())
|
||||
->send();
|
||||
}
|
||||
}),
|
||||
Tables\Actions\Action::make('view_error')
|
||||
->label('查看错误')
|
||||
->icon('heroicon-o-exclamation-triangle')
|
||||
->color('danger')
|
||||
->visible(fn (Document $record): bool =>
|
||||
$record->conversion_status === 'failed' && !empty($record->conversion_error)
|
||||
)
|
||||
->modalHeading('转换错误详情')
|
||||
->modalContent(fn (Document $record): \Illuminate\Contracts\View\View =>
|
||||
view('filament.modals.conversion-error', [
|
||||
'document' => $record,
|
||||
'error' => $record->conversion_error,
|
||||
])
|
||||
)
|
||||
->modalSubmitAction(false)
|
||||
->modalCancelActionLabel('关闭'),
|
||||
Tables\Actions\Action::make('preview')
|
||||
->label('预览 Markdown')
|
||||
->icon('heroicon-o-eye')
|
||||
|
||||
@@ -20,6 +20,47 @@ class ViewDocument extends ViewRecord
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\Action::make('retry_conversion')
|
||||
->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 {
|
||||
// 重置转换状态
|
||||
$this->record->conversion_status = 'pending';
|
||||
$this->record->conversion_error = null;
|
||||
$this->record->save();
|
||||
|
||||
// 重新派发转换任务
|
||||
\App\Jobs\ConvertDocumentToMarkdown::dispatch($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')
|
||||
@@ -107,6 +148,24 @@ class ViewDocument extends ViewRecord
|
||||
->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'),
|
||||
@@ -117,6 +176,19 @@ class ViewDocument extends ViewRecord
|
||||
])
|
||||
->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')
|
||||
|
||||
51
resources/views/filament/modals/conversion-error.blade.php
Normal file
51
resources/views/filament/modals/conversion-error.blade.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<div class="space-y-4">
|
||||
<div class="rounded-lg bg-danger-50 dark:bg-danger-900/20 p-4">
|
||||
<div class="flex items-start">
|
||||
<div class="flex-shrink-0">
|
||||
<svg class="h-5 w-5 text-danger-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-3 flex-1">
|
||||
<h3 class="text-sm font-medium text-danger-800 dark:text-danger-200">
|
||||
文档转换失败
|
||||
</h3>
|
||||
<div class="mt-2 text-sm text-danger-700 dark:text-danger-300">
|
||||
<p><strong>文档:</strong>{{ $document->title }}</p>
|
||||
<p><strong>文件名:</strong>{{ $document->file_name }}</p>
|
||||
<p><strong>失败时间:</strong>{{ $document->updated_at->format('Y年m月d日 H:i:s') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 class="text-sm font-medium text-gray-900 dark:text-gray-100 mb-2">错误信息:</h4>
|
||||
<div class="rounded-lg bg-gray-50 dark:bg-gray-800 p-4">
|
||||
<pre class="text-xs text-gray-700 dark:text-gray-300 whitespace-pre-wrap break-words font-mono">{{ $error }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rounded-lg bg-info-50 dark:bg-info-900/20 p-4">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<svg class="h-5 w-5 text-info-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-3 flex-1">
|
||||
<h3 class="text-sm font-medium text-info-800 dark:text-info-200">
|
||||
常见问题及解决方案
|
||||
</h3>
|
||||
<div class="mt-2 text-sm text-info-700 dark:text-info-300">
|
||||
<ul class="list-disc list-inside space-y-1">
|
||||
<li>如果错误提示无法连接到 Meilisearch,请确保搜索服务正常运行</li>
|
||||
<li>如果错误提示文件损坏或格式不支持,请检查原始文档是否完整</li>
|
||||
<li>如果错误提示超时,可能是文档过大或包含大量图片,请尝试优化文档</li>
|
||||
<li>您可以点击"重试转换"按钮重新尝试转换此文档</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,79 @@
|
||||
<div class="space-y-4">
|
||||
<div class="rounded-lg bg-danger-50 dark:bg-danger-900/20 p-4 border border-danger-200 dark:border-danger-800">
|
||||
<div class="flex items-start">
|
||||
<div class="flex-shrink-0">
|
||||
<svg class="h-6 w-6 text-danger-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-3 flex-1">
|
||||
<h3 class="text-base font-semibold text-danger-800 dark:text-danger-200">
|
||||
文档转换失败
|
||||
</h3>
|
||||
<div class="mt-3 text-sm text-danger-700 dark:text-danger-300">
|
||||
<p class="mb-1"><strong>失败时间:</strong>{{ $document->updated_at->format('Y年m月d日 H:i:s') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 class="text-sm font-semibold text-gray-900 dark:text-gray-100 mb-3">错误详情:</h4>
|
||||
<div class="rounded-lg bg-gray-100 dark:bg-gray-900 p-4 border border-gray-300 dark:border-gray-700">
|
||||
<pre class="text-sm text-gray-800 dark:text-gray-200 whitespace-pre-wrap break-words font-mono leading-relaxed">{{ $document->conversion_error }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rounded-lg bg-info-50 dark:bg-info-900/20 p-4 border border-info-200 dark:border-info-800">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<svg class="h-6 w-6 text-info-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-3 flex-1">
|
||||
<h3 class="text-sm font-semibold text-info-800 dark:text-info-200 mb-2">
|
||||
常见问题及解决方案
|
||||
</h3>
|
||||
<div class="text-sm text-info-700 dark:text-info-300">
|
||||
<ul class="space-y-2">
|
||||
<li class="flex items-start">
|
||||
<span class="mr-2">•</span>
|
||||
<span><strong>无法连接到 Meilisearch:</strong>请确保搜索服务正常运行,可以联系系统管理员检查服务状态</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="mr-2">•</span>
|
||||
<span><strong>文件损坏或格式不支持:</strong>请检查原始文档是否完整,确保文件格式为 .doc 或 .docx</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="mr-2">•</span>
|
||||
<span><strong>转换超时:</strong>可能是文档过大或包含大量图片,建议优化文档后重新上传</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="mr-2">•</span>
|
||||
<span><strong>Pandoc 错误:</strong>文档可能包含不支持的格式或特殊内容,请尝试简化文档格式</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rounded-lg bg-warning-50 dark:bg-warning-900/20 p-4 border border-warning-200 dark:border-warning-800">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<svg class="h-6 w-6 text-warning-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-3 flex-1">
|
||||
<h3 class="text-sm font-semibold text-warning-800 dark:text-warning-200 mb-2">
|
||||
下一步操作
|
||||
</h3>
|
||||
<div class="text-sm text-warning-700 dark:text-warning-300">
|
||||
<p>您可以点击页面右上角的 <strong>"重试转换"</strong> 按钮重新尝试转换此文档。如果问题持续存在,请联系系统管理员或尝试重新上传文档。</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user