diff --git a/backend/app/routers/ocr.py b/backend/app/routers/ocr.py
index 98e80dd..07097bc 100644
--- a/backend/app/routers/ocr.py
+++ b/backend/app/routers/ocr.py
@@ -61,30 +61,30 @@ async def recognize_image(
"Content-Type": "application/json"
}
- # 阿里云 DashScope API 格式 (qwen-vl-max 视觉模型)
+ # 阿里云 DashScope API 格式 (qwen-vl-plus 视觉模型)
payload = {
- "model": "qwen-vl-max",
- "messages": [{
- "role": "user",
- "content": [
- {
- "type": "image_url",
- "image_url": {
- "url": f"data:image/jpeg;base64,{image_base64}"
+ "model": "qwen-vl-plus",
+ "input": {
+ "messages": [{
+ "role": "user",
+ "content": [
+ {
+ "image": f"data:{image.content_type};base64,{image_base64}"
+ },
+ {
+ "text": PROFESSIONAL_PROMPT
}
- },
- {
- "type": "text",
- "text": PROFESSIONAL_PROMPT
- }
- ]
- }],
- "max_tokens": 1000
+ ]
+ }]
+ },
+ "parameters": {
+ "max_tokens": 1000
+ }
}
async with httpx.AsyncClient(timeout=60.0) as client:
response = await client.post(
- "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
+ "https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation",
json=payload,
headers=headers
)
@@ -94,8 +94,13 @@ async def recognize_image(
ocr_result = response.json()
text_content = ""
- if "choices" in ocr_result and len(ocr_result["choices"]) > 0:
- text_content = ocr_result["choices"][0]["message"]["content"]
+ # 新版API返回格式
+ if "output" in ocr_result and "choices" in ocr_result["output"]:
+ choices = ocr_result["output"]["choices"]
+ if choices and len(choices) > 0:
+ content = choices[0].get("message", {}).get("content", [])
+ if content and len(content) > 0:
+ text_content = content[0].get("text", "")
fields = extract_fields(text_content)
@@ -106,7 +111,9 @@ async def recognize_image(
return {"success": True, "text": text_content, "fields": fields}
except Exception as e:
- raise HTTPException(status_code=500, detail=f"识别失败:{str(e)}")
+ import traceback
+ error_detail = f"识别失败:{str(e)}\n{traceback.format_exc()}"
+ raise HTTPException(status_code=500, detail=error_detail)
def extract_fields(text: str) -> dict:
diff --git a/config/VERSION b/config/VERSION
index 7595223..56511a4 100644
--- a/config/VERSION
+++ b/config/VERSION
@@ -2,7 +2,7 @@
# Version Configuration for Zodiac Collection Management System
# 当前版本号 (语义化版本:主版本。次版本.修订版)
-VERSION=1.0.3
+VERSION=1.0.5
# 版本代号 (可选)
VERSION_CODENAME="新生"
diff --git a/frontend/index.html b/frontend/index.html
index 0e01b5f..4abaa48 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -4,7 +4,7 @@
-
甲辰收藏 v1.0.1
+ 甲辰收藏 v1.0.3-1773807001352
diff --git a/frontend/src/pages/Add.jsx b/frontend/src/pages/Add.jsx
index ae69d05..e32812c 100644
--- a/frontend/src/pages/Add.jsx
+++ b/frontend/src/pages/Add.jsx
@@ -170,14 +170,38 @@ export default function Add() {
const token = localStorage.getItem('token')
const formData = new FormData()
formData.append('image', selectedImage)
+
+ // 使用 XMLHttpRequest 替代 fetch
+ const data = await new Promise((resolve, reject) => {
+ const xhr = new XMLHttpRequest()
+ xhr.open('POST', '/api/ocr/recognize')
+ xhr.setRequestHeader('Authorization', 'Bearer ' + token)
+
+ xhr.onload = function() {
+ if (xhr.status >= 200 && xhr.status < 300) {
+ try {
+ const data = JSON.parse(xhr.responseText)
+ resolve(data)
+ } catch (e) {
+ reject(new Error('JSON解析失败: ' + xhr.responseText.substring(0, 100)))
+ }
+ } else {
+ try {
+ const data = JSON.parse(xhr.responseText)
+ reject(new Error(data.error?.message || data.detail || '识别失败'))
+ } catch (e) {
+ reject(new Error('请求失败: ' + xhr.status))
+ }
+ }
+ }
+
+ xhr.onerror = function() {
+ reject(new Error('网络错误'))
+ }
+
+ xhr.send(formData)
+ })
try {
- const res = await fetch('/api/ocr/recognize', {
- method: 'POST',
- headers: { 'Authorization': 'Bearer ' + token },
- body: formData
- })
- const data = await res.json()
- if (!res.ok) throw new Error(data.error?.message || '识别失败')
if (data.fields) {
const recognizedForm = { ...getDefaultForm() }
// 直接对应 AI 返回的字段,不需要二次解析
diff --git a/frontend/src/pages/BatchMode.jsx b/frontend/src/pages/BatchMode.jsx
index b9e6799..a8fcef7 100644
--- a/frontend/src/pages/BatchMode.jsx
+++ b/frontend/src/pages/BatchMode.jsx
@@ -85,7 +85,7 @@ export default function BatchMode() {
const formData = new FormData()
formData.append('image', file)
- const res = await fetch('/api/ocr', { method: 'POST', body: formData })
+ const res = await fetch('/api/ocr/recognize', { method: 'POST', body: formData })
const data = await res.json()
const text = data.result || ''
diff --git a/frontend/src/pages/OCR.jsx b/frontend/src/pages/OCR.jsx
index bf1cd2e..0b1229f 100644
--- a/frontend/src/pages/OCR.jsx
+++ b/frontend/src/pages/OCR.jsx
@@ -229,21 +229,38 @@ export default function OCR() {
const formData = new FormData()
formData.append('image', selectedImage)
- try {
- const res = await fetch('/api/ocr/recognize', {
- method: 'POST',
- headers: {
- 'Authorization': 'Bearer ' + token
- },
- body: formData
- })
+ // 使用 XMLHttpRequest 替代 fetch,兼容性更好
+ const data = await new Promise((resolve, reject) => {
+ const xhr = new XMLHttpRequest()
+ xhr.open('POST', '/api/ocr/recognize')
+ xhr.setRequestHeader('Authorization', 'Bearer ' + token)
- const data = await res.json()
-
- if (!res.ok) {
- throw new Error(data.error?.message || '识别失败')
+ xhr.onload = function() {
+ if (xhr.status >= 200 && xhr.status < 300) {
+ try {
+ const data = JSON.parse(xhr.responseText)
+ resolve(data)
+ } catch (e) {
+ reject(new Error('JSON解析失败: ' + xhr.responseText.substring(0, 100)))
+ }
+ } else {
+ try {
+ const data = JSON.parse(xhr.responseText)
+ reject(new Error(data.error?.message || data.detail || '识别失败'))
+ } catch (e) {
+ reject(new Error('请求失败: ' + xhr.status))
+ }
+ }
}
+ xhr.onerror = function() {
+ reject(new Error('网络错误'))
+ }
+
+ xhr.send(formData)
+ })
+
+ try {
// 自动填充识别结果
if (data.fields) {
const recognizedForm = { ...getDefaultForm() }
diff --git a/frontend/src/utils/api.js b/frontend/src/utils/api.js
index 110a88a..5ae698f 100644
--- a/frontend/src/utils/api.js
+++ b/frontend/src/utils/api.js
@@ -203,9 +203,9 @@ export const api = {
ocr: {
recognize: (file) => {
const formData = new FormData()
- formData.append('file', file)
+ formData.append('image', file)
- return request('/api/ocr', {
+ return request('/api/ocr/recognize', {
method: 'POST',
body: formData
})
diff --git a/frontend/vite.config.js b/frontend/vite.config.js
index e5d8607..ddfd244 100644
--- a/frontend/vite.config.js
+++ b/frontend/vite.config.js
@@ -16,7 +16,7 @@ function getVersion() {
}
}
-const APP_VERSION = getVersion()
+const APP_VERSION = getVersion() + '-' + Date.now()
console.log(`📦 构建版本:v${APP_VERSION}`)
// 构建时自动更新 index.html 的 title