diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 49b8e00..49857ca 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -1,7 +1,15 @@ { "permissions": { "allow": [ - "Bash(git commit:*)" + "Bash(git commit:*)", + "Bash(xargs ls:*)", + "Bash(jq:*)", + "Bash(python:*)", + "Bash(python3:*)", + "Bash(source venv/bin/activate)", + "Bash(find:*)", + "Bash(ls:*)", + "Bash(openspec list:*)" ], "deny": [], "ask": [] diff --git a/.gitignore b/.gitignore index ab61117..1bb1526 100644 --- a/.gitignore +++ b/.gitignore @@ -89,3 +89,12 @@ build/ Thumbs.db ehthumbs.db Desktop.ini + +# Test and temporary files +backend/uploads/* +storage/uploads/* +storage/results/* +*.log +__pycache__/ +*.bak +test_*.py diff --git a/API_REFERENCE.md b/API_REFERENCE.md deleted file mode 100644 index e19cd04..0000000 --- a/API_REFERENCE.md +++ /dev/null @@ -1,743 +0,0 @@ -# Tool_OCR API Reference & Issues Report - -## 文件資訊 -- **建立日期**: 2025-01-13 -- **版本**: v0.1.0 -- **目的**: 完整記錄所有 API 端點及前後端不一致問題 - ---- - -## 目錄 -1. [API 端點清單](#api-端點清單) -2. [前後端不一致問題](#前後端不一致問題) -3. [修正建議](#修正建議) - ---- - -## API 端點清單 - -### 1. 認證 API (Authentication) - -#### POST `/api/v1/auth/login` -- **功能**: 使用者登入 -- **請求 Body**: - ```typescript - { - username: string, - password: string - } - ``` -- **回應**: - ```typescript - { - access_token: string, - token_type: string, // "bearer" - expires_in: number // Token 過期時間(秒) - } - ``` -- **後端實作**: ✅ [backend/app/routers/auth.py:24](backend/app/routers/auth.py#L24) -- **前端使用**: ✅ [frontend/src/services/api.ts:106](frontend/src/services/api.ts#L106) -- **狀態**: ⚠️ **有問題** - 前端型別缺少 `expires_in` 欄位 - ---- - -### 2. 檔案上傳 API (File Upload) - -#### POST `/api/v1/upload` -- **功能**: 上傳檔案進行 OCR 處理 -- **請求 Body**: `multipart/form-data` - - `files`: File[] - 檔案列表 (PNG, JPG, JPEG, PDF) - - `batch_name`: string (optional) - 批次名稱 -- **回應**: - ```typescript - { - batch_id: number, - files: [ - { - id: number, - batch_id: number, - filename: string, - original_filename: string, - file_size: number, - file_format: string, // ⚠️ 後端用 file_format - status: string, - error: string | null, - created_at: string, - processing_time: number | null - } - ] - } - ``` -- **後端實作**: ✅ [backend/app/routers/ocr.py:39](backend/app/routers/ocr.py#L39) -- **前端使用**: ✅ [frontend/src/services/api.ts:128](frontend/src/services/api.ts#L128) -- **狀態**: ⚠️ **有問題** - 前端型別用 `format`,後端用 `file_format` - ---- - -### 3. OCR 處理 API (OCR Processing) - -#### POST `/api/v1/ocr/process` -- **功能**: 觸發 OCR 批次處理 -- **請求 Body**: - ```typescript - { - batch_id: number, - lang: string, // "ch", "en", "japan", "korean" - detect_layout: boolean // ⚠️ 後端用 detect_layout,前端用 confidence_threshold - } - ``` -- **回應**: - ```typescript - { - message: string, // ⚠️ 後端有此欄位 - batch_id: number, - total_files: number, // ⚠️ 後端有此欄位 - status: string // "processing" - // task_id: string // ❌ 前端期待此欄位,但後端沒有 - } - ``` -- **後端實作**: ✅ [backend/app/routers/ocr.py:95](backend/app/routers/ocr.py#L95) -- **前端使用**: ✅ [frontend/src/services/api.ts:148](frontend/src/services/api.ts#L148) -- **狀態**: ⚠️ **有問題** - 請求/回應模型不匹配 - ---- - -#### GET `/api/v1/batch/{batch_id}/status` -- **功能**: 取得批次處理狀態 -- **路徑參數**: - - `batch_id`: number - 批次 ID -- **回應**: - ```typescript - { - batch: { - id: number, - user_id: number, - batch_name: string | null, - status: string, - total_files: number, - completed_files: number, - failed_files: number, - progress_percentage: number, - created_at: string, - started_at: string | null, - completed_at: string | null - }, - files: [ - { - id: number, - batch_id: number, - filename: string, - original_filename: string, - file_size: number, - file_format: string, - status: string, - error: string | null, - created_at: string, - processing_time: number | null - } - ] - } - ``` -- **後端實作**: ✅ [backend/app/routers/ocr.py:148](backend/app/routers/ocr.py#L148) -- **前端使用**: ✅ [frontend/src/services/api.ts:172](frontend/src/services/api.ts#L172) -- **狀態**: ✅ **正常** - ---- - -#### GET `/api/v1/ocr/result/{file_id}` -- **功能**: 取得 OCR 結果 -- **路徑參數**: - - `file_id`: number - 檔案 ID -- **回應**: - ```typescript - { - file_id: number, - filename: string, - status: string, - markdown_content: string | null, - json_data: { - total_text_regions: number, - average_confidence: number, - detected_language: string, - layout_data: object | null, - images_metadata: array | null - } | null, - confidence: number | null, - processing_time: number | null - } - ``` -- **後端實作**: ✅ [backend/app/routers/ocr.py:182](backend/app/routers/ocr.py#L182) -- **前端使用**: ✅ [frontend/src/services/api.ts:164](frontend/src/services/api.ts#L164) - - ⚠️ **注意**: 前端使用 `taskId` 作為參數名稱,實際應該是 `file_id` -- **狀態**: ⚠️ **有問題** - 前端參數名稱誤導 - ---- - -#### ❌ GET `/api/v1/ocr/status/{task_id}` -- **功能**: 取得任務狀態 (前端期待但不存在) -- **狀態**: ❌ **不存在** - 前端呼叫此端點但後端沒有實作 -- **前端使用**: [frontend/src/services/api.ts:156](frontend/src/services/api.ts#L156) -- **問題**: 前端會收到 404 錯誤 - ---- - -### 4. 匯出 API (Export) - -#### POST `/api/v1/export` -- **功能**: 匯出 OCR 結果 -- **請求 Body**: - ```typescript - { - batch_id: number, - format: "txt" | "json" | "excel" | "markdown" | "pdf" | "zip", - rule_id: number | null, - css_template: string, // "default", "academic", "business" - include_formats: string[] | null, - options: { - confidence_threshold: number | null, - include_metadata: boolean, - filename_pattern: string | null, - css_template: string | null - } | null - } - ``` -- **回應**: File download (Blob) -- **後端實作**: ✅ [backend/app/routers/export.py:38](backend/app/routers/export.py#L38) -- **前端使用**: ✅ [frontend/src/services/api.ts:182](frontend/src/services/api.ts#L182) -- **狀態**: ✅ **正常** - ---- - -#### GET `/api/v1/export/pdf/{file_id}` -- **功能**: 產生單一檔案的 PDF -- **路徑參數**: - - `file_id`: number - 檔案 ID -- **查詢參數**: - - `css_template`: string - CSS 模板名稱 -- **回應**: PDF file (Blob) -- **後端實作**: ✅ [backend/app/routers/export.py:144](backend/app/routers/export.py#L144) -- **前端使用**: ✅ [frontend/src/services/api.ts:192](frontend/src/services/api.ts#L192) -- **狀態**: ✅ **正常** - ---- - -#### GET `/api/v1/export/rules` -- **功能**: 取得匯出規則清單 -- **回應**: - ```typescript - [ - { - id: number, - user_id: number, - rule_name: string, - description: string | null, - config_json: object, - css_template: string | null, - created_at: string, - updated_at: string - } - ] - ``` -- **後端實作**: ✅ [backend/app/routers/export.py:206](backend/app/routers/export.py#L206) -- **前端使用**: ✅ [frontend/src/services/api.ts:204](frontend/src/services/api.ts#L204) -- **狀態**: ✅ **正常** - ---- - -#### POST `/api/v1/export/rules` -- **功能**: 建立匯出規則 -- **請求 Body**: - ```typescript - { - rule_name: string, - description: string | null, - config_json: object, - css_template: string | null - } - ``` -- **回應**: 同 GET `/api/v1/export/rules` 的單個物件 -- **後端實作**: ✅ [backend/app/routers/export.py:220](backend/app/routers/export.py#L220) -- **前端使用**: ✅ [frontend/src/services/api.ts:212](frontend/src/services/api.ts#L212) -- **狀態**: ✅ **正常** - ---- - -#### PUT `/api/v1/export/rules/{rule_id}` -- **功能**: 更新匯出規則 -- **路徑參數**: - - `rule_id`: number - 規則 ID -- **請求 Body**: 同 POST `/api/v1/export/rules` (所有欄位可選) -- **回應**: 同 GET `/api/v1/export/rules` 的單個物件 -- **後端實作**: ✅ [backend/app/routers/export.py:254](backend/app/routers/export.py#L254) -- **前端使用**: ✅ [frontend/src/services/api.ts:220](frontend/src/services/api.ts#L220) -- **狀態**: ✅ **正常** - ---- - -#### DELETE `/api/v1/export/rules/{rule_id}` -- **功能**: 刪除匯出規則 -- **路徑參數**: - - `rule_id`: number - 規則 ID -- **回應**: - ```typescript - { - message: "Export rule deleted successfully" - } - ``` -- **後端實作**: ✅ [backend/app/routers/export.py:295](backend/app/routers/export.py#L295) -- **前端使用**: ✅ [frontend/src/services/api.ts:228](frontend/src/services/api.ts#L228) -- **狀態**: ✅ **正常** - ---- - -#### GET `/api/v1/export/css-templates` -- **功能**: 取得 CSS 模板清單 -- **回應**: - ```typescript - [ - { - name: string, - description: string, - filename: string // ⚠️ Schema 有定義,但實際回傳沒有 - } - ] - ``` -- **後端實作**: ✅ [backend/app/routers/export.py:326](backend/app/routers/export.py#L326) - - 實際回傳: `[{ name, description }]` - - Schema 定義: `[{ name, description, filename }]` -- **前端使用**: ✅ [frontend/src/services/api.ts:235](frontend/src/services/api.ts#L235) -- **狀態**: ⚠️ **有問題** - 缺少 `filename` 欄位 - ---- - -### 5. 翻譯 API (Translation - RESERVED) - -#### GET `/api/v1/translate/status` -- **功能**: 取得翻譯功能狀態 -- **回應**: - ```typescript - { - status: "RESERVED", - message: string, - planned_phase: string, - features: string[] - } - ``` -- **後端實作**: ✅ [backend/app/routers/translation.py:28](backend/app/routers/translation.py#L28) -- **前端使用**: ❌ 未使用 -- **狀態**: ✅ **正常** (預留功能) - ---- - -#### GET `/api/v1/translate/languages` -- **功能**: 取得支援的語言清單 -- **回應**: - ```typescript - [ - { - code: string, - name: string, - native_name: string - } - ] - ``` -- **後端實作**: ✅ [backend/app/routers/translation.py:43](backend/app/routers/translation.py#L43) -- **前端使用**: ❌ 未使用 -- **狀態**: ✅ **正常** (預留功能) - ---- - -#### POST `/api/v1/translate/document` -- **功能**: 翻譯文件 (未實作) -- **請求 Body**: - ```typescript - { - file_id: number, - source_lang: string, - target_lang: string, - engine_type: "argos" | "ernie" | "google" | "deepl", - preserve_structure: boolean, - engine_config: object | null - } - ``` -- **回應**: HTTP 501 Not Implemented -- **後端實作**: ✅ [backend/app/routers/translation.py:56](backend/app/routers/translation.py#L56) (Stub) -- **前端使用**: ✅ [frontend/src/services/api.ts:247](frontend/src/services/api.ts#L247) -- **狀態**: ⚠️ **預留功能** - 前端會收到 501 錯誤 - ---- - -#### ❌ GET `/api/v1/translate/configs` -- **功能**: 取得翻譯設定 (前端期待但不存在) -- **狀態**: ❌ **不存在** - 前端呼叫此端點但後端沒有實作 -- **前端使用**: [frontend/src/services/api.ts:258](frontend/src/services/api.ts#L258) -- **問題**: 前端會收到 404 錯誤 - ---- - -#### ❌ POST `/api/v1/translate/configs` -- **功能**: 建立翻譯設定 (前端期待但不存在) -- **狀態**: ❌ **不存在** - 前端呼叫此端點但後端沒有實作 -- **前端使用**: [frontend/src/services/api.ts:269](frontend/src/services/api.ts#L269) -- **問題**: 前端會收到 404 錯誤 - ---- - -### 6. 其他端點 - -#### GET `/health` -- **功能**: 健康檢查 -- **回應**: - ```typescript - { - status: "healthy", - service: "Tool_OCR", - version: "0.1.0" - } - ``` -- **後端實作**: ✅ [backend/app/main.py:84](backend/app/main.py#L84) -- **前端使用**: ❌ 未使用 -- **狀態**: ✅ **正常** - ---- - -#### GET `/` -- **功能**: API 資訊 -- **回應**: - ```typescript - { - message: "Tool_OCR API", - version: "0.1.0", - docs_url: "/docs", - health_check: "/health" - } - ``` -- **後端實作**: ✅ [backend/app/main.py:95](backend/app/main.py#L95) -- **前端使用**: ❌ 未使用 -- **狀態**: ✅ **正常** - ---- - -## 前後端不一致問題 - -### 問題 1: 登入回應結構不一致 - -**嚴重程度**: 🟡 中等 - -**問題描述**: -- 後端回傳包含 `expires_in` 欄位 (Token 過期時間) -- 前端 `LoginResponse` 型別定義缺少此欄位 - -**影響**: -- 前端無法實作 Token 自動續期功能 -- 無法提前提醒使用者 Token 即將過期 - -**位置**: -- 後端: [backend/app/routers/auth.py:66-70](backend/app/routers/auth.py#L66-L70) -- 前端: [frontend/src/types/api.ts:12-15](frontend/src/types/api.ts#L12-L15) - ---- - -### 問題 2: OCR 任務狀態 API 不存在 - -**嚴重程度**: 🔴 高 - -**問題描述**: -- 前端嘗試呼叫 `/api/v1/ocr/status/{taskId}` 取得任務進度 -- 後端僅提供 `/api/v1/batch/{batch_id}/status` 與 `/api/v1/ocr/result/{file_id}` -- 沒有對應的任務狀態追蹤端點 - -**影響**: -- 前端 `getTaskStatus()` 呼叫會收到 404 錯誤 -- 無法實作即時進度輪詢功能 -- 使用者無法看到處理進度 - -**位置**: -- 前端呼叫: [frontend/src/services/api.ts:156-159](frontend/src/services/api.ts#L156-L159) -- 後端路由: 不存在 - ---- - -### 問題 3: OCR 處理請求/回應模型不符 - -**嚴重程度**: 🔴 高 - -**問題描述**: -1. **請求欄位不匹配**: - - 前端傳送 `confidence_threshold` (信心度閾值) - - 後端接受 `detect_layout` (版面偵測開關) - -2. **回應欄位不匹配**: - - 前端期待 `task_id` (用於追蹤任務) - - 後端回傳 `message`, `total_files` (但沒有 `task_id`) - -**影響**: -- 前端無法正確傳遞參數給後端 -- 前端無法取得 `task_id` 進行後續狀態查詢 -- 型別檢查會失敗 -- 可能導致驗證錯誤 - -**位置**: -- 前端請求: [frontend/src/types/api.ts:37-41](frontend/src/types/api.ts#L37-L41) -- 前端回應: [frontend/src/types/api.ts:43-47](frontend/src/types/api.ts#L43-L47) -- 後端請求: [backend/app/schemas/ocr.py:120-133](backend/app/schemas/ocr.py#L120-L133) -- 後端回應: [backend/app/schemas/ocr.py:136-151](backend/app/schemas/ocr.py#L136-L151) - ---- - -### 問題 4: 上傳檔案欄位命名不一致 - -**嚴重程度**: 🟡 中等 - -**問題描述**: -- 後端使用 `file_format` 回傳檔案格式 -- 前端型別定義使用 `format` - -**影響**: -- 前端無法直接使用後端回傳的 `file_format` 欄位 -- 需要額外的欄位映射或轉換 -- UI 顯示檔案格式時可能為 undefined - -**位置**: -- 前端: [frontend/src/types/api.ts:32](frontend/src/types/api.ts#L32) -- 後端: [backend/app/schemas/ocr.py:19](backend/app/schemas/ocr.py#L19) - ---- - -### 問題 5: CSS 模板清單缺少 filename - -**嚴重程度**: 🟡 中等 - -**問題描述**: -- 前端 `CSSTemplate` 型別期待包含 `filename` 欄位 -- 後端 Schema `CSSTemplateResponse` 也定義了 `filename` -- 但後端實際回傳只有 `name` 和 `description` - -**影響**: -- 前端無法使用 `filename` 作為 `