dramaling-vocab-learning/前端圖片URL處理機制詳解.md

6.9 KiB
Raw Blame History

前端圖片 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"
}

前端處理流程

  1. 接收 API 回應 → 取得 primaryImageUrl
  2. 呼叫 getFlashcardImageUrl() → 檢查 URL 格式
  3. 格式判斷
    • 完整 URL (https://storage.googleapis.com/...) → 直接使用
    • 相對路徑 (/images/...) → 拼接後端域名(目前不會發生)
  4. 元件渲染<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: 前端設計了智能兼容性處理:

  1. 完整 URL → 直接使用(目前的情況)
  2. 相對路徝 → 自動拼接後端域名(向後兼容)
  3. 多重備用 → primaryImageUrl 失敗時使用 exampleImages

Q: 這樣的設計有什麼好處?

A:

  • 彈性切換:可以在本地開發和雲端部署間切換
  • 向後兼容:支援舊版 API 格式
  • 錯誤處理:多重備用方案確保圖片顯示
  • 維護性:集中化管理,易於修改

Q: 目前系統的實際運作狀況?

A:

  • 後端統一回傳完整的 Google Cloud Storage URLs
  • 前端接收到完整 URL直接使用不進入相對路徑處理邏輯
  • 圖片正常顯示,系統運作正常

📈 總結

flashcardUtils.ts 是一個設計良好的工具函數庫,實現了:

  • 統一化:所有詞卡相關的顯示邏輯集中管理
  • 兼容性:支援多種 URL 格式和資料來源
  • 可維護性:模組化設計,易於擴展和修改
  • 可靠性:防禦性編程,確保系統穩定運作

這種設計確保了前端系統的健壯性和可維護性,是現代前端架構的最佳實務範例。