27 KiB
27 KiB
DramaLing 後端開發計劃
1. 總體架構概述
1.1 技術棧確認 (已更新為 .NET Core)
- API 框架: ASP.NET Core Web API 8.0 ⚡ (已從 Next.js 14 API Routes 重寫)
- 資料庫: PostgreSQL via Supabase (Entity Framework Core)
- 認證系統: JWT + ASP.NET Core Identity (兼容 Supabase)
- AI 服務: Google Gemini API (.NET SDK)
- 檔案存儲: Supabase Storage
- 部署平台: Azure App Service / Railway (從 Vercel 遷移)
1.2 前端依賴對應
基於已實作的前端頁面,後端需要支援以下功能:
/app/dashboard/page.tsx→ 儀表板統計 API/app/flashcards/page.tsx→ 詞卡管理 API + 智能檢測 API/app/learn/page.tsx→ 學習系統 API + 錯誤回報 API/app/generate/page.tsx→ AI 生成詞卡 API
2. 資料庫架構設計
2.1 完整 Schema 設計
-- =========================================
-- 用戶相關表
-- =========================================
-- 用戶基本信息表
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE NOT NULL,
display_name VARCHAR(100),
avatar_url TEXT,
subscription_type VARCHAR(20) DEFAULT 'free', -- 'free', 'premium'
subscription_expires_at TIMESTAMP,
preferences JSONB DEFAULT '{}', -- 用戶偏好設定
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- 用戶學習設定表
CREATE TABLE user_settings (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
daily_goal INTEGER DEFAULT 20, -- 每日目標詞數
reminder_time TIME DEFAULT '09:00:00', -- 提醒時間
reminder_enabled BOOLEAN DEFAULT true,
difficulty_preference VARCHAR(20) DEFAULT 'balanced', -- 'conservative', 'balanced', 'aggressive'
auto_play_audio BOOLEAN DEFAULT true,
show_pronunciation BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- =========================================
-- 詞卡相關表
-- =========================================
-- 卡組表
CREATE TABLE card_sets (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
description TEXT,
color VARCHAR(50) DEFAULT 'bg-blue-500',
is_public BOOLEAN DEFAULT false,
card_count INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- 詞卡主表
CREATE TABLE flashcards (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
card_set_id UUID REFERENCES card_sets(id) ON DELETE CASCADE,
-- 基本詞卡信息
word VARCHAR(255) NOT NULL,
part_of_speech VARCHAR(50), -- 詞性
pronunciation_us VARCHAR(255), -- 美式發音
pronunciation_uk VARCHAR(255), -- 英式發音
translation TEXT NOT NULL, -- 中文翻譯
definition TEXT NOT NULL, -- 英文定義
difficulty_level VARCHAR(10), -- CEFR等級: A1, A2, B1, B2, C1, C2
-- 例句信息
original_example TEXT, -- 原始例句
original_example_translation TEXT, -- 原始例句翻譯
generated_example TEXT, -- AI生成例句
generated_example_translation TEXT, -- AI生成例句翻譯
example_image_url TEXT, -- 例句圖片URL
-- 學習相關
synonyms TEXT[], -- 同義詞陣列
antonyms TEXT[], -- 反義詞陣列
-- SM-2算法參數
easiness_factor FLOAT DEFAULT 2.5, -- 難度係數
repetitions INTEGER DEFAULT 0, -- 重複次數
interval_days INTEGER DEFAULT 1, -- 間隔天數
next_review_date DATE DEFAULT CURRENT_DATE,
-- 統計信息
times_reviewed INTEGER DEFAULT 0,
times_correct INTEGER DEFAULT 0,
last_reviewed_at TIMESTAMP,
-- 狀態
is_favorite BOOLEAN DEFAULT false,
is_archived BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- 標籤表
CREATE TABLE tags (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
name VARCHAR(100) NOT NULL,
color VARCHAR(50) DEFAULT '#3B82F6',
usage_count INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW(),
UNIQUE(user_id, name)
);
-- 詞卡標籤關聯表
CREATE TABLE flashcard_tags (
flashcard_id UUID REFERENCES flashcards(id) ON DELETE CASCADE,
tag_id UUID REFERENCES tags(id) ON DELETE CASCADE,
PRIMARY KEY (flashcard_id, tag_id)
);
-- =========================================
-- 學習系統表
-- =========================================
-- 學習會話表
CREATE TABLE study_sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
session_type VARCHAR(50), -- 'flip', 'quiz', 'fill', 'listening', 'speaking'
started_at TIMESTAMP DEFAULT NOW(),
ended_at TIMESTAMP,
total_cards INTEGER DEFAULT 0,
correct_count INTEGER DEFAULT 0,
duration_seconds INTEGER DEFAULT 0
);
-- 學習記錄表
CREATE TABLE study_records (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
flashcard_id UUID REFERENCES flashcards(id) ON DELETE CASCADE,
session_id UUID REFERENCES study_sessions(id) ON DELETE CASCADE,
study_mode VARCHAR(50) NOT NULL, -- 'flip', 'quiz', 'fill', 'listening', 'speaking'
rating INTEGER NOT NULL, -- 1-5評分
response_time_ms INTEGER, -- 回應時間(毫秒)
user_answer TEXT, -- 用戶答案
is_correct BOOLEAN,
-- SM-2算法更新後的值
new_easiness_factor FLOAT,
new_interval_days INTEGER,
new_repetitions INTEGER,
studied_at TIMESTAMP DEFAULT NOW()
);
-- =========================================
-- AI生成相關表
-- =========================================
-- AI生成任務表
CREATE TABLE ai_generation_tasks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
-- 輸入參數
input_text TEXT NOT NULL,
extraction_type VARCHAR(50) NOT NULL, -- 'vocabulary', 'smart'
card_count INTEGER DEFAULT 10,
-- 任務狀態
status VARCHAR(50) DEFAULT 'pending', -- 'pending', 'processing', 'completed', 'failed'
progress_percentage INTEGER DEFAULT 0,
-- 結果
generated_cards JSONB, -- 生成的詞卡JSON數據
error_message TEXT,
-- API使用統計
api_calls_used INTEGER DEFAULT 0,
cost_estimated DECIMAL(10,4) DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW(),
completed_at TIMESTAMP
);
-- =========================================
-- 錯誤回報系統表
-- =========================================
-- 錯誤回報表
CREATE TABLE error_reports (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
flashcard_id UUID REFERENCES flashcards(id) ON DELETE CASCADE,
-- 回報信息
report_type VARCHAR(100) NOT NULL, -- '發音錯誤', '翻譯不準確', '例句錯誤' 等
description TEXT,
study_mode VARCHAR(50), -- 回報來源的學習模式
-- 狀態追蹤
status VARCHAR(50) DEFAULT 'pending', -- 'pending', 'resolved', 'dismissed'
admin_notes TEXT,
resolved_at TIMESTAMP,
resolved_by UUID REFERENCES users(id),
created_at TIMESTAMP DEFAULT NOW()
);
-- =========================================
-- 統計相關表
-- =========================================
-- 每日學習統計表
CREATE TABLE daily_stats (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
date DATE NOT NULL,
-- 學習統計
words_studied INTEGER DEFAULT 0,
words_correct INTEGER DEFAULT 0,
study_time_seconds INTEGER DEFAULT 0,
session_count INTEGER DEFAULT 0,
-- 生成統計
cards_generated INTEGER DEFAULT 0,
ai_api_calls INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW(),
UNIQUE(user_id, date)
);
-- =========================================
-- 系統配置表
-- =========================================
-- 系統設定表
CREATE TABLE system_settings (
key VARCHAR(255) PRIMARY KEY,
value TEXT NOT NULL,
description TEXT,
updated_at TIMESTAMP DEFAULT NOW()
);
-- 插入預設系統設定
INSERT INTO system_settings (key, value, description) VALUES
('max_daily_ai_generations_free', '5', '免費用戶每日AI生成次數限制'),
('max_daily_ai_generations_premium', '50', '付費用戶每日AI生成次數限制'),
('max_cards_per_generation', '20', '單次生成最大詞卡數量'),
('sm2_initial_interval', '1', 'SM-2算法初始間隔天數'),
('sm2_max_interval', '365', 'SM-2算法最大間隔天數');
2.2 索引優化
-- 性能關鍵索引
CREATE INDEX idx_flashcards_user_next_review ON flashcards(user_id, next_review_date);
CREATE INDEX idx_flashcards_user_set ON flashcards(user_id, card_set_id);
CREATE INDEX idx_flashcards_word_search ON flashcards USING gin(to_tsvector('english', word || ' ' || translation));
CREATE INDEX idx_study_records_user_date ON study_records(user_id, studied_at);
CREATE INDEX idx_error_reports_status ON error_reports(status, created_at);
CREATE INDEX idx_daily_stats_user_date ON daily_stats(user_id, date);
2.3 Row Level Security (RLS) 設定
-- 啟用RLS
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE card_sets ENABLE ROW LEVEL SECURITY;
ALTER TABLE flashcards ENABLE ROW LEVEL SECURITY;
ALTER TABLE tags ENABLE ROW LEVEL SECURITY;
ALTER TABLE study_sessions ENABLE ROW LEVEL SECURITY;
ALTER TABLE study_records ENABLE ROW LEVEL SECURITY;
ALTER TABLE error_reports ENABLE ROW LEVEL SECURITY;
ALTER TABLE daily_stats ENABLE ROW LEVEL SECURITY;
-- 用戶只能存取自己的數據
CREATE POLICY "Users can only access their own data" ON users
FOR ALL USING (auth.uid() = id);
CREATE POLICY "Users can only access their own card sets" ON card_sets
FOR ALL USING (auth.uid() = user_id);
CREATE POLICY "Users can only access their own flashcards" ON flashcards
FOR ALL USING (auth.uid() = user_id);
CREATE POLICY "Users can only access their own tags" ON tags
FOR ALL USING (auth.uid() = user_id);
CREATE POLICY "Users can only access their own study data" ON study_sessions
FOR ALL USING (auth.uid() = user_id);
CREATE POLICY "Users can only access their own study records" ON study_records
FOR ALL USING (auth.uid() = user_id);
CREATE POLICY "Users can only access their own error reports" ON error_reports
FOR ALL USING (auth.uid() = user_id);
CREATE POLICY "Users can only access their own stats" ON daily_stats
FOR ALL USING (auth.uid() = user_id);
3. API 設計規格
3.1 認證系統 API
3.1.1 基於 Supabase Auth
// /app/api/auth/* 使用 Supabase Auth SDK
// 無需自建API,前端直接使用 Supabase 客戶端
// 需要的API: 用戶資料更新
PUT /api/users/profile
{
display_name?: string;
preferences?: Record<string, any>;
}
3.2 詞卡管理 API
3.2.1 卡組管理
// 獲取用戶所有卡組 (支援 /app/dashboard/page.tsx)
GET /api/card-sets
Response: {
sets: Array<{
id: string;
name: string;
description: string;
color: string;
card_count: number;
progress: number; // 計算得出
last_studied: string;
tags: string[];
}>
}
// 創建卡組
POST /api/card-sets
Body: {
name: string;
description?: string;
color?: string;
}
// 更新卡組
PUT /api/card-sets/:id
Body: {
name?: string;
description?: string;
color?: string;
}
// 刪除卡組
DELETE /api/card-sets/:id
3.2.2 詞卡 CRUD (支援 /app/flashcards/page.tsx)
// 獲取詞卡列表
GET /api/flashcards
Query: {
set_id?: string;
search?: string;
tags?: string[];
difficulty?: string;
favorites_only?: boolean;
limit?: number;
offset?: number;
}
Response: {
flashcards: Array<FlashcardType>;
total: number;
has_more: boolean;
}
// 創建詞卡
POST /api/flashcards
Body: {
card_set_id: string;
word: string;
translation: string;
definition: string;
// ... 其他欄位
}
// 更新詞卡
PUT /api/flashcards/:id
Body: Partial<FlashcardType>
// 刪除詞卡
DELETE /api/flashcards/:id
// 批量操作
POST /api/flashcards/batch
Body: {
action: 'delete' | 'move' | 'tag' | 'reset_progress';
flashcard_ids: string[];
target_set_id?: string; // for move
tag_ids?: string[]; // for tag
}
3.2.3 標籤管理
// 獲取標籤
GET /api/tags
Response: {
tags: Array<{
id: string;
name: string;
color: string;
usage_count: number;
}>
}
// 創建標籤
POST /api/tags
Body: {
name: string;
color?: string;
}
// 詞卡標籤關聯
POST /api/flashcards/:id/tags
Body: {
tag_ids: string[];
}
3.3 AI 生成 API (支援 /app/generate/page.tsx)
3.3.1 生成任務管理
// 創建生成任務
POST /api/ai/generate
Body: {
input_text: string;
extraction_type: 'vocabulary' | 'smart';
card_count: number; // 5-20
}
Response: {
task_id: string;
status: 'pending';
}
// 查詢生成進度
GET /api/ai/generate/:task_id
Response: {
task_id: string;
status: 'pending' | 'processing' | 'completed' | 'failed';
progress_percentage: number;
generated_cards?: Array<GeneratedCardType>;
error_message?: string;
}
// 保存生成的詞卡
POST /api/ai/generate/:task_id/save
Body: {
card_set_id: string;
selected_cards: string[]; // 生成卡片的ID
}
3.3.2 智能檢測 API (支援詞卡錯誤檢測)
// 檢測單一詞卡
POST /api/ai/validate-card
Body: {
flashcard_id: string;
error_report_id?: string; // 如果來自錯誤回報
}
Response: {
issues: Array<{
field: string;
original: string;
corrected: string;
reason: string;
}>;
suggestions: string[];
}
// 批量檢測
POST /api/ai/validate-cards
Body: {
flashcard_ids: string[];
}
Response: {
results: Array<{
flashcard_id: string;
issues: Array<ValidationIssue>;
}>;
}
// 應用修正
POST /api/ai/apply-corrections
Body: {
flashcard_id: string;
corrections: Array<{
field: string;
new_value: string;
}>;
}
3.4 學習系統 API (支援 /app/learn/page.tsx)
3.4.1 學習會話管理
// 獲取待複習詞卡
GET /api/study/due-cards
Query: {
limit?: number; // 預設50
mode?: 'flip' | 'quiz' | 'fill' | 'listening' | 'speaking';
}
Response: {
cards: Array<FlashcardType>;
total_due: number;
}
// 開始學習會話
POST /api/study/sessions
Body: {
mode: string;
card_ids: string[];
}
Response: {
session_id: string;
cards: Array<FlashcardType>;
}
// 記錄學習結果
POST /api/study/sessions/:session_id/record
Body: {
flashcard_id: string;
rating: number; // 1-5
response_time_ms: number;
user_answer?: string;
is_correct: boolean;
}
Response: {
next_review_date: string;
new_interval_days: number;
}
// 結束學習會話
POST /api/study/sessions/:session_id/complete
Body: {
duration_seconds: number;
}
3.4.2 錯誤回報 API
// 提交錯誤回報
POST /api/error-reports
Body: {
flashcard_id: string;
report_type: string;
description?: string;
study_mode: string;
}
// 獲取錯誤回報列表
GET /api/error-reports
Query: {
status?: 'pending' | 'resolved' | 'dismissed';
limit?: number;
offset?: number;
}
Response: {
reports: Array<{
id: string;
flashcard: FlashcardType;
report_type: string;
description: string;
status: string;
created_at: string;
}>;
total: number;
}
// 處理錯誤回報
PUT /api/error-reports/:id
Body: {
status: 'resolved' | 'dismissed';
admin_notes?: string;
}
3.5 統計分析 API (支援 /app/dashboard/page.tsx)
3.5.1 儀表板統計
// 獲取儀表板概覽
GET /api/stats/dashboard
Response: {
total_words: number;
words_today: number;
streak_days: number;
accuracy_percentage: number;
today_review_count: number;
completed_today: number;
recent_words: Array<{
word: string;
translation: string;
status: 'learned' | 'learning' | 'new';
}>;
}
// 獲取學習趨勢
GET /api/stats/trends
Query: {
period: 'week' | 'month' | 'year';
}
Response: {
daily_counts: Array<{
date: string;
words_studied: number;
words_correct: number;
study_time_seconds: number;
}>;
weekly_stats: {
current_week: number;
previous_week: number;
growth_percentage: number;
};
}
// 獲取詳細統計
GET /api/stats/detailed
Response: {
by_difficulty: Record<string, number>;
by_category: Record<string, number>;
learning_curve: Array<{
date: string;
accuracy: number;
}>;
top_mistakes: Array<{
word: string;
error_count: number;
}>;
}
3.6 用戶設定 API
// 獲取用戶設定
GET /api/users/settings
Response: UserSettingsType
// 更新用戶設定
PUT /api/users/settings
Body: Partial<UserSettingsType>
// 獲取使用配額
GET /api/users/usage
Response: {
current_month: {
ai_generations: number;
ai_generations_limit: number;
cards_generated: number;
};
subscription: {
type: 'free' | 'premium';
expires_at?: string;
features: string[];
};
}
4. AI 服務整合
4.1 Google Gemini API 整合
4.1.1 詞卡生成服務
// /lib/ai/gemini-generator.ts
export class GeminiCardGenerator {
async generateCards(params: {
inputText: string;
extractionType: 'vocabulary' | 'smart';
cardCount: number;
userLevel?: string;
}): Promise<GeneratedCard[]> {
// 實作 Gemini API 調用
// 使用不同的 prompt 模板
// 處理 API 回應和錯誤
}
async validateCard(card: FlashcardType): Promise<ValidationResult> {
// 智能檢測詞卡內容
// 返回修正建議
}
}
4.1.2 Prompt 模板設計
// /lib/ai/prompts.ts
export const CARD_GENERATION_PROMPTS = {
vocabulary: `
從以下英文文本中萃取重要詞彙,為每個詞彙生成詞卡:
輸入文本:{input_text}
目標數量:{card_count}
請按照以下JSON格式回應:
{
"cards": [
{
"word": "string",
"part_of_speech": "string",
"pronunciation_us": "string",
"pronunciation_uk": "string",
"translation": "string",
"definition": "string (A1-A2 level)",
"synonyms": ["string"],
"antonyms": ["string"],
"difficulty_level": "A1|A2|B1|B2|C1|C2",
"generated_example": "string",
"generated_example_translation": "string"
}
]
}
`,
smart: `
分析以下英文文本,識別片語、俚語和常用表達:
輸入文本:{input_text}
目標數量:{card_count}
重點關注:
1. 片語和俚語
2. 文化相關表達
3. 語境特定用法
請按照相同JSON格式回應...
`,
validation: `
檢查以下詞卡內容的準確性:
詞卡信息:{card_data}
錯誤回報:{error_report}
請指出任何錯誤並提供修正建議:
{
"issues": [
{
"field": "string",
"original": "string",
"corrected": "string",
"reason": "string"
}
],
"suggestions": ["string"]
}
`
};
4.2 API 配額管理
// /lib/ai/quota-manager.ts
export class APIQuotaManager {
async checkQuota(userId: string): Promise<{
canGenerate: boolean;
remaining: number;
resetTime: Date;
}> {
// 檢查用戶配額
}
async consumeQuota(userId: string, cost: number): Promise<void> {
// 消耗配額
}
}
5. SM-2 間隔重複算法實現
5.1 算法實現
// /lib/learning/sm2-algorithm.ts
export interface SM2Result {
easiness_factor: number;
repetitions: number;
interval_days: number;
next_review_date: Date;
}
export class SM2Algorithm {
calculate(params: {
quality: number; // 1-5 評分
easiness_factor: number;
repetitions: number;
interval_days: number;
}): SM2Result {
let { quality, easiness_factor, repetitions, interval_days } = params;
// SM-2 算法實現
if (quality >= 3) {
if (repetitions === 0) {
interval_days = 1;
} else if (repetitions === 1) {
interval_days = 6;
} else {
interval_days = Math.round(interval_days * easiness_factor);
}
repetitions += 1;
} else {
repetitions = 0;
interval_days = 1;
}
// 更新難度係數
easiness_factor = Math.max(1.3,
easiness_factor + (0.1 - (5 - quality) * (0.08 + (5 - quality) * 0.02))
);
// 計算下次複習日期
const next_review_date = new Date();
next_review_date.setDate(next_review_date.getDate() + interval_days);
return {
easiness_factor,
repetitions,
interval_days,
next_review_date
};
}
}
5.2 複習排程服務
// /lib/learning/review-scheduler.ts
export class ReviewScheduler {
async getDueCards(userId: string, limit: number = 50): Promise<FlashcardType[]> {
// 獲取到期詞卡
// 按優先級排序
}
async scheduleReview(flashcardId: string, result: SM2Result): Promise<void> {
// 更新詞卡複習排程
}
}
6. 錯誤處理與日誌
6.1 統一錯誤處理
// /lib/api/error-handler.ts
export interface APIError {
code: string;
message: string;
details?: any;
timestamp: Date;
}
export const errorCodes = {
// 認證錯誤
UNAUTHORIZED: 'AUTH_001',
INVALID_TOKEN: 'AUTH_002',
// 資源錯誤
NOT_FOUND: 'RESOURCE_001',
ALREADY_EXISTS: 'RESOURCE_002',
// AI服務錯誤
AI_QUOTA_EXCEEDED: 'AI_001',
AI_SERVICE_ERROR: 'AI_002',
// 驗證錯誤
VALIDATION_ERROR: 'VALIDATION_001',
// 系統錯誤
INTERNAL_ERROR: 'SYSTEM_001',
DATABASE_ERROR: 'SYSTEM_002'
};
export function handleAPIError(error: unknown): Response {
// 統一錯誤處理邏輯
}
6.2 結構化日誌
// /lib/logging/logger.ts
export class Logger {
static info(message: string, metadata?: Record<string, any>) {
console.log(JSON.stringify({
level: 'info',
message,
metadata,
timestamp: new Date().toISOString()
}));
}
static error(message: string, error?: Error, metadata?: Record<string, any>) {
console.error(JSON.stringify({
level: 'error',
message,
error: error?.stack,
metadata,
timestamp: new Date().toISOString()
}));
}
}
7. 快取策略
7.1 前端快取 (TanStack Query)
// 前端查詢配置
export const queryKeys = {
flashcards: (userId: string, filters?: any) => ['flashcards', userId, filters],
cardSets: (userId: string) => ['card-sets', userId],
dueCards: (userId: string) => ['due-cards', userId],
stats: (userId: string, period?: string) => ['stats', userId, period]
};
// 快取時間配置
export const cacheConfig = {
flashcards: 5 * 60 * 1000, // 5分鐘
cardSets: 10 * 60 * 1000, // 10分鐘
dueCards: 1 * 60 * 1000, // 1分鐘
stats: 15 * 60 * 1000 // 15分鐘
};
7.2 API層快取
// /lib/cache/redis-cache.ts (未來考慮)
export class CacheManager {
async get<T>(key: string): Promise<T | null> {
// Redis 快取獲取
}
async set<T>(key: string, value: T, ttl: number): Promise<void> {
// Redis 快取設置
}
async invalidate(pattern: string): Promise<void> {
// 快取失效
}
}
8. 安全措施
8.1 Rate Limiting
// /lib/security/rate-limiter.ts
export class RateLimiter {
// API 限流配置
static limits = {
'api/ai/generate': { requests: 10, window: 60 * 60 }, // 每小時10次
'api/flashcards': { requests: 100, window: 60 }, // 每分鐘100次
'api/study/record': { requests: 200, window: 60 } // 每分鐘200次
};
}
8.2 輸入驗證
// /lib/validation/schemas.ts
import { z } from 'zod';
export const flashcardSchema = z.object({
word: z.string().min(1).max(255),
translation: z.string().min(1),
definition: z.string().min(1),
card_set_id: z.string().uuid(),
difficulty_level: z.enum(['A1', 'A2', 'B1', 'B2', 'C1', 'C2']).optional()
});
export const aiGenerationSchema = z.object({
input_text: z.string().min(10).max(5000),
extraction_type: z.enum(['vocabulary', 'smart']),
card_count: z.number().min(5).max(20)
});
9. 測試策略
9.1 API 測試
// __tests__/api/flashcards.test.ts
describe('/api/flashcards', () => {
it('should create flashcard with valid data', async () => {
// 測試詞卡創建
});
it('should return 401 for unauthenticated requests', async () => {
// 測試認證
});
it('should validate input data', async () => {
// 測試輸入驗證
});
});
9.2 AI 服務測試
// __tests__/lib/ai/gemini-generator.test.ts
describe('GeminiCardGenerator', () => {
it('should generate valid flashcards from text', async () => {
// 測試AI生成
});
it('should handle API errors gracefully', async () => {
// 測試錯誤處理
});
});
10. 部署配置
10.1 環境變數配置
# Supabase
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key
# AI 服務
GEMINI_API_KEY=your_gemini_api_key
# 應用設定
NEXT_PUBLIC_APP_URL=https://your-domain.com
NODE_ENV=production
# 可選:Redis (Upstash)
REDIS_URL=your_redis_url
REDIS_TOKEN=your_redis_token
10.2 Vercel 部署設定
// vercel.json
{
"functions": {
"app/api/**": {
"maxDuration": 30
}
},
"env": {
"NODE_ENV": "production"
}
}
11. 開發階段規劃 (.NET Core 重寫版)
⚡ 重寫完成狀態
原 Next.js API Routes: 已完全移除 ✅ 新 .NET Core API: 開發中 🚀
Phase 1: .NET Core 基礎建設 (第1週)
- 清理 Next.js API 代碼
- 安裝 .NET 8 SDK
- 建立 ASP.NET Core Web API 專案
- Entity Framework Core 配置
- 基礎 CRUD API (卡組、詞卡)
Phase 2: 核心業務邏輯 (第2週)
- SM-2 算法 C# 實現
- 學習系統 API (會話管理、記錄)
- JWT 認證系統
- 統一錯誤處理和驗證
Phase 3: AI 和進階功能 (第3週)
- Google Gemini AI 服務整合
- 智能檢測和批量操作 API
- 統計分析系統
- 錯誤回報系統
Phase 4: 前端整合和優化 (第4週)
- 前端 API 調用更新
- 認證流程調整
- 性能優化和快取
- 部署配置 (Azure/Railway)
架構優勢:
- 🚀 性能提升 30-50%
- 🛡️ 強型別安全
- 🏢 企業級架構
- 🔧 更好的開發體驗
12. API 回應格式標準
12.1 成功回應格式
interface SuccessResponse<T> {
success: true;
data: T;
message?: string;
meta?: {
total?: number;
page?: number;
limit?: number;
};
}
12.2 錯誤回應格式
interface ErrorResponse {
success: false;
error: {
code: string;
message: string;
details?: any;
};
timestamp: string;
}
12.3 分頁回應格式
interface PaginatedResponse<T> {
success: true;
data: T[];
pagination: {
total: number;
page: number;
limit: number;
total_pages: number;
has_next: boolean;
has_prev: boolean;
};
}
13. 監控與維護
13.1 關鍵指標監控
- API 回應時間 (< 500ms 目標)
- 錯誤率 (< 1% 目標)
- AI API 配額使用率
- 資料庫連接池狀態
- 用戶活躍度
13.2 警報設定
- API 錯誤率超過 5%
- 回應時間超過 2 秒
- AI API 配額使用超過 80%
- 資料庫連接數超過閾值
13.3 備份策略
- 每日自動資料庫備份
- 用戶數據導出功能
- 災難恢復計劃
這個後端開發計劃完全基於已實作的前端功能,確保 API 能夠支援所有前端頁面的需求,包括儀表板統計、詞卡管理、學習系統、AI 生成和錯誤回報等核心功能。