# Bug 修复 v3 - 刷新后重复加载问题

## 修复的问题

### 刷新后加载两遍内容
**原因**:
1. `loadInitialData()` 会调用 `fetchAndDisplayHistory()` 加载历史记录
2. 1 秒后 `restoreTaskState()` 启动轮询
3. `loadRunningTask()` 设置 `lastEventIndex = 0`，从头开始获取所有事件
4. 导致已经在历史中的事件被重复处理

**解决方案**:

#### 1. 等待历史加载完成
在 `restoreTaskState()` 中检查历史是否已加载：
```javascript
async restoreTaskState() {
    // 检查历史是否已加载
    const hasMessages = Array.isArray(this.messages) && this.messages.length > 0;

    if (!hasMessages) {
        // 等待历史加载完成后再恢复
        setTimeout(() => {
            this.restoreTaskState();
        }, 500);
        return;
    }

    // 历史已加载，启动轮询
    taskStore.startPolling(...);
}
```

#### 2. 计算正确的事件偏移量
在 `loadRunningTask()` 中获取任务详情，计算已处理的事件数量：
```javascript
async loadRunningTask(conversationId) {
    // 查找运行中的任务
    const runningTask = result.data.find(...);

    if (runningTask) {
        // 获取任务详情，计算已处理的事件数量
        const detailResponse = await fetch(`/api/tasks/${runningTask.task_id}`);
        const detailResult = await detailResponse.json();

        // 设置为当前事件数量，只获取新事件
        this.lastEventIndex = detailResult.data.next_offset || detailResult.data.events.length;

        debugLog('[Task] 设置起始偏移量:', this.lastEventIndex);
    }
}
```

## 工作流程

### 页面刷新恢复流程（修复后）

1. **页面加载** (`mounted()`)
   - 调用 `loadInitialData()`
   - 加载历史记录（`fetchAndDisplayHistory()`）
   - 1 秒后调用 `restoreTaskState()`

2. **任务恢复** (`restoreTaskState()`)
   - 检查是否已在流式输出中 → 跳过
   - 查找运行中的任务
   - **检查历史是否已加载** → 如果未加载，等待 500ms 后重试
   - 历史已加载 → 继续

3. **加载任务详情** (`loadRunningTask()`)
   - 查找运行中的任务
   - **获取任务详情**
   - **计算已处理的事件数量**
   - 设置 `lastEventIndex` 为当前事件数量

4. **启动轮询** (`startPolling()`)
   - 从 `lastEventIndex` 开始轮询
   - **只获取新事件**
   - 每 150ms 轮询一次

5. **处理新事件**
   - 只处理新产生的事件
   - 追加到已有的历史记录后面
   - 不重复显示已有内容

## 关键改进

### 1. 等待历史加载
- 在 `restoreTaskState()` 中检查 `messages` 是否已加载
- 如果未加载，延迟 500ms 后重试
- 确保历史加载完成后再启动轮询

### 2. 正确的事件偏移量
- 在 `loadRunningTask()` 中获取任务详情
- 计算已处理的事件数量（`next_offset` 或 `events.length`）
- 设置 `lastEventIndex` 为当前事件数量
- 轮询只获取新事件（`from=lastEventIndex`）

### 3. 避免重复处理
- 历史记录由 `fetchAndDisplayHistory()` 加载
- 轮询只处理新事件
- 不会重复显示已有内容

## 修改的文件

### 1. static/src/app/methods/taskPolling.ts
**等待历史加载**:
```javascript
async restoreTaskState() {
    // 检查历史是否已加载
    const hasMessages = Array.isArray(this.messages) && this.messages.length > 0;

    if (!hasMessages) {
        debugLog('[TaskPolling] 历史未加载，等待历史加载完成');
        setTimeout(() => {
            this.restoreTaskState();
        }, 500);
        return;
    }

    debugLog('[TaskPolling] 历史已加载，启动轮询');
    // ... 启动轮询
}
```

### 2. static/src/stores/task.ts
**计算事件偏移量**:
```javascript
async loadRunningTask(conversationId) {
    const runningTask = result.data.find(...);

    if (runningTask) {
        // 获取任务详情
        const detailResponse = await fetch(`/api/tasks/${runningTask.task_id}`);
        const detailResult = await detailResponse.json();

        // 设置为当前事件数量
        this.lastEventIndex = detailResult.data.next_offset || detailResult.data.events.length;

        debugLog('[Task] 设置起始偏移量:', this.lastEventIndex);
    }
}
```

## 测试场景

### 1. 正常发送消息
- 发送消息
- 观察输出是否正常
- 观察是否只显示一次

### 2. 刷新页面（任务进行中）
- 任务执行中刷新页面
- 观察历史记录是否正确显示
- 观察是否只显示一次
- 观察新内容是否正常追加
- 观察工具块是否保留

### 3. 刷新页面（任务完成后）
- 任务完成后刷新页面
- 观察历史记录是否完整
- 观察是否没有重复内容

### 4. 多次刷新
- 任务执行中多次刷新
- 观察每次刷新是否正常
- 观察是否有累积的重复内容

## 构建

```bash
cd static
npm run build
```

构建成功！
- `static/dist/assets/main.js` (690.04 kB)
- `static/dist/assets/task.js` (4.01 kB)

## 最终效果

- ✅ 刷新后不重复显示内容
- ✅ 历史记录正确加载
- ✅ 新事件正常追加
- ✅ 工具块正确显示
- ✅ 流畅的输出效果（150ms 轮询）

现在可以测试了！刷新页面应该只显示一次内容，新内容会正常追加。
