这一课我们跟踪一个真实请求,从用户点击"发送"到下载 Excel 文件,看看每一步发生了什么。

第 9 课:完整项目实战


一个请求的完整生命周期

这一课我们跟踪一个真实请求,从用户点击"发送"到下载 Excel 文件,看看每一步发生了什么。

用户请求:"帮我做一个健身打卡表,包含日期、运动类型、时长、消耗卡路里,底部要有本周汇总"

第 1 站:MessageInput 组件

code
用户在输入框里打字 → 点击"发送"按钮

MessageInput 组件:
  1. 获取输入文本
  2. 检查是否有附件文件(这次没有)
  3. 调用 ChatInterface 的 sendMessage()

第 2 站:ChatInterface 组件

code
// ChatInterface.tsx
const sendMessage = async (content: string) => {
  // 1. 先把用户消息显示在界面上
  setMessages(prev => [...prev, {
    role: 'user',
    content: '帮我做一个健身打卡表...'
  }]);

  // 2. 设置 loading 状态
  setIsLoading(true);

  // 3. 通过 IPC 发送给主进程
  window.electron.ipcRenderer.sendMessage('claude-code:query', {
    content: '帮我做一个健身打卡表...',
    files: [],
  });
};

第 3 站:Electron 主进程

bash
// main.ts
ipcMain.on('claude-code:query', async (event, { content, files }) => {

  // 1. 记录当前已有的 xlsx 文件(用于后面检测新文件)
  const initialFiles = ['old_report.xlsx'];  // 之前的文件

  // 2. 创建 AbortController
  abortController = new AbortController();

  // 3. 调用 Claude Agent SDK
  const queryIterator = query({
    prompt: '帮我做一个健身打卡表...',
    options: {
      cwd: './agent',
      maxTurns: 100,
      settingSources: ['local', 'project'],
      allowedTools: ['Bash', 'Create', 'Edit', 'Read', 'Write',
                     'WebSearch', 'GrepTool', 'Skill',
                     'TodoWrite', 'TodoEdit'],
      abortController,
    },
  });

  // 4. 流式处理消息
  for await (const message of queryIterator) {
    messages.push(message);
    event.reply('claude-code:response', message);
  }

  // 5. 检测新文件
  // ...
});

第 4 站:Claude AI 开始工作

AI 收到任务后的内部决策过程:

python
AI 的思考链:

"用户要做健身打卡表 → 需要创建 Excel 文件
 → 我应该先读取 xlsx Skill 了解规范
 → 然后用 openpyxl 写 Python 代码
 → 执行代码生成 .xlsx
 → 验证公式"

第一轮:读取技能

code
AI → Skill 工具 → 读取 xlsx SKILL.md

消息流:
  type: 'assistant'
  content: [
    { type: 'text', text: '让我先了解一下 Excel 生成的规范...' },
    { type: 'tool_use', name: 'Skill', input: { command: 'xlsx' } }
  ]

前端收到这条消息 → 显示 "🎯 Using tool: Skill"

第二轮:创建任务列表

code
AI → TodoWrite 工具

消息流:
  type: 'assistant'
  content: [
    { type: 'tool_use', name: 'TodoWrite', input: {
      todos: [
        { content: '创建健身打卡表结构', status: 'in_progress' },
        { content: '添加公式和格式', status: 'pending' },
        { content: '验证公式', status: 'pending' }
      ]
    }}
  ]

前端收到 → TodoListDisplay 组件显示任务列表

第三轮:写 Python 代码

code
AI → Write 工具 → 创建 workout_tracker.py

消息流:
  type: 'assistant'
  content: [
    { type: 'text', text: '现在创建生成脚本...' },
    { type: 'tool_use', name: 'Write', input: {
      file_path: 'workout_tracker.py',
      content: 'from openpyxl import Workbook...'
    }}
  ]

前端收到 → 显示 "✏️ Using tool: Write"

第四轮:执行 Python

python
AI → Bash 工具 → python3 workout_tracker.py

消息流:
  type: 'assistant'
  content: [
    { type: 'tool_use', name: 'Bash', input: {
      command: 'python3 workout_tracker.py'
    }}
  ]

然后:
  type: 'result'
  content: 'Workout tracker created successfully!'

前端收到 → 显示 "⚙️ Using tool: Bash" + 执行结果

第五轮:验证公式

python
AI → Bash 工具 → python3 .claude/skills/xlsx/recalc.py Workout_Tracker.xlsx

