当前位置: 首页 > news >正文

美团面试:为什么要用分布式缓存?本地缓存呢?多级缓存一致性如何保证?掀

从 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 生态无缝集成

安装:

npm install @microsoft/fetch-event-source

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

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

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

1. 系统配置加载(含文件大小限制)

// 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 下拉框绑定

v-model:value="selectedModelId"

style="width: 100%"

@change="handleModelChange"

>

v-for="item in largeModelList"

:key="item.id"

:value="item.id"

>

{{ item.name }}

四、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. 防重复提交 + 加载状态

type="primary"

:loading="isTranslating"

@click="handleTranslate"

:disabled="!sourceLanguageText.trim()"

>

{{ isTranslating '翻译中...' : '开始翻译' }}

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

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

我们用 fetch-event-source 把冰冷的 token 流变成温暖的“打字机”;

我们用 Ant Design Vue 让复杂配置变得简单;

我们用状态机管理 OCR 的每一步,不让用户迷失。该读粤俟

http://www.jsqmd.com/news/609502/

相关文章:

  • STM32CubeMX+Keil联合开发环境配置全流程(附网盘资源)
  • 手把手教你用Zynq-7020部署YOLOv4-Tiny:从权重处理到板级验证的全流程指南
  • DotNetPy:现代.NET 与 Python 互操作 实战指南孛
  • ARM内存操作指令实战:从LDR、STR到LDM、STM的嵌入式开发应用
  • RTL8211F(I)与RTL8211FD(I)选型及电路差异详解:你的千兆网口该用哪一款?
  • .NET 9 容器化配置最佳实践(K8s生产环境验证版)
  • [ACM MM 2025] MIRA:多模态智能检索与增强驱动的医学诊断辅助框架
  • MARC,mm02/01/03,MM17增强
  • 全能图像工具ImageGlass:免费开源的图像浏览颠覆体验
  • 别再只用train/val了!用K折交叉验证给你的YOLOv8自定义数据集做个‘全面体检’
  • Git 二分法精准定位 Bug:git bisect 手把手实战教程,极速锁定缺陷提交,调试效率翻倍
  • 主构造函数到底该不该用?C# 13新语法落地避坑清单,含6个生产环境崩溃案例与修复补丁
  • 行人重识别(ReID)实战:从零搭建多摄像头追踪系统(附Python代码)
  • ZYNQ+OV5640+VDMA+HDMI视频链路搭建实录:从摄像头采集到实时显示
  • 别再死磕实物了!用Proteus 8.13仿真STM32矩阵按键,5分钟搞定硬件验证
  • 58:Agentic在金融风控中的应用实战
  • 英雄联盟智能助手:革新游戏体验的全方位工具集
  • 测试基本功之刷写ecu版本实操指导-ECU测试实践记录
  • Agent如何帮助企业提升客户满意度?2026年企业智能自动化的范式转移与落地实践
  • 幂等矩阵:从投影算子到机器学习中的隐藏应用
  • 基于mpc(最优控制)的车辆自适应巡航控制(acc),模型预测控制,通过carsim与matl...
  • 6 个开合跳的好处,第 3 个很多人不知道
  • 避坑指南:VGA电路设计中那些教科书没讲的细节(以440MHz案例为例)
  • 民办二本的未来规划
  • 论文与代码轻松搞定:8款AI毕业设计工具推荐
  • Blazor WebAssembly性能突破真相:2026新AOT编译器实测对比(冷启动提速3.8倍源码剖析)
  • SDD基于规范编程-OpenSpec及SuperPowers沙
  • PHP 8.9联合类型与泛型增强深度解析(2024唯一全链路适配手册)
  • 告别OpenNI:在Ubuntu 24.04上为树莓派5配置Astra SDK(以乐视体感摄像头为例)
  • 【K8s】【解决问题】---- 错误 DRV_AS_ROOT: The “docker“ driver should not be used with root privileges.