# 问题修复：批量发车超时 - 使用统一通信机制 v3.9.7

## 🚀 概述

**问题**：
- ✅ 游戏功能模块单独测试：**成功且非常快**
- ❌ 批量自动化测试：**超时（20秒）**

**用户反馈**：
> "单独测试是成功的，而且查询的非常快"

**根本原因**：
- 批量自动化和游戏功能模块使用了**不同的通信机制**
- 批量自动化复用 `client` 对象，在等待和执行期间 `client` 可能失效
- 导致后续命令的 Promise 永远不会被 resolve

---

## 🔍 问题分析

### 之前的实现（v3.9.6及之前）

#### 游戏功能模块（成功✅）
```javascript
// CarManagement.vue
const response = await tokenStore.sendMessageAsync(
  tokenId,
  'car_getrolecar',
  {},
  10000
)
```

**特点**：
- ✅ 每次发送时获取最新的 `client`
- ✅ 使用响应式连接对象 `wsConnections.value[tokenId]`
- ✅ 简单可靠

---

#### 批量自动化（失败❌）
```javascript
// batchTaskStore.js (v3.9.6)
const client = await ensureConnection(tokenId)  // 获取一次
await new Promise(resolve => setTimeout(resolve, 2000))  // 等待2秒

// 后续多次使用这个 client
await client.sendWithPromise('car_getrolecar', {}, 20000)  // ❌ 可能失效
await client.sendWithPromise('car_refresh', { carId }, 5000)  // ❌ 可能失效
await client.sendWithPromise('car_claim', { carId }, 5000)  // ❌ 可能失效
await client.sendWithPromise('car_send', { carId }, 5000)  // ❌ 可能失效
```

**问题**：
- ❌ 一次性获取 `client` 后长时间复用
- ❌ 在等待期间（2秒）和执行期间，`client` 可能失效
- ❌ 使用非响应式连接对象 `tokenStore.wsConnections[tokenId]`

---

### 为什么 client 会失效？

#### 原因1：等待期间连接被替换
```javascript
// 时间点 T0: 获取 client
const client = await ensureConnection(tokenId)

// 时间点 T0 → T2: 等待2秒
await new Promise(resolve => setTimeout(resolve, 2000))

// 时间点 T2: client 可能已经失效
// - 连接可能被重置
// - tokenStore.reconnectWebSocket 可能创建了新的 client
// - 旧的 client 引用失效
await client.sendWithPromise('car_getrolecar', {}, 20000)  // ❌ 超时
```

#### 原因2：Promise 管理器状态不一致
- WebSocket client 内部有 Promise 管理器
- 如果连接重置，Promise 管理器也会重置
- 旧的 Promise 永远不会被 resolve

#### 原因3：事件监听器失效
- WebSocket client 依赖 `onmessage` 事件
- 连接重置后，旧的事件监听器失效
- 新消息不会触发旧 client 的 Promise resolve

---

## 🛠️ 解决方案 v3.9.7

### 核心改进：统一使用 `tokenStore.sendMessageAsync`

**不再复用 `client` 对象，每次发送时都获取最新的 `client`**

---

### 修改详情

#### 修改1：查询车辆（第1152行）
```diff
- const queryResponse = await client.sendWithPromise('car_getrolecar', {}, 20000)
+ const queryResponse = await tokenStore.sendMessageAsync(tokenId, 'car_getrolecar', {}, 20000)
```

#### 修改2：刷新车辆（第1200行）
```diff
- await client.sendWithPromise('car_refresh', { carId: carId }, 5000)
+ await tokenStore.sendMessageAsync(tokenId, 'car_refresh', { carId: carId }, 5000)
```

#### 修改3：刷新后重新查询（第1227行）
```diff
- const reQueryResponse = await client.sendWithPromise('car_getrolecar', {}, 20000)
+ const reQueryResponse = await tokenStore.sendMessageAsync(tokenId, 'car_getrolecar', {}, 20000)
```

#### 修改4：收获车辆（第1268行）
```diff
- await client.sendWithPromise('car_claim', { carId: carId }, 5000)
+ await tokenStore.sendMessageAsync(tokenId, 'car_claim', { carId: carId }, 5000)
```

#### 修改5：发送前最后查询（第1298行）
```diff
- const finalQueryResponse = await client.sendWithPromise('car_getrolecar', {}, 20000)
+ const finalQueryResponse = await tokenStore.sendMessageAsync(tokenId, 'car_getrolecar', {}, 20000)
```

#### 修改6：发送车辆（第1311行）
```diff
- await client.sendWithPromise('car_send', { carId, helperId: 0, text: "" }, 5000)
+ await tokenStore.sendMessageAsync(tokenId, 'car_send', { carId, helperId: 0, text: "" }, 5000)
```

---

## ✅ 优势

### 1. 统一通信机制
- ✅ 批量自动化与游戏功能模块使用**相同的通信机制**
- ✅ 代码一致性和可维护性大幅提升

### 2. 每次获取最新 client
- ✅ 每次发送命令时都通过 `wsConnections.value[tokenId]` 获取最新的 `client`
- ✅ 避免 `client` 对象失效问题

### 3. 使用响应式状态
- ✅ `wsConnections.value[tokenId]` 是响应式的
- ✅ 总是获取到最新的连接状态

### 4. 简单可靠
- ✅ 逻辑更简单清晰
- ✅ 与游戏功能模块保持一致
- ✅ 避免复杂的 client 管理

---

## 📊 预期效果

