dramaling-vocab-learning/docs/03_development/api/backend-development-plan.md

27 KiB
Raw Blame History

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 生成和錯誤回報等核心功能。