Skip to content

EMI智慧SOP看板(安灯)— 速记版

📋 速记表(面试前快速扫)

一句话结论关键词
Q1事件驱动消息+45s心跳,但自动重连被注释事件驱动 心跳 重连被注
Q2Web Serial 控塔灯,0x协议,错误分支 catchWebSerial baud9600 私有协议
Q3MediaDevices 多摄像头,Canvas 取帧转 BlobenumerateDevices drawImage toBlob
Q4微信 OAuth 扫码绑定,URL query/hash 分工扫码绑定 OAuth hash路由
Q5v-scale-screen 等比缩放,键盘弹顶特殊处理等比缩放 transform 键盘
Q6Pinia websocket store + flags 布尔位flags watch storeToRefs
Q7多环境工厂函数 + ip.json工厂函数 环境 分网
Q8自研 MediaViewer 图+视频混播从零 viewer 视频混播
Q9SOP 树形模板 + SortableJS 行拖拽树形 拖拽 transform冲突

Q1: WebSocket 实时双向通信

面试官可能问:WebSocket 怎么设计的?断线怎么办?

🗣️ 口述稿

WebSocket 是通信中枢,事件驱动。定义几类消息:incomingRequest/pendingRequest(来新活提示跳处理页,5 秒倒计时自动跳)、towerLight(解析成十六进制指令控塔灯)、serialPort(串口状态)、heart(45 秒心跳)、close(被挤下线)。URL 拼工位 ID,后端就知道把请求推给哪个工位。

💡 关键词提示事件驱动 45s心跳 工位ID

⚠️ 备注

  • [重要] README/简历写"自动重连",但代码 reconnect()onclose 里是被注释掉的,实际是"弹窗确认后 location.reload 整页刷新"。别吹已实现自动重连
  • 被问为什么注释:自动重连会和"用户切工位"冲突,旧连接弹回来带旧工位身份乱跳,所以宁可让用户确认 reload 也不脚本乱来
  • 重连那段确实写了指数退避(1s→30s)思路和 reconnect() 方法,但没启用——可当"做过又踩坑暂缓"

追问①:为什么当初注释掉自动重连?

自动重连和用户切工位冲突,若换工位后旧连接自动回来带旧身份乱跳,所以宁可用户确认 reload。

追问②:要改回自动重连注意什么?

先分"真断线"还是"主动切工位",用 flags.webSocketUserIdChanged 区分:用户 ID 变了就不重连、没变才重连。这个区分条件讲出来说明不是无脑加回。


Q2: Web Serial + PLC 塔灯

面试官可能问:浏览器怎么控制塔灯?

🗣️ 口述稿

用 Web Serial API 做浏览器↔PLC 串口通信。navigator.serial.requestPort() 弹选择器选 USB,open({baudRate:9600}) 打开,writable.getWriter() 写十六进制指令。私有协议两位十六进制:第一位操作(1亮/4闪/2灭)、第二位目标(1红/2黄/4绿/8蜂鸣),如 11=红灯亮、42=黄灯闪。

💡 关键词提示WebSerial baud9600 私有协议 getWriter

⚠️ 备注

  • 难点在错误处理:open() 报错五花八门(Access denied/port already open/open in progress/device failed),全做分支 catch 给中文提示并引导回设置页+不再提示
  • 为什么不用 Node serialport:纯前端 SPA、无 Electron 主进程,Web Serial 是 Chrome 89+ 原生零依赖
  • [需自行确认]:"延迟低于 500ms"代码没埋点,按体感讲别当实测
  • 只 Chrome 支持是最大局限,非 Chrome 就得 Electron+serialport

追问①:为什么不用 Node serialport?

纯前端 Vue SPA 没主进程,Web Serial 是 Chrome 原生零依赖;转折点是它只 Chrome 支持,客户换浏览器就废,后续该评估 Electron。

追问②:非 Chrome 浏览器怎么办?

直接不支持,我用 'serial' in navigator 先判断给提示。真要可靠得上 Electron+serialport,但当时够用。边界说清比吹稳好。


Q3: 多摄像头 + 拍照上传

面试官可能问:多摄像头怎么管理、拍照怎么上传?

🗣️ 口述稿

用 MediaDevices:enumerateDevices() 列出视频输入过滤 videoinput,切换时先 stop() 旧流再按新 deviceId 重建。拍照 video→Canvas drawImage 取帧→toDataURL 预览→toBlob 转二进制→FormData 上传。

💡 关键词提示enumerateDevices drawImage toBlob FormData

⚠️ 备注

  • 为什么经 Canvas 不直接截 video:drawImage 精确控尺寸、toBlob 可指定压缩格式/质量、为裁剪标注留余地
  • 体验细节:加载 Loading、失败按"未找到/权限拒/其他"分类+刷新、拍照后变"重拍/确认上传"
  • 权限被拒和真是没设备要区分文案

