# 问题修复 - 功能未开启错误码识别 v3.12.2

**版本**: v3.12.2  
**日期**: 2025-10-08  
**类型**: 问题修复

## 问题描述

用户反馈在批量任务执行时遇到两个错误：

### 错误1：一键答题失败
```
一键答题失败
服务器错误: 200160 - 未知错误
```
**实际情况**：游戏未开启答题模块（等级不够或功能未解锁）

### 错误2：领取挂机奖励失败
```
领取挂机奖励失败
服务器错误: -10006 - 未知错误
```
**实际情况**：游戏未开启挂机奖励模块（等级不够或功能未解锁）

## 问题分析

这两个错误都是由于游戏功能未解锁导致的，属于正常情况：
- 新账号或等级较低的账号可能还未解锁某些功能
- 不同服务器的功能开启条件可能不同
- 这些错误不应该被标记为"失败"，而应该被识别为"功能未开启，跳过"

## 错误码说明

### 一键答题相关错误码

| 错误码 | 含义 | 原处理方式 | 修复后处理方式 |
|--------|------|-----------|--------------|
| `3100080` | 答题次数已用完或功能未开启 | ✅ 跳过，视为成功 | ✅ 跳过，视为成功 |
| `200160` | 答题功能未开启 | ❌ 标记为失败 | ✅ 跳过，视为成功 |

### 领取挂机奖励相关错误码

| 错误码 | 含义 | 原处理方式 | 修复后处理方式 |
|--------|------|-----------|--------------|
| `-10006` | 挂机奖励功能未开启 | ❌ 标记为失败 | ✅ 跳过，视为成功 |

## 解决方案

### 修改1：一键答题 (autoStudy)

在已有的 `3100080` 错误码处理基础上，增加对 `200160` 错误码的识别：

#### 修改前
```javascript
} catch (error) {
  const errorMsg = error.message || String(error)
  
  // 错误码 3100080 通常表示答题次数已用完或答题未开启
  if (errorMsg.includes('3100080')) {
    console.log(`⚠️ [${tokenId}] 答题任务: 答题次数已用完或功能未开启`)
    return {
      task: '一键答题',
      taskId: 'auto_study',
      success: true,
      skipped: true,
      message: '答题次数已用完或功能未开启'
    }
  }
  
  throw error
}
```

#### 修改后
```javascript
} catch (error) {
  const errorMsg = error.message || String(error)
  
  // 错误码 3100080 或 200160 表示答题次数已用完或答题功能未开启
  if (errorMsg.includes('3100080') || errorMsg.includes('200160')) {
    console.log(`⚠️ [${tokenId}] 答题任务: 答题次数已用完或功能未开启`)
    return {
      task: '一键答题',
      taskId: 'auto_study',
      success: true, // 视为成功，不影响整体任务
      skipped: true,
      message: '答题次数已用完或功能未开启'
    }
  }
  
  // 其他错误正常抛出
  throw error
}
```

### 修改2：领取挂机奖励 (claimHangupReward)

将原本简单的 `executeSubTask` 包装改为带错误处理的 try-catch 结构：

#### 修改前
```javascript
case 'claimHangupReward':
  // 领取奖励（领取挂机时间）
  return await executeSubTask(
    tokenId,
    'claim_hangup_reward',
    '领取挂机奖励',
    async () => await client.sendWithPromise('system_claimhangupreward', {}, 3000),
    false
  )
```

#### 修改后
```javascript
case 'claimHangupReward':
  // 领取挂机奖励
  return await executeSubTask(
    tokenId,
    'claim_hangup_reward',
    '领取挂机奖励',
    async () => {
      try {
        const result = await client.sendWithPromise('system_claimhangupreward', {}, 3000)
        return result
      } catch (error) {
        const errorMsg = error.message || String(error)
        
        // 错误码 -10006 表示挂机奖励功能未开启
        if (errorMsg.includes('-10006')) {
          console.log(`⚠️ [${tokenId}] 领取挂机奖励: 功能未开启`)
          return {
            notEnabled: true,
            message: '挂机奖励功能未开启'
          }
        }
        
        // 其他错误正常抛出
        throw error
      }
    },
    false
  )
```

## 修改文件

