15 KiB
15 KiB
批量自动化任务功能实现总结
📋 项目概述
本文档记录了批量自动化任务功能的完整技术实现,包括架构设计、核心逻辑、数据流转等。
🏗️ 架构设计
整体架构
┌─────────────────────────────────────────────────────────┐
│ TokenImport.vue │
│ (Token管理主页,集成批量任务面板和进度显示) │
└─────────────────┬───────────────────────────────────────┘
│
┌───────────┴───────────┐
│ │
┌─────▼──────────┐ ┌───────▼──────────┐
│BatchTaskPanel │ │TaskProgressCard │
│(控制面板) │ │(进度卡片) │
└─────┬──────────┘ └───────┬──────────┘
│ │
└──────────┬───────────┘
│
┌────────▼────────┐
│ batchTaskStore │
│ (核心状态管理) │
└────────┬────────┘
│
┌────────────┼────────────┐
│ │ │
┌───▼────┐ ┌───▼────┐ ┌───▼────┐
│tokenS- │ │task │ │WebSo- │
│tore │ │Schedu- │ │cket │
│ │ │ler │ │Client │
└────────┘ └────────┘ └────────┘
核心模块
-
UI层
BatchTaskPanel.vue- 批量任务控制面板TaskProgressCard.vue- 单Token进度卡片TemplateEditor.vue- 任务模板编辑器SchedulerConfig.vue- 定时任务配置ExecutionHistory.vue- 执行历史记录
-
状态管理层
batchTaskStore.js- 批量任务状态管理(Pinia)tokenStore.js- Token和WebSocket管理
-
工具层
taskScheduler.js- 任务调度器xyzwWebSocket.js- WebSocket客户端gameCommands.js- 游戏指令封装
🔧 核心功能实现
1. 批量任务执行流程
1.1 启动流程
// batchTaskStore.js
const startBatchExecution = async (tokenIds, tasks) => {
// 1. 验证参数
// 2. 初始化状态
// 3. 创建任务队列
// 4. 执行并发控制
// 5. 完成后清理
}
1.2 并发控制
const executeBatchWithConcurrency = async (tokenIds, tasks) => {
const queue = [...tokenIds]
const executing = []
while (queue.length > 0 || executing.length > 0) {
// 填充执行队列(最多maxConcurrency个)
while (executing.length < maxConcurrency.value && queue.length > 0) {
const tokenId = queue.shift()
const promise = executeTokenTasks(tokenId, tasks)
executing.push(promise)
}
// 等待至少一个任务完成
if (executing.length > 0) {
await Promise.race(executing)
}
}
}
1.3 单Token任务执行
const executeTokenTasks = async (tokenId, tasks) => {
try {
// 1. 确保WebSocket连接(自动从bin文件获取新token)
const wsClient = await ensureConnection(tokenId)
// 2. 依次执行任务
for (const taskName of tasks) {
const result = await executeTask(tokenId, taskName)
// 保存结果
taskProgress.value[tokenId].result[taskName] = {
success: true,
data: result
}
}
// 3. 标记完成
updateTaskProgress(tokenId, { status: 'completed' })
} catch (error) {
updateTaskProgress(tokenId, { status: 'failed', error })
} finally {
// 4. 自动断开WebSocket连接
tokenStore.closeWebSocketConnection(tokenId)
}
}
2. 任务实现详解
2.1 一键补差任务(dailyFix)
case 'dailyFix':
// 包含16大类任务
const fixResults = []
// 1. 分享游戏
fixResults.push(await client.sendWithPromise('system_mysharecallback', {
isSkipShareCard: true,
type: 2
}))
// 2. 赠送好友金币
fixResults.push(await client.sendWithPromise('friend_batch', {}))
// 3. 免费招募
fixResults.push(await client.sendWithPromise('hero_recruit', {
recruitType: 3,
recruitNumber: 1
}))
// 4. 免费点金(3次)
for (let i = 0; i < 3; i++) {
fixResults.push(await client.sendWithPromise('system_buygold', { buyNum: 1 }))
}
// 5. 福利签到
fixResults.push(await client.sendWithPromise('system_signinreward', {}))
// 6. 领取每日礼包
fixResults.push(await client.sendWithPromise('discount_claimreward', {}))
// 7. 领取免费礼包
fixResults.push(await client.sendWithPromise('card_claimreward', {}))
// 8. 领取永久卡礼包
fixResults.push(await client.sendWithPromise('card_claimreward', { cardId: 4003 }))
// 9. 领取邮件奖励
fixResults.push(await client.sendWithPromise('mail_claimallattachment', { category: 0 }))
// 10. 免费钓鱼(3次)
for (let i = 0; i < 3; i++) {
fixResults.push(await client.sendWithPromise('artifact_lottery', {
lotteryNumber: 1,
newFree: true,
type: 1
}))
}
// 11. 灯神免费扫荡(4个国家)
for (let gid = 1; gid <= 4; gid++) {
fixResults.push(await client.sendWithPromise('genie_sweep', { genieId: gid }))
}
// 12. 领取免费扫荡卷(3次)
for (let i = 0; i < 3; i++) {
fixResults.push(await client.sendWithPromise('genie_buysweep', {}))
}
// 13. 领取任务奖励(1-10)
for (let taskId = 1; taskId <= 10; taskId++) {
fixResults.push(await client.sendWithPromise('task_claimdailypoint', { taskId }))
}
// 14. 领取日常任务奖励
fixResults.push(await client.sendWithPromise('task_claimdailyreward', {}))
// 15. 领取周常任务奖励
fixResults.push(await client.sendWithPromise('task_claimweekreward', {}))
// 16. 重启盐罐机器人服务
// 16.1 停止机器人
try {
fixResults.push(await client.sendWithPromise('bottlehelper_stop', { bottleType: -1 }))
} catch (error) {
// 机器人可能未启动,跳过
}
// 16.2 启动机器人
fixResults.push(await client.sendWithPromise('bottlehelper_start', { bottleType: -1 }))
// 16.3 领取奖励
try {
fixResults.push(await client.sendWithPromise('bottlehelper_claim', {}))
} catch (error) {
// 暂无奖励可领取
}
return fixResults
一键补差包含的所有子任务:
- 分享一次游戏
- 赠送好友金币
- 免费招募
- 免费点金(3次)
- 福利签到
- 领取每日礼包
- 领取免费礼包
- 领取永久卡礼包
- 领取邮件奖励
- 免费钓鱼(3次)
- 魏国灯神免费扫荡
- 蜀国灯神免费扫荡
- 吴国灯神免费扫荡
- 群雄灯神免费扫荡
- 领取免费扫荡卷(3次)
- 领取任务奖励1-10(10个)
- 领取日常任务奖励
- 领取周常任务奖励
- 停止盐罐机器人
- 启动盐罐机器人
- 领取盐罐奖励
总计:约45+个子操作
2.2 俱乐部签到(legionSignIn)
case 'legionSignIn':
return await client.sendWithPromise('legion_signin', {}, 2000)
2.3 一键答题(autoStudy)
case 'autoStudy':
return await client.sendWithPromise('study_startgame', {}, 2000)
2.4 领取奖励-挂机(claimHangupReward)
case 'claimHangupReward':
return await client.sendWithPromise('system_claimhangupreward', {}, 2000)
2.5 加钟(addClock)
case 'addClock':
// 必须在领取挂机奖励之后执行
return await client.sendWithPromise('system_mysharecallback', {
type: 3,
isSkipShareCard: true
}, 2000)
📊 支持的任务列表
| 任务ID | 任务名称 | 实现方式 | 说明 |
|---|---|---|---|
dailyFix |
一键补差 | 16大类40+子任务 | 完整版每日任务,包含所有日常活动 |
legionSignIn |
俱乐部签到 | legion_signin |
军团/俱乐部每日签到 |
autoStudy |
一键答题 | study_startgame |
触发自动答题流程 |
claimHangupReward |
领取奖励(挂机) | system_claimhangupreward |
领取离线挂机收益 |
addClock |
加钟 | system_mysharecallback (type=3) |
延长挂机时间 |
🔄 数据流转
执行状态流转
pending → executing → completed/failed
↓
paused ⟷ executing
进度数据结构
taskProgress = {
[tokenId]: {
status: 'pending' | 'executing' | 'completed' | 'failed' | 'skipped',
progress: 0-100,
currentTask: 'dailyFix' | 'legionSignIn' | ...,
tasksCompleted: 3,
tasksTotal: 5,
error: null | string,
result: {
dailyFix: { success: true, data: [...] },
legionSignIn: { success: true, data: {...} },
...
},
startTime: timestamp,
endTime: timestamp
}
}
统计数据结构
executionStats = {
total: 10, // 总Token数
success: 8, // 成功数
failed: 1, // 失败数
skipped: 1, // 跳过数
startTime: timestamp,
endTime: timestamp
}
🔐 WebSocket连接管理
连接策略
const ensureConnection = async (tokenId) => {
const connection = tokenStore.wsConnections[tokenId]
// 已连接,直接返回
if (connection && connection.status === 'connected') {
return connection.client
}
// 重新连接(会自动从bin文件获取新token)
const wsClient = await tokenStore.reconnectWebSocket(tokenId)
return wsClient
}
自动断开机制
// executeTokenTasks的finally块
finally {
// 任务完成后自动断开WebSocket连接
if (tokenStore.wsConnections[tokenId]) {
tokenStore.closeWebSocketConnection(tokenId)
}
}
连接健康检查
- 每次执行前从bin文件重新获取roleToken
- 自动处理token失效问题
- 连接失败自动跳过,不影响其他Token
⚙️ 配置管理
并发数配置
const maxConcurrency = ref(
parseInt(localStorage.getItem('maxConcurrency') || '5')
)
const setMaxConcurrency = (count) => {
if (count < 1 || count > 6) return
maxConcurrency.value = count
localStorage.setItem('maxConcurrency', count.toString())
}
任务模板配置
const taskTemplates = {
'完整套餐': {
name: '完整套餐',
tasks: ['dailyFix', 'legionSignIn', 'autoStudy', 'claimHangupReward', 'addClock'],
enabled: true
},
'快速套餐': {
name: '快速套餐',
tasks: ['legionSignIn', 'autoStudy', 'claimHangupReward', 'addClock'],
enabled: true
},
'仅一键补差': {
name: '仅一键补差',
tasks: ['dailyFix'],
enabled: true
}
}
调度器配置
const schedulerConfig = {
enabled: false,
type: 'interval' | 'daily',
interval: 4, // 小时
dailyTimes: ['08:00', '12:00', '18:00', '22:00'],
lastExecutionTime: null
}
💾 数据存储结构
localStorage键值
{
"taskTemplates": {
"完整套餐": { ... },
"快速套餐": { ... },
...
},
"batchTaskHistory": [
{
id: "batch_1234567890",
template: "完整套餐",
stats: { total: 10, success: 9, ... },
timestamp: 1234567890,
duration: 120000
}
],
"schedulerConfig": { ... },
"maxConcurrency": "5"
}
🔧 扩展性设计
添加新任务
只需要在 batchTaskStore.js 的 executeTask 方法中添加新case:
case 'newTask':
// 新任务的WebSocket指令
return await client.sendWithPromise('command_name', { params }, 2000)
然后在以下位置添加任务定义:
BatchTaskPanel.vue- taskDefinitionsTemplateEditor.vue- availableTasksTaskProgressCard.vue- taskLabels- 默认模板(可选)
修改并发数
const maxConcurrency = ref(5) // 改为你想要的数字
自定义任务间隔
await new Promise(resolve => setTimeout(resolve, 500)) // 修改延迟时间
🐛 错误处理机制
单任务失败处理
try {
const result = await executeTask(tokenId, taskName)
taskProgress.value[tokenId].result[taskName] = { success: true, data: result }
} catch (error) {
// 单个任务失败不影响其他任务
taskProgress.value[tokenId].result[taskName] = { success: false, error: error.message }
// 继续执行下一个任务
}
Token执行失败处理
- 自动标记为失败状态
- 记录详细错误信息
- 不影响其他Token的执行
- 更新统计数据
连接失败处理
- 自动跳过该Token
- 记录为"skipped"状态
- 继续处理下一个Token
📈 性能优化
1. 并发控制
- 使用Promise.race实现高效并发控制
- 动态调整并发数(1-6可配置)
- 避免同时创建过多WebSocket连接
2. 资源管理
- 任务完成后自动断开WebSocket连接
- 限制历史记录数量(最多10条)
- 使用localStorage持久化配置
3. 任务间隔
- 每个任务间隔200-500ms
- 避免请求过快触发限流
- 保证服务器稳定性
🔒 安全性考虑
1. Token安全
- 每次从bin文件重新获取roleToken
- 不在内存中长期保存敏感信息
- 连接失败自动处理,不泄露错误
2. 数据验证
- 参数验证(并发数、任务列表等)
- 状态检查(是否正在执行、是否有Token等)
- 错误边界处理
3. 用户控制
- 提供暂停/继续/停止功能
- 手动控制进度显示
- 可查看详细执行结果
📝 开发日志
v2.0.0 (2024-10-07)
- ✨ 重大更新:重构任务结构
- 整合完整一键补差(16大类40+子任务)
- 新增俱乐部签到任务
- 新增领取奖励(挂机)任务
- 新增加钟任务
- 优化任务模板,提供更合理的预设
- 改进任务顺序,确保执行逻辑正确
v1.2.0
- ✨ 新增可配置并发数(1-6)
- ✨ 新增进度显示控制(手动关闭)
- ✨ 新增任务详情弹窗
- ✨ 优化WebSocket连接管理
- 🐛 修复连接未断开的问题
v1.1.0
- ✨ 新增"加钟"任务
- ✨ 新增"重启盐罐机器人"任务
- 🔧 改进任务间隔时间
v1.0.0
- 🎉 初始版本发布
- ✅ 基础批量任务功能
- ✅ 任务模板系统
- ✅ 定时调度功能
- ✅ 执行历史记录
🎯 后续优化方向
-
性能优化
- 实现任务结果缓存
- 优化大量Token的渲染性能
- 支持虚拟滚动
-
功能增强
- 支持任务条件执行(如:仅未完成的任务)
- 添加更多游戏任务
- 支持自定义任务参数
-
用户体验
- 提供任务执行预览
- 添加声音提示
- 支持深色主题
-
数据分析
- 任务成功率统计
- 执行时间趋势分析
- Token性能对比
📚 参考文档
技术实现完成! 🎉