7.1 KiB
7.1 KiB
Flashcards 頁面重構計劃
目標: 將 898行的 flashcards/page.tsx 重構為可維護的模組化架構 當前問題: 單一檔案過大,責任過多,難以維護
📊 現況分析
🚨 嚴重性評估
- 檔案大小: 898行 (超標 4.5倍,建議 <200行)
- 複雜度: 高 - 包含多個獨立功能模組
- 維護性: 低 - 修改風險高,測試困難
🔍 功能分析
- 搜尋與篩選 (~150行)
- 詞卡列表顯示 (~200行)
- 圖片生成邏輯 (~100行)
- 表單管理 (~100行)
- 狀態管理 (~150行)
- UI交互邏輯 (~200行)
🎯 重構目標架構
📁 新的檔案結構
/app/flashcards/
├── page.tsx (~150行) 主頁面容器
└── components/
├── FlashcardList.tsx (~120行) 詞卡列表組件
├── SearchFilters.tsx (~100行) 搜尋篩選器
├── FlashcardActions.tsx (~80行) 操作按鈕群組
└── ImageGenerationDialog.tsx (~100行) 圖片生成對話框
/hooks/flashcards/
├── useFlashcardActions.ts (~80行) 操作邏輯Hook
└── useImageGeneration.ts (~60行) 圖片生成Hook
/lib/utils/
└── flashcardUtils.ts (~40行) 工具函數
🔧 詳細重構方案
1. 主頁面容器 (page.tsx)
目標大小: ~150行 責任範圍:
- 路由控制和認證
- 頂層狀態管理
- 組件組合和佈局
保留內容:
// 頂層狀態
const [activeTab, setActiveTab] = useState<'all-cards' | 'favorites'>('all-cards')
const [showForm, setShowForm] = useState(false)
// 主要佈局結構
return (
<ProtectedRoute>
<Navigation />
<SearchFilters />
<FlashcardList />
<FlashcardActions />
</ProtectedRoute>
)
2. 詞卡列表組件 (FlashcardList.tsx)
目標大小: ~120行 責任範圍:
- 詞卡卡片渲染
- 分頁控制
- 載入狀態顯示
核心邏輯:
interface FlashcardListProps {
flashcards: Flashcard[]
pagination: PaginationState
onCardClick: (id: string) => void
onImageGenerate: (id: string) => void
}
3. 搜尋篩選器 (SearchFilters.tsx)
目標大小: ~100行 責任範圍:
- 搜尋輸入框
- 篩選下拉選單
- 排序控制
- 進階搜尋切換
介面定義:
interface SearchFiltersProps {
searchState: SearchState
searchActions: SearchActions
showAdvanced: boolean
onToggleAdvanced: () => void
}
4. 操作按鈕群組 (FlashcardActions.tsx)
目標大小: ~80行 責任範圍:
- 新增詞卡按鈕
- 批量操作按鈕
- 匯入/匯出功能
5. 圖片生成對話框 (ImageGenerationDialog.tsx)
目標大小: ~100行 責任範圍:
- 圖片生成進度顯示
- 生成參數設定
- 狀態輪詢管理
🎣 Custom Hooks 設計
1. useFlashcardActions
// 操作邏輯封裝
export const useFlashcardActions = () => {
const handleEdit = (id: string) => { /* 編輯邏輯 */ }
const handleDelete = (id: string) => { /* 刪除邏輯 */ }
const handleFavorite = (id: string) => { /* 收藏邏輯 */ }
return { handleEdit, handleDelete, handleFavorite }
}
2. useImageGeneration
// 圖片生成邏輯封裝
export const useImageGeneration = () => {
const [generating, setGenerating] = useState<Set<string>>(new Set())
const [progress, setProgress] = useState<{[id: string]: string}>({})
const generateImage = async (flashcardId: string) => { /* 生成邏輯 */ }
return { generating, progress, generateImage }
}
🛠️ 工具函數提取
flashcardUtils.ts
// 詞性顯示轉換
export const getPartOfSpeechDisplay = (partOfSpeech: string): string => { ... }
// CEFR顏色獲取
export const getCEFRColor = (level: string): string => { ... }
// 熟練度顏色獲取
export const getMasteryColor = (level: number): string => { ... }
📋 重構執行計劃
階段一: 工具函數提取 (30分鐘)
- ✅ 創建
lib/utils/flashcardUtils.ts - ✅ 移動工具函數
- ✅ 更新import引用
階段二: Custom Hooks 分離 (45分鐘)
- ✅ 創建
useFlashcardActions.ts - ✅ 創建
useImageGeneration.ts - ✅ 從主組件中提取邏輯
階段三: UI組件拆分 (1小時)
- ✅ 創建
SearchFilters.tsx - ✅ 創建
FlashcardList.tsx - ✅ 創建
FlashcardActions.tsx - ✅ 創建
ImageGenerationDialog.tsx
階段四: 主頁面重構 (30分鐘)
- ✅ 簡化主組件邏輯
- ✅ 整合新的子組件
- ✅ 測試功能完整性
階段五: 測試與優化 (15分鐘)
- ✅ 編譯測試
- ✅ 功能測試
- ✅ 效能驗證
🎯 預期成果
📊 量化目標
- 主檔案: 898行 → ~150行 (減少83%)
- 組件數量: 1個 → 5個 (模組化)
- 單一責任: ✅ 每個組件職責明確
- 可測試性: ✅ 組件獨立可測
🚀 品質提升
- 可維護性: 🔴 → 🟢 (大幅提升)
- 可讀性: 🟡 → 🟢 (結構清晰)
- 可擴展性: 🟡 → 🟢 (易於添加功能)
- 測試覆蓋: 🔴 → 🟢 (組件化便於測試)
💡 開發體驗
- 修改局部性: 修改特定功能時只需要動對應組件
- 協作友善: 多人開發時減少衝突
- debugging: 問題定位更精確
⚠️ 風險控制
🔴 潛在風險
- 狀態管理複雜化: 跨組件狀態傳遞
- Props Drilling: 深層組件傳值問題
- 功能回歸: 重構過程中功能遺失
🛡️ 緩解策略
- 漸進式重構: 一次拆分一個組件
- 保持向下相容: 確保API接口不變
- 充分測試: 每個階段完成後立即測試
- 備份計劃: Git commit 每個主要階段
📚 最佳實踐應用
🎨 設計原則
- 單一責任原則: 每個組件只負責一個核心功能
- 組合優於繼承: 通過組合小組件構建複雜功能
- Props接口明確: 清晰定義組件間的數據流
🔄 狀態管理策略
- 狀態上提: 共享狀態提升到最近的共同父組件
- 局部狀態: 組件特定狀態保持在組件內部
- Hook封裝: 複雜邏輯封裝到自定義Hook
🎉 重構價值
💼 商業價值
- 開發效率: 提升 50%+ (組件化開發)
- 維護成本: 降低 60%+ (責任明確)
- 新功能開發: 加速 40%+ (可復用組件)
🏗️ 技術價值
- 代碼品質: 企業級標準
- 架構清晰: 易於理解和擴展
- 測試友善: 單元測試覆蓋率可達 80%+
準備開始重構嗎?建議分階段執行,確保每個步驟都穩定可靠!
生成時間: 2025-10-01 18:15 預估工時: 2.5小時 風險等級: 🟡 中風險 (有完整計劃) 推薦執行: ✅ 立即開始