addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)); }); async function handleRequest(request) { const url = new URL(request.url); const cookie = request.headers.get('x-custom-cookie') || ''; // 从自定义请求头获取 cookie // 处理 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, x-custom-cookie', // 添加自定义请求头 }, }); } // 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 '/proxy/upload': if (request.method === 'POST') { return handleProxyUpload(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 handleProxyUpload(request) { try { const formData = await request.formData(); const token = request.headers.get('Authorization').replace('Bearer ', ''); const response = await fetch('https://chat.qwenlm.ai/api/v1/files/', { method: 'POST', headers: { 'accept': 'application/json', 'authorization': `Bearer ${token}`, }, body: formData, }); const data = await response.json(); return new Response(JSON.stringify(data), { headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', }, }); } catch (error) { return new Response(JSON.stringify({ error: error.message || 'Proxy upload failed' }), { status: 500, headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', }, }); } } // 通用的识别函数 async function recognizeImage(token, imageId) { const response = await fetch('https://chat.qwenlm.ai/api/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'User-Agent': 'PostmanRuntime/7.43.0', 'accept': '*/*', 'authorization': `Bearer ${token}`, 'cookie': 'cna=LI8HIAirQyACAWrg3cNOjH8F; _gcl_au=1.1.1200556497.1736728490; xlly_s=1; acw_tc=c2b96feb4d2929a1649ea96dc00590956477696933f61783d23e6c95429ecf74; x-ap=ap-southeast-1; token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjUzZTk0Nzg4LWMwM2QtNDY4Mi05OTNhLWE0ZDNjNGUyZDY0OSIsImV4cCI6MTc0MTE0ODM0MX0.-2hF4l1iJf8r5U6UzoXyc-TFqx0i5luWmtJk0kk8T5o; ssxmod_itna=Yq+hqIxjx=AKi7eitD8IDCWBfbxxl4BtGRDeq7tDRDFqApxDHmLWxoDUxxu2hE80DD0ADnG3BUxGN4tDxiNDAg40iDC4mL37ezTxthtQQhgDCTYCu2rpTCGGE7P3rnTE0M25BA6w3KxxGLDY=DCqhxl4eD4R3Dt4DIDAYDDxDWFeGIDGYD7hb=ymbDm44aYxGy3nbDA3TDbhb5xitYDDUAKeG2igbhDDNheFY49GG7yC0OorHDAqh==GbDjqPD/RxLP+bkXtkh/CTA=BapCeaWxBQD7we3xYE4c=IdqZawfiEwDELx0De/iGKGxdYmPlvzYKGlpVGGoWDqjqQlXnlvnnPDDc=Y9=buiDrP3KYtvS85lmHQDxPoGb0rz0THimDgri0i8B0=nxNCDtYDb30eDBeIG4/g8BvDD; ssxmod_itna2=Yq+hqIxjx=AKi7eitD8IDCWBfbxxl4BtGRDeq7tDRDFqApxDHmLWxoDUxxu2hE80DD0ADnG3BDxDfk7K7e5xDLiARWCTe9A4D/9o1+WeqlSGSWe4dTPhBUq4kzjyE41MPvWM=BtDwWHWiQ4B+GVChGZYlDDoA6gCj2VGnQeqqxeBSiqeT69Cg2Q6qrEGqv/DTQR8MRo3m3E7Gd7mf42Re2lYpNic=beSRp3tCDgWT7khOXGqf2lBpre5BtExlRw6cUwWwDxNSFUl/8Un/RGZz8/jLk2t1XZC79Eb7iRTPTMPn5MTHW2fs1DlsH0z9RxCLW1Rdb2QFhd9biugr+2aTW1oeYAbtORQNMW43+m2Gcb=TuFtQGqhiTqrNfdwSOe8WHSWTr7cRaw833Yzw31d4iN+Q9OO7izUj1uSdYrh4dIvx5CwYD45Vji4EbkiaNQQGbt1hDa8Ymmda3r3lThChY8Nm2IscznS+mS43izuLzUYN94syC3tQi03=u3Q6az931moHSOLY3OFPKoMjqMUDbtebxw=rT2rBAv08uRkWHzFtGp2lUSSb3z41pTZcx/8NB3jD+XnIpLFEw8bv4r58wRLLwubFTQ9cPDv+9k36tvoCYXlso4qGA44E3y737YNBDmUct2Iahxq76iTrlGotG1NBBN=Tx4hkA2Zp887gfc4Tp8V1wGCf49XeA=0Xu3uIKqYQADh0ABmqlQ4w=YVlDPjO9KH2xaG3C8ID5DeY41AxMxR2NIGhSD+5q0UQGx0Ue4dAi0DwbY+f7n1Gwz014LQ2DY+42xI2zG5TmhfDtXehC40aWxfDi0xIGNQ3gGkYeu2fAfADwY31mkAooDxD; SERVERID=da7472215188c88fe194f138f1242089|1738557149|1738556339; SERVERCORSID=da7472215188c88fe194f138f1242089|1738557149|1738556339; isg=BBcXHLltPM7zv7hi-FnT0HW6pothXOu-LIccEmlG4eZGmDrabS7mDq_--ziGPsM2; tfstk=gxYniE986HSQfEpYpd7Icypow5otjW_5cLUReaBrbOW6JLnCehbygKjRyBdPr4XN8gtde9BlrQ9m6x3xkBOCPgkxHqIXCrTVlurzY8QNb_blTz_06LRCPaktd3lv5B9qU3M64alG7_fz8aWFTPlGZsXPz9SzQl5VQT7yU9SaQ617YJzUzRlGNOWPzaJP7jQ8r9CV1FkgVOPK4CrD_6jh3BWH9KLadGrBiO4zzFjfxtuAIzzyS6Ot3kbuo0B2c9IACduT-aANZKfDKRkGzCYBoG8ECzvDIn7G1hMuqtxy9ntPjXueswXhmFI0Zk7H4pTlAHVSGC7eCn6fYcM1seLAqtsgQvR9s9SDqpH_z9KD_djvWRUA7I-GSgozbo5IVz1ZwFr7VM51stK4FEPS3FZLvfcg0MIF16r-sfq7VM51sthisoJlY11U2', // 直接填入 cookie }, body: JSON.stringify({ stream: false, chat_type: "t2t", model: 'qwen2.5-vl-72b-instruct', messages: [ { role: 'user', content: [ { type: 'text', text: '请识别图片中的内容,注意以下要求:\n' + '对于数学公式和普通文本:\n' + '1. 所有数学公式和数学符号都必须使用标准的LaTeX格式\n' + '2. 行内公式使用单个$符号包裹,如:$x^2$\n' + '3. 独立公式块使用两个$$符号包裹,如:$$\\sum_{i=1}^n i^2$$\n' + '4. 普通文本保持原样,不要使用LaTeX格式\n' + '5. 保持原文的段落格式和换行\n' + '6. 明显的换行使用\\n表示\n' + '7. 确保所有数学符号都被正确包裹在$或$$中\n\n' + '对于验证码图片:\n' + '1. 只输出验证码字符,不要加任何额外解释\n' + '2. 忽略干扰线和噪点\n' + '3. 注意区分相似字符,如0和O、1和l、2和Z等\n' + '4. 验证码通常为4-6位字母数字组合\n\n' + '不要输出任何额外的解释或说明', chat_type: "t2t" }, { type: 'image', image: imageId, chat_type: "t2t" }, ], }, ], session_id: '1', chat_id: '2', id: '3', }), }); const data = await response.json(); let result = data.choices[0]?.message?.content || '识别失败'; // 如果结果长度小于10且只包含字母数字,很可能是验证码 if (result.length <= 10 && /^[A-Za-z0-9]+$/.test(result)) { return new Response(JSON.stringify({ success: true, result: result.toUpperCase(), // 验证码统一转大写 type: 'captcha' }), { headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', }, }); } // 其他情况(数学公式和普通文本)的处理 result = result .replace(/\\(/g, '\\(') .replace(/\\)/g, '\\)') .replace(/\n{3,}/g, '\n\n') .replace(/([^\n])\n([^\n])/g, '$1\n$2') .replace(/\$\s+/g, '$') .replace(/\s+\$/g, '$') .replace(/\$\$/g, '$$') .trim(); return new Response(JSON.stringify({ success: true, result: result, type: 'text' }), { headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', }, }); } function getHTML() { const html = [ '', '', '', '', '', '', 'Qwen VL 智能识别系统', // 添加 MathJax 支持 '', '', '', '', '', '', '', '', ' ', ' ', ' ', '', '', '', '
', '

Qwen VL 智能识别系统

', '
基于通义千问大模型的多模态智能识别引擎
', '
', '📸', '
', '拖拽图片到这里,点击上传,或粘贴图片/Base64/URL
', '支持多种输入方式', '
', '
', '', '', '
', '', '', '
', '
', '', '
', '
', '
', '
', '识别结果', '', '
', '
', '
', '', '
', '

识别历史

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