### v3.9.6（修改前）
```
✅ WebSocket连接成功
⏳ 等待连接稳定... (2秒)
📤 发送消息: car_getrolecar {}
💓 心跳消息... (不断收发)
❌ 20秒后超时，没有收到 car_getrolecarresp
```

**问题**：client 对象在等待期间失效

---

### v3.9.7（修改后）
```
✅ WebSocket连接成功
⏳ 等待连接稳定... (2秒)
📤 发送消息: car_getrolecar {}
✅ 收到响应: car_getrolecarresp (1-2秒内)  ← 预期快速成功
✅ [token_xxx] 查询到 4 辆车
```

**改进**：每次发送都获取最新的 client，避免失效

---

## 🧪 验证步骤

### 1. 重启开发服务器
```bash
# 在项目根目录
npm run dev
```

### 2. 批量测试
1. 打开批量自动化面板
2. 选择**2个账号**（第2个账号待发车状态）
3. 只勾选**"发车"**任务
4. 点击"开始执行"

### 3. 观察结果

#### 期望结果（成功✅）
```
🎯 开始执行 Token: 805服-0-xxx
✅ WebSocket连接成功
⏳ 等待连接稳定...
📌 执行任务 [1/1]: sendCar
🚗 [token_xxx] 开始查询俱乐部车辆...
✅ [token_xxx] 查询到 4 辆车  ← 应该1-2秒内完成！
🔄 [token_xxx] 开始批量刷新车辆...
✅ [token_xxx] 刷新车辆成功: carId
🎁 [token_xxx] 开始批量收获...
✅ [token_xxx] 收获车辆成功: carId
🚀 [token_xxx] 开始批量发送...
✅ [token_xxx] 发送车辆成功: carId
✅ Token完成: 805服-0-xxx

⏳ Token token_xxx 将在 3.0秒 后建立连接  ← 串行执行

🎯 开始执行 Token: 805服-1-xxx
✅ WebSocket连接成功
⏳ 等待连接稳定...
📌 执行任务 [1/1]: sendCar
🚗 [token_xxx] 开始查询俱乐部车辆...
✅ [token_xxx] 查询到 4 辆车  ← 应该1-2秒内完成！
✅ Token完成: 805服-1-xxx

📊 统计信息: {total: 2, success: 2, failed: 0}  ✅
```

**关键指标**：
- ✅ 查询车辆应该在1-2秒内完成（而不是20秒超时）
- ✅ 每个步骤都能快速响应
- ✅ 整体流程顺畅

---

#### 如果仍然失败（unlikely）

如果修改后仍然超时，说明问题更深层：
1. 可能是服务器端限制
2. 可能需要增加账号间隔（5-10秒）
3. 可能需要检查网络环境

但根据分析，**v3.9.7应该能解决问题** ✅

---

## 📝 文件修改清单

### 修改文件
1. ✅ `src/stores/batchTaskStore.js`
   - 第1152行：查询车辆
   - 第1200行：刷新车辆
   - 第1227行：刷新后重新查询
   - 第1268行：收获车辆
   - 第1298行：发送前最后查询
   - 第1311行：发送车辆

### 新增文档
1. ✅ `MD说明/批量自动化发车流程分析v3.9.6.md` - 流程分析文档
2. ✅ `MD说明/问题修复-批量发车超时使用统一通信机制v3.9.7.md` - 本文档

---

## 🔄 版本信息

- **版本号**：v3.9.7
- **修复日期**：2025-10-08
- **影响范围**：批量自动化 - 发车任务
- **向后兼容**：✅ 完全兼容
- **破坏性变更**：❌ 无

---

## 💡 技术要点

### tokenStore.sendMessageAsync 内部实现

```javascript
// src/stores/tokenStore.js 第1414-1430行
const sendMessageWithPromise = async (tokenId, cmd, params = {}, timeout = 1000) => {
  // 1. 获取最新的连接对象（响应式）
  const connection = wsConnections.value[tokenId]
  
  // 2. 检查连接状态
  if (!connection || connection.status !== 'connected') {
    return Promise.reject(new Error(`WebSocket未连接 [${tokenId}]`))
  }
  
  // 3. 获取最新的 client
  const client = connection.client
  if (!client) {
    return Promise.reject(new Error(`WebSocket客户端不存在 [${tokenId}]`))
  }
  
  // 4. 发送命令
  try {
    return await client.sendWithPromise(cmd, params, timeout)
  } catch (error) {
    return Promise.reject(error)
  }
}
```

**关键优势**：
- ✅ 每次调用都重新获取 `connection` 和 `client`
- ✅ 使用 `wsConnections.value`（响应式）
- ✅ 检查 `connection.status === 'connected'`
- ✅ 确保 `client` 总是最新的

---

## 🎯 总结

### 问题本质
- **批量自动化复用 `client` 对象**
- **在等待和执行期间，`client` 可能失效**
- **导致命令的 Promise 永远不会被 resolve**

### 解决方案
- **统一使用 `tokenStore.sendMessageAsync`**
- **每次发送都获取最新的 `client`**
- **与游戏功能模块保持一致**

### 预期结果
- ✅ 批量发车应该和单独测试一样**快速成功**
- ✅ 查询车辆应该在1-2秒内完成
- ✅ 整体流程顺畅可靠

---

## 🚀 下一步

1. **重启开发服务器**
2. **批量测试2个账号**
3. **观察是否快速成功**
4. **享受批量发车的便利！** 🎉

如果测试成功，说明问题已完美解决！ ✅

