代码地址:点这里
注意分支

智能体工作流平台 - 面试SOP标准回答
目录
- 项目介绍(1-3分钟自我陈述)
- 常见问题标准回答
- 技术深挖问题应对
- 压力面试应对
- 行为面试问题
一、项目介绍(1-3分钟自我陈述)
版本1:1分钟精简版
"我做了一个智能体工作流的可视化编排平台,类似于Coze或者n8n那种。
项目背景是这样的:现在LLM应用越来越多,很多场景需要把多个AI能力串起来用,比如先用GPT分析内容,再根据结果决定要不要下载,最后再做数据处理。传统方式要写很多代码,维护起来也麻烦。
所以我就做了这个平台,用户可以通过拖拽的方式来编排工作流。技术栈用的Vue3和LogicFlow,我自己实现了一套工作流执行引擎,支持条件分支、并行执行这些。还集成了DeepSeek、ChatGPT这些LLM的API。
最大的难点是LogicFlow的自定义节点注册,官方文档不全,我摸索了好久才找到解决方案。现在平台功能基本完善,支持100多个节点的工作流编排。"
版本2:2-3分钟详细版
"好的,我介绍一下这个项目。
项目背景
这个项目叫AgentFlow,是一个智能体工作流的可视化编排平台。做这个项目的契机是我之前在尝试用ChatGPT API做一些自动化任务时发现,如果要串联多个步骤,比如先分析文本、再根据结果做决策、最后调用其他服务,就得写一堆代码,而且流程稍微复杂一点就很难维护。
我就想能不能做一个像Coze那样的可视化工具,让大家通过拖拽就能搭建AI工作流。
技术实现
技术栈我选的Vue3配合LogicFlow。Vue3是因为我对它比较熟悉,而且Composition API很适合做这种复杂状态管理的应用。LogicFlow是一个开源的流程图库,但它主要是给BPMN用的,要改造成Agent工作流还是有不少坑要踩。
整个项目分四个核心模块:
第一个是可视化编辑器。这块主要是基于LogicFlow实现,但遇到一个大坑就是自定义节点注册。LogicFlow 2.0版本的API跟1.0完全不一样,文档又不全,我尝试了好几种方案最后才找到解决办法。
第二个是工作流引擎。这个是我自己实现的,支持有向无环图的遍历,可以处理条件分支、并行执行、子流程嵌套这些复杂场景。执行过程中会维护一个Context上下文,实现节点之间的数据传递。
第三个是Agent执行器。这块我做了一个统一的抽象层,支持LLM调用、HTTP请求、视频下载等多种类型。特别的是我实现了模拟模式,用户不填API Key也能跑通流程,方便测试。
第四个是调试系统。支持断点、单步执行、实时日志这些功能,对于排查工作流问题很有用。
技术难点
最大的难点有两个:
一个是LogicFlow的节点注册问题。我原本想直接继承它的基类来自定义节点,但一直报错说基类是undefined。查了很久才发现2.0版本的基类获取方式变了。最后我换了个思路,用LogicFlow的内置节点类型,然后在properties里存业务类型,在业务层做映射。
另一个是状态管理。因为要区分编辑态和运行态,如果用同一个状态对象,调试时修改节点就会影响保存的数据。我的解决方案是运行前先深拷贝一份graphData,运行时操作副本,结束后再恢复。
项目成果
现在项目功能基本完整,写了20多个Vue组件,3000多行代码。支持100多个节点的工作流编排,实际测试下来性能还不错。我还写了详细的文档,包括使用指南、技术架构、API说明这些。
个人收获
通过这个项目,我对Vue3的响应式系统理解更深了,特别是watchEffect和computed这些API的使用场景。另外也积累了一些架构设计的经验,比如怎么做模块解耦、怎么设计可扩展的接口。还有就是集成第三方库时的问题排查能力提升了不少。"
二、常见问题标准回答
Q1: 为什么选择这个项目?
标准回答:
"主要有两个原因:
一是我对AI应用很感兴趣。这两年LLM发展很快,我一直在关注怎么把AI能力应用到实际场景中。之前用过Coze和Dify这些平台,觉得可视化编排这个方向很有价值,就想自己动手试试。
二是想提升前端技术能力。虽然我平时也写Vue,但大多是业务开发,没太多机会做复杂的架构设计。这个项目涉及到状态管理、工作流引擎、第三方库集成等,技术挑战性比较大,正好可以系统性地提升一下。
做完之后确实收获很大,不管是Vue3的掌握程度还是系统设计能力都有明显进步。"
Q2: 项目中遇到最大的困难是什么?如何解决的?
标准回答:
"最大的困难是LogicFlow的自定义节点注册问题。
问题描述: 我一开始想直接继承LogicFlow的CircleNode、RectNode这些基类来实现自定义节点,但一直报错'undefined is not a constructor'。查看堆栈信息也找不到明确的原因。
排查过程:
- 首先我怀疑是引入方式的问题,试了各种import写法,都不行
- 然后查官方文档,发现2.0版本的文档很不完整,自定义节点的例子基本都是1.0的
- 去看源码,发现2.0版本的基类结构确实改了,但没有清晰的迁移指南
- 在GitHub issues里翻了很久,有人遇到类似问题但没有明确答案
解决方案: 最后我换了个思路。既然自定义节点这条路走不通,那就用LogicFlow的内置节点类型,通过配置来实现业务需求:
- 用circle代表开始/结束节点
- 用rect代表Agent节点
- 用diamond代表条件分支
然后在每个节点的properties里存储customType字段,用来标识业务类型。在业务层做类型映射,根据customType来决定节点的行为。
这样既绕过了自定义节点的坑,又保持了代码的可维护性。
收获: 这个问题让我明白,遇到技术障碍时不要死磕一个方向,换个角度思考往往能找到更简单的解决方案。另外也意识到选择成熟稳定的技术栈的重要性。"
Q3: 项目的技术架构是怎样的?
标准回答:
"整体架构我是按照模块化的思路来设计的,主要分为四层:
展示层:
- 使用Vue3的Composition API开发
- 20多个组件,分为基础组件和业务组件
- 基础组件包括Toolbar、NodePanel、Canvas等
- 业务组件包括PropertiesPanel、DebugPanel等
状态管理层:
- 使用Pinia管理全局状态
- 分为两个Store:workflowStore和nodeStore
- workflowStore管理工作流数据、执行状态、日志等
- nodeStore管理节点类型定义、注册的Agent等
- 严格区分编辑态和运行态的状态
业务逻辑层:
- 工作流引擎(WorkflowEngine):负责执行工作流
- Agent执行器(RealAgentExecutor):负责执行具体的Agent
- LogicFlow配置器:负责初始化和配置画布
工具层:
- 表达式求值器
- 坐标转换工具
- 数据持久化工具
数据流向: 用户操作 → 触发组件事件 → 更新Pinia状态 → 状态变化触发视图更新 工作流执行 → 引擎遍历节点 → 调用Agent执行器 → 更新Context → 记录日志
为什么这样设计:
- 模块解耦:每个模块职责单一,便于维护和测试
- 状态集中:使用Pinia统一管理状态,避免组件间的耦合
- 可扩展:Agent执行器采用策略模式,新增类型很方便
- 可调试:执行过程中记录详细日志,便于排查问题"
Q4: 如果让你重新做这个项目,会做哪些改进?
标准回答:
"如果重新做,我会在以下几个方面做改进:
1. 引入TypeScript 当前项目用的纯JavaScript,虽然开发快,但类型安全没保障。特别是节点配置这块,不同类型的节点有不同的配置项,很容易出现拼写错误。如果用TypeScript,可以定义清晰的类型接口,编译期就能发现问题。
2. 完善测试 现在主要是手动测试,自动化测试覆盖率比较低。应该加入:
- 单元测试:用Vitest测试工具函数和业务逻辑
- 组件测试:用Vue Test Utils测试组件行为
- E2E测试:用Playwright测试完整流程
3. 优化工作流持久化 目前是用localStorage存储,数据量大了之后会有性能问题。可以改用IndexedDB,或者接入后端API,做版本管理和云端同步。
4. 增强错误处理 现在的错误处理比较简单,主要是try-catch加日志。应该:
- 定义统一的错误码体系
- 实现全局错误边界
- 提供更友好的错误提示
- 支持错误上报和监控
5. 性能优化
- 节点数量多时考虑虚拟渲染
- 大型工作流做懒加载
- 图数据做分页
- 使用Web Worker处理耗时计算
6. 国际化 代码里中文硬编码比较多,应该抽出来做i18n,支持多语言。
这些改进点是基于实际开发中遇到的问题总结出来的,如果有机会实践,能让项目更加完善。"
Q5: 工作流引擎是如何实现的?
标准回答:
"工作流引擎是这个项目的核心,我来详细说明一下实现思路。
核心数据结构: 工作流本质是一个有向图,我用邻接表来表示:
{
nodes: [{ id, type, properties }],
edges: [{ sourceNodeId, targetNodeId }]
}
执行算法: 采用基于栈的深度优先遍历:
- 找到开始节点,压入执行栈
- 从栈中取出节点执行
- 根据节点类型决定下一步:
- 普通节点:找到所有出边,把目标节点压栈
- 条件节点:根据表达式结果选择分支
- 并行节点:把所有分支节点都压栈
- 重复2-3直到栈为空
关键实现:
- Context上下文管理
this.context = {
'node-1': { output: '结果1' },
'node-2': { output: '结果2' },
lastOutput: { } // 最后一个节点的输出
}
每个节点执行完,把结果存到context,后续节点可以访问。
- 条件分支
const result = await executeConditionNode(node)
if (result.branch === 'true') {
// 找到true分支的边
} else {
// 找到false分支的边
}
- 断点支持
if (this.breakpoints.includes(node.id)) {
this.isPaused = true
return { paused: true }
}
- 单步执行
async stepOver() {
const node = this.executionStack.shift()
await this.executeNode(node)
// 不继续执行,返回控制权
}
难点处理:
- 循环检测:虽然理论上工作流应该是DAG,但用户可能画出循环。我加了一个visited集合,检测到重复访问就报错。
- 异步处理:节点执行都是异步的(调用API),用async/await保证顺序。
- 错误恢复:某个节点失败了不能让整个流程中断,要记录错误继续执行,或者根据配置决定是否继续。
性能考虑:
- 执行栈用数组实现,push/shift操作很快
- context只存必要的数据,避免内存占用过大
- 支持流式执行,不用等整个流程结束
这套引擎虽然简单,但足以支持大部分场景。如果要做商业化产品,还需要加入更多企业级特性,比如事务支持、补偿机制等。"
Q6: Agent执行器是如何设计的?
标准回答:
"Agent执行器我采用了策略模式来设计,主要考虑两点:可扩展性和灵活性。
架构设计:
class RealAgentExecutor {
constructor(node, context) {
this.node = node
this.context = context
this.config = node.properties
}
async execute() {
const type = this.config.agentType
switch(type) {
case 'llm': return await this.executeLLM()
case 'http': return await this.executeHTTP()
case 'video-download': return await this.executeVideoDownload()
// ...
}
}
}
核心功能:
- LLM调用 支持DeepSeek、ChatGPT、Claude三种。关键代码:
async executeLLM() {
const config = LLM_CONFIGS[this.config.llmProvider]
const response = await fetch(config.apiUrl, {
method: 'POST',
headers: { 'Authorization': `Bearer ${apiKey}` },
body: JSON.stringify({
model: config.model,
messages: [
{ role: 'system', content: systemPrompt },
{ role: 'user', content: prompt }
]
})
})
return response.json()
}
- 模拟模式 这个是我觉得比较巧妙的设计。用户不填API Key时,自动切换到模拟模式:
if (!apiKey) {
return {
success: true,
simulated: true,
output: '模拟的LLM响应...'
}
}
这样用户可以先测试流程,确认没问题再填真实API Key。
- 错误处理 API调用可能失败,我做了降级:
try {
// 真实调用
} catch (error) {
return {
success: true,
simulated: true,
output: '调用失败,返回模拟数据',
error: error.message
}
}
扩展性: 要新增Agent类型很简单:
- 在配置中加一个类型定义
- 在执行器中加一个方法
- 在UI上加配置表单
比如要加个Email发送Agent:
case 'email':
return await this.executeEmail()
async executeEmail() {
const { to, subject, body } = this.config
// 调用邮件API
}
优化点:
- 可以加个Agent插件系统,让用户自己注册Agent类型
- 支持Agent的链式调用
- 增加缓存机制,避免重复调用
- 实现流式输出,实时展示LLM响应
这个设计在简单够用的基础上,留了很好的扩展空间。"
Q7: 如何保证代码质量?
标准回答:
"我从几个方面来保证代码质量:
1. 代码规范
- 使用ESLint做静态检查,配置了recommended规则
- 用Prettier统一代码格式,团队协作时很重要
- 遵循Vue官方的风格指南,比如组件命名、props定义等
- 写详细的注释,特别是复杂逻辑的地方
2. 组件设计
- 遵循单一职责原则,一个组件只做一件事
- 区分容器组件和展示组件
- 合理拆分组件,避免单个组件过大(一般不超过200行)
- 使用Composition API时,把逻辑抽成可复用的hooks
3. 状态管理
- 用Pinia集中管理状态,避免组件间的props drilling
- 状态修改都通过actions,不直接修改
- 每个store职责明确,避免互相依赖
4. 错误处理
- 所有异步操作都有try-catch
- 用户操作加loading状态和错误提示
- 记录详细的日志便于排查问题
5. 性能考虑
- 合理使用v-if和v-show
- 列表渲染加key
- 避免不必要的响应式数据
- 大列表考虑虚拟滚动
6. 文档
- 写了详细的README和使用指南
- 核心模块都有注释说明
- 提供了快速开始的示例
虽然没有做很完善的测试,但通过这些规范,代码质量还是有保障的。如果是团队项目,我还会加上Code Review和CI/CD流程。"
三、技术深挖问题应对
Q8: Vue3的响应式原理是什么?你在项目中如何应用?
回答思路:
- 先简述Proxy原理
- 结合项目说明实际应用
- 提到遇到的坑和解决方案
标准回答:
"Vue3的响应式是基于Proxy实现的,跟Vue2的Object.defineProperty不同。
基本原理: 当你用reactive或ref创建响应式对象时,Vue会用Proxy包装这个对象。Proxy可以拦截对象的各种操作,比如get、set。当你访问对象属性时,Vue会收集依赖(track);当你修改属性时,Vue会触发更新(trigger)。
项目中的应用:
- 节点配置的响应式更新
const nodeProperties = ref({})
watch(selectedNode, (newNode) => {
nodeProperties.value = { ...newNode.properties }
})
当用户选中不同节点时,右侧配置面板会自动更新。这里我用了ref而不是reactive,因为要整个替换对象。
- 工作流数据的深度监听
watch(() => workflowStore.graphData, (newData) => {
lf.render(newData)
}, { deep: true })
graphData是个复杂对象,包含nodes和edges数组。用deep监听,任何嵌套属性变化都能捕获到。
踩过的坑:
- 直接修改props 一开始我在PropertiesPanel里直接修改props传过来的node对象,Vue给了warning。后来改成emit事件,由父组件更新。
- 响应式丢失 有次我这样写:
let { nodes, edges } = graphData.value
nodes.push(newNode) // 响应式丢失
应该直接操作graphData.value.nodes.push()
- ref的自动解包 在template里ref会自动解包,但在script里要加.value。有时候会搞混,特别是嵌套ref的情况。
优化建议:
- 避免在响应式对象里存大数据,会影响性能
- 用shallowRef处理大型不可变数据
- 必要时用markRaw标记不需要响应式的对象
Vue3的响应式虽然比Vue2强大,但也要理解原理才能用好。"
Q9: Pinia相比Vuex有什么优势?
标准回答:
"我在这个项目里用了Pinia,之前的项目用过Vuex,两个都比较熟悉。
Pinia的优势:
- API更简洁 Vuex需要定义mutations、actions、getters,比较繁琐。Pinia直接在store里定义:
export const useWorkflowStore = defineStore('workflow', () => {
const workflows = ref([])
const currentWorkflow = ref(null)
function saveWorkflow() {
// 直接修改state
}
return { workflows, currentWorkflow, saveWorkflow }
})
- TypeScript支持更好 虽然我这个项目没用TS,但Pinia对TypeScript的支持是原生的,不需要额外配置。
- 没有mutations Vuex要求修改state必须通过mutation,增加了心智负担。Pinia可以直接在action里修改state。
- 更好的模块化 Pinia的每个store自然就是独立的,不需要像Vuex那样注册modules。
- DevTools支持 两个都支持,但Pinia的DevTools体验更好,可以直接看到state变化的timeline。
项目中的使用:
我定义了两个store:
- workflowStore:管理工作流数据、执行状态
- nodeStore:管理节点类型、注册的Agent
好处是职责分离,互不干扰。如果用Vuex,可能会放在一个大的modules里,不够清晰。
什么时候用Pinia:
- 新项目,优先Pinia
- Vue3项目,Pinia是官方推荐
- 需要TypeScript的项目
什么时候还要用Vuex:
- 老项目迁移成本高
- 团队已经熟悉Vuex的工作流
- Vue2项目(虽然也能用Pinia,但不是最佳选择)
总的来说,Pinia是Vuex的进化版,更现代、更简洁。"
Q10: 如何处理大量节点时的性能问题?
标准回答:
"虽然我测试时最多放了100多个节点,没遇到明显的性能问题,但我有考虑过如果节点数量更多,比如1000个节点时怎么优化。
可能的性能瓶颈:
- 渲染性能 LogicFlow底层用SVG渲染,1000个节点意味着1000个SVG元素,浏览器渲染压力大。
- 数据更新 每次移动节点都会触发graphData更新,如果deep watch,开销很大。
- 拖拽卡顿 拖拽时频繁计算坐标、更新样式,可能卡顿。
优化方案:
- 虚拟渲染 类似虚拟列表,只渲染可视区域的节点:
const visibleNodes = computed(() => {
return nodes.filter(node => isInViewport(node))
})
- 分层渲染 把节点分成多个layer,对不常变的layer做缓存:
// 背景层:grid
// 内容层:nodes
// 交互层:selection、highlight
- 节流防抖 拖拽、缩放这些高频操作加throttle:
const handleDrag = throttle((event) => {
updateNodePosition(event)
}, 16) // 约60fps
- 懒加载 大型工作流分页加载:
const loadMore = () => {
const nextBatch = allNodes.slice(page * 50, (page + 1) * 50)
nodes.push(...nextBatch)
}
- Web Worker 把复杂计算放Worker里:
// 在worker里执行工作流
const worker = new Worker('workflow-engine.worker.js')
worker.postMessage({ graphData })
worker.onmessage = (result) => {
// 更新UI
}
- 选择性响应式 不是所有数据都需要响应式:
const staticNodes = markRaw(largeNodeArray)
const dynamicNodes = ref(smallNodeArray)
- Canvas替代SVG 如果节点非常多,考虑用Canvas渲染代替SVG,性能会好很多。
实际建议: 其实大部分场景100个节点已经够用了,如果真的有1000+节点的需求,可能工作流设计本身就有问题,应该考虑拆分成多个子流程。
但了解这些优化手段还是很重要的,说明你对性能有意识。"
四、压力面试应对
Q11: 你这个项目有实际用户吗?产生了什么价值?
回答思路: 诚实回答,但突出学习价值和潜在应用场景
标准回答:
"坦白说,这个项目目前还没有实际用户,主要是我个人的学习项目。
但我觉得它的价值体现在几个方面:
1. 技术能力提升 通过这个项目,我系统性地学习了:
- Vue3的深度应用
- 复杂状态管理
- 工作流引擎设计
- 第三方库集成 这些都是实际工作中会用到的技能。
2. 潜在应用场景 虽然没有真实用户,但我设想的应用场景包括:
- 个人自动化任务:比如定时抓取数据、处理文件
- 小团队工作流:比如内容审核、数据处理流程
- 教学演示:展示AI工作流的概念
3. 开源贡献 我把代码放在GitHub上,如果有人觉得有用可以直接拿去用或者参考。至少对想学习这个方向的人有帮助。
如果要商业化: 坦白说,要做商业产品还有很多工作要做:
- 后端服务和数据库
- 用户系统和权限管理
- 更完善的错误处理
- 性能优化和监控
- 部署和运维方案
但作为技术验证和学习项目,我觉得已经达到了目的。而且在面试中,它能很好地展示我的技术能力和学习态度。"
Q12: 你一个人做这个项目,怎么保证代码质量?
标准回答:
"你说得对,一个人开发确实有局限性,没有Code Review,可能会有考虑不周的地方。
但我还是尽量保证了质量:
开发过程:
- 参考了成熟项目的架构,比如Coze、n8n
- 遵循Vue官方最佳实践
- 使用ESLint和Prettier保证代码规范
- 写了详细的文档和注释
自我review: 虽然没有别人review,但我会:
- 提交前自己过一遍代码
- 隔段时间重构不合理的地方
- 遇到问题就查资料、看源码
测试覆盖:
- 功能测试:每个功能都手动测过
- 边界测试:测试极端情况,比如空数据、大量节点
- 兼容性:在Chrome、Firefox、Safari都跑过
实际问题: 确实遇到过一些问题,比如:
- 有些命名不够清晰,后来重构了
- 有些组件耦合太紧,拆分了
- 有些边界情况没考虑到,补充了
如果团队协作: 我肯定会:
- 认真参与Code Review
- 写更详细的注释
- 做更完善的测试
- 写设计文档供大家讨论
一个人的项目确实有局限,但也锻炼了我独立解决问题的能力。在团队里,我会虚心学习别人的经验,也会主动分享自己的思考。"
五、行为面试问题
Q13: 在这个项目中,你如何分解和规划任务的?
标准回答:
"我做这个项目的时候,是按照敏捷开发的思路来规划的,虽然是个人项目,但也借鉴了团队开发的一些方法。
第一阶段:需求分析(1周)
- 调研类似产品:Coze、Dify、n8n
- 列出核心功能清单
- 画原型图
- 评估技术可行性
第二阶段:技术选型(3天)
- 确定Vue3作为核心框架
- 选择LogicFlow做流程图
- 确定Pinia做状态管理
- 搭建项目脚手架
第三阶段:MVP开发(2周) 优先级:
- 可视化编辑器(最核心)
- 简单的工作流执行
- 基本的节点类型
- 数据持久化
第四阶段:功能完善(3周)
- 增加调试功能
- 集成真实API
- 优化UI体验
- 修复bug
第五阶段:文档和优化(1周)
- 写使用文档
- 代码重构
- 性能优化
- 准备开源
任务分解方法: 每个功能我会拆成更小的任务,比如'可视化编辑器':
- LogicFlow集成
- 节点拖拽
- 节点连线
- 节点配置面板
- 样式优化
进度管理: 我用Notion建了个简单的看板,分为:
- Todo
- In Progress
- Testing
- Done
每完成一个任务就移到Done,很有成就感。
遇到延期怎么办: 确实有些功能比预期花的时间长,比如LogicFlow的坑。这时候我会:
- 评估影响范围
- 调整优先级,先做核心功能
- 记录问题,后续优化
虽然是个人项目,但这种规划方法让我保持了节奏,避免了盲目开发。"
Q14: 项目中遇到过和他人(社区、文档)理解不一致的情况吗?
标准回答:
"有的,最典型的就是LogicFlow的使用。
情况描述: LogicFlow官方文档里的例子大多是1.0版本的,但我用的是2.0。文档说可以直接继承CircleNode来自定义节点,但我照着做一直报错。
处理过程:
- 首先我怀疑是自己理解错了,反复读文档
- 然后去看源码,发现2.0的API确实变了
- 去GitHub提issue,但响应比较慢
- 在Stack Overflow和掘金上搜,也没找到明确答案
- 最后自己看源码和尝试,找到了替代方案
反思: 这个经历让我意识到:
- 不能完全依赖文档,特别是快速迭代的开源项目
- 遇到问题要多渠道求证:官方文档、源码、社区、issue
- 有时候要敢于质疑权威,可能真的是文档过时了
- 解决后要记录下来,帮助后来的人
如果在团队里: 我会:
- 及时和team sync这个风险
- 评估影响,看是否需要换技术方案
- 解决后写成文档,避免别人踩坑
- 必要时提PR给开源项目,改进文档
这个经历也让我养成了看源码的习惯,不懂的时候直接看实现,往往比文档更可靠。"
六、反问环节建议
面试最后通常会让你提问,这很重要,体现你的思考深度。
好的问题
- "团队目前的技术栈是怎样的?如果我加入,主要会用到哪些技术?"
- 了解技术匹配度
- "团队的开发流程是怎样的?有哪些最佳实践?"
- 了解工作方式
- "这个岗位最大的挑战是什么?"
- 了解岗位难点
- "团队的技术氛围如何?有技术分享或学习机制吗?"
- 了解成长空间
- "我这个项目的技术栈和你们的有什么差异?有什么建议?"
- 显示学习态度
避免的问题
- "公司有没有加班?"(太功利)
- "试用期工资是多少?"(不合适问HR的问题问技术面试官)
- "什么时候能知道结果?"(HR会告诉你)
- 完全不问(显得不关心)