# 前端圖片 URL 處理機制詳解 ## 📋 概述 本文檔詳細解釋 DramaLing 前端如何處理詞卡圖片 URL,以及為什麼不同格式的 URL 都能正常運作。 ## 🎯 核心工具:`flashcardUtils.ts` ### 檔案位置 ``` frontend/lib/utils/flashcardUtils.ts ``` ### 檔案目的 **統一管理詞卡相關的顯示和處理邏輯** - 避免在各個元件中重複寫相同的處理代碼 --- ## 📝 核心函數詳細解析 ### 1. **圖片 URL 處理 - `getFlashcardImageUrl()`** **位置**: 第 77-99 行 **用途**: 智能處理詞卡圖片 URL,支援多種格式和來源 #### 處理邏輯流程: ```typescript export const getFlashcardImageUrl = (flashcard: any): string | null => { // 第一優先:檢查 primaryImageUrl if (flashcard.primaryImageUrl) { // 判斷是相對路徑還是完整 URL if (flashcard.primaryImageUrl.startsWith('/')) { // 相對路徑:拼接後端基礎 URL return `${API_CONFIG.BASE_URL}${flashcard.primaryImageUrl}` } // 完整 URL:直接使用 return flashcard.primaryImageUrl } // 第二優先:檢查 exampleImages 陣列 if (flashcard.exampleImages && flashcard.exampleImages.length > 0) { // 尋找標記為主要的圖片 const primaryImage = flashcard.exampleImages.find((img: any) => img.isPrimary) if (primaryImage) { const imageUrl = primaryImage.imageUrl return imageUrl?.startsWith('/') ? `${API_CONFIG.BASE_URL}${imageUrl}` : imageUrl } // 沒有主要圖片,使用第一張 const firstImageUrl = flashcard.exampleImages[0].imageUrl return firstImageUrl?.startsWith('/') ? `${API_CONFIG.BASE_URL}${firstImageUrl}` : firstImageUrl } // 都沒有圖片 return null } ``` #### 支援的 URL 格式: | 格式類型 | 範例 | 處理方式 | |---------|------|----------| | **Google Cloud Storage** | `https://storage.googleapis.com/dramaling-images/examples/file.png` | 直接使用完整 URL | | **本地服務** | `http://localhost:5008/images/examples/file.png` | 直接使用完整 URL | | **相對路徑** | `/images/examples/file.png` | 拼接為 `http://localhost:5008/images/examples/file.png` | --- ### 2. **其他工具函數** #### **詞性顯示 - `getPartOfSpeechDisplay()`** ```typescript // 輸入:"noun" → 輸出:"n." // 輸入:"adjective" → 輸出:"adj." // 輸入:"preposition/adverb" → 輸出:"prep./adv." (支援複合詞性) ``` #### **CEFR 等級顏色 - `getCEFRColor()`** ```typescript // A1 → "bg-green-100 text-green-700 border-green-200" (綠色) // B1 → "bg-yellow-100 text-yellow-700 border-yellow-200" (黃色) // C2 → "bg-purple-100 text-purple-700 border-purple-200" (紫色) ``` #### **熟練度處理** - **`getMasteryColor()`**: 根據數字返回顏色 (90+→綠色, <50→紅色) - **`getMasteryText()`**: 轉換為中文 (90+→"精通", <50→"學習中") #### **日期格式化** - **`formatNextReviewDate()`**: 複習時間 (過期→"需要複習", 明天→"明天") - **`formatCreatedDate()`**: 台灣日期格式 ("2024/1/15") #### **統計計算 - `calculateFlashcardStats()`** ```typescript { total: 總詞卡數, mastered: 精通詞卡數 (熟練度 ≥ 80), learning: 學習中詞卡數 (熟練度 40-79), new: 新詞卡數 (熟練度 < 40), favorites: 收藏詞卡數, masteryPercentage: 精通百分比 } ``` --- ## 🔍 實際運作流程 ### API 回應格式 **目前狀態(修復後):** - `/api/flashcards`: 回傳完整 Google Cloud Storage URL - `/api/flashcards/{id}`: 回傳完整 Google Cloud Storage URL ```json { "primaryImageUrl": "https://storage.googleapis.com/dramaling-images/examples/b2bb23b8-16dd-44b2-bf64-34c468f2d362_e6498ba6-742b-473f-93b6-f4b58c3dd3e9.png" } ``` ### 前端處理流程 1. **接收 API 回應** → 取得 `primaryImageUrl` 2. **呼叫 `getFlashcardImageUrl()`** → 檢查 URL 格式 3. **格式判斷**: - ✅ 完整 URL (`https://storage.googleapis.com/...`) → 直接使用 - ❌ 相對路徑 (`/images/...`) → 拼接後端域名(目前不會發生) 4. **元件渲染** → `` --- ## 🎯 設計優勢 ### **1. 兼容性設計** - 支援多種 URL 格式(相對路徑/完整 URL) - 可以無縫切換本地/雲端儲存 - 向後兼容舊版 API ### **2. 防禦性編程** - 多重備用方案(primaryImageUrl → exampleImages → null) - 自動處理路徑拼接邏輯 - 避免因 API 格式變更導致圖片顯示失敗 ### **3. 集中化管理** - 所有圖片 URL 處理邏輯集中在一個函數 - 修改邏輯時只需要改一個地方 - 多個元件可以重用相同邏輯 ### **4. 模組化架構** - 每個功能都有專門的工具函數 - 易於測試和維護 - 符合 DRY (Don't Repeat Yourself) 原則 --- ## 🔧 使用範例 ### 在元件中使用 ```typescript // FlashcardCard.tsx import { getFlashcardImageUrl, getCEFRColor, getPartOfSpeechDisplay } from '@/lib/utils/flashcardUtils' // 取得圖片 URL const imageUrl = getFlashcardImageUrl(flashcard) // 結果:https://storage.googleapis.com/dramaling-images/examples/file.png // 取得 CEFR 顏色 const cefrClasses = getCEFRColor(flashcard.cefr) // 結果:"bg-blue-100 text-blue-700 border-blue-200" // 取得詞性簡寫 const partOfSpeech = getPartOfSpeechDisplay(flashcard.partOfSpeech) // 結果:"n." // 在 JSX 中使用 example {flashcard.cefr} {partOfSpeech} ``` --- ## 📊 問題解答 ### Q: 為什麼不同格式的 URL 都能正常運作? **A**: 前端設計了智能兼容性處理: 1. **完整 URL** → 直接使用(目前的情況) 2. **相對路徝** → 自動拼接後端域名(向後兼容) 3. **多重備用** → primaryImageUrl 失敗時使用 exampleImages ### Q: 這樣的設計有什麼好處? **A**: - ✅ **彈性切換**:可以在本地開發和雲端部署間切換 - ✅ **向後兼容**:支援舊版 API 格式 - ✅ **錯誤處理**:多重備用方案確保圖片顯示 - ✅ **維護性**:集中化管理,易於修改 ### Q: 目前系統的實際運作狀況? **A**: - 後端統一回傳完整的 Google Cloud Storage URLs - 前端接收到完整 URL,直接使用(不進入相對路徑處理邏輯) - 圖片正常顯示,系統運作正常 --- ## 📈 總結 `flashcardUtils.ts` 是一個設計良好的工具函數庫,實現了: - **統一化**:所有詞卡相關的顯示邏輯集中管理 - **兼容性**:支援多種 URL 格式和資料來源 - **可維護性**:模組化設計,易於擴展和修改 - **可靠性**:防禦性編程,確保系統穩定運作 這種設計確保了前端系統的健壯性和可維護性,是現代前端架構的最佳實務範例。