6.9 KiB
6.9 KiB
前端圖片 URL 處理機制詳解
📋 概述
本文檔詳細解釋 DramaLing 前端如何處理詞卡圖片 URL,以及為什麼不同格式的 URL 都能正常運作。
🎯 核心工具:flashcardUtils.ts
檔案位置
frontend/lib/utils/flashcardUtils.ts
檔案目的
統一管理詞卡相關的顯示和處理邏輯 - 避免在各個元件中重複寫相同的處理代碼
📝 核心函數詳細解析
1. 圖片 URL 處理 - getFlashcardImageUrl()
位置: 第 77-99 行 用途: 智能處理詞卡圖片 URL,支援多種格式和來源
處理邏輯流程:
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()
// 輸入:"noun" → 輸出:"n."
// 輸入:"adjective" → 輸出:"adj."
// 輸入:"preposition/adverb" → 輸出:"prep./adv." (支援複合詞性)
CEFR 等級顏色 - getCEFRColor()
// 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()
{
total: 總詞卡數,
mastered: 精通詞卡數 (熟練度 ≥ 80),
learning: 學習中詞卡數 (熟練度 40-79),
new: 新詞卡數 (熟練度 < 40),
favorites: 收藏詞卡數,
masteryPercentage: 精通百分比
}
🔍 實際運作流程
API 回應格式
目前狀態(修復後):
/api/flashcards: 回傳完整 Google Cloud Storage URL/api/flashcards/{id}: 回傳完整 Google Cloud Storage URL
{
"primaryImageUrl": "https://storage.googleapis.com/dramaling-images/examples/b2bb23b8-16dd-44b2-bf64-34c468f2d362_e6498ba6-742b-473f-93b6-f4b58c3dd3e9.png"
}
前端處理流程
- 接收 API 回應 → 取得
primaryImageUrl - 呼叫
getFlashcardImageUrl()→ 檢查 URL 格式 - 格式判斷:
- ✅ 完整 URL (
https://storage.googleapis.com/...) → 直接使用 - ❌ 相對路徑 (
/images/...) → 拼接後端域名(目前不會發生)
- ✅ 完整 URL (
- 元件渲染 →
<img src={imageUrl} />
🎯 設計優勢
1. 兼容性設計
- 支援多種 URL 格式(相對路徑/完整 URL)
- 可以無縫切換本地/雲端儲存
- 向後兼容舊版 API
2. 防禦性編程
- 多重備用方案(primaryImageUrl → exampleImages → null)
- 自動處理路徑拼接邏輯
- 避免因 API 格式變更導致圖片顯示失敗
3. 集中化管理
- 所有圖片 URL 處理邏輯集中在一個函數
- 修改邏輯時只需要改一個地方
- 多個元件可以重用相同邏輯
4. 模組化架構
- 每個功能都有專門的工具函數
- 易於測試和維護
- 符合 DRY (Don't Repeat Yourself) 原則
🔧 使用範例
在元件中使用
// 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 中使用
<img src={imageUrl} alt="example" />
<span className={cefrClasses}>{flashcard.cefr}</span>
<span>{partOfSpeech}</span>
📊 問題解答
Q: 為什麼不同格式的 URL 都能正常運作?
A: 前端設計了智能兼容性處理:
- 完整 URL → 直接使用(目前的情況)
- 相對路徝 → 自動拼接後端域名(向後兼容)
- 多重備用 → primaryImageUrl 失敗時使用 exampleImages
Q: 這樣的設計有什麼好處?
A:
- ✅ 彈性切換:可以在本地開發和雲端部署間切換
- ✅ 向後兼容:支援舊版 API 格式
- ✅ 錯誤處理:多重備用方案確保圖片顯示
- ✅ 維護性:集中化管理,易於修改
Q: 目前系統的實際運作狀況?
A:
- 後端統一回傳完整的 Google Cloud Storage URLs
- 前端接收到完整 URL,直接使用(不進入相對路徑處理邏輯)
- 圖片正常顯示,系統運作正常
📈 總結
flashcardUtils.ts 是一個設計良好的工具函數庫,實現了:
- 統一化:所有詞卡相關的顯示邏輯集中管理
- 兼容性:支援多種 URL 格式和資料來源
- 可維護性:模組化設計,易於擴展和修改
- 可靠性:防禦性編程,確保系統穩定運作
這種設計確保了前端系統的健壯性和可維護性,是現代前端架構的最佳實務範例。