Files
xyzw_web_helper/MD说明文件夹/问题修复-发车显示不及时v3.10.2.md
2025-10-17 20:56:50 +08:00

10 KiB
Raw Permalink Blame History

问题修复 - 发车显示不及时 (v3.10.2)

📋 问题描述

用户反馈:"执行进度里token的发车显示不及时"

具体表现

在批量任务执行过程中,TaskProgressCard.vue 组件显示的发车状态和发车上限信息不会实时更新:

批量任务开始时:
┌─────────────────────┐
│ 809服-xxx           │
│ 发车: 0/4  今日未发车│  ← 初始显示
└─────────────────────┘

发车任务执行中...
└─ 服务器返回 12000050
└─ localStorage 更新为 4/4

执行完成后:
┌─────────────────────┐
│ 809服-xxx           │
│ 发车: 0/4  今日未发车│  ← 仍然显示旧数据!
└─────────────────────┘

🔍 问题根源

技术原因

TaskProgressCard.vue 中的 dailyCarSendCount 是一个 computed 属性,直接从 localStorage 读取数据:

// 原代码(有问题)
const dailyCarSendCount = computed(() => {
  const today = new Date().toLocaleDateString('zh-CN', { 
    year: 'numeric', 
    month: '2-digit', 
    day: '2-digit' 
  })
  const key = `car_daily_send_count_${today}_${props.tokenId}`
  return parseInt(localStorage.getItem(key) || '0')
})

为什么不更新?

Vue 的响应式系统无法追踪 localStorage 的变化!

  1. computed 的响应式机制

    • computed 只会在其依赖的 响应式数据 发生变化时重新计算
    • localStorage.getItem() 不是响应式的
  2. 数据流向

    batchTaskStore.js
    └─ 更新 localStorage.setItem('car_daily_send_count_...', '4')
       ↓
    localStorage 已更新
       ↓
    TaskProgressCard.vue
    └─ computed 不知道 localStorage 变了
    └─ 继续显示旧值 0
    
  3. 无法自动检测

    • Vue 无法监听到 localStoragesetItem 操作
    • 即使数据已经更新,组件也不会重新渲染

💡 v3.10.2 修复方案

核心思路

computed 改为 ref,并手动触发刷新

  1. 使用 ref 代替 computed,以便手动更新
  2. 监听任务结果的变化,自动刷新发车次数
  3. 在组件挂载时刷新一次,确保初始显示正确

修复内容

1. 改用 ref + 手动刷新函数

修改前

const dailyCarSendCount = computed(() => {
  const today = new Date().toLocaleDateString('zh-CN', { 
    year: 'numeric', 
    month: '2-digit', 
    day: '2-digit' 
  })
  const key = `car_daily_send_count_${today}_${props.tokenId}`
  return parseInt(localStorage.getItem(key) || '0')
})

修改后

// 获取今日发车次数的 key
const getCarSendCountKey = () => {
  const today = new Date().toLocaleDateString('zh-CN', { 
    year: 'numeric', 
    month: '2-digit', 
    day: '2-digit' 
  })
  return `car_daily_send_count_${today}_${props.tokenId}`
}

// 使用 ref 而不是 computed以便手动刷新
const dailyCarSendCount = ref(parseInt(localStorage.getItem(getCarSendCountKey()) || '0'))

// 刷新发车次数的函数
const refreshCarSendCount = () => {
  const key = getCarSendCountKey()
  const newCount = parseInt(localStorage.getItem(key) || '0')
  dailyCarSendCount.value = newCount
  console.log(`🔄 [${props.tokenId}] 刷新发车次数显示: ${newCount}/4`)
}

2. 监听任务结果变化

// 监听任务结果变化,自动刷新发车次数
watch(() => props.progress?.result?.sendCar, (newResult, oldResult) => {
  if (newResult && newResult !== oldResult) {
    // 发车任务有新结果,等待一小段时间确保 localStorage 已更新
    setTimeout(() => {
      refreshCarSendCount()
    }, 100)
  }
}, { deep: true })

工作原理

  • 监听 props.progress.result.sendCar 的变化
  • sendCar 任务有新结果时(成功或失败)
  • 等待 100ms 确保 localStorage 已更新
  • 调用 refreshCarSendCount()localStorage 读取最新值

3. 监听任务状态变化

// 监听任务状态变化,当任务完成或失败时刷新
watch(() => props.progress?.status, (newStatus, oldStatus) => {
  if (newStatus !== oldStatus && (newStatus === 'completed' || newStatus === 'failed')) {
    // 任务完成或失败时,刷新发车次数
    setTimeout(() => {
      refreshCarSendCount()
    }, 100)
  }
})

工作原理

  • 监听整个任务的状态变化
  • 当任务完成或失败时,刷新发车次数
  • 作为兜底机制,确保任务结束后一定会刷新

4. 组件挂载时刷新

// 组件挂载时刷新发车次数
onMounted(() => {
  refreshCarSendCount()
})

工作原理

  • 组件首次渲染时从 localStorage 读取最新值
  • 确保初始显示是准确的

5. 添加必要的导入

import { ref, computed, watch, onMounted } from 'vue'

