一、别焦虑了,先把"外挂"做出来
最近技术圈充满了"前端已死"、"AI 取代程序员"的论调。焦虑是真实的,但大部分焦虑来自"看别人做",而不是"自己做"。
当你真正动手用 AI 开发一个复杂的实时交互产品时,你会发现:AI 很强,但某些细节需要调试和把控。
用AI,三天从 0 开始打造一款AI 面试作弊助手。不是 Demo,是能实时听懂面试官提问、能看懂笔试题屏幕、并即时推送答案的"硬核外挂"。
这篇文章,就是这次前端架构的完整复盘。
项目地址:OfferCar AI - AI 面试笔试助手 | 智能面试模拟平台

二、架构美学:不做通用,做场景
市面上的 AI 聊天 Demo 满天飞,大多是 useChat 一把梭。但在"面试作弊"这个高压场景下,通用型架构根本扛不住。
我们需要的是极致的解耦。
1. UI 与逻辑的物理隔离
UI 组件不持有业务状态。

为此抽象了 SessionMainContent ------ 它是整个系统的"显示器"。它只负责一件事:渲染。
- 它不关心是"面试"还是"笔试"。
- 它不关心消息是 Socket 推送的还是 HTTP 拉取的。
- 它只接收
messages数组和回调函数。
typescript
// 纯粹的 UI 定义,没有杂乱的 useEffect
interface SessionMainContentProps {
messages: ChatMessage[]; // 数据源
streamingContent: string; // 流式缓冲区
isStreaming: boolean; // 状态位
sendPendingMessagesToAI: () => void; // 动作指令
// ...
}
2. 业务容器:Controller 的诞生
ExamSession 和 InterviewSession。这两个组件是真正的业务容器。
- InterviewSession :初始化
useInterviewSession,建立语音识别通道,挂载DeviceStatusPanel(音量监控)。 - ExamSession :初始化
useExamSession,监听全局截图指令,挂载简化版状态栏。
这种设计让 MVP 阶段的代码极易维护:改 UI 不动逻辑,改逻辑不崩 UI。
三、核心大脑:useChatSession 的炼成
这是整个前端最"重"的 Hook,也是与 LLM 搏斗的修罗场。在 MVP 阶段,我砍掉了所有花哨功能,只保留付费闭环所需的逻辑。
1. 思考链(CoT)的 60fps 渲染
现在的 DeepSeek 等推理模型会输出 <think> 标签。如果直接渲染,用户会看到一堆乱码;如果等思考完再显示,用户会以为网断了。
我的解法:流式解析 + 渲染节流。
我们实现了一个 thinkTagProcessor,实时将 <think> 转换为 Markdown 的引用块 > 。同时,为了防止高频 setState 导致 React 掉帧(尤其在低端笔记本上),我加入了 requestAnimationFrame 节流。
typescript
// 节流阀:让 AI 的思考过程如丝般顺滑,而不是卡顿的打印机
const tickThinkThrottle = useCallback(() => {
if (!isThinkRafRunningRef.current) return;
setStreamingContent(remainTextRef.current); // 只有这里才会触发重绘
thinkRafIdRef.current = requestAnimationFrame(tickThinkThrottle);
}, []);
2. 消息围栏:只听面试官的话
面试场景有一个痛点:面试者的废话太多。如果全发给 AI,上下文瞬间爆炸。
我在 sendPendingMessagesToAI 中加入了一层过滤器:
typescript
const sendPendingMessagesToAI = useCallback(async () => {
const pendingMessages = messages.filter((msg) => {
// 开启 scopeCharacter 后,AI 自动屏蔽面试者发言,只聚焦面试官的问题
if (scopeCharacter) {
return msg.speaker === 'interviewer';
}
return true;
});
// ...
}, [/*...*/]);
这不仅仅是省 Token,更是为了提高回答的信噪比。
四、降维打击:WebRTC 的另类用法
提到 WebRTC,大家第一反应是视频通话。但在我的架构里,WebRTC 是跨端通信的高速公路。
这是典型的"技术降维打击"。我们不需要视频流,我们需要的是低延迟的指令通道。
1. DataChannel:不传视频传指令
我利用 WebRTC 的 DataChannel 建立了两个核心管道:
exam-commands:传输控制指令。Electron 截图后,通过此通道直接将 Base64 推送到 Web 端,速度毫秒级。recognition-text:传输实时语音转写文本。
这种设计避开了传统 HTTP 轮询的延迟,也比 WebSocket 更轻量(P2P 直连)。
typescript:hooks.ts
// 监听来自 Electron 的"量子纠缠"信号
channel.onmessage = (event) => {
const message = JSON.parse(event.data);
if (message.type === 'screenshot') {
// 瞬间上屏,无感知传输
addImageToPendingMessages(message.data);
}
};
五、体验微操:Redux 配置中心
UI/UX 的作用是什么?是**"显得值钱"**。
为了让用户觉得"这个外挂很专业",我用 Redux Toolkit (settingsSlice) 管理了全局偏好:
- 字号微调:AI 回答字号、面试官字号独立控制。
- 双语开关:一键切换中英对照,瞬间提升逼格。
这些配置在 SessionMainContent 中被实时订阅。用户拖动滑块,界面即时响应。这种掌控感,是付费意愿的来源之一。
六、结语:AI 时代,拿回你的生产资料
写到这里,我想说:代码只是工具,是连接现实与数字世界的铲子。AI 让这把铲子变成了挖掘机,但挖掘机本身不会决定去哪里挖掘宝藏。
在这个项目里,AI 帮我生成了100% 的 业务逻辑。 别焦虑,去创造。打开编辑器,去想一个你真正想解决的问题。 项目地址:OfferCar AI - AI 面试笔试助手 | 智能面试模拟平台
下一篇,我们将深入 Electron 客户端,看看如何进入系统音频流,实现无感采集。