addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)); }); async function handleRequest(request) { const url = new URL(request.url); // 处理 CORS 预检请求 if (request.method === 'OPTIONS') { return new Response(null, { headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization', }, }); } // API路由处理 switch (url.pathname) { // 1. 通过图片URL识别 case '/api/recognize/url': if (request.method === 'POST') { return handleImageUrlRecognition(request); } break; // 2. 通过Base64识别 case '/api/recognize/base64': if (request.method === 'POST') { return handleBase64Recognition(request); } break; // 3. 通过图片文件识别 (原有的/recognize端点) case '/recognize': if (request.method === 'POST') { return handleFileRecognition(request); } break; // 返回前端界面 case '/': return new Response(getHTML(), { headers: { 'Content-Type': 'text/html' }, }); } return new Response('Not Found', { status: 404 }); } // 处理图片URL识别 async function handleImageUrlRecognition(request) { try { const { token, imageUrl } = await request.json(); if (!token || !imageUrl) { return new Response(JSON.stringify({ error: 'Missing token or imageUrl' }), { status: 400, headers: { 'Content-Type': 'application/json' }, }); } // 下载图片 const imageResponse = await fetch(imageUrl); const imageBlob = await imageResponse.blob(); // 上传到QwenLM const formData = new FormData(); formData.append('file', imageBlob); const uploadResponse = await fetch('https://chat.qwenlm.ai/api/v1/files/', { method: 'POST', headers: { 'accept': 'application/json', 'authorization': `Bearer ${token}`, }, body: formData, }); const uploadData = await uploadResponse.json(); if (!uploadData.id) throw new Error('File upload failed'); // 调用识别API return await recognizeImage(token, uploadData.id); } catch (error) { return new Response(JSON.stringify({ error: error.message || 'Internal Server Error' }), { status: 500, headers: { 'Content-Type': 'application/json' }, }); } } // 处理Base64识别 async function handleBase64Recognition(request) { try { const { token, base64Image } = await request.json(); if (!token || !base64Image) { return new Response(JSON.stringify({ error: 'Missing token or base64Image' }), { status: 400, headers: { 'Content-Type': 'application/json' }, }); } // 转换Base64为Blob const imageData = base64Image.startsWith('data:') ? base64Image : 'data:image/png;base64,' + base64Image; const response = await fetch(imageData); const blob = await response.blob(); // 上传到QwenLM const formData = new FormData(); formData.append('file', blob); const uploadResponse = await fetch('https://chat.qwenlm.ai/api/v1/files/', { method: 'POST', headers: { 'accept': 'application/json', 'authorization': `Bearer ${token}`, }, body: formData, }); const uploadData = await uploadResponse.json(); if (!uploadData.id) throw new Error('File upload failed'); // 调用识别API return await recognizeImage(token, uploadData.id); } catch (error) { return new Response(JSON.stringify({ error: error.message || 'Internal Server Error' }), { status: 500, headers: { 'Content-Type': 'application/json' }, }); } } // 处理文件识别 (原有功能) async function handleFileRecognition(request) { try { const { token, imageId } = await request.json(); if (!token || !imageId) { return new Response(JSON.stringify({ error: 'Missing token or imageId' }), { status: 400, headers: { 'Content-Type': 'application/json' }, }); } return await recognizeImage(token, imageId); } catch (error) { return new Response(JSON.stringify({ error: error.message || 'Internal Server Error' }), { status: 500, headers: { 'Content-Type': 'application/json' }, }); } } // 通用的识别函数 async function recognizeImage(token, imageId) { const response = await fetch('https://chat.qwenlm.ai/api/chat/completions', { method: 'POST', headers: { 'accept': '*/*', 'authorization': `Bearer ${token}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ stream: false, model: 'qwen-vl-max-latest', messages: [ { role: 'user', content: [ { type: 'text', text: '请识别图片中的内容。对于数学公式和数学符号,请使用标准的LaTeX格式输出。' + '要求:\n' + '1. 所有数学公式和单个数学符号都要用LaTeX格式\n' + '2. 普通文本保持原样\n' + '3. 对于行内公式使用$单个符号$\n' + '4. 对于独立公式块使用$$公式$$\n' + '5. 严格保持原文的段落格式和换行\n' + '6. 当文本明显换行时,使用\\n进行换行处理' }, { type: 'image', image: imageId }, ], }, ], session_id: '1', chat_id: '2', id: '3', }), }); const data = await response.json(); // 处理识别结果 let result = data.choices[0]?.message?.content || '识别失败'; result = result .replace(/\\(/g, '\\(') .replace(/\\)/g, '\\)') .replace(/\n{3,}/g, '\n\n') .replace(/([^\n])\n([^\n])/g, '$1\n$2') .trim(); return new Response(JSON.stringify({ success: true, result: result }), { headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', }, }); } function getHTML() { const html = [ '', '', '', '', '', 'Qwen VL 智能识别系统', // 添加 MathJax 支持 '', '', '', '', '', '', '', '', '
', '

Qwen VL 智能识别系统

', '
基于通义千问大模型的多模态智能识别引擎
', '
', '📸', '
', '拖拽图片到这里,点击上传,或粘贴Base64图片内容
', '支持复制粘贴图片', '
', '', '', '', '
', '
', '
', '
', '识别结果', '', '
', '
', '
', '', '
', '

识别历史

', '
', '
', '', '
', '', '', '', '' ].join('\n'); return html; }