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>
This commit is contained in:
beabigegg
2025-11-13 08:54:37 +08:00
parent fed112656f
commit 9cf36d8e21
7 changed files with 2865 additions and 34 deletions

743
API_REFERENCE.md Normal file
View File

@@ -0,0 +1,743 @@
# 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)?
- [ ] 相關文件是否更新?
- [ ] 現有功能是否受影響?
- [ ] 是否需要版本遷移?