项目问答
面试中围绕项目经历展开回答的亮点、问题与答题素材汇总
#type / resource
#status / evergreen
#life / work
#topic / interview
[!info] related notes
项目问答
这是一份为你量身定制的面试复习笔记。我把你简历上那些“高大上”的总结,和你在开发日记里踩过的坑、写过的逻辑一一对应了起来。
面试的时候,面试官最喜欢问的就是:“你当时是怎么想的?” 和 “你遇到了什么困难,是怎么解决的?” 你可以把这份笔记当成你的“面试题库”和“故事大纲”,直接背诵和理解。
🚀 面试实战复习笔记:项目核心亮点解析
🎯 项目一:OLP 在线学习平台
亮点 1:独立负责 AI 知识管理系统
- 简历原文:复用并改造大模型对话(Chatbot)组件,实现流式对话、自动提取摘要及标签打标功能;实现各类生成与上传文档的富文本渲染、在线预览及流式下载功能,完善管理端的批量审批与管理链路。
- 业务背景:业务需要一个能利用 AI 生成知识并管理的闭环系统,分为用户端(生成和沉淀)和管理端(审批和管理)。
- 你的具体实现(怎么做的):
- 复用组件:并没有从零手写,而是聪明地把系统里原有的 Chatbot 聊天页面抽离出来进行改造,复用了其基础 UI。
- 接口对接闭环:独立跑通了从“创建新会话 -> 聊天生成回答 -> 获取/修改会话标题 -> 保存知识文档”的一整套复杂 API 链路。
- 文档流转:管理端增加了按类型(生成/上传)的条件筛选,并写了批量删除、批量拒绝发布的操作。对接了下载接口,解决了非 PDF 附件下载失败的 bug,并实现了文档预览。
- 💡 面试官可能会问:
- Q:你在做这个模块时遇到了什么坑?
- 回答参考:“主要是业务逻辑的闭环比较繁琐。比如最初生成的文档需要申请才能下载,我后来根据业务需求优化逻辑,让用户在生成页面直接下载,优化了体验。还有就是管理端复用动态路由时遇到过子组件无法渲染的报错,通过梳理路由配置解决了。”
- Q:你在做这个模块时遇到了什么坑?
亮点 2:EDP(员工发展计划)模块开发
- 简历原文:开发多维度的推荐学习内容搜索,并实现手工更新与重算 AI 匹配度的交互逻辑。
- 业务背景:公司需要一套将“岗位所需技能”与“已有课程”进行 AI 匹配的系统。
- 你的具体实现(怎么做的):
- 复杂的搜索与展示:实现了按技能精确搜索、Title模糊搜索、匹配度范围精确搜索等多个维度的复合查询。
- AI 匹配交互闭环:实现了未匹配课程的弹窗展示,允许用户手动调用 AI 接口一个个去 Match(匹配);对于已经匹配过的,增加了一个重算按钮,调用 AI 得出新匹配度和原因后,需要用户点击 Confirm(确认)才能更新入库。
- JD 生成器优化:在 Chat 页面展示完整的职位层级路径(部门 - 子部门 - 岗位 - 编码),处理了超长单行省略和悬浮 Tooltip 完整显示。
亮点 3:复杂组件状态管理优化(高含金量 ⭐️)
- 简历原文:修复管理端人员列表中因接口分页导致的“跨页选中状态丢失”缺陷,结合 isSettingSelection 锁机制,实现数据无缝翻页与表单回填。
- 业务背景:在 Element Plus 的表格中勾选了第 1 页的几个人,翻到第 2 页再翻回来,第 1 页勾选的人全没了(状态丢失)。
- 你的具体实现(怎么做的):
- 三重状态维护:你在本地维护了三个关键数组:
所有已选用户ID、当前页面用户ID、当前页选中的用户ID。 - 状态同步逻辑:每次触发
selection-change,先更新“当前页选中项”,接着从“全局选中项”中剔除所有“当前页面的用户”,最后把最新的“当前页选中项”塞回全局,实现精准同步。 - 核心锁机制(高光点):你发现翻页请求新数据后调用
setTableSelected(代码回显勾选)时,会意外触发原生的handleSelection事件,导致状态被误清空。你巧妙地加了一个isSettingSelection的布尔值锁,回显时上锁跳过原生事件,完美解决死循环冲突。 - 数据结构优化:原本选中组件只给父组件传 ID 数组,但上传接口需要完整的用户信息。你修改了逻辑,直接透传完整 User 对象,避免了父组件需要再次去该页查找数据的尴尬。
- 三重状态维护:你在本地维护了三个关键数组:
🎯 项目二:DDCC 档案管理与线上协作系统
亮点 1:高精度报表打印模块重构(最高含金量 ⭐️⭐️⭐️)
- 简历原文:引入 vue-print-next 结合 CSS Paged Media 规范实现基于纯 DOM 的浏览器原生打印。利用 CSS @page 和 break-inside 属性实现数据表的智能自动分页;通过 position: fixed 实现动态签批表格在每一页底部的完美重复渲染。
- 业务背景:系统需要打印带有“正文表格 + 底部签名表”的审批单。老代码用的是
html2canvas截图方案,不仅打印出来模糊,而且表格一长就被拦腰截断,更要命的是签名表只能在最后一页显示,无法每页重复。 - 你的具体实现(怎么做的):
- 技术选型推翻:你调研了 Canvas切片、JS手动截取数据分页等方案,最终决定抛弃 Canvas,采用纯 DOM 原生打印方案,引入
vue-print-next库。你还尝试过引入paged.js库,但发现其增加了额外复杂度和依赖加载风险,最终仅凭强大的原生 CSS 搞定了。 - 智能防截断:给表格的
tr加上了break-inside: avoid; page-break-inside: avoid;,把分页的数学计算直接交给浏览器底层引擎处理,不再用 JS 算高度。 - 签名表跨页重复(神来之笔):你利用了打印环境(
@media print)下一个极少有人知道的特性——给底部签名区域加上position: fixed; bottom: 0;,浏览器打印时就会自动把它渲染在每一页的最下面。 - 解决层叠 Bug:为了防止固定的签名表挡住正文表格,你给数据表的容器加上了对应的
margin-bottom: 140mm预留出物理空间。同时在全局注入了<style>强行把 body 的overflow设为visible,解决打印预览只有一页的 Bug。
- 技术选型推翻:你调研了 Canvas切片、JS手动截取数据分页等方案,最终决定抛弃 Canvas,采用纯 DOM 原生打印方案,引入
- 💡 面试官可能会问:
- Q:为什么不用 paged.js?
- 回答参考:“我早期调研过 paged.js,但它需要注入 polyfill 脚本,在
vue-print-next提取 DOM 去 iframe 渲染时容易因为脚本加载时序导致白屏。后来我钻研了 CSS Paged Media 规范,发现依靠纯原生 CSS(@page和fixed定位)就已经能完美覆盖我们的业务需求,大道至简,性能更好。”
- 回答参考:“我早期调研过 paged.js,但它需要注入 polyfill 脚本,在
- Q:为什么不用 paged.js?
亮点 2:BBB 视频会议系统二次开发
- 简历原文:在测试服务器的 Docker 环境下,对基准版 BigBlueButton 的前端仓库进行定制开发。将原有的 Smart Caption 从独立悬浮窗重构集成至页面左侧抽屉面板。
- 业务背景:开源会议系统 BBB 的实时字幕功能原本是一个突兀的悬浮弹窗,用户体验很差,产品要求把它收纳到左侧的侧边栏里。
- 你的具体实现(怎么做的):
- 架构重构:修改了 React 源码中的
actions-bar/component.jsx,增加新的功能切换按钮,并在左侧导航栏(Messages, Notes 同级)新增了 “Translation” 模块。 - UI 降本增效:没有硬画样式,而是去研究了它本身的“Public Chat(公共聊天)”面板源码,把它的头部、消息流容器、人名排列的 CSS 结构直接复用到了智能字幕面板上,保证了风格极其统一。
- 搞定 Docker 运维难题:开发时发现修改字幕微服务的代码(
bbb-transcription-controller)不生效。你亲自去改了docker-compose.yml,把它从拉取线上镜像改成了读取本地源码构建。期间还遇到了阿里云镜像 403 导致构建死锁的报错,你排查出是多阶段构建缓存脏了,用docker builder prune -f清理了 90多G 缓存,成功修复构建链。
- 架构重构:修改了 React 源码中的
- 💡 面试官可能会问:
- Q:你一个前端,为什么要去碰 Docker?
- 回答参考:“这个项目是高度耦合的微服务架构。前端(HTML5客户端)是作为 Nginx 容器的上下文被一起打包的。为了验证我的 React 代码修改,我必须掌握如何局部编译对应的容器。这让我对前端工程化和容器化部署有了更深的理解。”
- Q:你一个前端,为什么要去碰 Docker?
📝 面试沟通技巧总结
- 聊 OLP 状态管理时:重点突出你的思维严谨性(懂得维护三套状态、懂得用锁机制解决原生事件冲突)。
- 聊 DDCC 打印重构时:重点突出你的技术深度和解决问题的能力(调研了多种方案,最终找到了成本最低、性能最好的原生 CSS 方案)。
- 聊 Docker/BBB 时:重点突出你的综合素养和学习能力(前端不只写页面,还能改 React 源码、调 Docker 脚本、处理环境报错)。