### src/stores/batchTaskStore.js

**修改位置1**: Line 1206-1207 (autoStudy)
- 将 `errorMsg.includes('3100080')` 改为 `errorMsg.includes('3100080') || errorMsg.includes('200160')`
- 更新注释说明包含两个错误码

**修改位置2**: Line 1222-1249 (claimHangupReward)
- 将简单的函数调用改为 try-catch 包装
- 添加对 `-10006` 错误码的识别
- 返回 `{ notEnabled: true }` 表示功能未开启

## 用户体验改进

### 一键答题

**修改前**：
```
执行进度详情
┌─────────────────────────────┐
│ ❌ 一键答题                 │
│    服务器错误: 200160 -     │
│    未知错误                 │
└─────────────────────────────┘

统计：
- 总任务: 7
- 成功: 6
- 失败: 1  ← 误判
```

**修改后**：
```
执行进度详情
┌─────────────────────────────┐
│ ✅ 一键答题                 │
│    答题次数已用完或功能     │
│    未开启                   │
└─────────────────────────────┘

统计：
- 总任务: 7
- 成功: 7  ← 正确识别
- 失败: 0
```

### 领取挂机奖励

**修改前**：
```
执行进度详情
┌─────────────────────────────┐
│ ❌ 领取挂机奖励             │
│    服务器错误: -10006 -     │
│    未知错误                 │
└─────────────────────────────┘

统计：
- 总任务: 7
- 成功: 6
- 失败: 1  ← 误判
```

**修改后**：
```
执行进度详情
┌─────────────────────────────┐
│ ✅ 领取挂机奖励             │
│    挂机奖励功能未开启       │
└─────────────────────────────┘

统计：
- 总任务: 7
- 成功: 7  ← 正确识别
- 失败: 0
```

### 控制台日志

**一键答题**：
```
// 修改前
❌ [10694服-0-7167...] 一键答题失败: 服务器错误: 200160 - 未知错误

// 修改后
⚠️ [10694服-0-7167...] 答题任务: 答题次数已用完或功能未开启
```

**领取挂机奖励**：
```
// 修改前
❌ [10694服-0-7167...] 领取挂机奖励失败: 服务器错误: -10006 - 未知错误

// 修改后
⚠️ [10694服-0-7167...] 领取挂机奖励: 功能未开启
```

## 功能开启条件

### 一键答题功能

通常需要满足以下条件之一：
- 账号等级达到一定要求（如15级）
- 完成特定的主线任务
- 服务器开启答题活动

### 挂机奖励功能

通常需要满足以下条件：
- 账号等级达到一定要求（如10级）
- 解锁挂机系统
- 完成新手引导

## 技术要点

### 1. 错误码识别优先级

在错误处理中，应优先识别"可预期的非错误状态"：

```javascript
// 优先级1: 功能未开启（视为成功，跳过）
if (errorMsg.includes('200160') || errorMsg.includes('3100080')) {
  return { success: true, skipped: true }
}

// 优先级2: 其他可识别错误
// ...

// 优先级3: 未知错误（抛出）
throw error
```

### 2. 返回格式统一

对于"功能未开启"的情况，统一返回格式：

```javascript
{
  task: '任务名称',
  taskId: 'task_id',
  success: true,      // 标记为成功
  skipped: true,      // 标记为跳过
  message: '友好的提示信息'
}
```

### 3. executeSubTask 的返回处理

当 executor 函数返回一个对象时，`executeSubTask` 会将其包装为：

```javascript
{
  task: taskName,
  taskId: taskId,
  success: true,
  data: {
    notEnabled: true,    // executor 返回的内容
    message: '...'
  },
  skipped: false
}
```

这样也能正确表示"成功但功能未开启"的状态。

## 特殊错误码格式

### 负数错误码

错误码 `-10006` 是一个负数，这在游戏服务器中比较少见：
- 可能表示系统级错误
- 可能表示配置未加载
- 需要使用 `errorMsg.includes('-10006')` 进行字符串匹配

## 相关错误码汇总

### 答题相关

| 错误码 | 含义 | 处理方式 | 版本 |
|--------|------|---------|------|
| `3100080` | 答题次数已用完或功能未开启 | ✅ 成功（跳过） | v3.11.5 |
| `200160` | 答题功能未开启 | ✅ 成功（跳过） | v3.12.2 |

