4baa4cb52b
後端:
- Migration:diving_offers 新增 cover_image 欄位、新增 course_images 表(含索引)
- CourseImage Model(CREATED_AT、url accessor)
- DivingOffer:cover_image_url accessor、hasMany courseImages、static::deleting() 孤兒清理
- CourseImageController:封面上傳/刪除、相簿上傳(max 3)/刪除,統一 mimes+size 驗證
- DivingOfferController:index/show 回傳加入 cover_image_url 與 images 陣列
- 修正 APP_URL 加入 port(:8080),Storage::url() 才能產生正確圖片連結
前端:
- courseImageApi.js:uploadCover/deleteCover/uploadImage/deleteImage
- CourseCard:有封面顯示 <img>,無封面顯示漸層佔位
- CourseDetailView:封面大圖 + 相簿縮圖橫列(點擊開新分頁)
- OfferFormView(編輯模式):封面預覽/更換/刪除、相簿縮圖管理(達 3 張隱藏上傳按鈕)
基礎設施:
- docker-entrypoint.sh:加入 storage:link --force
- docker-compose.yml:移除 storage-data named volume(改用 bind mount,避免 Nginx 讀不到圖片)
測試:
- CourseImageTest.php:14 個 Feature Test 全部 PASS(Storage::fake)
涵蓋:上傳成功/格式驗證/大小驗證/所有權、刪除/無封面不報錯、
相簿上限/sort_order 遞增、孤兒清理
OpenSpec:
- course-images change 歸檔至 archive/2026-05-12-course-images
- 新增 specs/course-image-upload 主規格(含 bind mount 持久化說明)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2.0 KiB
2.0 KiB
Why
目前課程頁面以 🤿 emoji 作為佔位,缺乏視覺吸引力。課程圖片是潛水平台的核心體驗,直接影響會員瀏覽意願與教練品牌形象。
What Changes
- 新增
diving_offers.cover_image欄位:課程封面,顯示於課程卡與詳情頁頂部 - 新增
course_images資料表:相簿最多 3 張,顯示於課程詳情頁 - 新增 Provider API:上傳/刪除封面、上傳/刪除相簿圖片
- 更新前端:CourseCard 顯示封面、CourseDetailView 顯示封面 + 相簿、OfferFormView 加入圖片管理 UI
- Docker volume 掛載
storage/app/public,圖片跨 build 持久化 php artisan storage:link整合至 entrypoint,確保 symlink 正確
Capabilities
New Capabilities
course-image-upload:Provider 上傳課程封面與相簿圖片(本地 public disk、max 2MB、支援 jpg/jpeg/png/webp)、相簿上限 3 張、刪除圖片同步移除實體檔案
Modified Capabilities
coach-offers-api:新增圖片上傳/刪除端點,DivingOffer回應加入cover_image_url與images
Impact
後端
- Migration:
diving_offers加cover_image(nullable string) - Migration:新增
course_images(id、diving_offer_id、image_path、sort_order) - Model:
CourseImage;DivingOffer加hasMany CourseImage、cover_image_urlaccessor - Controller:
CourseImageController(上傳封面、刪除封面、上傳相簿、刪除相簿) - Route:
/provider/offers/{id}/cover(POST/DELETE)、/provider/offers/{id}/images(POST)、/provider/images/{id}(DELETE)
前端
frontend/src/api/courseImageApi.jsCourseCard.vue:有封面顯示圖片,無封面顯示漸層佔位CourseDetailView.vue:頂部大圖(封面)+ 相簿縮圖列OfferFormView.vue(或新建OfferImageManager.vue):封面上傳預覽、相簿管理
Docker
docker-compose.yml新增 named volumestorage-data掛載/var/www/storage/app/publicdocker-entrypoint.sh加入php artisan storage:link --force