From 13f017e806c3babec5cfecd58c32ff60dbb9b80a Mon Sep 17 00:00:00 2001 From: gouki Date: Sun, 11 Oct 2026 19:31:11 +0000 Subject: [PATCH] fix(import): preserve original attachment filepath structure; enable admin SPA mode --- app/Blog/Services/AttachmentImporter.php | 51 +++++++++++-------- app/Providers/Filament/AdminPanelProvider.php | 1 + 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/app/Blog/Services/AttachmentImporter.php b/app/Blog/Services/AttachmentImporter.php index 9cb27f9..cb44e89 100644 --- a/app/Blog/Services/AttachmentImporter.php +++ b/app/Blog/Services/AttachmentImporter.php @@ -53,31 +53,42 @@ class AttachmentImporter if ($source && $syncNow) { try { - $media = $post->addMedia($source) - ->preservingOriginal() - ->withCustomProperties($properties) - ->usingFileName(basename($row['filename']) ?: basename($source)) - ->toMediaCollection('attachments', MediaDisk::name()); + $disk = MediaDisk::name(); + $filename = basename($row['filename']) ?: basename($source); + $legacyPath = ltrim($row['filepath'] ?? '', '/'); - $media->setCustomProperty('pending_sync', false); + // 保留原始目录结构:date_200802/xxx.jpg + if ($legacyPath) { + $legacyDir = dirname($legacyPath); + $storagePath = ($legacyDir !== '.' ? $legacyDir . '/' : '') . $filename; + } else { + $storagePath = $filename; + } + + // 直接写文件到目标存储,不走 spatie 的自动路径生成 + $content = file_get_contents($source); + \Illuminate\Support\Facades\Storage::disk($disk)->put($storagePath, $content, ['visibility' => 'public']); + + // 手动创建 media 记录 + $media = new Media; + $media->model_type = Post::class; + $media->model_id = $post->id; + $media->uuid = (string) Str::uuid(); + $media->collection_name = 'attachments'; + $media->name = pathinfo($filename, PATHINFO_FILENAME) ?: 'attachment'; + $media->file_name = $filename; + $media->mime_type = $row['filetype'] ?: null; + $media->size = (int) ($row['filesize'] ?? 0); + $media->disk = $disk; + $media->conversions_disk = $disk; + $media->manipulations = []; + $media->custom_properties = $properties; + $media->generated_conversions = []; + $media->responsive_images = []; $media->save(); return $media; } catch (\Throwable $e) { - // addMedia 可能已插入记录并保存文件,仅缩略图生成失败:找回该记录标记完成 - $existing = Media::query() - ->where('collection_name', 'attachments') - ->where('custom_properties->legacy_attachmentid', (int) ($row['attachmentid'] ?? 0)) - ->latest('id') - ->first(); - - if ($existing) { - $existing->setCustomProperty('pending_sync', false); - $existing->save(); - - return $existing; - } - // 文件损坏无法入库时降级为 pending,不中断整批导入 \Illuminate\Support\Facades\Log::warning('附件导入失败,已降级为待同步', [ 'attachment' => $row['attachmentid'] ?? null, diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index a541358..83558a5 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -44,6 +44,7 @@ class AdminPanelProvider extends PanelProvider 'primary' => Color::Sky, ]) ->brandName(config('blog.name')) + ->spa() ->sidebarWidth('13rem') ->maxContentWidth(\Filament\Support\Enums\Width::Full) ->userMenuItems([