### 挂机奖励相关

| 错误码 | 含义 | 处理方式 | 版本 |
|--------|------|---------|------|
| `-10006` | 挂机奖励功能未开启 | ✅ 成功（跳过） | v3.12.2 |

### 其他功能相关

| 错误码 | 功能 | 含义 | 处理方式 |
|--------|------|------|---------|
| `2300190` | 俱乐部签到 | 今日已签到 | ✅ 成功 |
| `200020` | 俱乐部签到 | 今日已签到 | ✅ 成功 |
| `2300070` | 俱乐部签到/发车 | 未加入俱乐部 | ❌ 失败 |
| `200350` | 发车 | 非发车时间 | ⚠️ 跳过 |

## 测试验证

### 测试场景1：低等级账号（功能未开启）

```
账号等级: 5级
答题功能: 未解锁
挂机奖励: 未解锁

执行结果:
- ✅ 一键答题: 答题次数已用完或功能未开启（跳过）
- ✅ 领取挂机奖励: 挂机奖励功能未开启（跳过）
- 总任务: 7
- 成功: 7
- 失败: 0
```

### 测试场景2：高等级账号（功能已开启）

```
账号等级: 50级
答题功能: 已解锁
挂机奖励: 已解锁

执行结果:
- ✅ 一键答题: 答题完成
- ✅ 领取挂机奖励: 领取成功
- 总任务: 7
- 成功: 7
- 失败: 0
```

### 测试场景3：答题次数已用完

```
账号等级: 50级
答题功能: 已解锁
今日答题: 已完成

执行结果:
- ✅ 一键答题: 答题次数已用完或功能未开启（跳过）
  （错误码可能是 3100080 或 200160）
- 总任务: 7
- 成功: 7
- 失败: 0
```

## 最佳实践

### 1. 功能未开启的识别

对于"功能未开启"类的错误，应该：
- ✅ 识别为成功状态（不影响整体任务）
- ✅ 标记为跳过（`skipped: true`）
- ✅ 提供友好的提示信息
- ❌ 不应标记为失败

### 2. 错误消息优化

```javascript
// ❌ 不好的做法：显示原始错误码
return { error: '服务器错误: 200160 - 未知错误' }

// ✅ 好的做法：提供友好的说明
return { 
  success: true, 
  skipped: true,
  message: '答题功能未开启'
}
```

### 3. 批量任务中的处理

在批量任务中，应区分：
- **真正的失败**：需要重试或用户处理
- **可预期的跳过**：功能未开启、已完成等
- **成功**：正常执行成功

## 使用建议

### 对于用户

如果看到"功能未开启"的提示：
1. **不用担心**：这不是错误，而是正常的状态
2. **提升等级**：继续升级角色，解锁更多功能
3. **关注任务**：完成主线任务，通常会解锁新功能
4. **自定义模板**：可以创建不包含未解锁功能的任务模板

### 对于开发者

添加新功能时，应考虑：
1. **功能未开启的错误码**是什么
2. **如何友好地处理**这些错误
3. **是否需要区分**"未开启"和"已用完"

## 相关版本

- **v3.11.5**: 首次添加错误码 3100080 识别（答题）
- **v3.12.1**: 添加错误码 200020 识别（俱乐部签到）
- **v3.12.2**: 添加错误码 200160 和 -10006 识别（本版本）

## 总结

**问题**：
- ❌ 错误码 200160（答题功能未开启）被识别为失败
- ❌ 错误码 -10006（挂机奖励功能未开启）被识别为失败
- ❌ 影响低等级账号的批量任务成功率

**修复**：
- ✅ 识别错误码 200160 为"答题功能未开启"
- ✅ 识别错误码 -10006 为"挂机奖励功能未开启"
- ✅ 标记为成功（跳过）状态，不影响整体任务

**效果**：
- ✅ 低等级账号也能正常执行批量任务
- ✅ 避免误判功能未开启为失败
- ✅ 提供友好的提示信息
- ✅ 提高批量任务成功率统计准确性

---

**状态**: ✅ 已修复  
**版本**: v3.12.2

