Files
OCR/API_REFERENCE.md
beabigegg 9cf36d8e21 fix: resolve 7 frontend-backend API inconsistencies and add comprehensive documentation
- Fixed LoginResponse: added expires_in field
- Renamed format to file_format across FileInfo interface
- Updated ProcessRequest: replaced confidence_threshold with detect_layout
- Modified ProcessResponse: added message and total_files, removed task_id
- Removed non-existent getTaskStatus API call
- Fixed getOCRResult parameter from taskId to fileId
- Commented out translation config APIs pending backend implementation

Documentation:
- Added API_REFERENCE.md: Complete API endpoint inventory
- Added API_FIX_SUMMARY.md: Detailed before/after comparison of all fixes
- Added FRONTEND_API.md: Frontend integration documentation
- Added FRONTEND_QUICK_START.md: Quick start guide
- Added FRONTEND_UPGRADE_SUMMARY.md: Upgrade summary

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 08:54:37 +08:00

744 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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` 作為 `<option>` 的 key/value
- 渲染時 `filename` 為 undefined
- 前端需要額外邏輯處理或使用 `name` 代替
**位置**:
- 前端型別: [frontend/src/types/api.ts:132-136](frontend/src/types/api.ts#L132-L136)
- 後端 Schema: [backend/app/schemas/export.py:91-104](backend/app/schemas/export.py#L91-L104)
- 後端實作: [backend/app/routers/export.py:333-338](backend/app/routers/export.py#L333-L338)
- PDF 服務: [backend/app/services/pdf_generator.py:485-496](backend/app/services/pdf_generator.py#L485-L496)
**根本原因**:
`PDFGenerator.get_available_templates()` 只回傳 `{name: description}` 的 dict沒有包含 filename
---
### 問題 6: 翻譯設定端點未實作
**嚴重程度**: 🟢 低 (預留功能)
**問題描述**:
- 前端嘗試呼叫 `/api/v1/translate/configs` (GET/POST)
- 後端翻譯路由僅實作 `/status`, `/languages`, `/document`
- 沒有 configs 相關端點
**影響**:
- 前端呼叫會收到 404 錯誤
- 無法管理翻譯設定
- 但因為翻譯功能整體都是 Phase 5 預留功能,影響較小
**位置**:
- 前端 GET: [frontend/src/services/api.ts:258-262](frontend/src/services/api.ts#L258-L262)
- 前端 POST: [frontend/src/services/api.ts:269-275](frontend/src/services/api.ts#L269-L275)
- 後端路由: 不存在
---
## 修正建議
### 建議 1: 統一登入回應模型
**優先順序**: P2 (中優先)
**方案 A - 前端新增 expires_in** (推薦):
```typescript
// frontend/src/types/api.ts
export interface LoginResponse {
access_token: string
token_type: string
expires_in: number // 新增此欄位
}
```
**方案 B - 後端移除 expires_in**:
- 如果不需要 Token 過期管理,可移除此欄位
- 不推薦,因為這是常見的 JWT 最佳實踐
---
### 建議 2: 統一 OCR 任務追蹤策略
**優先順序**: P1 (高優先)
**方案 A - 統一使用批次狀態** (推薦):
1. 前端刪除 `getTaskStatus()` 方法
2. 統一使用 `getBatchStatus()` 輪詢批次狀態
3. 修改 `ProcessResponse` 移除 `task_id`
**方案 B - 後端新增任務狀態端點**:
1. 新增 `GET /api/v1/ocr/status/{task_id}` 端點
2. `ProcessResponse` 真正回傳 `task_id`
3. 實作任務級別的狀態追蹤
**建議**: 採用方案 A因為目前架構已經有批次級別的狀態管理
---
### 建議 3: 校正 OCR 處理請求/回應
**優先順序**: P1 (高優先)
**方案 A - 前端配合後端** (推薦):
```typescript
// frontend/src/types/api.ts
export interface ProcessRequest {
batch_id: number
lang?: string
detect_layout?: boolean // 改為 detect_layout
}
export interface ProcessResponse {
message: string // 新增
batch_id: number
total_files: number // 新增
status: string
// 移除 task_id
}
```
**方案 B - 後端配合前端**:
- 支援 `confidence_threshold` 參數
- 回應包含 `task_id`
- 需要較大改動,不推薦
---
### 建議 4: 對齊上傳檔案欄位命名
**優先順序**: P2 (中優先)
**方案 A - 前端改用 file_format** (推薦):
```typescript
// frontend/src/types/api.ts
export interface FileInfo {
id: number
filename: string
file_size: number
file_format: string // 改名為 file_format
status: 'pending' | 'processing' | 'completed' | 'failed'
}
```
**方案 B - 後端使用 Pydantic Alias**:
```python
# backend/app/schemas/ocr.py
file_format: str = Field(..., alias='format')
```
---
### 建議 5: 補充 CSS 模板 filename
**優先順序**: P2 (中優先)
**方案 A - 修改 PDF Generator 回傳結構** (推薦):
```python
# backend/app/services/pdf_generator.py
def get_available_templates(self) -> Dict[str, Dict[str, str]]:
"""Get list of available CSS templates with filename"""
return {
"default": {
"description": "通用排版模板,適合大多數文檔",
"filename": "default.css"
},
"academic": {
"description": "學術論文模板,適合研究報告",
"filename": "academic.css"
},
"business": {
"description": "商業報告模板,適合企業文檔",
"filename": "business.css"
},
}
```
**方案 B - 前端使用 name 作為 filename**:
- 因為實際上模板名稱就是識別碼
- 不需要額外的 filename
---
### 建議 6: 處理翻譯設定 Stub
**優先順序**: P3 (低優先)
**方案 A - 前端移除相關呼叫** (推薦):
1. 移除或註解 `getTranslationConfigs()` 和 `createTranslationConfig()`
2. UI 顯示「即將推出」訊息
**方案 B - 後端補上 Stub 端點**:
```python
# backend/app/routers/translation.py
@router.get("/configs")
async def get_translation_configs():
raise HTTPException(status_code=501, detail="Feature reserved for Phase 5")
@router.post("/configs")
async def create_translation_config():
raise HTTPException(status_code=501, detail="Feature reserved for Phase 5")
```
---
## 實作優先順序總結
### P1 - 立即修正 (影響核心功能)
1.**建議 2**: 統一 OCR 任務追蹤策略
2.**建議 3**: 校正 OCR 處理請求/回應模型
### P2 - 近期修正 (影響使用體驗)
3.**建議 1**: 統一登入回應模型
4.**建議 4**: 對齊上傳檔案欄位命名
5.**建議 5**: 補充 CSS 模板 filename
### P3 - 可延後 (預留功能)
6. ⏸️ **建議 6**: 處理翻譯設定 Stub (Phase 5 再處理)
---
## 文件維護
**更新記錄**:
- 2025-01-13: 初始版本,完整盤點所有 API 端點及問題
**維護責任**:
- 每次 API 變更時必須更新此文件
- 新增 API 端點時補充到對應章節
- 修正問題後更新狀態
---
## 附錄: 快速檢查清單
### 新增 API 端點時的檢查項目
- [ ] 後端 Schema 定義是否完整?
- [ ] 前端 TypeScript 型別是否匹配?
- [ ] 欄位命名是否一致 (camelCase vs snake_case)?
- [ ] 回應結構是否符合前端期待?
- [ ] 錯誤處理是否完整?
- [ ] API 文件是否更新?
- [ ] 是否有對應的測試?
### API 修改時的檢查項目
- [ ] 前後端是否同步修改?
- [ ] 是否有破壞性變更 (Breaking Change)?
- [ ] 相關文件是否更新?
- [ ] 現有功能是否受影響?
- [ ] 是否需要版本遷移?