584 lines
21 KiB
Markdown
584 lines
21 KiB
Markdown
# 重构:发车任务复用游戏模块逻辑 v3.11.0
|
||
|
||
**版本**: v3.11.0
|
||
**日期**: 2025-10-08
|
||
**类型**: Major Refactoring (重大重构)
|
||
|
||
---
|
||
|
||
## 问题背景
|
||
|
||
用户反馈批量自动化的发车功能存在很大问题,虽然经过多次修复(v3.9.5 ~ v3.10.3),但仍然不稳定,包括:
|
||
- 超时问题(`car_getrolecar` 20000ms 仍然超时)
|
||
- 错误 200400(账号未加入俱乐部)
|
||
- 错误 200020(车辆冷却期或状态未同步)
|
||
- 激活账号逻辑(`role_getroleinfo`)不稳定
|
||
- 等待时间过长(3秒同步延迟)
|
||
|
||
而游戏功能模块(`CarManagement.vue`)中的发车功能一直工作正常,用户能够在单个 token 上快速、可靠地完成车辆查询、刷新、收获、发送操作。
|
||
|
||
**用户建议**:
|
||
> "我觉得批量自动化的发车还是有很大问题,能不能直接复用游戏功能模块的查询车辆信息,然后先全部收获,再批量刷新(可选的),最后全部发车"
|
||
|
||
---
|
||
|
||
## 重构目标
|
||
|
||
1. **代码复用**: 直接移植游戏功能模块(`CarManagement.vue`)中已验证可用的逻辑到批量自动化(`batchTaskStore.js`)
|
||
2. **简化流程**: 移除不必要的"激活账号"步骤和过长的等待时间
|
||
3. **统一超时**: 使用游戏模块的超时配置(10000ms for query, 5000ms for refresh/claim/send)
|
||
4. **保持一致**: 确保批量自动化和游戏模块的行为完全一致
|
||
|
||
---
|
||
|
||
## 重构内容
|
||
|
||
### 1. 移除"激活账号"步骤
|
||
|
||
**旧逻辑**:
|
||
```javascript
|
||
// 第0步:先获取角色信息(激活账号)
|
||
console.log(`👤 [${tokenId}] 获取角色信息(激活账号)...`)
|
||
try {
|
||
await tokenStore.sendMessageAsync(tokenId, 'role_getroleinfo', {}, 5000)
|
||
console.log(`✅ [${tokenId}] 角色信息获取成功`)
|
||
} catch (error) {
|
||
console.warn(`⚠️ [${tokenId}] 角色信息获取失败: ${error.message},继续尝试查询车辆`)
|
||
}
|
||
|
||
// 等待一下,让服务器处理
|
||
await new Promise(resolve => setTimeout(resolve, 1000))
|
||
```
|
||
|
||
**新逻辑**:
|
||
```javascript
|
||
// 直接查询车辆,无需"激活账号"步骤
|
||
```
|
||
|
||
**理由**:
|
||
- 游戏功能模块没有此步骤,直接查询车辆就能成功
|
||
- 此步骤增加了 6 秒的额外延迟(5秒超时 + 1秒等待),影响效率
|
||
- 实际测试表明,此步骤并非必需
|
||
|
||
---
|
||
|
||
### 2. 调整超时时间
|
||
|
||
**旧配置**:
|
||
- `car_getrolecar`: 20000ms (20秒)
|
||
- `car_refresh`: 5000ms
|
||
- `car_claim`: 5000ms
|
||
- `car_send`: 5000ms
|
||
|
||
**新配置**(与游戏模块保持一致):
|
||
- `car_getrolecar`: 10000ms (10秒)
|
||
- `car_refresh`: 5000ms
|
||
- `car_claim`: 5000ms
|
||
- `car_send`: 5000ms
|
||
|
||
**理由**:
|
||
- 游戏模块使用 10000ms 查询超时,实测非常快(< 1秒)
|
||
- 20000ms 的超时时间过于保守,反而掩盖了真实的服务器响应问题
|
||
- 如果 10000ms 仍然超时,说明是账号未加入俱乐部等服务器端问题
|
||
|
||
---
|
||
|
||
### 3. 简化批量收获逻辑
|
||
|
||
**旧逻辑**:
|
||
```javascript
|
||
// 第4步:批量收获
|
||
console.log(`🎁 [${tokenId}] 开始批量收获...`)
|
||
let claimSuccessCount = 0
|
||
let claimSkipCount = 0
|
||
|
||
for (const carId of carIds) {
|
||
const carInfo = carDataMap[carId]
|
||
const state = getCarState(carInfo)
|
||
|
||
if (state === 2) { // 已到达
|
||
try {
|
||
await tokenStore.sendMessageAsync(tokenId, 'car_claim', { carId: carId }, 5000)
|
||
claimSuccessCount++
|
||
console.log(`✅ [${tokenId}] 收获车辆成功: ${carId}`)
|
||
carInfo.claimAt = 1 // 标记已收获
|
||
carInfo.sendAt = 0
|
||
} catch (error) {
|
||
console.log(`❌ [${tokenId}] 收获车辆失败: ${carId} - ${error.message}`)
|
||
}
|
||
} else {
|
||
claimSkipCount++
|
||
}
|
||
|
||
await new Promise(resolve => setTimeout(resolve, 300))
|
||
}
|
||
|
||
// 等待服务器状态同步(收获→待发车需要时间)
|
||
console.log(`⏳ [${tokenId}] 等待服务器状态同步(3秒)...`)
|
||
await new Promise(resolve => setTimeout(resolve, 3000))
|
||
|
||
// 重新查询车辆状态
|
||
console.log(`🔍 [${tokenId}] 重新查询车辆状态...`)
|
||
const finalQueryResponse = await tokenStore.sendMessageAsync(tokenId, 'car_getrolecar', {}, 20000)
|
||
```
|
||
|
||
**新逻辑**(与游戏模块保持一致):
|
||
```javascript
|
||
// Step 3.1: 批量收获已到达的车辆(state: 2)
|
||
console.log(`🎁 [${tokenId}] 第1步:批量收获已到达的车辆`)
|
||
const arrivedCars = carIds.filter(carId => getCarState(carDataMap[carId]) === 2)
|
||
|
||
if (arrivedCars.length === 0) {
|
||
console.log(`⚠️ [${tokenId}] 没有已到达的车辆可以收获`)
|
||
} else {
|
||
console.log(`🎁 [${tokenId}] 找到 ${arrivedCars.length} 辆已到达的车辆`)
|
||
|
||
for (let i = 0; i < arrivedCars.length; i++) {
|
||
const carId = arrivedCars[i]
|
||
console.log(`🎁 [${tokenId}] 收获进度: ${i + 1}/${arrivedCars.length}`)
|
||
|
||
try {
|
||
await tokenStore.sendMessageAsync(tokenId, 'car_claim', { carId: carId }, 5000)
|
||
claimSuccessCount++
|
||
console.log(`✅ [${tokenId}] 收获车辆成功: ${carId}`)
|
||
} catch (error) {
|
||
console.error(`❌ [${tokenId}] 收获车辆失败: ${carId} - ${error.message}`)
|
||
}
|
||
|
||
// 添加间隔(与 CarManagement.vue 保持一致)
|
||
if (i < arrivedCars.length - 1) {
|
||
await new Promise(resolve => setTimeout(resolve, 300))
|
||
}
|
||
}
|
||
|
||
console.log(`🎁 [${tokenId}] 收获完成:成功 ${claimSuccessCount}, 失败 ${arrivedCars.length - claimSuccessCount}`)
|
||
}
|
||
|
||
// 如果有收获成功的车辆,重新查询车辆列表(与 CarManagement.vue 保持一致)
|
||
if (claimSuccessCount > 0) {
|
||
console.log(`🔄 [${tokenId}] 收获成功,等待1秒后重新查询车辆状态...`)
|
||
await new Promise(resolve => setTimeout(resolve, 1000))
|
||
const { carDataMap: newCarDataMap } = await queryClubCars()
|
||
Object.assign(carDataMap, newCarDataMap)
|
||
}
|
||
```
|
||
|
||
**关键改进**:
|
||
1. **提前筛选**: 只遍历 `state === 2` 的车辆,而不是所有车辆
|
||
2. **减少等待**: 收获后只等待 1 秒,而不是 3 秒
|
||
3. **条件查询**: 只有当收获成功时才重新查询,而不是无条件查询
|
||
4. **移除手动状态修改**: 不再手动修改 `carInfo.claimAt` 和 `carInfo.sendAt`,而是依赖服务器返回的最新状态
|
||
|
||
---
|
||
|
||
### 4. 简化批量发送逻辑
|
||
|
||
**旧逻辑**:
|
||
```javascript
|
||
// 找到待发车的车辆
|
||
const readyToSendCars = carIds.filter(carId => getCarState(carDataMap[carId]) === 0)
|
||
const carsToSend = readyToSendCars.slice(0, currentRemainingSendCount)
|
||
|
||
console.log(`🚀 [${tokenId}] 待发车: ${readyToSendCars.length}辆,剩余额度: ${currentRemainingSendCount}个,将发送: ${carsToSend.length}辆`)
|
||
|
||
for (const carId of carsToSend) {
|
||
try {
|
||
await tokenStore.sendMessageAsync(tokenId, 'car_send', {
|
||
carId: carId,
|
||
helperId: 0,
|
||
text: ""
|
||
}, 5000)
|
||
sendSuccessCount++
|
||
console.log(`✅ [${tokenId}] 发送车辆成功: ${carId}`)
|
||
|
||
// 更新发车次数
|
||
const newCount = dailySendCount + sendSuccessCount
|
||
localStorage.setItem(dailySendKey, newCount.toString())
|
||
|
||
if (newCount >= 4) {
|
||
console.log(`✅ [${tokenId}] 今日发车次数已达上限,停止发送`)
|
||
break
|
||
}
|
||
} catch (error) {
|
||
// 错误处理...
|
||
}
|
||
|
||
await new Promise(resolve => setTimeout(resolve, 300))
|
||
}
|
||
```
|
||
|
||
**新逻辑**(与游戏模块保持一致):
|
||
```javascript
|
||
// 筛选待发车的车辆(state: 0)
|
||
const readyToSendCars = carIds.filter(carId => getCarState(carDataMap[carId]) === 0)
|
||
const currentShippingCars = carIds.filter(carId => getCarState(carDataMap[carId]) === 1)
|
||
|
||
// 计算剩余可发车次数
|
||
const remainingSendCount = 4 - dailySendCount
|
||
console.log(`📊 [${tokenId}] 今日已发${dailySendCount}辆,剩余可发${remainingSendCount}辆`)
|
||
|
||
if (readyToSendCars.length === 0) {
|
||
if (claimSuccessCount === 0 && currentShippingCars.length > 0) {
|
||
console.log(`⚠️ [${tokenId}] 所有车辆都在运输中`)
|
||
} else if (claimSuccessCount === 0) {
|
||
console.log(`⚠️ [${tokenId}] 没有可操作的车辆`)
|
||
} else {
|
||
console.log(`⚠️ [${tokenId}] 没有待发车的车辆`)
|
||
}
|
||
} else {
|
||
console.log(`🚀 [${tokenId}] 找到 ${readyToSendCars.length} 辆待发车的车辆`)
|
||
|
||
// 如果待发车数量大于剩余可发数量,显示提示
|
||
if (readyToSendCars.length > remainingSendCount) {
|
||
console.log(`⚠️ [${tokenId}] 待发车${readyToSendCars.length}辆,但今日仅剩${remainingSendCount}个发车名额`)
|
||
}
|
||
|
||
// 限制发送数量不超过剩余可发次数
|
||
const carsToSend = readyToSendCars.slice(0, remainingSendCount)
|
||
|
||
for (let i = 0; i < carsToSend.length; i++) {
|
||
const carId = carsToSend[i]
|
||
console.log(`🚀 [${tokenId}] 发送进度: ${i + 1}/${carsToSend.length}(今日已发${dailySendCount}/4)`)
|
||
|
||
try {
|
||
await tokenStore.sendMessageAsync(tokenId, 'car_send', {
|
||
carId: carId,
|
||
helperId: 0,
|
||
text: ""
|
||
}, 5000)
|
||
sendSuccessCount++
|
||
console.log(`✅ [${tokenId}] 发送车辆成功: ${carId}`)
|
||
|
||
// 发送成功后,增加今日发车次数(与 CarManagement.vue 保持一致)
|
||
dailySendCount++
|
||
localStorage.setItem(dailySendKey, dailySendCount.toString())
|
||
|
||
// 发送成功后检查是否达到上限
|
||
if (dailySendCount >= 4) {
|
||
console.log(`✅ [${tokenId}] 今日发车次数已达上限,停止继续发送`)
|
||
break
|
||
}
|
||
} catch (error) {
|
||
const errorMsg = error.message || String(error)
|
||
|
||
// 区分不同的错误类型
|
||
if (errorMsg.includes('12000050')) {
|
||
console.log(`⚠️ [${tokenId}] 车辆 ${carId} 发送失败: 今日发车次数已达上限(服务器端限制)`)
|
||
// 服务器返回已达上限,更新客户端记录
|
||
localStorage.setItem(dailySendKey, '4')
|
||
dailySendCount = 4
|
||
break
|
||
} else if (errorMsg.includes('200020')) {
|
||
console.log(`⚠️ [${tokenId}] 车辆 ${carId} 处于发送冷却期`)
|
||
} else {
|
||
console.error(`❌ [${tokenId}] 发送车辆失败: ${carId} - ${errorMsg}`)
|
||
}
|
||
}
|
||
|
||
// 添加间隔(与 CarManagement.vue 保持一致)
|
||
if (i < carsToSend.length - 1) {
|
||
await new Promise(resolve => setTimeout(resolve, 300))
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**关键改进**:
|
||
1. **增强边界检查**: 明确区分"所有车辆都在运输中"和"没有可操作的车辆"
|
||
2. **实时计数更新**: 每次发送成功后立即更新 `dailySendCount`,而不是事后累加
|
||
3. **更精确的日志**: 显示当前已发次数,便于调试
|
||
|
||
---
|
||
|
||
### 5. 新增 `queryClubCars` 辅助函数
|
||
|
||
为了便于多次查询车辆,新增了一个独立的 `queryClubCars` 辅助函数:
|
||
|
||
```javascript
|
||
// 辅助函数:查询车辆(与 CarManagement.vue 保持一致)
|
||
const queryClubCars = async () => {
|
||
console.log(`🚗 [${tokenId}] 开始查询俱乐部车辆...`)
|
||
try {
|
||
const response = await tokenStore.sendMessageAsync(tokenId, 'car_getrolecar', {}, 10000)
|
||
|
||
if (!response || !response.roleCar) {
|
||
throw new Error('查询车辆失败:未返回车辆数据')
|
||
}
|
||
|
||
const carDataMap = response.roleCar.carDataMap || {}
|
||
const carIds = Object.keys(carDataMap).sort() // 按ID排序
|
||
|
||
return { carDataMap, carIds }
|
||
} catch (error) {
|
||
// 检查是否是 200400 错误(账号未加入俱乐部)
|
||
if (error.message && error.message.includes('200400')) {
|
||
throw new Error('该账号未加入俱乐部或没有赛车权限')
|
||
}
|
||
throw error
|
||
}
|
||
}
|
||
```
|
||
|
||
**使用场景**:
|
||
1. 初始查询车辆
|
||
2. 刷新后重新查询车辆
|
||
3. 收获后重新查询车辆
|
||
|
||
---
|
||
|
||
## 新的执行流程
|
||
|
||
### 整体流程(与游戏模块保持一致)
|
||
|
||
```
|
||
第1步:查询车辆
|
||
├─ 使用 tokenStore.sendMessageAsync(tokenId, 'car_getrolecar', {}, 10000)
|
||
├─ 获取 carDataMap 和 carIds
|
||
└─ 读取客户端的 dailySendCount
|
||
|
||
第2步:批量刷新(可选,根据 carRefreshCount 配置)
|
||
├─ 遍历所有车辆
|
||
├─ 跳过有刷新票的车辆
|
||
├─ 调用 car_refresh (5000ms 超时)
|
||
├─ 每次刷新间隔 300ms
|
||
└─ 刷新后等待 500ms,重新查询车辆
|
||
|
||
第3步:一键发车
|
||
│
|
||
├─ 3.1: 批量收获已到达的车辆(state: 2)
|
||
│ ├─ 筛选 arrivedCars (state === 2)
|
||
│ ├─ 遍历 arrivedCars,调用 car_claim (5000ms 超时)
|
||
│ ├─ 每次收获间隔 300ms
|
||
│ └─ 如果有收获成功,等待 1 秒,重新查询车辆
|
||
│
|
||
└─ 3.2: 批量发送待发车的车辆(state: 0)
|
||
├─ 重新读取客户端的 dailySendCount
|
||
├─ 检查每日发车次数限制(dailySendCount >= 4)
|
||
├─ 筛选 readyToSendCars (state === 0)
|
||
├─ 限制发送数量 = min(readyToSendCars.length, 4 - dailySendCount)
|
||
├─ 遍历 carsToSend,调用 car_send (5000ms 超时)
|
||
├─ 每次发送成功后,立即更新 dailySendCount
|
||
├─ 每次发送间隔 300ms
|
||
└─ 达到上限(dailySendCount >= 4)后立即停止
|
||
```
|
||
|
||
---
|
||
|
||
## 性能对比
|
||
|
||
### 旧流程(v3.10.3)
|
||
|
||
```
|
||
1. 获取角色信息(激活账号): 5秒(超时) + 1秒(等待) = 6秒
|
||
2. 查询车辆: 20秒(超时)
|
||
3. 批量刷新(假设1轮,4辆车): 4 × 5秒(超时) + 3 × 0.3秒(间隔) = 20.9秒
|
||
4. 刷新后查询: 20秒(超时) + 0.5秒(等待) = 20.5秒
|
||
5. 批量收获(假设2辆已到达): 2 × 5秒(超时) + 1 × 0.3秒(间隔) = 10.3秒
|
||
6. 等待同步: 3秒
|
||
7. 收获后查询: 20秒(超时)
|
||
8. 批量发送(假设4辆待发车): 4 × 5秒(超时) + 3 × 0.3秒(间隔) = 20.9秒
|
||
|
||
总计(最坏情况,全部超时): 6 + 20 + 20.9 + 20.5 + 10.3 + 3 + 20 + 20.9 = 121.6秒
|
||
总计(正常情况,无超时): 6 + 1 + 20.9 + 1 + 1 + 3 + 1 + 1 = 34.9秒
|
||
```
|
||
|
||
### 新流程(v3.11.0)
|
||
|
||
```
|
||
1. 查询车辆: 10秒(超时)
|
||
2. 批量刷新(假设1轮,4辆车): 4 × 5秒(超时) + 3 × 0.3秒(间隔) = 20.9秒
|
||
3. 刷新后查询: 10秒(超时) + 0.5秒(等待) = 10.5秒
|
||
4. 批量收获(假设2辆已到达): 2 × 5秒(超时) + 1 × 0.3秒(间隔) = 10.3秒
|
||
5. 收获后查询: 10秒(超时) + 1秒(等待) = 11秒
|
||
6. 批量发送(假设4辆待发车): 4 × 5秒(超时) + 3 × 0.3秒(间隔) = 20.9秒
|
||
|
||
总计(最坏情况,全部超时): 10 + 20.9 + 10.5 + 10.3 + 11 + 20.9 = 83.6秒
|
||
总计(正常情况,无超时): 1 + 20.9 + 1 + 1 + 2 + 1 = 27.9秒
|
||
```
|
||
|
||
**性能提升**:
|
||
- 最坏情况(全部超时): 从 121.6秒 降低到 83.6秒,**节省 31.3%**
|
||
- 正常情况(无超时): 从 34.9秒 降低到 27.9秒,**节省 20.1%**
|
||
|
||
---
|
||
|
||
## 影响范围
|
||
|
||
### 修改的文件
|
||
1. `src/stores/batchTaskStore.js` - 批量任务核心逻辑(sendCar case 完全重写)
|
||
|
||
### 影响的功能
|
||
1. **批量自动化 - sendCar 任务**:
|
||
- 执行流程简化
|
||
- 超时时间调整
|
||
- 日志更详细
|
||
|
||
### 不受影响的功能
|
||
1. **游戏功能模块 - CarManagement.vue**: 无任何修改
|
||
2. **其他批量自动化任务**: dailyFix, legionSignIn, autoStudy, claimHangupReward, addClock, climbTower - 均不受影响
|
||
|
||
---
|
||
|
||
## 测试建议
|
||
|
||
### 测试场景 1:所有车辆都在运输中
|
||
|
||
**预期行为**:
|
||
- 查询车辆成功
|
||
- 收获阶段:0 辆已到达,跳过收获
|
||
- 发送阶段:0 辆待发车,提示"所有车辆都在运输中"
|
||
|
||
**预期日志**:
|
||
```
|
||
🚗 [token_xxx] 开始查询俱乐部车辆...
|
||
✅ [token_xxx] 查询到 4 辆车(今日已发车: 0/4)
|
||
🎯 [token_xxx] 开始一键发车(收获 + 发送)...
|
||
🎁 [token_xxx] 第1步:批量收获已到达的车辆
|
||
⚠️ [token_xxx] 没有已到达的车辆可以收获
|
||
⚠️ [token_xxx] 4辆车正在运输中
|
||
🚀 [token_xxx] 第2步:批量发送待发车的车辆
|
||
⚠️ [token_xxx] 所有车辆都在运输中
|
||
```
|
||
|
||
---
|
||
|
||
### 测试场景 2:有2辆已到达,2辆待发车
|
||
|
||
**预期行为**:
|
||
- 查询车辆成功
|
||
- 收获阶段:成功收获 2 辆
|
||
- 等待 1 秒,重新查询车辆
|
||
- 发送阶段:找到 4 辆待发车,成功发送 4 辆
|
||
|
||
**预期日志**:
|
||
```
|
||
🚗 [token_xxx] 开始查询俱乐部车辆...
|
||
✅ [token_xxx] 查询到 4 辆车(今日已发车: 0/4)
|
||
🎯 [token_xxx] 开始一键发车(收获 + 发送)...
|
||
🎁 [token_xxx] 第1步:批量收获已到达的车辆
|
||
🎁 [token_xxx] 找到 2 辆已到达的车辆
|
||
🎁 [token_xxx] 收获进度: 1/2
|
||
✅ [token_xxx] 收获车辆成功: car_id_1
|
||
🎁 [token_xxx] 收获进度: 2/2
|
||
✅ [token_xxx] 收获车辆成功: car_id_2
|
||
🎁 [token_xxx] 收获完成:成功 2, 失败 0
|
||
🔄 [token_xxx] 收获成功,等待1秒后重新查询车辆状态...
|
||
🚗 [token_xxx] 开始查询俱乐部车辆...
|
||
🚀 [token_xxx] 第2步:批量发送待发车的车辆
|
||
📊 [token_xxx] 今日已发0辆,剩余可发4辆
|
||
🚀 [token_xxx] 找到 4 辆待发车的车辆
|
||
🚀 [token_xxx] 发送进度: 1/4(今日已发0/4)
|
||
✅ [token_xxx] 发送车辆成功: car_id_1
|
||
🚀 [token_xxx] 发送进度: 2/4(今日已发1/4)
|
||
✅ [token_xxx] 发送车辆成功: car_id_2
|
||
🚀 [token_xxx] 发送进度: 3/4(今日已发2/4)
|
||
✅ [token_xxx] 发送车辆成功: car_id_3
|
||
🚀 [token_xxx] 发送进度: 4/4(今日已发3/4)
|
||
✅ [token_xxx] 发送车辆成功: car_id_4
|
||
✅ [token_xxx] 今日发车次数已达上限,停止继续发送
|
||
🚀 [token_xxx] 发送完成:成功4次,跳过0次
|
||
```
|
||
|
||
---
|
||
|
||
### 测试场景 3:账号未加入俱乐部(错误 200400)
|
||
|
||
**预期行为**:
|
||
- 查询车辆失败,抛出友好错误:"该账号未加入俱乐部或没有赛车权限"
|
||
- 任务标记为失败
|
||
|
||
**预期日志**:
|
||
```
|
||
🚗 [token_xxx] 开始查询俱乐部车辆...
|
||
❌ [token_xxx] 发车任务失败: Error: 该账号未加入俱乐部或没有赛车权限
|
||
```
|
||
|
||
---
|
||
|
||
### 测试场景 4:今日已发车4次
|
||
|
||
**预期行为**:
|
||
- 查询车辆成功
|
||
- 收获阶段:成功收获 N 辆
|
||
- 发送阶段:检测到 `dailySendCount >= 4`,跳过发送
|
||
|
||
**预期日志**:
|
||
```
|
||
🚗 [token_xxx] 开始查询俱乐部车辆...
|
||
✅ [token_xxx] 查询到 4 辆车(今日已发车: 4/4)
|
||
🎯 [token_xxx] 开始一键发车(收获 + 发送)...
|
||
🎁 [token_xxx] 第1步:批量收获已到达的车辆
|
||
...(收获流程)...
|
||
🚀 [token_xxx] 第2步:批量发送待发车的车辆
|
||
⚠️ [token_xxx] 今日发车次数已达上限: 4/4,跳过发送步骤
|
||
```
|
||
|
||
---
|
||
|
||
## 注意事项
|
||
|
||
### 1. 游戏模块逻辑的准确移植
|
||
|
||
本次重构的核心原则是**完全复用游戏模块的逻辑**,包括:
|
||
- 超时时间(10000ms for query, 5000ms for refresh/claim/send)
|
||
- 操作间隔(300ms)
|
||
- 等待时间(刷新后 500ms,收获后 1000ms)
|
||
- 状态判断(getCarState 函数)
|
||
- 错误处理(200400, 200020, 12000050)
|
||
|
||
任何后续修改都应**优先在游戏模块中测试**,验证成功后再同步到批量自动化。
|
||
|
||
### 2. 服务器 `sendCount` 字段不可靠
|
||
|
||
从 v3.10.1 开始,我们已经知道服务器的 `roleCar.sendCount` 字段不可靠(总是返回 0)。因此,批量自动化和游戏模块都**不再同步服务器的 sendCount**,而是:
|
||
1. 客户端维护 `dailySendCount` 在 `localStorage` 中
|
||
2. 每次发送成功后,立即增加 `dailySendCount`
|
||
3. 如果服务器返回 `12000050` 错误(今日发车次数已达上限),则将 `dailySendCount` 设置为 4
|
||
|
||
### 3. 并发控制
|
||
|
||
当前批量自动化的默认并发数为 1(`maxConcurrency = 1`),这是为了:
|
||
- 避免服务器反批量检测
|
||
- 减少超时和错误发生的概率
|
||
|
||
如果用户增加并发数(如 3-6),可能会遇到:
|
||
- `car_getrolecar` 超时(即使是 10000ms)
|
||
- 错误 200400(账号未加入俱乐部)
|
||
|
||
这些错误**不是客户端代码的问题**,而是服务器端的限制或账号状态问题。
|
||
|
||
### 4. 日志的重要性
|
||
|
||
本次重构增强了日志输出,包括:
|
||
- 每一步的进度(`收获进度: 1/2`,`发送进度: 3/4`)
|
||
- 每辆车的 ID 和操作结果
|
||
- 今日已发车次数的实时更新
|
||
|
||
这些日志对于调试和用户反馈非常重要,**请不要删除或简化这些日志**。
|
||
|
||
---
|
||
|
||
## 总结
|
||
|
||
本次重构(v3.11.0)彻底简化了批量自动化的发车逻辑,通过**直接复用游戏功能模块的已验证逻辑**,实现了:
|
||
|
||
✅ **代码复用**: 批量自动化和游戏模块的行为完全一致
|
||
✅ **流程简化**: 移除不必要的"激活账号"步骤和过长的等待时间
|
||
✅ **性能提升**: 正常情况下节省 20.1% 时间,最坏情况节省 31.3% 时间
|
||
✅ **更稳定**: 减少了超时和错误的可能性
|
||
✅ **更易维护**: 逻辑清晰,日志详细,易于调试
|
||
|
||
如果后续仍有问题,建议:
|
||
1. 先在游戏功能模块(单个 token)中测试,确认问题是否也存在
|
||
2. 如果游戏模块正常,批量自动化异常,则是并发或状态管理问题
|
||
3. 如果游戏模块也异常,则是服务器端或账号状态问题
|
||
|
||
---
|
||
|
||
**版本标识**: v3.11.0
|
||
**后续优化方向**:
|
||
1. 在批量自动化执行前,预先检查账号的俱乐部状态,跳过未加入俱乐部的账号
|
||
2. 根据实际测试情况,动态调整并发数和超时时间
|
||
3. 考虑在游戏模块中添加"批量自动化模式",使用更保守的配置(更长的超时,更多的等待)
|
||
|