bug fix order

This commit is contained in:
董海洋
2026-05-26 14:04:14 +08:00
parent 1b0adcc705
commit 53e9a1247f
2 changed files with 18 additions and 35 deletions
+15 -33
View File
@@ -138,13 +138,18 @@ router.post('/recognize-product', async (ctx) => {
ctx.body = { code: 500, message: 'AI 功能未配置(缺少 DASHSCOPE_API_KEY' } ctx.body = { code: 500, message: 'AI 功能未配置(缺少 DASHSCOPE_API_KEY' }
return return
} }
const { imageUrl } = ctx.request.body; const { imageBase64, imageUrl } = ctx.request.body;
if (!imageUrl) { let inputImageUrl = imageUrl;
if (imageBase64) {
inputImageUrl = `data:image/jpeg;base64,${imageBase64}`;
}
if (!inputImageUrl) {
ctx.status = 400; ctx.status = 400;
ctx.body = { ctx.body = {
code: 400, code: 400,
message: '请提供商品图片地址' message: '请提供商品图片'
}; };
return; return;
} }
@@ -160,7 +165,7 @@ router.post('/recognize-product', async (ctx) => {
"confidence": 0到1之间的数字(识别置信度) "confidence": 0到1之间的数字(识别置信度)
}`; }`;
console.log('Calling Qwen Omni API with image:', imageUrl); console.log('Calling Qwen Omni API with image...');
const response = await fetch(AI_API_URL, { const response = await fetch(AI_API_URL, {
method: 'POST', method: 'POST',
headers: { headers: {
@@ -168,7 +173,7 @@ router.post('/recognize-product', async (ctx) => {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
}, },
body: JSON.stringify({ body: JSON.stringify({
model: 'qwen3.5-omni-flash', model: 'qwen3.5-omni',
messages: [ messages: [
{ {
role: 'user', role: 'user',
@@ -176,7 +181,7 @@ router.post('/recognize-product', async (ctx) => {
{ {
type: 'image_url', type: 'image_url',
image_url: { image_url: {
url: imageUrl url: inputImageUrl
} }
}, },
{ {
@@ -186,11 +191,8 @@ router.post('/recognize-product', async (ctx) => {
] ]
} }
], ],
modalities: ['text'],
temperature: 0.3, temperature: 0.3,
max_tokens: 500, max_tokens: 500
stream: true,
stream_options: { include_usage: true }
}), }),
timeout: 60000 timeout: 60000
}); });
@@ -210,8 +212,6 @@ router.post('/recognize-product', async (ctx) => {
errorMsg = 'API 调用次数超限,请稍后重试'; errorMsg = 'API 调用次数超限,请稍后重试';
} else if (response.status === 503) { } else if (response.status === 503) {
errorMsg = 'AI 服务暂时不可用,请稍后重试'; errorMsg = 'AI 服务暂时不可用,请稍后重试';
} else if (response.status === 404) {
errorMsg = '模型不支持图片输入,正在尝试兼容模式...';
} }
ctx.status = response.status; ctx.status = response.status;
@@ -222,26 +222,8 @@ router.post('/recognize-product', async (ctx) => {
return; return;
} }
// 解析 SSE 流式响应 const data = await response.json();
const text = await response.text(); const aiResponse = data.choices?.[0]?.message?.content;
const lines = text.split('\n');
let aiResponse = '';
for (const line of lines) {
if (line.startsWith('data: ')) {
const dataStr = line.slice(6).trim();
if (dataStr === '[DONE]') break;
try {
const parsed = JSON.parse(dataStr);
const content = parsed.choices?.[0]?.delta?.content;
if (content) {
aiResponse += content;
}
} catch (e) {
// 跳过解析失败的行
}
}
}
if (!aiResponse) { if (!aiResponse) {
ctx.status = 500; ctx.status = 500;
@@ -281,7 +263,7 @@ router.post('/recognize-product', async (ctx) => {
let matchedGoods = []; let matchedGoods = [];
if (keyword) { if (keyword) {
const dbResult = await query( const dbResult = await query(
'SELECT id, name, price, unit, category_id, images, stock, pricing_type, is_hot, is_new, description, goods_no, barcode FROM goods WHERE name LIKE ? LIMIT 20', 'SELECT id, name, price, unit, category_id, images, stock, pricing_type, is_hot, is_new, description FROM goods WHERE name LIKE ? LIMIT 20',
[`%${keyword}%`] [`%${keyword}%`]
); );
matchedGoods = dbResult; matchedGoods = dbResult;
+3 -2
View File
@@ -9,9 +9,10 @@ async function paginate(queryFn, sql, params, page = 1, pageSize = 20) {
const total = countResult[0].total const total = countResult[0].total
const totalPages = Math.ceil(total / ps) const totalPages = Math.ceil(total / ps)
const offset = (p - 1) * ps
const data = await queryFn( const data = await queryFn(
`${sql} LIMIT ? OFFSET ?`, `${sql} LIMIT ${ps} OFFSET ${offset}`,
[...params, ps, (p - 1) * ps] params
) )
return { data, total, page: p, pageSize: ps, totalPages } return { data, total, page: p, pageSize: ps, totalPages }