30 KiB
30 KiB
後端API架構分離計劃
文件版本: 1.0
建立日期: 2025-09-10
更新日期: 2025-09-10
負責人: Drama Ling 開發團隊
📋 概述
由於Drama Ling需要同時支援移動端App和Web端應用,現有的單一後端API架構將面臨以下挑戰:
- 移動端和Web端資料需求差異
- 認證方式和安全要求不同
- 效能優化需求各異
- 維護和擴展複雜度增加
本文件提出後端API分離的架構方案和實施計劃。
🎯 目標
主要目標
- API專業化: 為移動端和Web端提供專門優化的API
- 提升效能: 減少不必要的資料傳輸,提升回應速度
- 簡化維護: 降低不同端點間的耦合度
- 增強安全: 針對不同平台實施適當的安全策略
- 支援擴展: 為未來微服務架構奠定基礎
成功指標
- API回應時間減少30%以上
- 移動端資料傳輸量減少50%
- 代碼維護複雜度降低
- 支援獨立部署和擴展
🏗 架構方案
方案一: API Gateway + 微服務分離 (推薦)
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)]
優勢
- 🎯 高度專業化: 每個服務專注特定功能
- 🚀 獨立擴展: 可根據負載獨立擴展服務
- 🔒 安全隔離: 服務間隔離,降低安全風險
- 🛠 技術選型靈活: 不同服務可選用不同技術
- 👥 團隊分工: 支援多團隊並行開發
挑戰
- 複雜度較高,需要服務發現和配置管理
- 分散式系統的一致性問題
- 運維複雜度增加
方案二: 單體 + 多端點適配 (階段性)
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特點
{
"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特點
{
"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認證"
]
}
認證策略差異
移動端認證
[ApiController]
[Route("api/v1/mobile/[controller]")]
[Authorize(AuthenticationSchemes = "JwtBearer")]
public class MobileVocabularyController : ControllerBase
{
// JWT Token + Refresh Token
// 生物識別支援
// OAuth2.0 整合
}
Web端認證
[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. 路由結構
// 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. 基礎控制器
// 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>(T data, string message = null)
{
return Ok(new MobileApiResponse<T>
{
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>(T data, object meta = null)
{
return Ok(new WebApiResponse<T>
{
Data = data,
Meta = meta,
Links = GenerateHATEOASLinks(),
Timestamp = DateTimeOffset.UtcNow
});
}
}
3. 專業化控制器
// Mobile Vocabulary Controller
public class MobileVocabularyController : MobileBaseController
{
private readonly IVocabularyService _vocabularyService;
public MobileVocabularyController(
ILogger<MobileVocabularyController> logger,
IMapper mapper,
IVocabularyService vocabularyService)
: base(logger, mapper)
{
_vocabularyService = vocabularyService;
}
[HttpGet("{id}")]
public async Task<IActionResult> GetVocabulary(int id)
{
var vocabulary = await _vocabularyService.GetByIdAsync(id);
var mobileDto = Mapper.Map<MobileVocabularyDto>(vocabulary);
return MobileSuccess(mobileDto);
}
[HttpGet("sync")]
public async Task<IActionResult> SyncVocabulary([FromQuery] DateTime? lastSync)
{
var changes = await _vocabularyService.GetChangesAsync(lastSync);
var mobileDtos = Mapper.Map<List<MobileVocabularyDto>>(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<WebVocabularyController> logger,
IMapper mapper,
IVocabularyService vocabularyService,
ILearningAnalyticsService analyticsService)
: base(logger, mapper)
{
_vocabularyService = vocabularyService;
_analyticsService = analyticsService;
}
[HttpGet("{id}")]
public async Task<IActionResult> GetVocabulary(int id)
{
var vocabulary = await _vocabularyService.GetByIdAsync(id);
var analytics = await _analyticsService.GetVocabularyAnalyticsAsync(id);
var webDto = Mapper.Map<WebVocabularyDto>(vocabulary);
webDto.LearningAnalytics = Mapper.Map<LearningAnalyticsDto>(analytics);
return WebSuccess(webDto, new {
Related = await _vocabularyService.GetRelatedWordsAsync(id),
Recommendations = await _vocabularyService.GetRecommendationsAsync(id)
});
}
[HttpGet("search")]
public async Task<IActionResult> 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<List<WebVocabularyDto>>(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)
// 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<T>
{
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<ExampleDto> Examples { get; set; }
public List<string> Synonyms { get; set; }
public List<string> Antonyms { get; set; }
public string Etymology { get; set; }
public double UsageFrequency { get; set; }
public string DifficultyLevel { get; set; }
public List<string> RelatedWords { get; set; }
public LearningAnalyticsDto LearningAnalytics { get; set; }
public DateTimeOffset CreatedAt { get; set; }
public DateTimeOffset UpdatedAt { get; set; }
}
public class WebApiResponse<T>
{
public T Data { get; set; }
public object Meta { get; set; }
public Dictionary<string, string> Links { get; set; }
public DateTimeOffset Timestamp { get; set; }
}
📈 效能考量
移動端優化策略
- 資料壓縮: 使用Gzip/Brotli壓縮
- 增量同步: 僅傳輸變更資料
- 快取策略: 積極的客戶端快取
- 分頁載入: 小批次資料載入
- 連接複用: HTTP/2 多工處理
Web端優化策略
- 快取分層: Redis + Memory + CDN
- 資料預載: 相關資料預先載入
- 即時更新: WebSocket/SignalR
- 搜尋優化: ElasticSearch整合
- 圖片優化: WebP格式和響應式圖片
🔒 安全性設計
共同安全措施
- HTTPS強制執行
- API版本控制
- 輸入驗證和清理
- 輸出編碼
- 安全標頭設定
移動端專屬
- JWT Token安全存儲
- Certificate Pinning
- Root Detection
- API密鑰混淆
- 生物識別整合
Web端專屬
- CSRF保護
- XSS防護
- Content Security Policy
- Session管理
- Same-Site Cookie
📊 監控和分析
關鍵指標 (KPIs)
-
效能指標
- API回應時間 (P95 < 200ms)
- 錯誤率 (< 0.1%)
- 吞吐量 (TPS)
-
使用者體驗
- 移動端資料傳輸量
- Web端頁面載入時間
- 離線功能可用性
-
業務指標
- API使用率
- 功能採用率
- 使用者滿意度
監控工具
- Application Insights: .NET應用監控
- Prometheus + Grafana: 指標收集和視覺化
- ELK Stack: 日誌分析
- Postman/Newman: API測試自動化
🚦 風險管理
技術風險
| 風險 | 機率 | 影響 | 緩解措施 |
|---|---|---|---|
| 服務間通信複雜度 | 中 | 高 | 使用成熟的API Gateway解決方案 |
| 資料一致性問題 | 中 | 高 | 實施Saga模式和補償事務 |
| 效能退化 | 低 | 中 | 充分的效能測試和監控 |
| 安全漏洞 | 低 | 高 | 安全掃描和滲透測試 |
業務風險
| 風險 | 機率 | 影響 | 緩解措施 |
|---|---|---|---|
| 開發時程延遲 | 中 | 中 | 分階段實施,降低每階段風險 |
| 使用者體驗下降 | 低 | 高 | 充分的使用者測試 |
| 維護成本增加 | 中 | 中 | 自動化部署和監控 |
📝 後續步驟
立即行動項目
- 技術評估: 評估現有程式碼庫分離可行性
- 團隊培訓: 微服務架構和API設計最佳實踐
- 工具準備: 開發、測試、部署工具鏈建立
- 原型開發: 建立MVP驗證架構可行性
決策點
- Week 4: Phase 1完成度評估,決定是否進入Phase 2
- Week 10: 效能和安全性評估,決定微服務遷移時機
- Week 18: 全面評估,決定生產環境部署策略
📚 詞彙學習系統API實施計畫
階段一:核心詞彙API開發 (Week 1-3)
1.1 資料庫架構建立
-- 詞彙基礎表設計 (基於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 核心服務層實現
// IVocabularyService 介面設計
public interface IVocabularyService
{
// 基本詞彙CRUD
Task<VocabularyDto> GetByIdAsync(Guid vocabId);
Task<PagedResult<VocabularyDto>> GetVocabularyListAsync(VocabularyFilter filter);
Task<List<VocabularyDto>> SearchVocabularyAsync(string query, int limit = 20);
// 用戶學習進度
Task<UserVocabularyProgressDto> GetUserProgressAsync(Guid userId, Guid vocabId);
Task UpdateProgressAsync(Guid userId, UpdateProgressRequest request);
Task<List<VocabularyDto>> GetDueForReviewAsync(Guid userId);
// 間隔重複演算法
Task<SpacedRepetitionResult> ProcessReviewResultAsync(
Guid userId, Guid vocabId, ReviewQuality quality);
// 學習分析
Task<LearningAnalyticsDto> 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控制器實現
// 移動端詞彙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<ActionResult<MobileApiResponse<List<MobileVocabularyDto>>>> GetDailyReview()
{
var userId = GetCurrentUserId();
var vocabularyList = await _vocabularyService.GetDueForReviewAsync(userId);
var mobileDtos = Mapper.Map<List<MobileVocabularyDto>>(vocabularyList);
return MobileSuccess(mobileDtos);
}
[HttpPost("{vocabId}/review")]
public async Task<ActionResult<MobileApiResponse<ReviewResultDto>>> 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<ActionResult<MobileApiResponse<List<MobileVocabularyDto>>>> Search(
[FromQuery] string query, [FromQuery] int limit = 10)
{
var results = await _vocabularyService.SearchVocabularyAsync(query, limit);
var mobileDtos = Mapper.Map<List<MobileVocabularyDto>>(results);
return MobileSuccess(mobileDtos);
}
}
// Web端詞彙API控制器
[ApiController]
[Route("api/v1/web/vocabulary")]
[Authorize]
public class WebVocabularyController : WebBaseController
{
[HttpGet("{id}")]
public async Task<ActionResult<WebApiResponse<WebVocabularyDto>>> GetVocabulary(Guid id)
{
var vocabulary = await _vocabularyService.GetByIdAsync(id);
var webDto = Mapper.Map<WebVocabularyDto>(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<ActionResult<WebApiResponse<LearningAnalyticsDto>>> 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驅動的詞彙推薦系統
public interface IVocabularyRecommendationService
{
Task<List<VocabularyDto>> GetPersonalizedRecommendationsAsync(
Guid userId, int count = 10);
Task<List<VocabularyDto>> GetContextualVocabularyAsync(
string context, DifficultyLevel level);
Task<List<VocabularyDto>> GetRelatedVocabularyAsync(Guid vocabId);
}
public class AIVocabularyRecommendationService : IVocabularyRecommendationService
{
private readonly IOpenAIService _openAiService;
private readonly IVocabularyRepository _vocabularyRepo;
public async Task<List<VocabularyDto>> 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 自適應複習系統
public class AdaptiveReviewService : IAdaptiveReviewService
{
public async Task<AdaptiveReviewSession> 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
[ApiController]
[Route("api/v1/mobile/vocabulary/analytics")]
public class MobileVocabularyAnalyticsController : MobileBaseController
{
[HttpGet("dashboard")]
public async Task<ActionResult<MobileApiResponse<DashboardData>>> 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<ActionResult<MobileApiResponse<ProgressChartData>>> GetProgressChart(
[FromQuery] ChartPeriod period = ChartPeriod.Month)
{
var userId = GetCurrentUserId();
var chartData = await _analyticsService.GetProgressChartDataAsync(userId, period);
return MobileSuccess(chartData);
}
}
3.2 遊戲化系統整合
public interface IVocabularyGamificationService
{
Task<AchievementResult> CheckAchievementsAsync(Guid userId, LearningActivity activity);
Task<List<BadgeDto>> GetUserBadgesAsync(Guid userId);
Task<LeaderboardPosition> GetLeaderboardPositionAsync(Guid userId);
Task<int> CalculateExperiencePointsAsync(ReviewResult result);
}
public class VocabularyGamificationService : IVocabularyGamificationService
{
public async Task<int> 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快取策略
public class CachedVocabularyService : IVocabularyService
{
private readonly IVocabularyService _baseService;
private readonly IRedisCache _cache;
public async Task<VocabularyDto> GetByIdAsync(Guid vocabId)
{
var cacheKey = $"vocabulary:{vocabId}";
var cached = await _cache.GetAsync<VocabularyDto>(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<List<VocabularyDto>> GetDueForReviewAsync(Guid userId)
{
var cacheKey = $"user:{userId}:due-review";
var cached = await _cache.GetAsync<List<VocabularyDto>>(cacheKey);
if (cached != null)
return cached;
var dueWords = await _baseService.GetDueForReviewAsync(userId);
await _cache.SetAsync(cacheKey, dueWords, TimeSpan.FromMinutes(15));
return dueWords;
}
}
4.2 資料庫查詢優化
-- 高效能索引設計
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)
- 基礎詞彙CRUD API
- 用戶學習進度追蹤
- 間隔重複演算法
- 移動端基礎API
中優先級 (Week 7-9)
- AI推薦系統
- 學習分析功能
- 遊戲化元素
- Web端豐富功能
低優先級 (Week 10-12)
- 效能優化
- 進階快取策略
- 資料匯出功能
- 管理後台API
最後更新: 2025-09-10
版本: 1.1 - 新增詞彙學習系統實施計畫
維護者: Drama Ling 開發團隊