1.0
This commit is contained in:
354
MD说明文件夹/问题修复-发车显示不及时v3.10.2.md
Normal file
354
MD说明文件夹/问题修复-发车显示不及时v3.10.2.md
Normal file
@@ -0,0 +1,354 @@
|
||||
# 问题修复 - 发车显示不及时 (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`
|
||||
|
||||
**解决问题**:
|
||||
- 发车次数显示不及时
|
||||
- 任务执行后显示不更新
|
||||
- 需要刷新页面才能看到最新数据
|
||||
|
||||
**用户体验提升**:
|
||||
- ✅ 发车次数实时更新
|
||||
- ✅ 任务完成后自动刷新
|
||||
- ✅ 无需手动刷新页面
|
||||
- ✅ 初始显示准确
|
||||
|
||||
Reference in New Issue
Block a user