# 後端API架構分離計劃 **文件版本**: 1.0 **建立日期**: 2025-09-10 **更新日期**: 2025-09-10 **負責人**: Drama Ling 開發團隊 ## 📋 概述 由於Drama Ling需要同時支援移動端App和Web端應用,現有的單一後端API架構將面臨以下挑戰: - 移動端和Web端資料需求差異 - 認證方式和安全要求不同 - 效能優化需求各異 - 維護和擴展複雜度增加 本文件提出後端API分離的架構方案和實施計劃。 ## 🎯 目標 ### 主要目標 1. **API專業化**: 為移動端和Web端提供專門優化的API 2. **提升效能**: 減少不必要的資料傳輸,提升回應速度 3. **簡化維護**: 降低不同端點間的耦合度 4. **增強安全**: 針對不同平台實施適當的安全策略 5. **支援擴展**: 為未來微服務架構奠定基礎 ### 成功指標 - API回應時間減少30%以上 - 移動端資料傳輸量減少50% - 代碼維護複雜度降低 - 支援獨立部署和擴展 ## 🏗 架構方案 ### 方案一: API Gateway + 微服務分離 (推薦) ```mermaid graph TB MA[Mobile App] --> AG[API Gateway] WA[Web App] --> AG AG --> AUTH[Authentication Service] AG --> USER[User Service] AG --> VOCAB[Vocabulary Service] AG --> LEARN[Learning Service] AG --> PROG[Progress Service] AUTH --> DB1[(Auth DB)] USER --> DB2[(User DB)] VOCAB --> DB3[(Vocabulary DB)] LEARN --> DB4[(Learning DB)] PROG --> DB5[(Progress DB)] ``` #### 優勢 - 🎯 **高度專業化**: 每個服務專注特定功能 - 🚀 **獨立擴展**: 可根據負載獨立擴展服務 - 🔒 **安全隔離**: 服務間隔離,降低安全風險 - 🛠 **技術選型靈活**: 不同服務可選用不同技術 - 👥 **團隊分工**: 支援多團隊並行開發 #### 挑戰 - 複雜度較高,需要服務發現和配置管理 - 分散式系統的一致性問題 - 運維複雜度增加 ### 方案二: 單體 + 多端點適配 (階段性) ```mermaid graph TB MA[Mobile App] --> ME[/api/v1/mobile] WA[Web App] --> WE[/api/v1/web] ME --> BS[Backend Service] WE --> BS BS --> SL[Shared Logic Layer] BS --> MH[Mobile Handler] BS --> WH[Web Handler] SL --> DB[(Database)] ``` #### 優勢 - 🏃‍♂️ **快速實施**: 在現有架構基礎上調整 - 🔧 **維護簡單**: 單一部署單位 - 💰 **成本較低**: 無需額外的基礎設施 - 🧪 **風險可控**: 漸進式改進 #### 挑戰 - 單體應用的擴展限制 - 不同端點間仍有耦合 - 長期維護複雜度仍然較高 ## 📊 API差異化設計 ### 移動端API特點 ```json { "endpoint": "/api/v1/mobile/vocabulary/{id}", "response": { "word": "confidence", "phonetic": "/ˈkɒnfɪdəns/", "definition": "信心", "audio_url": "https://cdn.dramaling.com/audio/confidence.mp3", "last_reviewed": "2025-09-10T10:30:00Z" }, "features": [ "精簡資料結構", "支援離線緩存", "增量同步", "推播通知", "JWT認證" ] } ``` ### Web端API特點 ```json { "endpoint": "/api/v1/web/vocabulary/{id}", "response": { "word": "confidence", "phonetic": "/ˈkɒnfɪdəns/", "definitions": { "primary": "信心;自信心;把握", "secondary": ["確信", "秘密", "信賴"] }, "examples": [ { "sentence": "She spoke with great confidence during the presentation.", "translation": "她在簡報中表現出很大的自信。" } ], "synonyms": ["assurance", "self-assurance", "poise"], "etymology": "來自拉丁語 confidentia", "usage_frequency": 0.85, "difficulty_level": "intermediate", "related_words": ["confident", "confidential"], "learning_analytics": { "total_reviews": 15, "success_rate": 0.87, "avg_response_time": 2.3 } }, "features": [ "完整資料結構", "即時互動", "豐富的學習分析", "SEO友好", "Session認證" ] } ``` ### 認證策略差異 #### 移動端認證 ```csharp [ApiController] [Route("api/v1/mobile/[controller]")] [Authorize(AuthenticationSchemes = "JwtBearer")] public class MobileVocabularyController : ControllerBase { // JWT Token + Refresh Token // 生物識別支援 // OAuth2.0 整合 } ``` #### Web端認證 ```csharp [ApiController] [Route("api/v1/web/[controller]")] [Authorize(AuthenticationSchemes = "Cookie,OpenIdConnect")] public class WebVocabularyController : ControllerBase { // Session + Cookie // Social Login (Google, Facebook) // CSRF Protection } ``` ## 🚀 實施計劃 ### Phase 1: 基礎分離 (4週) **目標**: 建立移動端和Web端分離的API端點 #### Week 1: 路由分離 - [ ] 建立 `/api/v1/mobile/*` 路由結構 - [ ] 建立 `/api/v1/web/*` 路由結構 - [ ] 實現路由中介軟體和版本控制 - [ ] 測試基本路由功能 #### Week 2: 控制器分離 - [ ] 複製現有控制器為Mobile和Web版本 - [ ] 實現MobileBaseController和WebBaseController - [ ] 調整回應格式和資料結構 - [ ] 單元測試覆蓋 #### Week 3: 資料模型差異化 - [ ] 建立MobileDto和WebDto資料傳輸物件 - [ ] 實現AutoMapper配置 - [ ] 調整序列化設定 - [ ] API文件生成 #### Week 4: 認證系統調整 - [ ] 實現JWT認證for移動端 - [ ] 保持Session認證for Web端 - [ ] 測試認證流程 - [ ] 效能基準測試 ### Phase 2: 功能優化 (6週) **目標**: 針對不同平台優化API功能 #### Week 5-6: 移動端優化 - [ ] 實現離線支援和增量同步 - [ ] 優化資料傳輸量和壓縮 - [ ] 推播通知整合 - [ ] 移動端特有功能開發 #### Week 7-8: Web端優化 - [ ] 實現即時互動功能 - [ ] 豐富學習分析資料 - [ ] SEO優化和Open Graph支援 - [ ] Web端專屬功能開發 #### Week 9-10: 效能和安全優化 - [ ] API快取策略實施 - [ ] 安全性強化(CORS, CSRF, Rate Limiting) - [ ] 監控和日誌系統 - [ ] 負載測試和調優 ### Phase 3: 微服務準備 (8週) **目標**: 為未來微服務架構做準備 #### Week 11-12: 服務邊界定義 - [ ] 識別和定義服務邊界 - [ ] 資料庫分離規劃 - [ ] API Gateway選型和POC - [ ] 服務發現機制設計 #### Week 13-16: 核心服務提取 - [ ] 提取User Service - [ ] 提取Vocabulary Service - [ ] 提取Learning Service - [ ] 服務間通信機制 #### Week 17-18: 整合和測試 - [ ] API Gateway整合 - [ ] 端到端測試 - [ ] 效能測試和調優 - [ ] 生產環境部署準備 ## 🛠 技術實現 ### .NET Core 實現範例 #### 1. 路由結構 ```csharp // Program.cs app.MapControllerRoute( name: "mobile-api", pattern: "api/v1/mobile/{controller}/{action=Index}/{id?}"); app.MapControllerRoute( name: "web-api", pattern: "api/v1/web/{controller}/{action=Index}/{id?}"); ``` #### 2. 基礎控制器 ```csharp // MobileBaseController.cs [ApiController] [Route("api/v1/mobile/[controller]")] [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public abstract class MobileBaseController : ControllerBase { protected readonly ILogger Logger; protected readonly IMapper Mapper; protected MobileBaseController(ILogger logger, IMapper mapper) { Logger = logger; Mapper = mapper; } protected IActionResult MobileSuccess(T data, string message = null) { return Ok(new MobileApiResponse { Data = data, Message = message, Timestamp = DateTimeOffset.UtcNow, Success = true }); } } // WebBaseController.cs [ApiController] [Route("api/v1/web/[controller]")] [Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)] public abstract class WebBaseController : ControllerBase { protected readonly ILogger Logger; protected readonly IMapper Mapper; protected WebBaseController(ILogger logger, IMapper mapper) { Logger = logger; Mapper = mapper; } protected IActionResult WebSuccess(T data, object meta = null) { return Ok(new WebApiResponse { Data = data, Meta = meta, Links = GenerateHATEOASLinks(), Timestamp = DateTimeOffset.UtcNow }); } } ``` #### 3. 專業化控制器 ```csharp // Mobile Vocabulary Controller public class MobileVocabularyController : MobileBaseController { private readonly IVocabularyService _vocabularyService; public MobileVocabularyController( ILogger logger, IMapper mapper, IVocabularyService vocabularyService) : base(logger, mapper) { _vocabularyService = vocabularyService; } [HttpGet("{id}")] public async Task GetVocabulary(int id) { var vocabulary = await _vocabularyService.GetByIdAsync(id); var mobileDto = Mapper.Map(vocabulary); return MobileSuccess(mobileDto); } [HttpGet("sync")] public async Task SyncVocabulary([FromQuery] DateTime? lastSync) { var changes = await _vocabularyService.GetChangesAsync(lastSync); var mobileDtos = Mapper.Map>(changes); return MobileSuccess(new { Vocabularies = mobileDtos, LastSyncTime = DateTimeOffset.UtcNow, HasMore = changes.Count >= 50 }); } } // Web Vocabulary Controller public class WebVocabularyController : WebBaseController { private readonly IVocabularyService _vocabularyService; private readonly ILearningAnalyticsService _analyticsService; public WebVocabularyController( ILogger logger, IMapper mapper, IVocabularyService vocabularyService, ILearningAnalyticsService analyticsService) : base(logger, mapper) { _vocabularyService = vocabularyService; _analyticsService = analyticsService; } [HttpGet("{id}")] public async Task GetVocabulary(int id) { var vocabulary = await _vocabularyService.GetByIdAsync(id); var analytics = await _analyticsService.GetVocabularyAnalyticsAsync(id); var webDto = Mapper.Map(vocabulary); webDto.LearningAnalytics = Mapper.Map(analytics); return WebSuccess(webDto, new { Related = await _vocabularyService.GetRelatedWordsAsync(id), Recommendations = await _vocabularyService.GetRecommendationsAsync(id) }); } [HttpGet("search")] public async Task SearchVocabulary( [FromQuery] string query, [FromQuery] int page = 1, [FromQuery] int size = 20, [FromQuery] string[] filters = null) { var result = await _vocabularyService.SearchAsync(query, page, size, filters); var webDtos = Mapper.Map>(result.Items); return WebSuccess(webDtos, new { Pagination = new { Page = page, Size = size, Total = result.Total, Pages = (int)Math.Ceiling((double)result.Total / size) }, Filters = await _vocabularyService.GetAvailableFiltersAsync(), Aggregations = result.Aggregations }); } } ``` #### 4. 資料傳輸物件 (DTOs) ```csharp // Mobile DTOs - 精簡結構 public class MobileVocabularyDto { public int Id { get; set; } public string Word { get; set; } public string Phonetic { get; set; } public string Definition { get; set; } public string AudioUrl { get; set; } public DateTimeOffset LastReviewed { get; set; } public int ReviewCount { get; set; } public double MasteryLevel { get; set; } } public class MobileApiResponse { public T Data { get; set; } public string Message { get; set; } public bool Success { get; set; } public DateTimeOffset Timestamp { get; set; } } // Web DTOs - 豐富結構 public class WebVocabularyDto { public int Id { get; set; } public string Word { get; set; } public string Phonetic { get; set; } public DefinitionDto Definitions { get; set; } public List Examples { get; set; } public List Synonyms { get; set; } public List Antonyms { get; set; } public string Etymology { get; set; } public double UsageFrequency { get; set; } public string DifficultyLevel { get; set; } public List RelatedWords { get; set; } public LearningAnalyticsDto LearningAnalytics { get; set; } public DateTimeOffset CreatedAt { get; set; } public DateTimeOffset UpdatedAt { get; set; } } public class WebApiResponse { public T Data { get; set; } public object Meta { get; set; } public Dictionary Links { get; set; } public DateTimeOffset Timestamp { get; set; } } ``` ## 📈 效能考量 ### 移動端優化策略 1. **資料壓縮**: 使用Gzip/Brotli壓縮 2. **增量同步**: 僅傳輸變更資料 3. **快取策略**: 積極的客戶端快取 4. **分頁載入**: 小批次資料載入 5. **連接複用**: HTTP/2 多工處理 ### Web端優化策略 1. **快取分層**: Redis + Memory + CDN 2. **資料預載**: 相關資料預先載入 3. **即時更新**: WebSocket/SignalR 4. **搜尋優化**: ElasticSearch整合 5. **圖片優化**: WebP格式和響應式圖片 ## 🔒 安全性設計 ### 共同安全措施 - HTTPS強制執行 - API版本控制 - 輸入驗證和清理 - 輸出編碼 - 安全標頭設定 ### 移動端專屬 - JWT Token安全存儲 - Certificate Pinning - Root Detection - API密鑰混淆 - 生物識別整合 ### Web端專屬 - CSRF保護 - XSS防護 - Content Security Policy - Session管理 - Same-Site Cookie ## 📊 監控和分析 ### 關鍵指標 (KPIs) 1. **效能指標** - API回應時間 (P95 < 200ms) - 錯誤率 (< 0.1%) - 吞吐量 (TPS) 2. **使用者體驗** - 移動端資料傳輸量 - Web端頁面載入時間 - 離線功能可用性 3. **業務指標** - API使用率 - 功能採用率 - 使用者滿意度 ### 監控工具 - **Application Insights**: .NET應用監控 - **Prometheus + Grafana**: 指標收集和視覺化 - **ELK Stack**: 日誌分析 - **Postman/Newman**: API測試自動化 ## 🚦 風險管理 ### 技術風險 | 風險 | 機率 | 影響 | 緩解措施 | |------|------|------|----------| | 服務間通信複雜度 | 中 | 高 | 使用成熟的API Gateway解決方案 | | 資料一致性問題 | 中 | 高 | 實施Saga模式和補償事務 | | 效能退化 | 低 | 中 | 充分的效能測試和監控 | | 安全漏洞 | 低 | 高 | 安全掃描和滲透測試 | ### 業務風險 | 風險 | 機率 | 影響 | 緩解措施 | |------|------|------|----------| | 開發時程延遲 | 中 | 中 | 分階段實施,降低每階段風險 | | 使用者體驗下降 | 低 | 高 | 充分的使用者測試 | | 維護成本增加 | 中 | 中 | 自動化部署和監控 | ## 📝 後續步驟 ### 立即行動項目 1. [ ] **技術評估**: 評估現有程式碼庫分離可行性 2. [ ] **團隊培訓**: 微服務架構和API設計最佳實踐 3. [ ] **工具準備**: 開發、測試、部署工具鏈建立 4. [ ] **原型開發**: 建立MVP驗證架構可行性 ### 決策點 1. **Week 4**: Phase 1完成度評估,決定是否進入Phase 2 2. **Week 10**: 效能和安全性評估,決定微服務遷移時機 3. **Week 18**: 全面評估,決定生產環境部署策略 ## 📚 詞彙學習系統API實施計畫 ### 階段一:核心詞彙API開發 (Week 1-3) #### 1.1 資料庫架構建立 ```sql -- 詞彙基礎表設計 (基於database-schema.md) CREATE TABLE vocabulary_bank ( vocab_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), word VARCHAR(100) NOT NULL, phonetic VARCHAR(200), part_of_speech VARCHAR(50), definition_en TEXT, definition_native JSONB, category VARCHAR(50), difficulty_level VARCHAR(10), frequency_rank INTEGER, audio_url TEXT, example_sentences JSONB, synonyms JSONB, antonyms JSONB, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(), UNIQUE(word, part_of_speech) ); -- 用戶詞彙進度表 CREATE TABLE user_vocabulary_progress ( progress_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES users(user_id) ON DELETE CASCADE, vocab_id UUID REFERENCES vocabulary_bank(vocab_id) ON DELETE CASCADE, mastery_level VARCHAR(20) DEFAULT 'learning', mastery_score INTEGER DEFAULT 0, review_count INTEGER DEFAULT 0, correct_count INTEGER DEFAULT 0, ease_factor DECIMAL(4,2) DEFAULT 2.50, interval_days INTEGER DEFAULT 1, next_review_date DATE, first_encountered TIMESTAMPTZ DEFAULT NOW(), last_reviewed TIMESTAMPTZ, UNIQUE(user_id, vocab_id) ); ``` #### 1.2 核心服務層實現 ```csharp // IVocabularyService 介面設計 public interface IVocabularyService { // 基本詞彙CRUD Task GetByIdAsync(Guid vocabId); Task> GetVocabularyListAsync(VocabularyFilter filter); Task> SearchVocabularyAsync(string query, int limit = 20); // 用戶學習進度 Task GetUserProgressAsync(Guid userId, Guid vocabId); Task UpdateProgressAsync(Guid userId, UpdateProgressRequest request); Task> GetDueForReviewAsync(Guid userId); // 間隔重複演算法 Task ProcessReviewResultAsync( Guid userId, Guid vocabId, ReviewQuality quality); // 學習分析 Task GetLearningAnalyticsAsync(Guid userId); } // 間隔重複演算法實現 public class SpacedRepetitionService : ISpacedRepetitionService { public SpacedRepetitionResult CalculateNextReview( double easeFactor, int interval, ReviewQuality quality) { // SuperMemo SM-2 算法實現 var newEaseFactor = Math.Max(1.3, easeFactor + (0.1 - (5 - (int)quality) * (0.08 + (5 - (int)quality) * 0.02))); int newInterval = quality switch { ReviewQuality.Again => 1, ReviewQuality.Hard => (int)(interval * 1.2), ReviewQuality.Good => (int)(interval * newEaseFactor), ReviewQuality.Easy => (int)(interval * newEaseFactor * 1.3), _ => 1 }; return new SpacedRepetitionResult { NextInterval = newInterval, NewEaseFactor = newEaseFactor, NextReviewDate = DateTime.UtcNow.AddDays(newInterval) }; } } ``` #### 1.3 API控制器實現 ```csharp // 移動端詞彙API控制器 [ApiController] [Route("api/v1/mobile/vocabulary")] [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public class MobileVocabularyController : MobileBaseController { private readonly IVocabularyService _vocabularyService; [HttpGet("daily-review")] public async Task>>> GetDailyReview() { var userId = GetCurrentUserId(); var vocabularyList = await _vocabularyService.GetDueForReviewAsync(userId); var mobileDtos = Mapper.Map>(vocabularyList); return MobileSuccess(mobileDtos); } [HttpPost("{vocabId}/review")] public async Task>> SubmitReview( Guid vocabId, [FromBody] SubmitReviewRequest request) { var userId = GetCurrentUserId(); var result = await _vocabularyService.ProcessReviewResultAsync( userId, vocabId, request.Quality); return MobileSuccess(new ReviewResultDto { NextReviewDate = result.NextReviewDate, MasteryLevelChange = result.MasteryLevelChange, PointsEarned = result.PointsEarned }); } [HttpGet("search")] public async Task>>> Search( [FromQuery] string query, [FromQuery] int limit = 10) { var results = await _vocabularyService.SearchVocabularyAsync(query, limit); var mobileDtos = Mapper.Map>(results); return MobileSuccess(mobileDtos); } } // Web端詞彙API控制器 [ApiController] [Route("api/v1/web/vocabulary")] [Authorize] public class WebVocabularyController : WebBaseController { [HttpGet("{id}")] public async Task>> GetVocabulary(Guid id) { var vocabulary = await _vocabularyService.GetByIdAsync(id); var webDto = Mapper.Map(vocabulary); return WebSuccess(webDto, new { RelatedWords = await _vocabularyService.GetRelatedWordsAsync(id), LearningTips = await _vocabularyService.GetLearningTipsAsync(id), UsageExamples = await _vocabularyService.GetUsageExamplesAsync(id) }); } [HttpGet("analytics")] public async Task>> GetAnalytics( [FromQuery] DateTime? from, [FromQuery] DateTime? to) { var userId = GetCurrentUserId(); var analytics = await _vocabularyService.GetLearningAnalyticsAsync( userId, from, to); return WebSuccess(analytics); } } ``` ### 階段二:智能學習功能 (Week 4-6) #### 2.1 AI驅動的詞彙推薦系統 ```csharp public interface IVocabularyRecommendationService { Task> GetPersonalizedRecommendationsAsync( Guid userId, int count = 10); Task> GetContextualVocabularyAsync( string context, DifficultyLevel level); Task> GetRelatedVocabularyAsync(Guid vocabId); } public class AIVocabularyRecommendationService : IVocabularyRecommendationService { private readonly IOpenAIService _openAiService; private readonly IVocabularyRepository _vocabularyRepo; public async Task> GetPersonalizedRecommendationsAsync( Guid userId, int count = 10) { // 獲取用戶學習歷史和偏好 var userProfile = await GetUserLearningProfileAsync(userId); // 使用GPT-4o-mini分析用戶需求 var prompt = $@" Based on user learning profile: - Current level: {userProfile.Level} - Weak categories: {string.Join(',', userProfile.WeakCategories)} - Interests: {string.Join(',', userProfile.Interests)} Recommend 10 vocabulary words that would be most beneficial for this learner's progression."; var aiResponse = await _openAiService.GetCompletionAsync(prompt); // 解析AI回應並匹配資料庫詞彙 return await MatchWordsFromDatabase(aiResponse, count); } } ``` #### 2.2 自適應複習系統 ```csharp public class AdaptiveReviewService : IAdaptiveReviewService { public async Task CreateReviewSessionAsync(Guid userId) { var dueWords = await _vocabularyService.GetDueForReviewAsync(userId); var userStats = await GetUserStatisticsAsync(userId); // 根據用戶表現調整複習策略 var strategy = DetermineReviewStrategy(userStats); // 智能排序複習詞彙 var optimizedOrder = OptimizeReviewOrder(dueWords, strategy); return new AdaptiveReviewSession { SessionId = Guid.NewGuid(), UserId = userId, Words = optimizedOrder, Strategy = strategy, EstimatedDuration = CalculateEstimatedDuration(optimizedOrder.Count) }; } private ReviewStrategy DetermineReviewStrategy(UserStatistics stats) { // 基於用戶統計數據選擇最佳複習策略 if (stats.AccuracyRate < 0.7) return ReviewStrategy.Reinforcement; // 加強練習 else if (stats.ReviewStreak > 7) return ReviewStrategy.Challenging; // 挑戰模式 else return ReviewStrategy.Balanced; // 平衡模式 } } ``` ### 階段三:高級分析與遊戲化 (Week 7-9) #### 3.1 學習分析API ```csharp [ApiController] [Route("api/v1/mobile/vocabulary/analytics")] public class MobileVocabularyAnalyticsController : MobileBaseController { [HttpGet("dashboard")] public async Task>> GetDashboard() { var userId = GetCurrentUserId(); var data = new DashboardData { TodayProgress = await _analyticsService.GetTodayProgressAsync(userId), WeeklyStreak = await _analyticsService.GetWeeklyStreakAsync(userId), MasteryDistribution = await _analyticsService.GetMasteryDistributionAsync(userId), RecentAchievements = await _analyticsService.GetRecentAchievementsAsync(userId) }; return MobileSuccess(data); } [HttpGet("progress-chart")] public async Task>> GetProgressChart( [FromQuery] ChartPeriod period = ChartPeriod.Month) { var userId = GetCurrentUserId(); var chartData = await _analyticsService.GetProgressChartDataAsync(userId, period); return MobileSuccess(chartData); } } ``` #### 3.2 遊戲化系統整合 ```csharp public interface IVocabularyGamificationService { Task CheckAchievementsAsync(Guid userId, LearningActivity activity); Task> GetUserBadgesAsync(Guid userId); Task GetLeaderboardPositionAsync(Guid userId); Task CalculateExperiencePointsAsync(ReviewResult result); } public class VocabularyGamificationService : IVocabularyGamificationService { public async Task CalculateExperiencePointsAsync(ReviewResult result) { var basePoints = result.Quality switch { ReviewQuality.Again => 1, ReviewQuality.Hard => 3, ReviewQuality.Good => 5, ReviewQuality.Easy => 8, _ => 0 }; // 連續正確答案加成 var streakMultiplier = Math.Min(result.StreakCount / 5.0 + 1, 2.0); // 詞彙難度加成 var difficultyMultiplier = result.Difficulty switch { "A1" => 1.0, "A2" => 1.2, "B1" => 1.5, "B2" => 1.8, "C1" => 2.0, "C2" => 2.5, _ => 1.0 }; return (int)(basePoints * streakMultiplier * difficultyMultiplier); } } ``` ### 階段四:效能優化與快取 (Week 10-12) #### 4.1 Redis快取策略 ```csharp public class CachedVocabularyService : IVocabularyService { private readonly IVocabularyService _baseService; private readonly IRedisCache _cache; public async Task GetByIdAsync(Guid vocabId) { var cacheKey = $"vocabulary:{vocabId}"; var cached = await _cache.GetAsync(cacheKey); if (cached != null) return cached; var vocabulary = await _baseService.GetByIdAsync(vocabId); await _cache.SetAsync(cacheKey, vocabulary, TimeSpan.FromHours(6)); return vocabulary; } public async Task> GetDueForReviewAsync(Guid userId) { var cacheKey = $"user:{userId}:due-review"; var cached = await _cache.GetAsync>(cacheKey); if (cached != null) return cached; var dueWords = await _baseService.GetDueForReviewAsync(userId); await _cache.SetAsync(cacheKey, dueWords, TimeSpan.FromMinutes(15)); return dueWords; } } ``` #### 4.2 資料庫查詢優化 ```sql -- 高效能索引設計 CREATE INDEX CONCURRENTLY idx_user_vocab_due_review ON user_vocabulary_progress(user_id, next_review_date) WHERE next_review_date <= CURRENT_DATE; CREATE INDEX CONCURRENTLY idx_vocabulary_search ON vocabulary_bank USING gin(to_tsvector('english', word || ' ' || definition_en)); -- 用戶學習統計物化視圖 CREATE MATERIALIZED VIEW user_vocabulary_stats AS SELECT user_id, COUNT(*) as total_words, COUNT(*) FILTER (WHERE mastery_level = 'mastered') as mastered_count, AVG(mastery_score) as average_mastery, COUNT(*) FILTER (WHERE last_reviewed >= CURRENT_DATE - INTERVAL '7 days') as weekly_reviews FROM user_vocabulary_progress GROUP BY user_id; CREATE UNIQUE INDEX ON user_vocabulary_stats(user_id); ``` ### 詞彙學習API端點總結 #### 移動端API端點 | 端點 | 方法 | 描述 | 快取策略 | |------|------|------|----------| | `/api/v1/mobile/vocabulary/daily-review` | GET | 獲取每日複習詞彙 | 15分鐘 | | `/api/v1/mobile/vocabulary/{id}/review` | POST | 提交複習結果 | 無快取 | | `/api/v1/mobile/vocabulary/search` | GET | 詞彙搜尋 | 30分鐘 | | `/api/v1/mobile/vocabulary/recommendations` | GET | 個人化推薦 | 1小時 | | `/api/v1/mobile/vocabulary/analytics/dashboard` | GET | 學習儀表板 | 10分鐘 | #### Web端API端點 | 端點 | 方法 | 描述 | 快取策略 | |------|------|------|----------| | `/api/v1/web/vocabulary/{id}` | GET | 詞彙詳細資訊 | 6小時 | | `/api/v1/web/vocabulary/analytics` | GET | 學習分析報告 | 30分鐘 | | `/api/v1/web/vocabulary/batch` | GET | 批量詞彙資料 | 1小時 | | `/api/v1/web/vocabulary/export` | POST | 匯出學習資料 | 無快取 | ### 實施優先級 #### 高優先級 (Week 1-6) 1. 基礎詞彙CRUD API 2. 用戶學習進度追蹤 3. 間隔重複演算法 4. 移動端基礎API #### 中優先級 (Week 7-9) 1. AI推薦系統 2. 學習分析功能 3. 遊戲化元素 4. Web端豐富功能 #### 低優先級 (Week 10-12) 1. 效能優化 2. 進階快取策略 3. 資料匯出功能 4. 管理後台API --- **最後更新**: 2025-09-10 **版本**: 1.1 - 新增詞彙學習系統實施計畫 **維護者**: Drama Ling 開發團隊