# 功能优化 - 同步服务器发车次数 (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` 任务

**解决问题**:
- 客户端和服务器端发车次数不一致
- 发车次数达到上限后仍尝试发送
- 错误信息不明确

**性能提升**:
- 减少无效的发送请求
- 提前检测并退出，节省时间
- 日志更清晰，便于排查问题

