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

355 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 问题修复 - 发车显示不及时 (v3.10.2)
## 📋 问题描述
用户反馈:"执行进度里token的发车显示不及时"
### 具体表现
在批量任务执行过程中,`TaskProgressCard.vue` 组件显示的发车状态和发车上限信息不会实时更新:
```
批量任务开始时:
┌─────────────────────┐
│ 809服-xxx │
│ 发车: 0/4 今日未发车│ ← 初始显示
└─────────────────────┘
发车任务执行中...
└─ 服务器返回 12000050
└─ localStorage 更新为 4/4
执行完成后:
┌─────────────────────┐
│ 809服-xxx │
│ 发车: 0/4 今日未发车│ ← 仍然显示旧数据!
└─────────────────────┘
```
## 🔍 问题根源
### 技术原因
`TaskProgressCard.vue` 中的 `dailyCarSendCount` 是一个 `computed` 属性,直接从 `localStorage` 读取数据:
```javascript
// 原代码(有问题)
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 无法监听到 `localStorage` 的 `setItem` 操作
- 即使数据已经更新,组件也不会重新渲染
## 💡 v3.10.2 修复方案
### 核心思路
**将 `computed` 改为 `ref`,并手动触发刷新**
1. 使用 `ref` 代替 `computed`,以便手动更新
2. 监听任务结果的变化,自动刷新发车次数
3. 在组件挂载时刷新一次,确保初始显示正确
### 修复内容
#### 1. 改用 `ref` + 手动刷新函数
**修改前**
```javascript
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')
})
```
**修改后**
```javascript
// 获取今日发车次数的 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. 监听任务结果变化
```javascript
// 监听任务结果变化,自动刷新发车次数
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. 监听任务状态变化
```javascript
// 监听任务状态变化,当任务完成或失败时刷新
watch(() => props.progress?.status, (newStatus, oldStatus) => {
if (newStatus !== oldStatus && (newStatus === 'completed' || newStatus === 'failed')) {
// 任务完成或失败时,刷新发车次数
setTimeout(() => {
refreshCarSendCount()
}, 100)
}
})
```
**工作原理**
- 监听整个任务的状态变化
- 当任务完成或失败时,刷新发车次数
- 作为兜底机制,确保任务结束后一定会刷新
#### 4. 组件挂载时刷新
```javascript
// 组件挂载时刷新发车次数
onMounted(() => {
refreshCarSendCount()
})
```
**工作原理**
- 组件首次渲染时从 `localStorage` 读取最新值
- 确保初始显示是准确的
#### 5. 添加必要的导入
```javascript
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)`
```javascript
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 }`
```javascript
watch(() => props.progress?.result?.sendCar, ..., { deep: true })
```
**原因**
- `result.sendCar` 是一个对象,包含 `success`、`data`、`message` 等字段
- `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. ✅ 将 `dailyCarSendCount` 从 `computed` 改为 `ref`
2. ✅ 添加 `refreshCarSendCount()` 手动刷新函数
3. ✅ 监听 `props.progress.result.sendCar` 变化,自动刷新
4. ✅ 监听 `props.progress.status` 变化,兜底刷新
5. ✅ 在 `onMounted` 时刷新,确保初始显示准确
6. ✅ 添加必要的导入:`watch`、`onMounted`
**影响范围**:
- `src/components/TaskProgressCard.vue`
**解决问题**:
- 发车次数显示不及时
- 任务执行后显示不更新
- 需要刷新页面才能看到最新数据
**用户体验提升**:
- ✅ 发车次数实时更新
- ✅ 任务完成后自动刷新
- ✅ 无需手动刷新页面
- ✅ 初始显示准确