307 lines
10 KiB
Markdown
307 lines
10 KiB
Markdown
|
|
# 功能优化 - 同步服务器发车次数 (v3.10.0)
|
|||
|
|
|
|||
|
|
## 📋 优化背景
|
|||
|
|
|
|||
|
|
### v3.9.9 测试发现的问题
|
|||
|
|
|
|||
|
|
在v3.9.9测试中,发现了客户端和服务器端发车次数不一致的问题:
|
|||
|
|
|
|||
|
|
| 位置 | 今日发车次数 | 是否达到上限 |
|
|||
|
|
|------|-------------|-------------|
|
|||
|
|
| **客户端(localStorage)** | 0/4 | 否 |
|
|||
|
|
| **服务器端** | ?/4 | **是(错误码12000050)** |
|
|||
|
|
|
|||
|
|
**问题原因**:
|
|||
|
|
- 客户端使用 `localStorage` 存储发车次数
|
|||
|
|
- 用户可能清除缓存或在不同设备登录
|
|||
|
|
- 服务器端的发车次数是权威数据源
|
|||
|
|
- 导致客户端和服务器端数据不一致
|
|||
|
|
|
|||
|
|
## 💡 v3.10.0 解决方案
|
|||
|
|
|
|||
|
|
### 核心思路
|
|||
|
|
|
|||
|
|
**服务器端数据为准,客户端实时同步**:
|
|||
|
|
1. 每次查询车辆时,获取服务器端的 `sendCount`
|
|||
|
|
2. 与客户端 `localStorage` 中的值比较
|
|||
|
|
3. 如果不一致,以服务器端为准,更新本地存储
|
|||
|
|
4. 在发送前再次确认,避免不必要的发送尝试
|
|||
|
|
|
|||
|
|
### 优化点
|
|||
|
|
|
|||
|
|
#### 1. 查询车辆时同步发车次数
|
|||
|
|
|
|||
|
|
**位置**: 初次查询车辆后
|
|||
|
|
|
|||
|
|
**代码**:
|
|||
|
|
```javascript
|
|||
|
|
// 获取服务器端的发车次数并同步到本地
|
|||
|
|
const serverSendCount = queryResponse.roleCar?.sendCount || 0
|
|||
|
|
const dailySendKey = getTodayKey(tokenId)
|
|||
|
|
let dailySendCount = parseInt(localStorage.getItem(dailySendKey) || '0')
|
|||
|
|
|
|||
|
|
// 以服务器端的值为准(服务器端更权威)
|
|||
|
|
if (serverSendCount !== dailySendCount) {
|
|||
|
|
console.log(`🔄 [${tokenId}] 同步服务器发车次数: 客户端${dailySendCount} → 服务器${serverSendCount}`)
|
|||
|
|
localStorage.setItem(dailySendKey, serverSendCount.toString())
|
|||
|
|
dailySendCount = serverSendCount
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log(`✅ [${tokenId}] 查询到 ${carIds.length} 辆车(今日已发车: ${dailySendCount}/4)`)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**效果**:
|
|||
|
|
- ✅ 立即发现并修正客户端和服务器端的差异
|
|||
|
|
- ✅ 提前告知用户真实的发车次数
|
|||
|
|
- ✅ 避免后续不必要的操作
|
|||
|
|
|
|||
|
|
#### 2. 刷新车辆后再次同步
|
|||
|
|
|
|||
|
|
**位置**: 批量刷新车辆并重新查询后
|
|||
|
|
|
|||
|
|
**代码**:
|
|||
|
|
```javascript
|
|||
|
|
// 重新查询车辆状态
|
|||
|
|
const reQueryResponse = await tokenStore.sendMessageAsync(tokenId, 'car_getrolecar', {}, 20000)
|
|||
|
|
if (reQueryResponse?.roleCar?.carDataMap) {
|
|||
|
|
Object.assign(carDataMap, reQueryResponse.roleCar.carDataMap)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 同步服务器端的发车次数
|
|||
|
|
if (reQueryResponse?.roleCar?.sendCount !== undefined) {
|
|||
|
|
const newServerSendCount = reQueryResponse.roleCar.sendCount
|
|||
|
|
if (newServerSendCount !== dailySendCount) {
|
|||
|
|
console.log(`🔄 [${tokenId}] 刷新后同步发车次数: ${dailySendCount} → ${newServerSendCount}`)
|
|||
|
|
localStorage.setItem(dailySendKey, newServerSendCount.toString())
|
|||
|
|
dailySendCount = newServerSendCount
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**效果**:
|
|||
|
|
- ✅ 确保刷新操作后数据依然同步
|
|||
|
|
- ✅ 检测是否有其他设备/页面发车
|
|||
|
|
|
|||
|
|
#### 3. 发送前最后一次确认
|
|||
|
|
|
|||
|
|
**位置**: 等待3秒状态同步后,发送车辆前
|
|||
|
|
|
|||
|
|
**代码**:
|
|||
|
|
```javascript
|
|||
|
|
// 重新查询车辆状态
|
|||
|
|
console.log(`🔍 [${tokenId}] 重新查询车辆状态...`)
|
|||
|
|
const finalQueryResponse = await tokenStore.sendMessageAsync(tokenId, 'car_getrolecar', {}, 20000)
|
|||
|
|
if (finalQueryResponse?.roleCar?.carDataMap) {
|
|||
|
|
Object.assign(carDataMap, finalQueryResponse.roleCar.carDataMap)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 同步服务器端的发车次数(发送前最后一次确认)
|
|||
|
|
if (finalQueryResponse?.roleCar?.sendCount !== undefined) {
|
|||
|
|
const latestServerSendCount = finalQueryResponse.roleCar.sendCount
|
|||
|
|
if (latestServerSendCount !== dailySendCount) {
|
|||
|
|
console.log(`🔄 [${tokenId}] 发送前同步发车次数: ${dailySendCount} → ${latestServerSendCount}`)
|
|||
|
|
localStorage.setItem(dailySendKey, latestServerSendCount.toString())
|
|||
|
|
dailySendCount = latestServerSendCount
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 最后检查发车次数限制
|
|||
|
|
const currentRemainingSendCount = 4 - dailySendCount
|
|||
|
|
|
|||
|
|
if (currentRemainingSendCount <= 0) {
|
|||
|
|
console.warn(`⚠️ [${tokenId}] 发送前检查: 今日发车次数已达上限(${dailySendCount}/4),跳过发送`)
|
|||
|
|
sendCarResults.push({
|
|||
|
|
task: '批量发送',
|
|||
|
|
success: true,
|
|||
|
|
message: `今日发车次数已达上限(${dailySendCount}/4),跳过发送`
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
task: '发车',
|
|||
|
|
taskId: 'send_car',
|
|||
|
|
success: true,
|
|||
|
|
data: sendCarResults,
|
|||
|
|
message: `今日发车次数已达上限(${dailySendCount}/4)`
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**效果**:
|
|||
|
|
- ✅ 发送前最后一次检查,避免浪费发送请求
|
|||
|
|
- ✅ 如果已达上限,提前退出并告知用户
|
|||
|
|
- ✅ 使用最新的发车次数计算剩余额度
|
|||
|
|
|
|||
|
|
#### 4. 增强错误处理
|
|||
|
|
|
|||
|
|
**位置**: 发送车辆失败时
|
|||
|
|
|
|||
|
|
**代码**:
|
|||
|
|
```javascript
|
|||
|
|
catch (error) {
|
|||
|
|
const errorMsg = error.message || String(error)
|
|||
|
|
|
|||
|
|
// 区分不同的错误类型
|
|||
|
|
if (errorMsg.includes('12000050')) {
|
|||
|
|
console.log(`⚠️ [${tokenId}] 车辆 ${carId} 发送失败: 今日发车次数已达上限(服务器端限制)`)
|
|||
|
|
} else if (errorMsg.includes('200020')) {
|
|||
|
|
console.log(`⚠️ [${tokenId}] 车辆 ${carId} 发送失败: 处于冷却期或状态未同步`)
|
|||
|
|
} else {
|
|||
|
|
console.log(`❌ [${tokenId}] 发送车辆失败: ${carId} - ${errorMsg}`)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**效果**:
|
|||
|
|
- ✅ 清晰区分不同类型的失败原因
|
|||
|
|
- ✅ 用户能快速理解问题所在
|
|||
|
|
- ✅ 避免误认为是bug
|
|||
|
|
|
|||
|
|
## 📊 优化效果对比
|
|||
|
|
|
|||
|
|
### 修改前(v3.9.9及之前)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
📊 [token_xxx] 今日已发车次数: 0/4 ← 客户端数据(可能不准确)
|
|||
|
|
🚀 [token_xxx] 待发车: 4辆,剩余额度: 4个,将发送: 4辆
|
|||
|
|
❌ [token_xxx] 发送车辆失败: xxx - 服务器错误: 12000050 - 未知错误
|
|||
|
|
❌ [token_xxx] 发送车辆失败: xxx - 服务器错误: 12000050 - 未知错误
|
|||
|
|
❌ [token_xxx] 发送车辆失败: xxx - 服务器错误: 12000050 - 未知错误
|
|||
|
|
❌ [token_xxx] 发送车辆失败: xxx - 服务器错误: 12000050 - 未知错误
|
|||
|
|
🚀 [token_xxx] 发送完成:成功0次,跳过0次
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**问题**:
|
|||
|
|
- ❌ 客户端显示 0/4,但服务器认为已达上限
|
|||
|
|
- ❌ 尝试发送4辆车,全部失败
|
|||
|
|
- ❌ 错误信息不明确("未知错误")
|
|||
|
|
- ❌ 浪费了4次发送请求
|
|||
|
|
|
|||
|
|
### 修改后(v3.10.0)
|
|||
|
|
|
|||
|
|
**场景1:服务器端已达上限**
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
✅ [token_xxx] 查询到 4 辆车(今日已发车: 0/4)
|
|||
|
|
🔄 [token_xxx] 同步服务器发车次数: 客户端0 → 服务器4 ← 立即发现差异
|
|||
|
|
✅ [token_xxx] 查询到 4 辆车(今日已发车: 4/4) ← 更新显示
|
|||
|
|
📊 [token_xxx] 检查每日发车次数限制: 4/4
|
|||
|
|
⚠️ [token_xxx] 今日发车次数已达上限: 4/4 ← 提前检测
|
|||
|
|
🚀 [token_xxx] 开始批量发送...
|
|||
|
|
⏳ [token_xxx] 等待服务器状态同步(3秒)...
|
|||
|
|
🔍 [token_xxx] 重新查询车辆状态...
|
|||
|
|
⚠️ [token_xxx] 发送前检查: 今日发车次数已达上限(4/4),跳过发送 ← 提前退出
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**效果**:
|
|||
|
|
- ✅ 立即发现并修正数据差异
|
|||
|
|
- ✅ 提前检测到已达上限
|
|||
|
|
- ✅ 避免了4次无效的发送请求
|
|||
|
|
- ✅ 清晰告知用户原因
|
|||
|
|
|
|||
|
|
**场景2:服务器端还有额度**
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
✅ [token_xxx] 查询到 4 辆车(今日已发车: 0/4)
|
|||
|
|
🔄 [token_xxx] 同步服务器发车次数: 客户端0 → 服务器2 ← 同步差异
|
|||
|
|
✅ [token_xxx] 查询到 4 辆车(今日已发车: 2/4) ← 更新显示
|
|||
|
|
📊 [token_xxx] 检查每日发车次数限制: 2/4
|
|||
|
|
🚀 [token_xxx] 开始批量发送...
|
|||
|
|
⏳ [token_xxx] 等待服务器状态同步(3秒)...
|
|||
|
|
🔍 [token_xxx] 重新查询车辆状态...
|
|||
|
|
🚀 [token_xxx] 待发车: 4辆,剩余额度: 2个,将发送: 2辆 ← 正确计算
|
|||
|
|
✅ [token_xxx] 发送车辆成功: xxx
|
|||
|
|
✅ [token_xxx] 发送车辆成功: xxx
|
|||
|
|
🚀 [token_xxx] 发送完成:成功2次,跳过0次,今日4/4 ← 完美!
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**效果**:
|
|||
|
|
- ✅ 同步真实的发车次数
|
|||
|
|
- ✅ 正确计算剩余额度
|
|||
|
|
- ✅ 成功发送2辆车(不多不少)
|
|||
|
|
- ✅ 最终达到每日上限 4/4
|
|||
|
|
|
|||
|
|
## 🎯 关键改进点总结
|
|||
|
|
|
|||
|
|
| 优化点 | 修改前 | 修改后 |
|
|||
|
|
|--------|--------|--------|
|
|||
|
|
| **数据来源** | 只使用客户端 localStorage | 以服务器端为准,实时同步 |
|
|||
|
|
| **同步时机** | 只在发送成功后更新 | 查询、刷新、发送前都同步 |
|
|||
|
|
| **错误处理** | 通用错误信息 | 区分 12000050、200020 等错误码 |
|
|||
|
|
| **提前检测** | 无 | 发送前检测并提前退出 |
|
|||
|
|
| **用户体验** | 尝试发送才知道失败 | 提前告知,避免无效请求 |
|
|||
|
|
| **日志清晰度** | 显示客户端数据(可能不准) | 显示真实数据并标注同步 |
|
|||
|
|
|
|||
|
|
## 📝 测试建议
|
|||
|
|
|
|||
|
|
### 测试场景1:客户端数据过期
|
|||
|
|
|
|||
|
|
1. 在游戏功能页面手动发车2辆
|
|||
|
|
2. 清除浏览器 localStorage
|
|||
|
|
3. 在批量自动化中发车
|
|||
|
|
4. **预期**:自动同步服务器端的2次记录,只发送剩余2辆
|
|||
|
|
|
|||
|
|
### 测试场景2:服务器端已达上限
|
|||
|
|
|
|||
|
|
1. 确保服务器端已有4次发车记录
|
|||
|
|
2. 在批量自动化中尝试发车
|
|||
|
|
3. **预期**:
|
|||
|
|
- 查询时立即发现并同步(0→4)
|
|||
|
|
- 提前检测到已达上限
|
|||
|
|
- 跳过发送,避免无效请求
|
|||
|
|
- 清晰告知用户原因
|
|||
|
|
|
|||
|
|
### 测试场景3:正常发车流程
|
|||
|
|
|
|||
|
|
1. 等待服务器日切后(每日0次)
|
|||
|
|
2. 在批量自动化中发车
|
|||
|
|
3. **预期**:
|
|||
|
|
- 同步服务器端的0次记录
|
|||
|
|
- 成功发送4辆车
|
|||
|
|
- 发送过程中实时更新计数
|
|||
|
|
- 最终显示 4/4
|
|||
|
|
|
|||
|
|
### 测试场景4:跨设备发车
|
|||
|
|
|
|||
|
|
1. 在设备A发车2辆
|
|||
|
|
2. 在设备B(批量自动化)发车
|
|||
|
|
3. **预期**:
|
|||
|
|
- 设备B查询时同步设备A的2次记录
|
|||
|
|
- 只发送剩余2辆
|
|||
|
|
- 两设备数据一致
|
|||
|
|
|
|||
|
|
## 📋 相关错误码说明
|
|||
|
|
|
|||
|
|
| 错误码 | 错误信息 | 原因 | 解决方法 |
|
|||
|
|
|--------|---------|------|---------|
|
|||
|
|
| **12000050** | 今日发车次数已达上限 | 服务器端已有4次发车记录 | 等待服务器日切或使用新账号 |
|
|||
|
|
| **200020** | 出了点小问题 | 冷却期/状态未同步 | 已通过3秒等待修复 |
|
|||
|
|
| **12000102** | 车未到终点 | 车辆还在运输中 | 等待车辆到达后收获 |
|
|||
|
|
|
|||
|
|
## 🔄 更新日志
|
|||
|
|
|
|||
|
|
**版本**: v3.10.0
|
|||
|
|
**日期**: 2025-10-08
|
|||
|
|
**类型**: 功能优化
|
|||
|
|
|
|||
|
|
**修改内容**:
|
|||
|
|
1. ✅ 查询车辆时同步服务器端的 `sendCount`
|
|||
|
|
2. ✅ 刷新车辆后再次同步 `sendCount`
|
|||
|
|
3. ✅ 发送前最后一次确认并同步 `sendCount`
|
|||
|
|
4. ✅ 发送前提前检测发车次数上限
|
|||
|
|
5. ✅ 增强错误处理,区分 12000050 和 200020
|
|||
|
|
6. ✅ 优化日志输出,显示同步过程
|
|||
|
|
|
|||
|
|
**影响范围**:
|
|||
|
|
- `src/stores/batchTaskStore.js` - `sendCar` 任务
|
|||
|
|
|
|||
|
|
**解决问题**:
|
|||
|
|
- 客户端和服务器端发车次数不一致
|
|||
|
|
- 发车次数达到上限后仍尝试发送
|
|||
|
|
- 错误信息不明确
|
|||
|
|
|
|||
|
|
**性能提升**:
|
|||
|
|
- 减少无效的发送请求
|
|||
|
|
- 提前检测并退出,节省时间
|
|||
|
|
- 日志更清晰,便于排查问题
|
|||
|
|
|