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:
368
API_FIX_SUMMARY.md
Normal file
368
API_FIX_SUMMARY.md
Normal file
@@ -0,0 +1,368 @@
|
||||
# API 前後端不一致問題修正總結
|
||||
|
||||
## 修正日期
|
||||
2025-01-13
|
||||
|
||||
## 修正概覽
|
||||
|
||||
本次修正針對前後端 API 整合的 6 個主要問題進行了全面修復,確保前後端資料結構完全一致。
|
||||
|
||||
---
|
||||
|
||||
## 已修正的問題
|
||||
|
||||
### ✅ 問題 1: 登入回應結構不一致
|
||||
|
||||
**修正內容**:
|
||||
- 在前端 `LoginResponse` 型別新增 `expires_in` 欄位
|
||||
|
||||
**修改檔案**:
|
||||
- [frontend/src/types/api.ts:12-16](frontend/src/types/api.ts#L12-L16)
|
||||
|
||||
**變更**:
|
||||
```typescript
|
||||
// 修正前
|
||||
export interface LoginResponse {
|
||||
access_token: string
|
||||
token_type: string
|
||||
}
|
||||
|
||||
// 修正後
|
||||
export interface LoginResponse {
|
||||
access_token: string
|
||||
token_type: string
|
||||
expires_in: number // Token expiration time in seconds
|
||||
}
|
||||
```
|
||||
|
||||
**影響**:
|
||||
- ✅ 前端現在可以接收 Token 過期時間
|
||||
- ✅ 可實作 Token 自動續期功能
|
||||
- ✅ 可提前提醒使用者 Token 即將過期
|
||||
|
||||
---
|
||||
|
||||
### ✅ 問題 2: OCR 任務狀態 API 不存在
|
||||
|
||||
**修正內容**:
|
||||
- 移除前端的 `getTaskStatus()` 方法
|
||||
- 統一使用 `getBatchStatus()` 進行批次狀態追蹤
|
||||
- 從 import 中移除 `TaskStatus` 型別
|
||||
|
||||
**修改檔案**:
|
||||
- [frontend/src/services/api.ts:3-18](frontend/src/services/api.ts#L3-L18) - 移除 TaskStatus import
|
||||
- [frontend/src/services/api.ts:153-160](frontend/src/services/api.ts#L153-L160) - 移除 getTaskStatus 方法
|
||||
|
||||
**變更**:
|
||||
```typescript
|
||||
// 修正前
|
||||
import type {
|
||||
// ... 其他型別
|
||||
TaskStatus,
|
||||
// ...
|
||||
}
|
||||
|
||||
async getTaskStatus(taskId: string): Promise<TaskStatus> {
|
||||
const response = await this.client.get<TaskStatus>(`/ocr/status/${taskId}`)
|
||||
return response.data
|
||||
}
|
||||
|
||||
// 修正後
|
||||
// TaskStatus 已從 import 移除
|
||||
// getTaskStatus 方法已刪除
|
||||
// 統一使用 getBatchStatus() 追蹤狀態
|
||||
```
|
||||
|
||||
**影響**:
|
||||
- ✅ 避免呼叫不存在的 API 端點 (404 錯誤)
|
||||
- ✅ 統一使用批次狀態管理
|
||||
- ✅ 簡化狀態追蹤邏輯
|
||||
|
||||
---
|
||||
|
||||
### ✅ 問題 3: OCR 處理請求/回應模型不符
|
||||
|
||||
**修正內容**:
|
||||
- 修改 `ProcessRequest` 型別,改用 `detect_layout` 取代 `confidence_threshold`
|
||||
- 修改 `ProcessResponse` 型別,新增 `message` 和 `total_files` 欄位,移除 `task_id`
|
||||
|
||||
**修改檔案**:
|
||||
- [frontend/src/types/api.ts:37-50](frontend/src/types/api.ts#L37-L50)
|
||||
|
||||
**變更**:
|
||||
```typescript
|
||||
// 修正前
|
||||
export interface ProcessRequest {
|
||||
batch_id: number
|
||||
lang?: string
|
||||
confidence_threshold?: number // ❌ 後端不支援此欄位
|
||||
}
|
||||
|
||||
export interface ProcessResponse {
|
||||
task_id: string // ❌ 後端不回傳此欄位
|
||||
batch_id: number
|
||||
status: string
|
||||
}
|
||||
|
||||
// 修正後
|
||||
export interface ProcessRequest {
|
||||
batch_id: number
|
||||
lang?: string
|
||||
detect_layout?: boolean // ✅ 與後端一致
|
||||
}
|
||||
|
||||
export interface ProcessResponse {
|
||||
message: string // ✅ 新增
|
||||
batch_id: number
|
||||
total_files: number // ✅ 新增
|
||||
status: string
|
||||
// task_id 已移除
|
||||
}
|
||||
```
|
||||
|
||||
**影響**:
|
||||
- ✅ 前端可正確傳遞版面偵測參數給後端
|
||||
- ✅ 前端可接收處理訊息和檔案總數
|
||||
- ✅ 避免型別檢查錯誤
|
||||
- ✅ 避免驗證失敗
|
||||
|
||||
---
|
||||
|
||||
### ✅ 問題 4: 上傳檔案欄位命名不一致
|
||||
|
||||
**修正內容**:
|
||||
- 將 `FileInfo.format` 改名為 `FileInfo.file_format`
|
||||
|
||||
**修改檔案**:
|
||||
- [frontend/src/types/api.ts:28-35](frontend/src/types/api.ts#L28-L35)
|
||||
|
||||
**變更**:
|
||||
```typescript
|
||||
// 修正前
|
||||
export interface FileInfo {
|
||||
id: number
|
||||
filename: string
|
||||
file_size: number
|
||||
format: string // ❌ 與後端欄位名稱不同
|
||||
status: 'pending' | 'processing' | 'completed' | 'failed'
|
||||
}
|
||||
|
||||
// 修正後
|
||||
export interface FileInfo {
|
||||
id: number
|
||||
filename: string
|
||||
file_size: number
|
||||
file_format: string // ✅ 與後端一致
|
||||
status: 'pending' | 'processing' | 'completed' | 'failed'
|
||||
}
|
||||
```
|
||||
|
||||
**影響**:
|
||||
- ✅ 前端可直接使用後端回傳的 `file_format` 欄位
|
||||
- ✅ 無需額外的欄位映射或轉換
|
||||
- ✅ UI 可正確顯示檔案格式
|
||||
|
||||
---
|
||||
|
||||
### ✅ 問題 5: CSS 模板清單缺少 filename
|
||||
|
||||
**修正內容**:
|
||||
- 移除 `CSSTemplate.filename` 欄位定義
|
||||
- 改用 `name` 作為模板識別碼
|
||||
|
||||
**修改檔案**:
|
||||
- [frontend/src/types/api.ts:135-139](frontend/src/types/api.ts#L135-L139)
|
||||
|
||||
**變更**:
|
||||
```typescript
|
||||
// 修正前
|
||||
export interface CSSTemplate {
|
||||
name: string
|
||||
description: string
|
||||
filename: string // ❌ 後端實際不回傳此欄位
|
||||
}
|
||||
|
||||
// 修正後
|
||||
export interface CSSTemplate {
|
||||
name: string
|
||||
description: string
|
||||
// filename 已移除,使用 name 作為識別碼
|
||||
}
|
||||
```
|
||||
|
||||
**影響**:
|
||||
- ✅ 避免 `filename` 為 undefined 的問題
|
||||
- ✅ 使用 `name` 作為 `<option>` 的 key/value
|
||||
- ✅ 與後端實際回傳結構一致
|
||||
|
||||
---
|
||||
|
||||
### ✅ 問題 6: 翻譯設定端點未實作
|
||||
|
||||
**修正內容**:
|
||||
- 註解 `getTranslationConfigs()` 方法
|
||||
- 註解 `createTranslationConfig()` 方法
|
||||
- 新增 `@deprecated` 標記說明
|
||||
|
||||
**修改檔案**:
|
||||
- [frontend/src/services/api.ts:246-266](frontend/src/services/api.ts#L246-L266)
|
||||
|
||||
**變更**:
|
||||
```typescript
|
||||
// 修正前
|
||||
async getTranslationConfigs(): Promise<TranslationConfig[]> {
|
||||
const response = await this.client.get<TranslationConfig[]>('/translate/configs')
|
||||
return response.data
|
||||
}
|
||||
|
||||
async createTranslationConfig(
|
||||
config: Omit<TranslationConfig, 'id' | 'created_at'>
|
||||
): Promise<TranslationConfig> {
|
||||
const response = await this.client.post<TranslationConfig>('/translate/configs', config)
|
||||
return response.data
|
||||
}
|
||||
|
||||
// 修正後
|
||||
/**
|
||||
* Get translation configs (NOT IMPLEMENTED)
|
||||
* @deprecated Backend endpoint does not exist - will return 404
|
||||
*/
|
||||
// async getTranslationConfigs(): Promise<TranslationConfig[]> { ... }
|
||||
|
||||
/**
|
||||
* Create translation config (NOT IMPLEMENTED)
|
||||
* @deprecated Backend endpoint does not exist - will return 404
|
||||
*/
|
||||
// async createTranslationConfig(...): Promise<TranslationConfig> { ... }
|
||||
```
|
||||
|
||||
**影響**:
|
||||
- ✅ 避免呼叫不存在的 API 端點 (404 錯誤)
|
||||
- ✅ 明確標示這些方法尚未實作
|
||||
- ✅ 保留型別定義供 Phase 5 使用
|
||||
|
||||
---
|
||||
|
||||
### ✅ 問題 7: OCR 結果查詢參數名稱誤導
|
||||
|
||||
**修正內容**:
|
||||
- 修改 `getOCRResult()` 方法參數名稱從 `taskId` 改為 `fileId`
|
||||
- 更新註解說明使用檔案級別追蹤
|
||||
|
||||
**修改檔案**:
|
||||
- [frontend/src/services/api.ts:153-160](frontend/src/services/api.ts#L153-L160)
|
||||
|
||||
**變更**:
|
||||
```typescript
|
||||
// 修正前
|
||||
async getOCRResult(taskId: string): Promise<OCRResult> {
|
||||
const response = await this.client.get<OCRResult>(`/ocr/result/${taskId}`)
|
||||
return response.data
|
||||
}
|
||||
|
||||
// 修正後
|
||||
/**
|
||||
* Get OCR result by file ID
|
||||
* Note: Backend uses file-level tracking, not task-level
|
||||
*/
|
||||
async getOCRResult(fileId: number): Promise<OCRResult> {
|
||||
const response = await this.client.get<OCRResult>(`/ocr/result/${fileId}`)
|
||||
return response.data
|
||||
}
|
||||
```
|
||||
|
||||
**影響**:
|
||||
- ✅ 參數名稱更準確反映實際用途
|
||||
- ✅ 型別從 `string` 改為 `number` 更符合後端
|
||||
- ✅ 減少開發者混淆
|
||||
|
||||
---
|
||||
|
||||
## 修正檔案清單
|
||||
|
||||
### 前端修改
|
||||
1. **frontend/src/types/api.ts**
|
||||
- LoginResponse 新增 `expires_in`
|
||||
- FileInfo `format` → `file_format`
|
||||
- ProcessRequest `confidence_threshold` → `detect_layout`
|
||||
- ProcessResponse 新增 `message`, `total_files`,移除 `task_id`
|
||||
- CSSTemplate 移除 `filename`
|
||||
|
||||
2. **frontend/src/services/api.ts**
|
||||
- 移除 `TaskStatus` import
|
||||
- 移除 `getTaskStatus()` 方法
|
||||
- 修正 `getOCRResult()` 參數名稱和型別
|
||||
- 註解 `getTranslationConfigs()` 和 `createTranslationConfig()`
|
||||
|
||||
### 後端修改
|
||||
- **無需修改** - 所有修正都在前端配合後端
|
||||
|
||||
---
|
||||
|
||||
## 驗證建議
|
||||
|
||||
### 1. 型別檢查
|
||||
```bash
|
||||
cd frontend
|
||||
npm run type-check
|
||||
```
|
||||
|
||||
### 2. 編譯檢查
|
||||
```bash
|
||||
cd frontend
|
||||
npm run build
|
||||
```
|
||||
|
||||
### 3. 測試建議
|
||||
- ✅ 測試登入功能,確認可接收 `expires_in`
|
||||
- ✅ 測試檔案上傳,確認 `file_format` 欄位正確顯示
|
||||
- ✅ 測試 OCR 處理,確認 `detect_layout` 參數正確傳遞
|
||||
- ✅ 測試批次狀態追蹤,確認 `getBatchStatus()` 正常運作
|
||||
- ✅ 測試 OCR 結果查詢,確認 `fileId` 參數正確使用
|
||||
- ✅ 確認不再呼叫不存在的翻譯設定端點
|
||||
|
||||
---
|
||||
|
||||
## 後續工作建議
|
||||
|
||||
### 立即工作
|
||||
1. ✅ 更新前端 UI 使用新的欄位名稱 (`file_format` 而非 `format`)
|
||||
2. ✅ 移除任何使用 `getTaskStatus()` 的程式碼
|
||||
3. ✅ 更新使用 `getOCRResult()` 的程式碼,改用 `fileId` 參數
|
||||
|
||||
### Phase 5 (翻譯功能) 工作
|
||||
1. ⏸️ 實作後端 `/api/v1/translate/configs` 端點 (GET/POST)
|
||||
2. ⏸️ 取消註解前端的 `getTranslationConfigs()` 和 `createTranslationConfig()`
|
||||
3. ⏸️ 移除 `@deprecated` 標記
|
||||
|
||||
---
|
||||
|
||||
## API 文件
|
||||
|
||||
完整的 API 端點清單和說明請參考:
|
||||
- 📄 [API_REFERENCE.md](./API_REFERENCE.md) - 完整 API 端點文件
|
||||
|
||||
---
|
||||
|
||||
## 修正統計
|
||||
|
||||
- **總問題數**: 7
|
||||
- **已修正**: 7
|
||||
- **修正率**: 100%
|
||||
- **修改檔案數**: 2
|
||||
- **新增文件數**: 2
|
||||
|
||||
---
|
||||
|
||||
## 簽核
|
||||
|
||||
- **修正人員**: Claude AI
|
||||
- **審核狀態**: ✅ 待使用者驗證
|
||||
- **版本**: v0.1.0-fix1
|
||||
- **修正日期**: 2025-01-13
|
||||
|
||||
---
|
||||
|
||||
## 附註
|
||||
|
||||
所有修正都遵循「前端配合後端」的原則,避免破壞性變更。後端 API 保持穩定,前端型別定義完全對齊後端實作。
|
||||
Reference in New Issue
Block a user