feat(cms): sync site assets, revalidate webhook, and document download naming

This commit is contained in:
2026-02-10 23:38:31 +08:00
parent c4969cd4d2
commit b6e18a83ec
27 changed files with 1019 additions and 26 deletions

View File

@@ -8,6 +8,8 @@ use App\Models\ArticleAttachment;
use App\Models\ArticleCategory;
use App\Models\ArticleTag;
use App\Models\AuditLog;
use App\Services\SiteAssetSyncService;
use App\Services\SiteRevalidationService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
@@ -117,7 +119,15 @@ class ArticleController extends Controller
];
if ($request->hasFile('featured_image')) {
$articleData['featured_image_path'] = $request->file('featured_image')->store('articles/images', 'public');
$storagePath = $request->file('featured_image')->store('articles/images', 'public');
$nextPublicPath = SiteAssetSyncService::syncPublicDiskFileToNext($storagePath);
if ($nextPublicPath) {
$articleData['featured_image_path'] = $nextPublicPath;
$articleData['featured_image_storage_path'] = $storagePath;
} else {
$articleData['featured_image_path'] = $storagePath;
}
}
$article = Article::create($articleData);
@@ -148,6 +158,10 @@ class ArticleController extends Controller
'ip_address' => request()->ip(),
]);
if ($validated['save_action'] === 'publish') {
SiteRevalidationService::revalidateArticle($article->slug);
}
$message = $validated['save_action'] === 'publish' ? '文章已成功發布' : '文章已儲存為草稿';
return redirect()
@@ -227,13 +241,35 @@ class ArticleController extends Controller
}
if ($request->hasFile('featured_image')) {
if ($article->featured_image_path) {
// Remove old copies (best-effort). If we synced to Next.js, the DB path is relative (uploads/...).
if ($article->featured_image_storage_path) {
Storage::disk('public')->delete($article->featured_image_storage_path);
} elseif ($article->featured_image_path && str_starts_with($article->featured_image_path, 'articles/')) {
Storage::disk('public')->delete($article->featured_image_path);
}
$updateData['featured_image_path'] = $request->file('featured_image')->store('articles/images', 'public');
SiteAssetSyncService::deleteNextPublicFile($article->featured_image_path);
$storagePath = $request->file('featured_image')->store('articles/images', 'public');
$nextPublicPath = SiteAssetSyncService::syncPublicDiskFileToNext($storagePath);
if ($nextPublicPath) {
$updateData['featured_image_path'] = $nextPublicPath;
$updateData['featured_image_storage_path'] = $storagePath;
} else {
$updateData['featured_image_path'] = $storagePath;
$updateData['featured_image_storage_path'] = null;
}
} elseif ($request->boolean('remove_featured_image') && $article->featured_image_path) {
Storage::disk('public')->delete($article->featured_image_path);
if ($article->featured_image_storage_path) {
Storage::disk('public')->delete($article->featured_image_storage_path);
} elseif (str_starts_with($article->featured_image_path, 'articles/')) {
Storage::disk('public')->delete($article->featured_image_path);
}
SiteAssetSyncService::deleteNextPublicFile($article->featured_image_path);
$updateData['featured_image_path'] = null;
$updateData['featured_image_storage_path'] = null;
}
$article->update($updateData);
@@ -264,6 +300,10 @@ class ArticleController extends Controller
'ip_address' => request()->ip(),
]);
if ($article->isPublished()) {
SiteRevalidationService::revalidateArticle($article->slug);
}
return redirect()
->route('admin.articles.show', $article)
->with('status', '文章已成功更新');
@@ -276,6 +316,8 @@ class ArticleController extends Controller
}
$title = $article->title;
$slug = $article->slug;
$wasPublished = $article->isPublished();
$article->delete();
AuditLog::create([
@@ -285,6 +327,10 @@ class ArticleController extends Controller
'ip_address' => request()->ip(),
]);
if ($wasPublished) {
SiteRevalidationService::revalidateArticle($slug);
}
return redirect()
->route('admin.articles.index')
->with('status', '文章已成功刪除');
@@ -313,6 +359,8 @@ class ArticleController extends Controller
'ip_address' => request()->ip(),
]);
SiteRevalidationService::revalidateArticle($article->slug);
return back()->with('status', '文章已成功發布');
}
@@ -339,6 +387,8 @@ class ArticleController extends Controller
'ip_address' => request()->ip(),
]);
SiteRevalidationService::revalidateArticle($article->slug);
return back()->with('status', '文章已成功歸檔');
}