追问①:getUserMedia 权限被拒怎么提示?

区分"用户拒绝"和"真没设备",分别给权限类和设备类文案,不是一把 try-catch 完事。

追问②:多路同时开会不会压垮平板?

会,切换时不关旧流多路很伤,我尽量同一时刻只开一路并回收流,有内存意识。


Q4: 动态二维码 + 微信绑定

面试官可能问:微信扫码绑定怎么实现?

🗣️ 口述稿

用 qrcodejs2 生成二维码,URL 拼微信 OAuth:redirect_uri=...&response_type=code&scope=snsapi_userinfo&state=...#wechat_redirect,工位信息放 query、路由放 hash。用户扫码→微信回调带 code 回 /wechat→前端取 code+工位信息调 /andon/wechat/bind→之后能在微信收推送。

💡 关键词提示OAuth扫码 redirect_uri query/hash分工

⚠️ 备注

  • 最有含金量:redirect_uri 怎么同时塞工位信息和路由——项目用 createWebHashHistory,微信只认 ? 前 path 忽略 #,所以工位放 query、路由留 hash 两边不丢
  • [需自行确认]:"从 5 分钟缩到 20 秒"是体验描述没精确计时,别当硬数据

追问①:为什么工位信息放 query、路由留 hash?

项目路由在 hash 后,微信只认 ? 前 path 忽略 #。工位放 query、路由留 hash,两边都不丢。

追问②:绑定以前为什么 5 分钟?

以前人工纸质登记再管理员录入;现在扫码带 openid、表单预填、补手机号姓名就确认。


Q5: 工业平板屏幕适配

面试官可能问:分辨率五花八门怎么适配?

🗣️ 口述稿

用 v-scale-screen 等比缩放,固定设计 1080×1920(竖屏)。监听容器 resize,按实际/设计比例算 transform:scale() 等比。特殊处理软键盘弹出把页面顶上去的问题:给 v-screen-box 设 minWidth/minHeight 为实际屏尺寸,防键盘 resize 挤压。

💡 关键词提示等比缩放 transform:scale 键盘顶起

⚠️ 备注

  • 最值得讲:键盘弹出触发 resize 导致缩放乱跳——移动端不监听 resize、只在 DOM 加载完设一次尺寸,专避键盘 resize
  • 追问会套到 transform scale 后鼠标坐标反算(同数字孪生/v-zoom-up 同款坑)
  • 为什么不用 rem:等比缩放保证逐像素一致不破版,rem 是自适应非等比

追问①:transform scale 后点击坐标怎么对?

要用 scale 系数反算真实坐标,这和数字孪生、v-zoom-up 是同一个坑,说明你这方面有连续心智。

追问②:为什么不用 rem?

等比缩放保证和设计稿逐像素一致绝不破版,rem 是自适应不是等比,大屏要的是所见即得。


Q6: Pinia WebSocket Store

面试官可能问:把 WS/串口/消息路由塞进一个 store 怎么组织?

🗣️ 口述稿

用 Pinia Composition API 风格(defineStore+setup)写 webSocket store 当状态中心:管 ws 实例、serialPort、flags 布尔位、定时器引用;方法有 webSocketConnect/sendMessageToSerialPort/openSerialPortConnection 等;onmessage 按 type 分发到统一入口。

💡 关键词提示defineStore setup flags 统一分发

⚠️ 备注:为什么 flags 一个 ref 包一组布尔位——为了 storeToRefs 解构后前端 watch(flags.value.refreshRequestMap) 精确监听某一位。

追问①:页面卸载怎么清理?

window.onbeforeunload 里 ws.close()+清心跳/重连定时器+设 isUnloading 防止 onclose 触发重连逻辑。

追问②:为什么消息走 store 方法不走全局改?

统一收敛到入口,方便在消息路由处统一日志/状态/分发,不散在组件。


Q7: 多环境 API 配置

面试官可能问:开发和线上 API 怎么区分?

🗣️ 口述稿

src/api/utils.ts 封装四类工厂函数:baseURLApi(REST)、wsApi(WebSocket)、baseURL(页面基地址)、wechatAppId;内部 switch 分 dev/test/prod/demo/trial 五种环境。开发走本机/局域网 IP、线上走 goomaker。

💡 关键词提示工厂函数 五环境 分网IP

⚠️ 备注:为什么 API 和页面 baseURL 分开——前端静态在 /andon-system/、API 独立后端走 /andon-test-api/、开发后端可能在别人本机。

追问①:ip.json 干嘛用?

团队协作时后端 IP 不同,抽到 gitignore 的 ip.json 每人填自己的,不用改代码。这体现全栈团队意识。


Q8: 自定义 MediaViewer

