diff --git a/app/Console/Commands/FixStuckDocuments.php b/app/Console/Commands/FixStuckDocuments.php new file mode 100644 index 0000000..4c980c0 --- /dev/null +++ b/app/Console/Commands/FixStuckDocuments.php @@ -0,0 +1,103 @@ +option('timeout'); + $status = $this->option('status'); + $dryRun = $this->option('dry-run'); + + $this->info("正在查找卡住的文档..."); + $this->info("状态: {$status}"); + $this->info("超时时间: {$timeout} 分钟"); + + // 查找卡住的文档 + $stuckDocuments = Document::where('conversion_status', $status) + ->where('updated_at', '<', now()->subMinutes($timeout)) + ->get(); + + if ($stuckDocuments->isEmpty()) { + $this->info('✓ 没有发现卡住的文档'); + return self::SUCCESS; + } + + $this->warn("发现 {$stuckDocuments->count()} 个卡住的文档:"); + + // 显示文档列表 + $tableData = $stuckDocuments->map(function ($doc) { + return [ + 'ID' => $doc->id, + '标题' => \Illuminate\Support\Str::limit($doc->title, 40), + '状态' => $doc->conversion_status, + '更新时间' => $doc->updated_at->format('Y-m-d H:i:s'), + '卡住时长' => $doc->updated_at->diffForHumans(), + ]; + })->toArray(); + + $this->table( + ['ID', '标题', '状态', '更新时间', '卡住时长'], + $tableData + ); + + if ($dryRun) { + $this->info(''); + $this->info('这是预览模式,没有实际修改任何数据'); + $this->info('移除 --dry-run 选项以执行修复'); + return self::SUCCESS; + } + + // 确认操作 + if (!$this->confirm('是否要将这些文档标记为失败状态?', true)) { + $this->info('操作已取消'); + return self::SUCCESS; + } + + // 修复文档 + $fixed = 0; + foreach ($stuckDocuments as $document) { + try { + $document->update([ + 'conversion_status' => 'failed', + 'conversion_error' => "转换任务超时(卡在 {$status} 状态超过 {$timeout} 分钟)", + ]); + $fixed++; + $this->line("✓ 已修复: [{$document->id}] {$document->title}"); + } catch (\Exception $e) { + $this->error("✗ 修复失败: [{$document->id}] {$document->title} - {$e->getMessage()}"); + } + } + + $this->info(''); + $this->info("修复完成!共修复 {$fixed} 个文档"); + $this->info('现在可以在管理界面使用"重试转换"功能重新处理这些文档'); + + return self::SUCCESS; + } +} diff --git a/app/Filament/Resources/DocumentResource.php b/app/Filament/Resources/DocumentResource.php index 56e633c..f0f93e2 100644 --- a/app/Filament/Resources/DocumentResource.php +++ b/app/Filament/Resources/DocumentResource.php @@ -226,12 +226,20 @@ class DocumentResource extends Resource ->label('重试转换') ->icon('heroicon-o-arrow-path') ->color('warning') - ->visible(fn (Document $record): bool => $record->conversion_status === 'failed') + ->visible(fn (Document $record): bool => + in_array($record->conversion_status, ['failed', 'processing', 'pending']) + ) ->requiresConfirmation() ->modalHeading('重试文档转换') ->modalDescription(fn (Document $record): string => '确定要重新转换文档 "' . $record->title . '" 吗?' . - ($record->conversion_error ? "\n\n上次失败原因:" . $record->conversion_error : '') + "\n\n当前状态:" . match($record->conversion_status) { + 'failed' => '转换失败', + 'processing' => '转换中(可能卡住)', + 'pending' => '等待转换', + default => $record->conversion_status, + } . + ($record->conversion_error ? "\n\n错误信息:" . $record->conversion_error : '') ) ->modalSubmitActionLabel('确认重试') ->action(function (Document $record) {