579 lines
14 KiB
Markdown
579 lines
14 KiB
Markdown
# DramaLing API 規格總覽
|
||
|
||
## 1. API 架構概覽
|
||
|
||
### 1.1 基礎資訊
|
||
- **基礎 URL**: `http://localhost:5008/api` (開發環境)
|
||
- **協議**: HTTP/HTTPS
|
||
- **資料格式**: JSON
|
||
- **認證方式**: JWT Bearer Token
|
||
- **CORS**: 允許 localhost:3000-3002
|
||
|
||
### 1.2 標準回應格式
|
||
|
||
#### 成功回應格式
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": {
|
||
// 實際資料內容
|
||
},
|
||
"message": "操作成功" // 可選
|
||
}
|
||
```
|
||
|
||
#### 錯誤回應格式
|
||
```json
|
||
{
|
||
"success": false,
|
||
"error": "錯誤描述",
|
||
"details": "詳細錯誤信息", // 可選
|
||
"timestamp": "2025-09-24T10:30:00Z" // 可選
|
||
}
|
||
```
|
||
|
||
## 2. 詞卡管理 API
|
||
|
||
### 2.1 API 端點清單
|
||
|
||
| 方法 | 端點 | 描述 | 認證 |
|
||
|------|------|------|------|
|
||
| GET | `/api/flashcards` | 取得詞卡列表 | ✅ |
|
||
| GET | `/api/flashcards/{id}` | 取得單一詞卡 | ✅ |
|
||
| POST | `/api/flashcards` | 創建新詞卡 | ✅ |
|
||
| PUT | `/api/flashcards/{id}` | 更新詞卡 | ✅ |
|
||
| DELETE | `/api/flashcards/{id}` | 刪除詞卡 | ✅ |
|
||
| POST | `/api/flashcards/{id}/favorite` | 切換收藏狀態 | ✅ |
|
||
|
||
### 2.2 詳細 API 規格
|
||
|
||
#### GET /api/flashcards
|
||
**描述**: 取得用戶的詞卡列表,支援搜尋和篩選
|
||
|
||
**查詢參數**:
|
||
```typescript
|
||
interface GetFlashcardsQuery {
|
||
search?: string; // 搜尋關鍵字 (詞彙、翻譯、定義)
|
||
favoritesOnly?: boolean; // 僅顯示收藏詞卡 (預設: false)
|
||
}
|
||
```
|
||
|
||
**回應範例**:
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": {
|
||
"flashcards": [
|
||
{
|
||
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||
"word": "sophisticated",
|
||
"translation": "精密的",
|
||
"definition": "Highly developed or complex",
|
||
"partOfSpeech": "adjective",
|
||
"pronunciation": "/səˈfɪstɪkeɪtɪd/",
|
||
"example": "A sophisticated system",
|
||
"exampleTranslation": "一個精密的系統",
|
||
"masteryLevel": 75,
|
||
"timesReviewed": 12,
|
||
"isFavorite": true,
|
||
"nextReviewDate": "2025-09-25T00:00:00Z",
|
||
"difficultyLevel": "C1",
|
||
"createdAt": "2025-09-20T08:30:00Z",
|
||
"updatedAt": "2025-09-24T10:15:00Z"
|
||
}
|
||
],
|
||
"count": 1
|
||
}
|
||
}
|
||
```
|
||
|
||
#### POST /api/flashcards
|
||
**描述**: 創建新的詞卡
|
||
|
||
**請求體**:
|
||
```json
|
||
{
|
||
"word": "sophisticated",
|
||
"translation": "精密的",
|
||
"definition": "Highly developed or complex",
|
||
"pronunciation": "/səˈfɪstɪkeɪtɪd/",
|
||
"partOfSpeech": "adjective",
|
||
"example": "A sophisticated system",
|
||
"exampleTranslation": "一個精密的系統"
|
||
}
|
||
```
|
||
|
||
**回應範例**:
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": {
|
||
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||
"word": "sophisticated",
|
||
// ... 完整詞卡資料
|
||
"createdAt": "2025-09-24T10:30:00Z"
|
||
},
|
||
"message": "詞卡創建成功"
|
||
}
|
||
```
|
||
|
||
#### PUT /api/flashcards/{id}
|
||
**描述**: 更新現有詞卡
|
||
|
||
**路徑參數**:
|
||
- `id`: 詞卡唯一識別碼 (GUID)
|
||
|
||
**請求體**: 與 POST 相同格式
|
||
|
||
**回應範例**:
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": {
|
||
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||
// ... 更新後的詞卡資料
|
||
"updatedAt": "2025-09-24T10:35:00Z"
|
||
},
|
||
"message": "詞卡更新成功"
|
||
}
|
||
```
|
||
|
||
#### DELETE /api/flashcards/{id}
|
||
**描述**: 刪除詞卡 (軟刪除,設定 IsArchived = true)
|
||
|
||
**路徑參數**:
|
||
- `id`: 詞卡唯一識別碼 (GUID)
|
||
|
||
**回應範例**:
|
||
```json
|
||
{
|
||
"success": true,
|
||
"message": "詞卡已刪除"
|
||
}
|
||
```
|
||
|
||
#### POST /api/flashcards/{id}/favorite
|
||
**描述**: 切換詞卡的收藏狀態
|
||
|
||
**路徑參數**:
|
||
- `id`: 詞卡唯一識別碼 (GUID)
|
||
|
||
**回應範例**:
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": {
|
||
"isFavorite": true
|
||
},
|
||
"message": "已加入收藏"
|
||
}
|
||
```
|
||
|
||
## 3. AI 分析 API
|
||
|
||
### 3.1 API 端點
|
||
|
||
| 方法 | 端點 | 描述 | 認證 |
|
||
|------|------|------|------|
|
||
| POST | `/api/ai/analyze-sentence` | AI 句子分析 | ✅ |
|
||
|
||
### 3.2 句子分析 API
|
||
|
||
#### POST /api/ai/analyze-sentence
|
||
**描述**: 使用 AI 分析英語句子,提供詞彙分析、語法檢查、翻譯等功能
|
||
|
||
**請求體**:
|
||
```json
|
||
{
|
||
"inputText": "The sophisticated algorithm processes data efficiently.",
|
||
"analysisMode": "full",
|
||
"options": {
|
||
"includeGrammarCheck": true,
|
||
"includeVocabularyAnalysis": true,
|
||
"includeTranslation": true,
|
||
"includeIdiomDetection": true,
|
||
"includeExamples": true
|
||
}
|
||
}
|
||
```
|
||
|
||
**回應範例**:
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": {
|
||
"originalText": "The sophisticated algorithm processes data efficiently.",
|
||
"sentenceMeaning": "這個精密的算法高效地處理資料。",
|
||
"grammarCorrection": {
|
||
"hasErrors": false,
|
||
"correctedText": null,
|
||
"corrections": [],
|
||
"confidenceScore": 0.95
|
||
},
|
||
"vocabularyAnalysis": {
|
||
"sophisticated": {
|
||
"word": "sophisticated",
|
||
"translation": "精密的",
|
||
"definition": "Highly developed or complex",
|
||
"partOfSpeech": "adjective",
|
||
"pronunciation": "/səˈfɪstɪkeɪtɪd/",
|
||
"difficultyLevel": "C1",
|
||
"frequency": "high",
|
||
"cefrLevel": "C1",
|
||
"synonyms": ["advanced", "complex", "refined"]
|
||
},
|
||
"algorithm": {
|
||
"word": "algorithm",
|
||
"translation": "算法",
|
||
"definition": "A set of rules for solving problems",
|
||
"partOfSpeech": "noun",
|
||
"pronunciation": "/ˈælɡərɪðəm/",
|
||
"difficultyLevel": "B2",
|
||
"frequency": "medium",
|
||
"cefrLevel": "B2"
|
||
}
|
||
},
|
||
"idioms": [
|
||
{
|
||
"idiom": "processes data",
|
||
"translation": "處理資料",
|
||
"definition": "To handle and analyze information",
|
||
"difficultyLevel": "B1",
|
||
"frequency": "high",
|
||
"cefrLevel": "B1"
|
||
}
|
||
]
|
||
},
|
||
"processingTime": "2.34s"
|
||
}
|
||
```
|
||
|
||
## 4. 認證 API
|
||
|
||
### 4.1 API 端點
|
||
|
||
| 方法 | 端點 | 描述 | 認證 |
|
||
|------|------|------|------|
|
||
| POST | `/api/auth/login` | 用戶登入 | ❌ |
|
||
| POST | `/api/auth/register` | 用戶註冊 | ❌ |
|
||
| POST | `/api/auth/refresh` | 更新 Token | ✅ |
|
||
| POST | `/api/auth/logout` | 用戶登出 | ✅ |
|
||
|
||
### 4.2 認證流程
|
||
|
||
#### 開發階段認證
|
||
```csharp
|
||
// 目前使用固定測試用戶 ID
|
||
private Guid GetUserId()
|
||
{
|
||
return Guid.Parse("00000000-0000-0000-0000-000000000001");
|
||
}
|
||
|
||
// 控制器暫時設定為 [AllowAnonymous]
|
||
[AllowAnonymous]
|
||
public class FlashcardsController : ControllerBase
|
||
```
|
||
|
||
#### 生產環境認證 (未來啟用)
|
||
```csharp
|
||
// JWT Token 解析
|
||
private Guid GetUserId()
|
||
{
|
||
var userIdString = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
||
if (Guid.TryParse(userIdString, out var userId))
|
||
return userId;
|
||
throw new UnauthorizedAccessException("Invalid user ID in token");
|
||
}
|
||
```
|
||
|
||
## 5. 錯誤代碼標準
|
||
|
||
### 5.1 HTTP 狀態碼使用
|
||
|
||
| 狀態碼 | 意義 | 使用場景 |
|
||
|--------|------|----------|
|
||
| 200 | OK | 請求成功 |
|
||
| 201 | Created | 資源創建成功 |
|
||
| 400 | Bad Request | 請求參數錯誤 |
|
||
| 401 | Unauthorized | 認證失敗 |
|
||
| 403 | Forbidden | 權限不足 |
|
||
| 404 | Not Found | 資源不存在 |
|
||
| 409 | Conflict | 資源衝突 (如重複創建) |
|
||
| 500 | Internal Server Error | 伺服器內部錯誤 |
|
||
|
||
### 5.2 自定義錯誤碼
|
||
|
||
| 錯誤碼 | 描述 | HTTP 狀態 |
|
||
|--------|------|-----------|
|
||
| `FLASHCARD_NOT_FOUND` | 詞卡不存在 | 404 |
|
||
| `FLASHCARD_ALREADY_EXISTS` | 詞卡已存在 | 409 |
|
||
| `INVALID_CEFR_LEVEL` | 無效的 CEFR 等級 | 400 |
|
||
| `USER_NOT_FOUND` | 用戶不存在 | 404 |
|
||
| `DATABASE_ERROR` | 資料庫操作失敗 | 500 |
|
||
| `AI_SERVICE_UNAVAILABLE` | AI 服務不可用 | 503 |
|
||
|
||
## 6. 請求/回應範例
|
||
|
||
### 6.1 詞卡 CRUD 完整範例
|
||
|
||
#### 創建詞卡
|
||
```bash
|
||
curl -X POST http://localhost:5008/api/flashcards \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"word": "elaborate",
|
||
"translation": "詳細說明",
|
||
"definition": "To explain in detail",
|
||
"pronunciation": "/ɪˈlæbərət/",
|
||
"partOfSpeech": "verb",
|
||
"example": "Please elaborate on your idea",
|
||
"exampleTranslation": "請詳細說明你的想法"
|
||
}'
|
||
```
|
||
|
||
#### 更新詞卡
|
||
```bash
|
||
curl -X PUT http://localhost:5008/api/flashcards/550e8400-e29b-41d4-a716-446655440000 \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"word": "elaborate",
|
||
"translation": "詳細闡述",
|
||
"definition": "To explain something in greater detail",
|
||
"pronunciation": "/ɪˈlæbərət/",
|
||
"partOfSpeech": "verb",
|
||
"example": "Could you elaborate on that point?",
|
||
"exampleTranslation": "你能詳細闡述那個觀點嗎?"
|
||
}'
|
||
```
|
||
|
||
#### 查詢詞卡 (帶搜尋)
|
||
```bash
|
||
curl "http://localhost:5008/api/flashcards?search=elaborate&favoritesOnly=false"
|
||
```
|
||
|
||
#### 切換收藏
|
||
```bash
|
||
curl -X POST http://localhost:5008/api/flashcards/550e8400-e29b-41d4-a716-446655440000/favorite
|
||
```
|
||
|
||
### 6.2 AI 分析範例
|
||
|
||
#### 句子分析請求
|
||
```bash
|
||
curl -X POST http://localhost:5008/api/ai/analyze-sentence \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"inputText": "I need to elaborate on this concept",
|
||
"analysisMode": "full",
|
||
"options": {
|
||
"includeGrammarCheck": true,
|
||
"includeVocabularyAnalysis": true,
|
||
"includeTranslation": true,
|
||
"includeIdiomDetection": true,
|
||
"includeExamples": true
|
||
}
|
||
}'
|
||
```
|
||
|
||
## 7. 資料驗證規則
|
||
|
||
### 7.1 詞卡資料驗證
|
||
|
||
#### 必填欄位
|
||
```csharp
|
||
[Required]
|
||
[MaxLength(255)]
|
||
public string Word { get; set; }
|
||
|
||
[Required]
|
||
public string Translation { get; set; }
|
||
|
||
[Required]
|
||
public string Definition { get; set; }
|
||
|
||
[Required]
|
||
public string Example { get; set; }
|
||
```
|
||
|
||
#### 選填欄位約束
|
||
```csharp
|
||
[MaxLength(50)]
|
||
public string? PartOfSpeech { get; set; }
|
||
|
||
[MaxLength(255)]
|
||
public string? Pronunciation { get; set; }
|
||
|
||
[MaxLength(10)]
|
||
public string? DifficultyLevel { get; set; } // A1, A2, B1, B2, C1, C2
|
||
```
|
||
|
||
#### 數值範圍驗證
|
||
```csharp
|
||
[Range(0, 100)]
|
||
public int MasteryLevel { get; set; } = 0;
|
||
|
||
[Range(0, int.MaxValue)]
|
||
public int TimesReviewed { get; set; } = 0;
|
||
```
|
||
|
||
### 7.2 前端驗證規則
|
||
|
||
#### TypeScript 型別約束
|
||
```typescript
|
||
interface CreateFlashcardRequest {
|
||
word: string; // 1-255 字元
|
||
translation: string; // 必填
|
||
definition: string; // 必填
|
||
pronunciation: string; // 選填,建議 IPA 格式
|
||
partOfSpeech: string; // 選填,預設 'noun'
|
||
example: string; // 必填
|
||
exampleTranslation?: string; // 選填
|
||
}
|
||
```
|
||
|
||
## 8. 快取策略
|
||
|
||
### 8.1 伺服器端快取
|
||
|
||
#### 記憶體快取
|
||
```csharp
|
||
// 常用詞卡快取 30 分鐘
|
||
var cacheKey = $"flashcards:user:{userId}";
|
||
await _cacheService.SetAsync(cacheKey, flashcards, TimeSpan.FromMinutes(30));
|
||
```
|
||
|
||
#### 查詢結果快取
|
||
```csharp
|
||
// 搜尋結果快取 10 分鐘
|
||
var searchCacheKey = $"search:{userId}:{searchTerm}:{favoritesOnly}";
|
||
await _cacheService.SetAsync(searchCacheKey, results, TimeSpan.FromMinutes(10));
|
||
```
|
||
|
||
### 8.2 客戶端快取
|
||
|
||
#### API 服務層快取
|
||
```typescript
|
||
// 簡單的記憶體快取 (未來可改用 SWR 或 React Query)
|
||
class FlashcardsService {
|
||
private cache = new Map<string, any>();
|
||
|
||
async getFlashcards(search?: string, favoritesOnly: boolean = false) {
|
||
const cacheKey = `flashcards:${search || 'all'}:${favoritesOnly}`;
|
||
|
||
if (this.cache.has(cacheKey)) {
|
||
return this.cache.get(cacheKey);
|
||
}
|
||
|
||
const result = await this.makeRequest(endpoint);
|
||
this.cache.set(cacheKey, result);
|
||
|
||
// 5 分鐘後清除快取
|
||
setTimeout(() => this.cache.delete(cacheKey), 5 * 60 * 1000);
|
||
|
||
return result;
|
||
}
|
||
}
|
||
```
|
||
|
||
## 9. 速率限制
|
||
|
||
### 9.1 API 速率限制 (未來實作)
|
||
|
||
| 端點類型 | 限制 | 時間窗口 |
|
||
|----------|------|----------|
|
||
| 詞卡 CRUD | 100 requests | 每分鐘 |
|
||
| AI 分析 | 10 requests | 每分鐘 |
|
||
| 搜尋 | 200 requests | 每分鐘 |
|
||
|
||
### 9.2 使用量追蹤
|
||
|
||
#### AI API 使用量
|
||
```csharp
|
||
// 記錄 AI API 使用量
|
||
public class UsageTrackingService
|
||
{
|
||
public async Task RecordApiUsage(Guid userId, string apiType, decimal cost)
|
||
{
|
||
var usage = new ApiUsage
|
||
{
|
||
UserId = userId,
|
||
ApiType = apiType,
|
||
Cost = cost,
|
||
Timestamp = DateTime.UtcNow
|
||
};
|
||
|
||
_context.ApiUsages.Add(usage);
|
||
await _context.SaveChangesAsync();
|
||
}
|
||
}
|
||
```
|
||
|
||
## 10. 開發工具
|
||
|
||
### 10.1 API 文檔
|
||
|
||
#### Swagger 配置
|
||
```csharp
|
||
services.AddSwaggerGen(c =>
|
||
{
|
||
c.SwaggerDoc("v1", new() { Title = "DramaLing API", Version = "v1" });
|
||
|
||
// JWT 認證配置
|
||
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
|
||
{
|
||
Description = "JWT Authorization header using the Bearer scheme",
|
||
Name = "Authorization",
|
||
In = ParameterLocation.Header,
|
||
Type = SecuritySchemeType.ApiKey,
|
||
Scheme = "Bearer"
|
||
});
|
||
});
|
||
|
||
// 存取位置: http://localhost:5008/swagger
|
||
```
|
||
|
||
### 10.2 API 測試
|
||
|
||
#### 使用 curl 測試
|
||
```bash
|
||
# 設定基礎 URL
|
||
export API_BASE="http://localhost:5008/api"
|
||
|
||
# 測試詞卡列表
|
||
curl "$API_BASE/flashcards"
|
||
|
||
# 測試詞卡創建
|
||
curl -X POST "$API_BASE/flashcards" \
|
||
-H "Content-Type: application/json" \
|
||
-d @test-flashcard.json
|
||
```
|
||
|
||
#### 使用 Postman Collection (未來)
|
||
```json
|
||
{
|
||
"info": {
|
||
"name": "DramaLing API",
|
||
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
||
},
|
||
"item": [
|
||
{
|
||
"name": "Flashcards",
|
||
"item": [
|
||
// 詞卡相關 API 測試
|
||
]
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
**文檔版本**: v1.0
|
||
**建立日期**: 2025-09-24
|
||
**維護負責**: API 開發團隊
|
||
**更新頻率**: API 變更時即時更新
|
||
|
||
> 📋 相關文檔:
|
||
> - [系統架構總覽](./system-architecture.md)
|
||
> - [後端架構詳細說明](./backend-architecture.md)
|
||
> - [前端架構詳細說明](./frontend-architecture.md) |