feat(images): 課程圖片伺服器端壓縮——scaleDown 2048 + JPEG 85,上限放寬至 10MB
Run Tests / test (pull_request) Successful in 2m0s

實作 openspec change course-image-compression(O3.1 體感優化):
- 新增 App\Traits\CompressesImages:與聊天圖片管線參數一致的共用壓縮邏輯
- CourseImageController 封面/相簿套用壓縮,上傳上限 2MB→10MB(容納手機原圖)
- 前端課程卡片與相簿縮圖加 loading=lazy(詳情頁首屏封面刻意不加)
- CourseImageTest +4 案例(10MB 邊界、轉存 .jpg、>2048 縮小、小圖不放大)
- course-image-upload 主規格同步(新增伺服器端壓縮 requirement)

容器內全套件 155 passed / 400 assertions。
聊天端改用 trait 留待後續(該處無測試覆蓋,不在本 change 重構)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 23:43:24 +08:00
parent 87a4f70e65
commit 6414222a18
11 changed files with 255 additions and 11 deletions
@@ -0,0 +1,23 @@
## 1. 共用壓縮 trait
- [x] 1.1 新增 `app/Traits/CompressesImages.php``compressToJpeg(UploadedFile $file, string $directory): string`——Intervention v3 讀取 → 長邊 >2048 時 `scaleDown(2048, 2048)``toJpeg(quality: 85)``Storage::disk('public')->put("{$directory}/{uuid}.jpg", ...)`,回傳相對路徑
## 2. CourseImageController 套用
- [x] 2.1 `validateImage()``max:2048``max:10240`
- [x] 2.2 `uploadCover()``store()` 改用 `compressToJpeg($file, "offers/{$offerId}/cover")`
- [x] 2.3 `uploadImage()`:同上,目錄 `offers/{$offerId}/gallery`
## 3. 前端 lazy loading
- [x] 3.1 `frontend/src/views/CoursesView.vue``CourseDetailView.vue` 的課程圖 `<img>``loading="lazy"`(其他列表元件若有課程圖一併處理)
## 4. 測試
- [x] 4.1 更新 `CourseImageTest`:大小上限案例改 >10MB 422、新增 5MB 通過案例、儲存路徑斷言改 `.jpg`
- [x] 4.2 新增壓縮行為案例:上傳 3000×3000 fake 圖 → 讀回實際尺寸 ≤2048;上傳 PNG → 儲存為 `.jpg`
- [x] 4.3 容器內 `php artisan test` 全綠(基準:151 passed;本機缺 GD 不可作準)
## 5. 規格同步
- [x] 5.1 將本 change 的 specs 增量套用至主規格 `openspec/specs/course-image-upload/spec.md`