news 2026/2/28 5:31:13

用 Vue3 #x2B; fetch-event-source 打造流式 AI 翻译平台:OCR #x2B; 大模型 #x2B; SSE 全链路实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用 Vue3 #x2B; fetch-event-source 打造流式 AI 翻译平台:OCR #x2B; 大模型 #x2B; SSE 全链路实战

从 UI 工程师到 AI 应用架构者

13 年前,我的工作是让按钮在 IE6 上对齐;
13 年后,我用fetch-event-source订阅大模型的“思维流”,用 OCR 解锁图片中的文字——前端,正在成为 AI 产品的第一道体验防线

最近,我基于Vue 3 + Vite + TypeScript + Ant Design Vue开发了一款企业级 AI 多语翻译平台。它支持:

    • ✅ 文本/图片/文档多模态输入
    • ✅ 大模型动态切换(通义千问、DeepSeek 等)
    • ✅ 行业领域定制(医疗、法律、金融)
    • SSE 流式输出(使用fetch-event-source

今天,我将逐行拆解核心代码,带你复现这一高价值 AI 应用的前端架构。


一、技术选型:为什么是fetch-event-source

虽然浏览器原生支持EventSource,但在现代前端工程中,我们更倾向使用@microsoft/fetch-event-source

    • ✅ 基于fetch,天然支持AbortController(可取消请求)
    • ✅ 支持自定义 headers(用于鉴权)
    • ✅ 更好的TypeScript 类型支持
    • ✅ 与 Axios/Vite 生态无缝集成

安装:

/* by 01022.hk - online tools website : 01022.hk/zh/checkweixin.html */ npm install @microsoft/fetch-event-source

二、OCR 图片识别:前端只管“传”和“显”

用户上传一张英文菜单截图,系统自动提取文字并翻译。前端不碰 OCR 算法,但要管理全流程状态

🔧 真实代码实现(来自文本_r9uv.txt

1.系统配置加载(含文件大小限制)
/* by 01022.hk - online tools website : 01022.hk/zh/checkweixin.html */ // src/views/translation/index.vue const loadSystemPublicConfig = async () => { try { const response = await findSystemPublicConfig({ configKey: 'upload_file_max_limit_mb' }); const config = response.data[0]; systemConfig.value.uploadFileMaxLimit = parseInt(config.value) || 10; // 默认10MB } catch (error) { ElMessage.error('加载系统配置失败'); } };
2.文件选择与校验
const handleFileSelect = (event: Event) => { const input = event.target as HTMLInputElement; if (input.files && input.files.length > 0) { const file = input.files[0]; const maxSize = systemConfig.value.uploadFileMaxLimit * 1024 * 1024; if (file.size > maxSize) { message.error(`文件不能超过 ${systemConfig.value.uploadFileMaxLimit} MB`); return; } currentFile.value = file; startParsing(file); } };
3.调用 OCR 接口(Ant Design Vue 组件反馈)
const handleObtainFileContentText = async () => { if (!currentFile.value) return; const formData = new FormData(); formData.append('file', currentFile.value); try { const response = await obtainFileContentText(formData); if (response.success) { sourceLanguageText.value = response.data.contentText; currentUploadStatus.value = 'success'; } else { currentUploadStatus.value = 'failed'; message.error(response.message || '解析失败'); } } catch (error) { currentUploadStatus.value = 'failed'; message.error('网络错误,请重试'); } };

💡关键设计:状态分为'idle' | 'parsing' | 'success' | 'failed',对应四个 UI 区块,避免用户困惑。


三、大模型动态集成:让选择“无感而智能”

AI 模型不是越多越好,而是要默认最优 + 动态适配

🔧 真实代码实现

1.加载模型与语种字典
// 加载大模型列表 const loadLargeModelDictionary = async () => { const response = await findLargeModelDictionary({ keyword: '' }); largeModelList.value = response.data; if (largeModelList.value.length > 0) { const firstModel = largeModelList.value[0]; selectedModelId.value = firstModel.id; await loadLargeModelLanguageSupport(firstModel.id); // 关键:联动语种 } }; // 加载某模型支持的语种 const loadLargeModelLanguageSupport = async (modelId: string) => { const response = await findLargeModelLanguageSupport({ largeModelId: modelId }); languageSupportList.value = response.data; };
2.行业领域初始化
const loadIndustrySectorDictionary = async () => { const response = await findIndustrySectorDictionary({ keyword: '' }); industrySectorList.value = response.data; // 业务逻辑:若默认为 'general',则跳过 if (defaultIndustrySector.value === 'general' && industrySectorList.value.length > 1) { defaultIndustrySector.value = industrySectorList.value[1].code; } };
3.Ant Design Vue 下拉框绑定
<!-- 模型选择 --> <a-select v-model:value="selectedModelId" style="width: 100%" @change="handleModelChange" > <a-select-option v-for="item in largeModelList" :key="item.id" :value="item.id" > {{ item.name }} </a-select-option> </a-select>

四、SSE 流式翻译:用fetch-event-source实现“打字机效果”

这是体验升级的核心!我们使用@microsoft/fetch-event-source替代原生EventSource

🔧 完整流式翻译实现(结合你的项目结构)

import { fetchEventSource } from '@microsoft/fetch-event-source'; // 存储控制器,用于取消请求 let abortController: AbortController | null = null; const handleTranslate = async () => { if (isTranslating.value) return; // 重置结果 translationResult.value = ''; isTranslating.value = true; // 创建 AbortController abortController = new AbortController(); const params = new URLSearchParams({ largeModelId: selectedModelId.value, sourceLangCode: selectedSourceLangCode.value, targetLangCode: selectedTargetLangCode.value, industrySector: defaultIndustrySector.value, enableDeepThinking: String(enableDeepThinking.value), content: sourceLanguageText.value.trim(), }); try { await fetchEventSource(`/api/v1/large-model/translate/stream?${params}`, { method: 'GET', headers: { 'Authorization': `Bearer ${getToken()}`, // 从 Pinia 或 localStorage 获取 }, signal: abortAssistant.signal, // 支持取消 onmessage(event) { if (event.data) { translationResult.value += event.data; nextTick(() => { scrollToBottom(); }); } }, onclose() { isTranslating.value = false; }, onerror(err) { console.error('SSE Error:', err); message.error('翻译服务异常,请稍后重试'); isTranslating.value = false; abortController?.abort(); // 主动关闭 }, }); } catch (error) { if (abortController?.signal.aborted) { console.log('翻译已取消'); } else { message.error('连接失败'); } isTranslating.value = false; } }; // 取消翻译 const cancelTranslation = () => { if (abortController) { abortController.abort(); isTranslating.value = false; message.info('翻译已取消'); } };

🔧 自动滚动到底部

const scrollToBottom = () => { const container = document.querySelector('.translation-result-content'); if (container) { container.scrollTop = container.scrollHeight; } };

💡为什么不用 WebSocket?

    • SSE 是单向流(服务端 → 客户端),完美匹配“AI 生成文本”场景
    • fetch-event-source提供Promise 风格 API,更符合现代前端习惯

五、工程化亮点:13年经验的沉淀

✅ 1.响应式布局(PC/Mobile 适配)

const updateMainHeight = () => { const mainEl = document.querySelector('.main') as HTMLElement; if (!mainEl) return; if (isMobile.value) { mainEl.style.minHeight = '100vh'; mainEl.style.height = 'auto'; } else { mainEl.style.height = '100vh'; mainEl.style.minHeight = 'auto'; } };

✅ 2.内存清理(防止泄漏)

onUnmounted(() => { if (abortController) { abortController.abort(); } window.removeEventListener('resize', checkIsMobile); });

✅ 3.防重复提交 + 加载状态

<a-button type="primary" :loading="isTranslating" @click="handleTranslate" :disabled="!sourceLanguageText.trim()" > {{ isTranslating ? '翻译中...' : '开始翻译' }} </a-button>

结语:前端的价值,在“AI 与人之间”

这个项目让我确信:AI 时代,前端工程师的不可替代性在于“体验设计”

    • 我们用fetch-event-source把冰冷的 token 流变成温暖的“打字机”;
    • 我们用 Ant Design Vue 让复杂配置变得简单;
    • 我们用状态机管理 OCR 的每一步,不让用户迷失。

如果你也想从“切图仔”转型为“AI 应用架构者”,不妨从一个流式翻译工具开始。技术会过时,但解决问题的能力永远稀缺

项目技术栈:Vue 3.4 + Vite 5 + TypeScript + Ant Design Vue 4 + fetch-event-source
代码来源:本文所有逻辑均来自实际生产项目(已脱敏)
互动:你用过fetch-event-source吗?欢迎分享你的 SSE 实践!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/24 22:06:27

20 GNOME Extensions To Perfectly Balance GNOME

GNOME is one of the most controversial Linux desktops out there, but luckily, you can remove a bit of that controversy by adding GNOME extensions to your desktop for extra functionalities. These extensions serve as “addons” that you can easily install a…

作者头像 李华
网站建设 2026/2/27 7:46:59

信赖的广州太赫兹足疗仪源头厂家哪个公司好

随着健康消费升级&#xff0c;太赫兹足疗仪因深层养生的特性成为养生市场的热门品类&#xff0c;不少中小品牌、创业者在寻找源头厂家时&#xff0c;常陷入“技术不足、代工繁琐、合规存疑”的困境。在广州&#xff0c;广州市浩能电子科技有限公司&#xff08;简称浩能&#xf…

作者头像 李华
网站建设 2026/2/28 0:26:08

Python Web框架的首选:FastAPI讲解

文章目录一、FastAPI 是什么&#xff1f;二、为什么 FastAPI 会火&#xff1f;2.1 性能接近 Node / Go2.2 类型即文档&#xff0c;文档即接口2.3 内置 Swagger / ReDoc三、一个最小 FastAPI 应用3.1 安装3.2 创建 main.py3.3 启动服务四、请求参数详解4.1 路径参数4.2 Query 参…

作者头像 李华
网站建设 2026/2/25 6:03:34

InVivoMAb Anti-Mouse CD4:从基础免疫研究到转化医学应用的科研利器

在免疫学研究领域&#xff0c;抗体试剂是探索细胞功能、信号通路和疾病机制的关键工具。其中&#xff0c;针对小鼠CD4分子的单克隆抗体&#xff08;InVivoMAb anti-mouse CD4&#xff09;因其高特异性与强效中和能力&#xff0c;已成为众多科研人员的首选。作为该领域的领先品牌…

作者头像 李华