在构建一个 AI 模拟测试平台时,遇到了前后端交互的问题。
比如:按钮点了之后,问题怎么生成?数据怎么存进数据库?页面怎么更新?
决定自己彻底拆解,梳理从 0 开始构建系统。
✅ 二、完整流程概览:用户 → AI → 数据库 → 页面
[用户点击按钮]
↓
[前端 Agent.tsx 触发 handleCall() 函数]
↓
[fetch 请求 → 后端 route.ts 接收并生成问题]
↓
[生成问题后 → 存入 Firestore 数据库]
↓
[后端返回问题 → 前端 setMessages 更新状态]
↓
[页面重新渲染出 AI 面试问题]
✅ 三、文件结构中两大主角
| 文件 | 作用 |
|---|---|
Agent.tsx | 负责前端 UI、显示面试官和按钮、调用后端接口 |
route.ts | 负责接收请求、生成 AI 面试题、存入数据库 |
✅ 四、每一步的核心逻辑 & 代码拆解
🔹 Step 1. 用户点击按钮,触发 handleCall
<button className="btn-call" onClick={handleCall}>
创建点击事件,发起 POST 请求:
const handleCall = async () => {
const requestBody = {
type: 'technical',
role: 'Frontend Developer',
level: 'Junior',
techstack: 'React,TypeScript,Tailwind',
amount: 5,
userid: 'user-123',
};
const res = await fetch('/api/vapi/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestBody),
});
const data = await res.json();
setMessages(data.questions);
};
🔹 Step 2. route.ts 接收请求体,调用 AI 模型生成问题
const { type, role, level, techstack, amount, userid } = await request.json();
const { text: questions } = await generateText({
model: google("gemini-2.0-flash-001"),
prompt: `Prepare ${amount} questions for a ${level} ${role} interview with ${techstack}`,
});
🔹 Step 3. 生成问题后,封装对象写入 Firestore
const interview = {
role,
type,
level,
techstack: techstack.split(','),
questions: JSON.parse(questions),
userId: userid,
createdAt: new Date().toISOString(),
};
await db.collection("interviews").add(interview);
需要提前在
lib/db.ts中初始化 Firestore,并在此处引入db
🔹 Step 4. 后端返回成功 → 前端状态更新
return Response.json({ success: true, questions: JSON.parse(questions) });
前端接收到后,调用 setMessages(),页面自动显示问题。
✅ 五、关键技术点总结
| 技术 | 应用点 |
|---|---|
| ✅ React 状态管理 | 控制对话内容显示 |
| ✅ fetch API | 发起 POST 请求 |
| ✅ Next.js API Route | 创建 route.ts 接口文件 |
| ✅ Firestore | 数据库存储、写入对象 |
| ✅ AI 文本生成 API | 使用 Gemini 生成问题内容 |
✅ 六、从中学到了什么?
- 再也不怕“按钮点了没反应”这种模糊的错误了
- 数据的流动路径清晰之后,前端页面更可控了
📎 附:项目结构图(推荐截图)
├── app/
│ ├── api/vapi/generate/route.ts ← 后端接口
│ └── components/Agent.tsx ← 前端页面组件
├── lib/db.ts ← 数据库连接
├── public/ai-avatar.png ← 考官头像