📊 修复效果对比

修改前v3.10.1

时间线:
00:00 - 批量任务开始
        TaskProgressCard 显示: 发车: 0/4 ✓
        
00:05 - sendCar 任务执行
        batchTaskStore 更新 localStorage: 0 → 4
        
00:06 - sendCar 任务完成
        TaskProgressCard 显示: 发车: 0/4 ✗ (未更新!)
        
00:10 - 批量任务完成
        TaskProgressCard 显示: 发车: 0/4 ✗ (仍未更新!)
        
用户需要刷新页面才能看到正确的 4/4

修改后v3.10.2

时间线:
00:00 - 批量任务开始
        TaskProgressCard 显示: 发车: 0/4 ✓
        
00:05 - sendCar 任务执行
        batchTaskStore 更新 localStorage: 0 → 4
        
00:06 - sendCar 任务完成
        props.progress.result.sendCar 更新
        触发 watch 回调
        100ms 后调用 refreshCarSendCount()
        TaskProgressCard 显示: 发车: 4/4 ✓ (自动更新!)
        
00:10 - 批量任务完成
        再次触发刷新(兜底)
        TaskProgressCard 显示: 发车: 4/4 ✓
        
用户无需刷新页面,自动显示正确的 4/4

🎯 关键优势

特性 修改前 修改后
数据类型 computed ref + 手动刷新
更新机制 依赖响应式系统 主动监听和刷新
初始显示 可能不准确 onMounted 确保准确
任务执行中 不更新 实时更新
任务完成后 不更新 自动更新
用户体验 需要手动刷新页面 自动显示最新数据

📝 技术细节

为什么使用 setTimeout(100)

setTimeout(() => {
  refreshCarSendCount()
}, 100)

原因

  1. 确保 localStorage 已更新

    • batchTaskStore 更新 localStorage
    • Vue 更新 props.progress.result.sendCar
    • watch 回调触发
    • 这些操作可能不是完全同步的
  2. 异步写入的保险

    • 虽然 localStorage.setItem() 通常是同步的
    • 但在某些浏览器或情况下可能有延迟
    • 100ms 的延迟可以确保数据已经写入
  3. 避免竞态条件

    • 如果立即读取,可能还是旧值
    • 延迟后读取,确保是最新值

为什么使用两个 watch

  1. 第一个 watch:监听 sendCar 任务结果

    • 更精确:只在发车任务有结果时触发
    • 更及时:任务一完成就立即刷新
  2. 第二个 watch:监听整体任务状态

    • 兜底机制:确保任务结束时一定会刷新
    • 更全面:即使第一个 watch 没触发,这个也会

为什么使用 { deep: true }

watch(() => props.progress?.result?.sendCar, ..., { deep: true })

原因

  • result.sendCar 是一个对象,包含 successdatamessage 等字段
  • deep: true 确保对象内部任何属性变化都会触发 watch
  • 这样无论任务成功还是失败,都能正确触发刷新

🧪 测试建议

测试场景1首次打开批量任务面板

  1. 打开批量任务面板
  2. 观察 Token 卡片的发车显示
  3. 预期结果:显示正确的发车次数(从 localStorage 读取)

测试场景2执行发车任务

  1. 执行包含发车任务的批量自动化
  2. 观察 Token 卡片的发车显示
  3. 预期结果
    • 发车任务执行过程中,显示实时更新
    • 任务完成后,立即显示最新的发车次数
    • 控制台输出:🔄 [token_xxx] 刷新发车次数显示: X/4

测试场景3服务器端已达上限

  1. 使用已达上限的账号服务器端4次
  2. 客户端 localStorage 为 0/4
  3. 执行批量任务
  4. 预期结果
    • 初始显示0/4
    • 任务执行后立即更新为4/4根据错误码 12000050 更新)
    • Token 卡片显示:"今日已达上限"

测试场景4多 Token 并发

  1. 选择多个 Token 执行批量任务
  2. 观察每个 Token 卡片的发车显示
  3. 预期结果
    • 每个 Token 的发车次数独立更新
    • 不会互相干扰
    • 所有 Token 都显示正确的发车次数

🔗 相关修复

本次修复建立在以下修复的基础上:

  1. v3.10.0 - 同步服务器发车次数(失败)
  2. v3.10.1 - 修复服务器 sendCount 不可靠
  3. v3.10.2 - 修复发车显示不及时(本次)

📋 更新日志

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

修改内容:

  1. dailyCarSendCountcomputed 改为 ref
  2. 添加 refreshCarSendCount() 手动刷新函数
  3. 监听 props.progress.result.sendCar 变化,自动刷新
  4. 监听 props.progress.status 变化,兜底刷新
  5. onMounted 时刷新,确保初始显示准确
  6. 添加必要的导入:watchonMounted

影响范围:

  • src/components/TaskProgressCard.vue

解决问题:

  • 发车次数显示不及时
  • 任务执行后显示不更新
  • 需要刷新页面才能看到最新数据

用户体验提升:

  • 发车次数实时更新
  • 任务完成后自动刷新
  • 无需手动刷新页面
  • 初始显示准确