消息流:
  type: 'result'
  content: '{"status":"success","total_errors":0,"total_formulas":8}'

AI 看到"0 个错误",任务完成!

最后:AI 总结

code
AI 的回复:
  "健身打卡表已创建!包含以下特性:
   - 日期、运动类型、时长(分钟)、消耗卡路里四列
   - 底部有 SUM 公式自动计算本周总时长和总卡路里
   - 蓝色文字表示你可以修改的数据
   - 表头已冻结,滚动时始终可见"

第 5 站:文件检测

code
// main.ts —— query() 循环结束后
const finalFiles = fs.readdirSync(outputDir)
  .filter(f => f.endsWith('.xlsx'));
// 发现了 'Workout_Tracker.xlsx'(新文件!)

event.reply('claude-code:output-files', [{
  name: 'Workout_Tracker.xlsx',
  path: '/path/to/agent/Workout_Tracker.xlsx',
}]);

第 6 站:前端显示下载按钮

code
ChatInterface 收到 'claude-code:output-files'
  → 把文件信息关联到最后一条 AI 消息
  → Message 组件渲染下载按钮

界面效果:
  🤖 AI:健身打卡表已创建!...
       📥 [下载 Workout_Tracker.xlsx]

第 7 站:用户下载

code
用户点击 [下载 Workout_Tracker.xlsx]
  ↓
前端 → IPC('download-file', filePath)
  ↓
主进程 → dialog.showSaveDialog()
  ↓
用户选择保存位置
  ↓
主进程 → fs.copyFileSync(source, destination)
  ↓
文件保存到用户电脑

完整时序图

bash
用户          React 前端       Electron 主进程       Claude AI
 │              │                   │                   │
 │──输入文字───→│                   │                   │
 │              │──IPC:query──────→│                   │
 │              │                   │──query()─────────→│
 │              │                   │                   │
 │              │                   │←─msg: Skill──────│
 │              │←─IPC:response────│                   │
 │ 看到工具展示  │                   │                   │
 │              │                   │←─msg: TodoWrite──│
 │              │←─IPC:response────│                   │
 │ 看到任务列表  │                   │                   │
 │              │                   │←─msg: Write──────│
 │              │←─IPC:response────│                   │
 │ 看到代码写入  │                   │                   │
 │              │                   │←─msg: Bash───────│
 │              │←─IPC:response────│                   │
 │ 看到代码执行  │                   │                   │
 │              │                   │←─msg: text───────│
 │              │←─IPC:response────│                   │
 │ 看到 AI 总结  │                   │                   │
 │              │                   │                   │
 │              │                   │──检测新文件─→      │
 │              │←─IPC:files───────│                   │
 │ 看到下载按钮  │                   │                   │
 │              │                   │                   │
 │──点击下载───→│                   │                   │
 │              │──IPC:download───→│                   │
 │              │                   │──另存为对话框──→ 用户电脑
 │ 得到文件     │                   │                   │

带文件上传的场景

如果用户拖了一个 Excel 进来说"分析一下这个数据":

code
额外步骤:
  1. MessageInput 验证文件类型和大小
  2. IPC 发送 content + files
  3. 主进程保存文件到 agent/problems/
     Budget_1704747600000_a3b5c2.xlsx
  4. prompt 里追加文件路径信息
  5. AI 用 Read 工具读取文件
  6. 后续流程一样

错误处理场景

如果 AI 生成的 Python 代码有 bug:

bash
第 1 次 Bash 执行:
  Error: NameError: name 'PatternFill' is not defined

AI 看到错误 → 自动修复(加上 import)

第 2 次 Bash 执行:
  Workout tracker created successfully!

→ 继续验证公式 → 完成

本课小结

  • 一个请求经过 7 站:输入 → 前端 → IPC → 主进程 → AI → 文件检测 → 下载
  • AI 的工作通常是 5-6 轮:读技能 → 建任务 → 写代码 → 执行 → 验证
  • 前端实时展示每一步的工具调用
  • 主进程是"中转站",连接前端和 AI
  • 有完善的错误处理和自动重试机制

课后练习

  1. 发送一个复杂请求(比如"做一个包含图表的销售分析"),数一数 AI 用了多少轮
  2. 故意发一个模糊请求("帮我做个表"),看看 AI 会不会追问你要什么内容
  3. 上传一个有问题的 Excel 文件,让 AI 帮你修复

沿着当前专题继续,或返回课程目录重新整理阅读顺序。

返回课程目录