# 问题修复：发车和爬塔错误 v3.10.3

**版本**: v3.10.3  
**日期**: 2025-10-08  
**类型**: Bug Fix

---

## 问题描述

在批量自动化运行时，发现以下三个错误：

### 1. `role_getroleinfo` 请求超时 (1000ms)

**现象**:
```
❌ [token_xxx] 请求超时: role_getroleinfo (1000ms)
```

**影响**: 
- Token 1 和 Token 3 在执行 `dailyFix` 任务时遇到此超时
- 虽然 Token 1 的后续 `car_getrolecar` 仍成功，但 Token 3 因此失败

**原因**:
- `dailyFix` 任务中的 `role_getroleinfo` 命令使用 1000ms 超时
- 在高并发或服务器负载较高时，1000ms 不足以等待服务器响应

---

### 2. `car_getrolecar` 返回错误 200400

**现象**:
```
❌ [token_xxx] 发车任务失败: Error: 服务器错误: 200400 - 未知错误
```

**影响**:
- Token 2 和 Token 3 在执行 `sendCar` 任务时遇到此错误
- 导致发车任务完全失败，无法查询车辆

**原因**:
- 错误码 200400 表示账号未加入俱乐部或没有赛车权限
- 当前代码没有针对此错误码的特定处理，仅抛出通用错误

---

### 3. `presetteam_changeteam` 未知命令

**现象**:
```
❌ [token_xxx] presetteam_changeteam Error: Unknown cmd: presetteam_changeteam
```

**影响**:
- Token 2 在执行 `climbTower` 任务时遇到此错误
- 导致爬塔任务中的阵容切换失败

**原因**:
- `presetteam_changeteam` 命令未在 `CommandRegistry` 中注册
- `presetteam_changeteamresp` 响应未在 `responseToCommandMap` 中映射

---

## 解决方案

### 1. 增加 `role_getroleinfo` 超时时间

**修改文件**: `src/stores/batchTaskStore.js`

**修改内容**:
- 将 `role_getroleinfo` 的超时时间从 **1000ms** 增加到 **10000ms**
- 影响范围：`dailyFix` 任务中的两处 `role_getroleinfo` 调用
  - 执行前获取任务状态（第 538 行）
  - 执行后获取任务状态（第 918 行）

**修改前**:
```javascript
const beforeRoleInfo = await client.sendWithPromise('role_getroleinfo', {}, 1000)
```

**修改后**:
```javascript
const beforeRoleInfo = await client.sendWithPromise('role_getroleinfo', {}, 10000)
```

**优势**:
- 为服务器响应提供更充足的时间
- 减少因网络波动导致的超时
- 与其他关键命令（如 `car_getrolecar` 20000ms）的超时策略保持一致

---

### 2. 为错误 200400 添加特定错误处理

**修改文件**: `src/stores/batchTaskStore.js`

**修改内容**:
- 在 `sendCar` 任务的 `car_getrolecar` 调用处添加 try-catch
- 检测错误消息是否包含 "200400"
- 如果是，抛出更友好的错误消息："该账号未加入俱乐部或没有赛车权限"

**修改前**:
```javascript
const queryResponse = await tokenStore.sendMessageAsync(tokenId, 'car_getrolecar', {}, 20000)

if (!queryResponse || !queryResponse.roleCar) {
  throw new Error('查询车辆失败：未返回车辆数据')
}
```

**修改后**:
```javascript
let queryResponse
try {
  queryResponse = await tokenStore.sendMessageAsync(tokenId, 'car_getrolecar', {}, 20000)
} catch (error) {
  // 检查是否是 200400 错误（账号未加入俱乐部或没有赛车权限）
  if (error.message && error.message.includes('200400')) {
    throw new Error('该账号未加入俱乐部或没有赛车权限')
  }
  // 其他错误直接抛出
  throw error
}

if (!queryResponse || !queryResponse.roleCar) {
  throw new Error('查询车辆失败：未返回车辆数据')
}
```

**优势**:
- 为用户提供更明确的错误原因
- 便于快速定位问题（账号未加入俱乐部）
- 避免误认为是服务器或客户端代码错误

---

### 3. 注册 `presetteam_changeteam` 命令

**修改文件**: `src/utils/xyzwWebSocket.js`

**修改内容**:

#### 3.1 在 `CommandRegistry` 中注册命令

**修改位置**: 第 163 行（`registerDefaultCommands` 函数）