面试官可能问:图片/视频预览为什么自己写?

🗣️ 口述稿

基于 el-image-viewer 源码改造支持图片+视频混播:el-image-viewer 只支持图片,安灯类型说明要视频。urlList 每项带 type、v-show 切 img/video;teleport to body + z-index 9999 避免父容器裁切。

💡 关键词提示自研 图+视频混播 teleport

⚠️ 备注:为什么不用现成 viewer.js/photoswipe——都不支持视频且包体积敏感(viewer 带 jQuery、photoswipe 偏重);自研零依赖但工作量+责任自担。

追问①:自研有没有代价?

有——自己维护键盘/滚轮/拖拽交互,工作量不小、边界处理不如现成库。自研=控体积但责任自担,成熟。


Q9: SOP 模板 + 拖拽排序

面试官可能问:SOP 模板和排序怎么实现?

🗣️ 口述稿

安灯类型按车间分不同模板(织造/印染各一套),用树形 templateTableData + el-table 的 tree-props 展示;行排序用 SortableJS,handle 只允许专门手柄拖,拖完调后端更新 oldIndex→newIndex。

💡 关键词提示树形模板 SortableJS transform冲突

⚠️ 备注

  • 最值钱的真实坑:SortableJS 的 ghost 元素在 v-scale-screen 的 transform:scale 环境下定位异常,用全局 CSS 覆盖 sortable-chosen/ghost 为 position:relative!important 修
  • 为什么不用 EP 自带:EP 只有列拖拽没行拖拽,SortableJS 是标准方案还能编辑态禁拖

追问①:排序为什么不用 Element Plus 自带?

EP 只有列拖拽没行拖拽;SortableJS 是标准方案、动画好、兼容好,还能用 disabled/pointer-events-none 在编辑状态禁拖。


🎙️ 行为面试

为什么做这个项目?

公司给纺织厂做数智化改造。传统安灯靠物理按钮+对讲机:慢、没记录、无法追溯。老板要做数字化版,工人点平板发起请求、处理人实时收到、全程有记录。我从 0 独立搭前端,后端 Java 同事配合。

💡 关键词安灯数字化 慢无记录 独立前端

⚠️ 备注:后端是 Java,不是全栈项目这个,别答成"我也写了后端"。


最大难点?

  1. Web Serial 调试——浏览器控串口冷门、资料少报错不友好,我在产线枚举各种异常做成分类引导
  2. v-scale-screen 和 SortableJS 的 transform 冲突,调几小时定位到 ghost 的 position 问题

💡 关键词串口异常枚举 transform碰拖拽

⚠️ 备注:挑 1-2 个"坑+怎么磨"讲,别报菜名。


遗憾/弯路?

  1. WebSocket 自动重连被我注释掉了——遇工位切换冲突降级成弹窗确认+整页刷新,坑没回来收
  2. 没写单元测试(WS/WebSerial 要 mock 环境没搭)
  3. 强依赖 Chrome(Web Serial 只有 Chrome)+ 推送只微信有频率限制,并发大要加页面播报兜底

💡 关键词重连被注 零测试 依赖Chrome

⚠️ 备注:第 1 条呼应 Q1 修正,讲它比掩着加分。


怎么跟后端协作?

后端 Java 写的。我先和后端定死 WebSocket 消息结构({type,msg})和 REST 接口定义,开发用本地 Mock+Vite 代理联调。先静态契约后联调是标准姿势。

💡 关键词先契约后联调 Mock+Vite

⚠️ 备注:讲"连接口含义先定、再各自开发"这套协作节奏。


为什么叫安灯?

Andon 来自丰田生产模式——产线拉绳亮灯、班组长看到就处理。我们把它数字化:拉绳变成点平板、请求变成实时通知。既讲业务又讲技术,一箭双雕。

💡 关键词丰田Andon 拉绳→点平板

⚠️ 备注:短,但讲"业务+技术各一半"很完。


🃏 极简速记卡(面试前5分钟看)

  • Q1 WebSocket:事件驱动+45s心跳,但自动重连被注释
  • Q2 塔灯:WebSerial baud9600,私有协议,错误分支
  • Q3 摄像:enumerateDevices+Canvas取帧toBlob
  • Q4 绑定:OAuth扫码,工位query路由hash
  • Q5 适配:等比缩放+键盘弹顶处理
  • Q6 store:Pinia websocket+flags布尔位
  • Q7 环境:工厂函数五环境+ip.json
  • Q8 viewer:自研图+视频混播
  • Q9 SOP:树形模板+SortableJS拖拽
  • 行为 动机:安灯数字化;难点:串口异常+transform冲突;遗憾:重连被注+零测试

上一篇:04-惠东移动(微信小程序) 下一篇:06-EMI数字孪生平台

前端开发工程师 · 面试准备