Files
xyzw_web_helper/MD说明文件夹/问题修复-批量任务统计计数错误v3.6.1.md
2025-10-17 20:56:50 +08:00

9.3 KiB
Raw Blame History

问题修复 - 批量任务统计计数错误 v3.6.1

📌 修复时间

2025-10-07

🐛 问题描述

现象

在批量自动化任务执行过程中,出现严重的统计错误

统计数据异常

  • 总计: 318个token
  • 成功: 132个
  • 失败: 0个 (明显错误)
  • 跳过: 0个
  • 遗失: 186个token未被统计

显示矛盾

大量token卡片出现自相矛盾的显示

  • 状态标签:"已完成"(绿色)
  • 显示文字:"失败名"(红色)
  • 矛盾失败的token被错误标记为"已完成"

用户反馈

  1. "明明有存在失败的没有进行wss链接的token卡片但是总计却没有显示失败的"

  2. "有大量失败的token卡片显示已完成可能这是导致失败统计错误的关键" (关键发现)

🔍 问题分析

核心问题(主要)⚠️

问题1: 子任务失败被忽略

executeTokenTasks 函数第327-413行存在严重逻辑错误

} catch (error) {
  console.error(`  ❌ 任务失败: ${taskName}`, error.message)
  
  // 保存错误信息
  taskProgress.value[tokenId].result[taskName] = {
    success: false,
    error: error.message
  }
  
  // ❌ 问题:只记录错误,没有统计失败数量
  // 继续执行下一个任务(单个任务失败不影响整体)
}

// ❌ 核心问题:无论上面有多少任务失败,都标记为完成
updateTaskProgress(tokenId, {
  status: 'completed',  // ❌ 错误!
  progress: 100,
  currentTask: null,
  endTime: Date.now()
})

executionStats.value.success++  // ❌ 错误!计入成功
console.log(`✅ Token完成: ${token.name}`)

问题本质

  • for循环中的catch块捕获了子任务错误
  • 但只是记录错误,继续执行下一个任务
  • 循环结束后,无论有多少任务失败,都标记为"completed"并计入成功
  • 这导致所有token都显示"已完成",即使所有子任务都失败了

次要问题

问题2: Promise异常处理不完整

executeBatchWithConcurrency 函数中外层catch块未更新失败计数已在上次提交修复

解决方案

修复1: 智能状态判断(核心修复)

添加失败计数和智能状态判断逻辑:

// 依次执行任务
let taskFailedCount = 0 // 🆕 记录失败的任务数量

for (let i = 0; i < tasks.length; i++) {
  // ... 任务执行代码 ...
  
  try {
    const result = await executeTask(tokenId, taskName)
    // ... 成功处理 ...
  } catch (error) {
    console.error(`  ❌ 任务失败: ${taskName}`, error.message)
    
    taskProgress.value[tokenId].result[taskName] = {
      success: false,
      error: error.message
    }
    
    taskFailedCount++ // 🆕 增加失败计数
  }
}

// 🆕 根据任务执行情况决定最终状态
const hasAnyTaskFailed = taskFailedCount > 0
const allTasksFailed = taskFailedCount === tasks.length

if (allTasksFailed) {
  // 所有任务都失败 - 标记为失败
  updateTaskProgress(tokenId, {
    status: 'failed',
    progress: 100,
    currentTask: null,
    error: `所有任务执行失败 (${taskFailedCount}/${tasks.length})`,
    endTime: Date.now()
  })
  executionStats.value.failed++
  console.log(`❌ Token失败: ${token.name} (所有任务都失败)`)
} else if (hasAnyTaskFailed) {
  // 部分任务失败 - 标记为部分完成(视为完成但记录错误)
  updateTaskProgress(tokenId, {
    status: 'completed',
    progress: 100,
    currentTask: null,
    error: `部分任务失败 (${taskFailedCount}/${tasks.length})`,
    endTime: Date.now()
  })
  executionStats.value.success++
  console.log(`⚠️ Token部分完成: ${token.name} (${taskFailedCount}个任务失败)`)
} else {
  // 所有任务成功 - 标记为完成
  updateTaskProgress(tokenId, {
    status: 'completed',
    progress: 100,
    currentTask: null,
    endTime: Date.now()
  })
  executionStats.value.success++
  console.log(`✅ Token完成: ${token.name}`)
}

修复逻辑

三种状态判断

  1. 所有任务失败 (taskFailedCount === tasks.length)

    • 标记为 'failed'
    • 计入失败统计
    • 记录详细错误信息
  2. 部分任务失败 (taskFailedCount > 0)

    • 标记为 'completed'(视为部分完成)
    • 计入成功统计(因为至少完成了部分任务)
    • 在error字段记录失败信息便于查看
  3. 所有任务成功 (taskFailedCount === 0)

    • 标记为 'completed'
    • 计入成功统计