**修改前**:
```javascript
.register("presetteam_getinfo")
.register("presetteam_getinfo")
.register("presetteam_setteam")
.register("presetteam_saveteam", { teamId: 1 })
.register("role_gettargetteam")
```

**修改后**:
```javascript
.register("presetteam_getinfo")
.register("presetteam_getinfo")
.register("presetteam_setteam")
.register("presetteam_changeteam", { teamId: 1 })
.register("presetteam_saveteam", { teamId: 1 })
.register("role_gettargetteam")
```

#### 3.2 在 `responseToCommandMap` 中添加响应映射

**修改位置**: 第 638 行（`_handlePromiseResponse` 方法）

**修改前**:
```javascript
'presetteam_saveteamresp': 'presetteam_saveteam',
'presetteam_getinforesp': 'presetteam_getinfo',
```

**修改后**:
```javascript
'presetteam_saveteamresp': 'presetteam_saveteam',
'presetteam_changeteamresp': 'presetteam_changeteam',
'presetteam_getinforesp': 'presetteam_getinfo',
```

**优势**:
- 使 `presetteam_changeteam` 命令能够被 WebSocket 客户端识别
- 确保 Promise 能够正确解析响应
- 修复爬塔任务中的阵容切换功能

---

## 测试验证

### 测试场景 1：`role_getroleinfo` 不再超时

**预期结果**:
- `dailyFix` 任务中的 `role_getroleinfo` 命令在 10000ms 内成功响应
- 不再出现 "请求超时: role_getroleinfo (1000ms)" 错误

**日志示例**:
```
🔍 正在获取执行前的任务完成状态...
📊 执行前任务状态: { "101": true, "102": true, ... }
```

---

### 测试场景 2：错误 200400 显示友好消息

**预期结果**:
- 对于未加入俱乐部的账号，`sendCar` 任务失败，但显示明确的错误原因
- 错误消息为："该账号未加入俱乐部或没有赛车权限"

**日志示例**:
```
🚗 [token_xxx] 开始查询俱乐部车辆...
❌ [token_xxx] 发车任务失败: Error: 该账号未加入俱乐部或没有赛车权限
```

---

### 测试场景 3：`presetteam_changeteam` 命令正常工作

**预期结果**:
- `climbTower` 任务中的阵容切换功能正常工作
- 不再出现 "Unknown cmd: presetteam_changeteam" 错误

**日志示例**:
```
🗼 [token_xxx] 开始爬塔（目标层数: 18）...
✅ 已切换到阵容1
🏆 [token_xxx] 成功挑战第 1 层
```

---

## 影响范围

### 修改的文件
1. `src/stores/batchTaskStore.js` - 批量任务核心逻辑
2. `src/utils/xyzwWebSocket.js` - WebSocket 客户端命令注册

### 影响的功能
1. **批量自动化 - dailyFix 任务**: 任务状态获取更稳定
2. **批量自动化 - sendCar 任务**: 错误提示更友好
3. **批量自动化 - climbTower 任务**: 阵容切换功能可用

---

## 注意事项

### 1. 错误 200400 的根本解决

虽然我们添加了友好的错误提示，但根本解决方法是：
- **确保账号已加入俱乐部**
- 在执行 `sendCar` 任务前，先检查账号的俱乐部状态

### 2. `role_getroleinfo` 超时时间平衡

- **10000ms** 是一个较为保守的超时时间
- 如果服务器响应速度很快，可能会增加整体任务执行时间
- 如果发现超时仍频繁发生，可考虑进一步增加到 15000ms 或 20000ms

### 3. 并发控制

目前批量自动化的默认并发数为 1（`maxConcurrency = 1`），这是为了：
- 避免服务器反批量检测
- 减少超时和错误发生的概率

如果用户增加并发数（如 3-6），可能需要进一步优化超时策略或添加更多的延迟。

---

## 总结

本次修复解决了批量自动化中的三个关键问题：

1. ✅ **`role_getroleinfo` 超时** - 增加超时到 10000ms
2. ✅ **错误 200400 提示不明确** - 添加友好的错误消息
3. ✅ **`presetteam_changeteam` 未注册** - 注册命令和响应映射

这些修复提高了批量自动化的稳定性和用户体验，尤其是在处理未加入俱乐部的账号时。

---

**版本标识**: v3.10.3  
**后续优化方向**:
1. 在执行 `sendCar` 任务前，预先检查账号的俱乐部状态
2. 根据实际测试情况，动态调整各命令的超时时间
3. 为所有 WebSocket 命令建立统一的超时管理机制

