import { ExtendedFlashcard } from '@/store/useReviewSessionStore' // 錯誤類型定義 export enum ErrorType { NETWORK_ERROR = 'NETWORK_ERROR', API_ERROR = 'API_ERROR', VALIDATION_ERROR = 'VALIDATION_ERROR', AUTHENTICATION_ERROR = 'AUTHENTICATION_ERROR', UNKNOWN_ERROR = 'UNKNOWN_ERROR' } export interface AppError { type: ErrorType message: string details?: any timestamp: Date context?: string } // 錯誤處理器 export class ErrorHandler { private static errorQueue: AppError[] = [] private static maxQueueSize = 50 // 記錄錯誤 static logError(error: AppError) { console.error(`[${error.type}] ${error.message}`, error.details) // 添加到錯誤隊列 this.errorQueue.unshift(error) if (this.errorQueue.length > this.maxQueueSize) { this.errorQueue.pop() } } // 創建錯誤 static createError( type: ErrorType, message: string, details?: any, context?: string ): AppError { const error: AppError = { type, message, details, context, timestamp: new Date() } this.logError(error) return error } // 處理 API 錯誤 static handleApiError(error: any, context?: string): AppError { if (error?.response?.status === 401) { return this.createError( ErrorType.AUTHENTICATION_ERROR, '認證失效,請重新登入', error, context ) } if (error?.response?.status >= 500) { return this.createError( ErrorType.API_ERROR, '伺服器錯誤,請稍後再試', error, context ) } if (error?.code === 'NETWORK_ERROR' || !error?.response) { return this.createError( ErrorType.NETWORK_ERROR, '網路連線錯誤,請檢查網路狀態', error, context ) } return this.createError( ErrorType.API_ERROR, error?.response?.data?.message || '請求失敗', error, context ) } // 處理驗證錯誤 static handleValidationError(message: string, details?: any, context?: string): AppError { return this.createError(ErrorType.VALIDATION_ERROR, message, details, context) } // 獲取用戶友好的錯誤訊息 static getUserFriendlyMessage(error: AppError): string { switch (error.type) { case ErrorType.NETWORK_ERROR: return '網路連線有問題,請檢查網路後重試' case ErrorType.AUTHENTICATION_ERROR: return '登入狀態已過期,請重新登入' case ErrorType.API_ERROR: return error.message || '伺服器暫時無法回應,請稍後再試' case ErrorType.VALIDATION_ERROR: return error.message || '輸入資料有誤,請檢查後重試' default: return '發生未知錯誤,請聯繫技術支援' } } // 獲取錯誤歷史 static getErrorHistory(): AppError[] { return [...this.errorQueue] } // 清除錯誤歷史 static clearErrorHistory() { this.errorQueue = [] } // 判斷是否可以重試 static canRetry(error: AppError): boolean { return [ErrorType.NETWORK_ERROR, ErrorType.API_ERROR].includes(error.type) } // 判斷是否需要重新登入 static needsReauth(error: AppError): boolean { return error.type === ErrorType.AUTHENTICATION_ERROR } } // 重試邏輯 export class RetryHandler { private static retryConfig = { maxRetries: 3, baseDelay: 1000, // 1秒 maxDelay: 5000 // 5秒 } // 執行帶重試的操作 static async withRetry( operation: () => Promise, context?: string, maxRetries?: number ): Promise { const attempts = maxRetries || this.retryConfig.maxRetries let lastError: any for (let attempt = 1; attempt <= attempts; attempt++) { try { return await operation() } catch (error) { lastError = error console.warn(`[Retry ${attempt}/${attempts}] Operation failed:`, error) // 如果是最後一次嘗試,拋出錯誤 if (attempt === attempts) { throw ErrorHandler.handleApiError(error, context) } // 計算延遲時間 (指數退避) const delay = Math.min( this.retryConfig.baseDelay * Math.pow(2, attempt - 1), this.retryConfig.maxDelay ) console.log(`等待 ${delay}ms 後重試...`) await new Promise(resolve => setTimeout(resolve, delay)) } } throw ErrorHandler.handleApiError(lastError, context) } // 更新重試配置 static updateConfig(config: Partial) { this.retryConfig = { ...this.retryConfig, ...config } } } // 降級數據服務 export class FallbackService { // 緊急降級數據 static getEmergencyFlashcards(): ExtendedFlashcard[] { return [ { id: 'emergency-1', word: 'hello', definition: '你好,哈囉', example: 'Hello, how are you?', difficultyLevel: 'A1', translation: '你好,你還好嗎?' } ] } // 檢查是否需要使用降級模式 static shouldUseFallback(errorCount: number, networkStatus: boolean): boolean { return errorCount >= 3 || !networkStatus } // 本地儲存學習進度 static saveProgressToLocal(progress: { currentCardId?: string completedTests: any[] score: { correct: number; total: number } }) { try { const timestamp = new Date().toISOString() const progressData = { ...progress, timestamp, version: '1.0' } localStorage.setItem('learn_progress_backup', JSON.stringify(progressData)) console.log('💾 學習進度已備份到本地') } catch (error) { console.error('本地進度備份失敗:', error) } } // 從本地恢復學習進度 static loadProgressFromLocal(): any | null { try { const saved = localStorage.getItem('learn_progress_backup') if (saved) { const progress = JSON.parse(saved) console.log('📂 從本地恢復學習進度:', progress) return progress } } catch (error) { console.error('本地進度恢復失敗:', error) } return null } // 清除本地進度 static clearLocalProgress() { try { localStorage.removeItem('learn_progress_backup') console.log('🗑️ 本地進度備份已清除') } catch (error) { console.error('清除本地進度失敗:', error) } } }