设计考量

  • 为什么部分失败算成功?

    • 一键补差有40+个子任务
    • 如果1个任务失败就算整体失败会导致成功率过低
    • 部分完成仍有价值(大部分奖励已领取)
    • 通过error字段可查看具体失败了哪些任务
  • 如何区分部分失败和全部成功?

    • 查看token卡片的error信息
    • 部分失败会显示:部分任务失败 (3/43)
    • 全部成功不会有error信息

修复2: Promise异常处理补充

在外层catch中添加状态检查避免重复计数

.catch(error => {
  console.error(`❌ Token ${tokenId} 执行失败:`, error)
  
  // 🆕 确保失败计数被正确更新
  const tokenProgress = taskProgress.value[tokenId]
  if (!tokenProgress || tokenProgress.status === 'pending' || tokenProgress.status === 'executing') {
    // 只有当状态还未最终确定时才更新(避免重复计数)
    updateTaskProgress(tokenId, {
      status: 'failed',
      error: error.message,
      endTime: Date.now()
    })
    executionStats.value.failed++
  }
  
  // 清理执行队列
  const index = executing.indexOf(promise)
  if (index > -1) {
    executing.splice(index, 1)
  }
  executingTokens.value.delete(tokenId)
})

📊 修复效果对比

修复前(错误)

总计: 318
成功: 132  ← 包含了大量实际失败的token
失败: 0    ← 错误!所有失败都被误判为成功
跳过: 0
合计: 132  ← 遗失了186个token

Token显示矛盾
- 状态:已完成(绿色)❌
- 文字:失败名(红色)❌

修复后(正确)

总计: 318
成功: X    ← 只包含真正成功或部分完成的token
失败: Y    ← 正确统计所有任务都失败的token
跳过: 0
合计: 318  ← 完整统计

Token显示一致
- 所有任务失败:状态=失败(红色),文字=失败名(红色)✅
- 部分任务失败:状态=已完成绿色error=部分任务失败 (X/43)
- 所有任务成功:状态=已完成(绿色),无错误信息

🔧 涉及文件

  • src/stores/batchTaskStore.js
    • 第327-413行executeTokenTasks 函数(核心修复)
    • 第257-279行Promise异常处理补充修复

📝 测试建议

测试场景1: 所有任务失败

  1. 断开网络或使用无效token
  2. 执行批量任务
  3. 验证:
    • token状态标记为"失败"
    • 失败计数正确增加
    • error显示所有任务执行失败 (6/6)

测试场景2: 部分任务失败

  1. 使用正常token但模拟部分子任务失败
  2. 验证:
    • token状态标记为"已完成"
    • 成功计数增加
    • error显示部分任务失败 (2/6)

测试场景3: 所有任务成功

  1. 使用正常token和网络
  2. 验证:
    • token状态标记为"已完成"
    • 成功计数增加
    • error为空

测试场景4: 高并发混合场景

  1. 并发100个token成功、部分失败、全部失败混合
  2. 验证:
    • 成功 + 失败 + 跳过 = 总计
    • 不存在"遗失"的统计
    • 每个token状态与实际情况一致

🎯 预期结果

统计准确性

  • 所有token都被正确统计
  • 成功 + 失败 + 跳过 = 总计
  • 失败计数准确反映"所有任务都失败"的token数量
  • 成功计数包含"全部成功"和"部分成功"的token

显示一致性

  • token状态与实际执行结果一致
  • 不再出现"已完成"但显示"失败名"的矛盾
  • 部分失败的token通过error字段明确标识

用户体验

  • 清晰了解哪些token完全失败
  • 可通过error信息查看部分失败详情
  • 统计数据可信,便于决策

📌 注意事项

1. 部分失败的处理策略

  • 部分失败计入"成功"是合理的设计
  • 一键补差有40+个子任务,允许部分容错
  • 用户可通过详情查看具体失败的子任务

2. 避免重复计数

  • 通过 taskFailedCount 精确统计失败数量
  • 外层catch通过状态检查避免重复更新
  • 确保每个token只被计入一次

3. 错误信息保留

  • 所有失败都会记录详细错误信息
  • 部分失败会注明失败比例
  • 便于后续排查和优化

🔗 相关文档

📅 版本信息

  • 版本号: v3.6.1
  • 修复日期: 2025-10-07
  • 问题类型: 严重Bug修复
  • 优先级: 最高(影响核心统计逻辑)
  • 影响范围: 所有批量任务执行