# 批量自动化任务功能实现总结

## 📋 项目概述

本文档记录了批量自动化任务功能的完整技术实现，包括架构设计、核心逻辑、数据流转等。

---

## 🏗️ 架构设计

### 整体架构

```
┌─────────────────────────────────────────────────────────┐
│                    TokenImport.vue                      │
│  (Token管理主页，集成批量任务面板和进度显示)              │
└─────────────────┬───────────────────────────────────────┘
                  │
      ┌───────────┴───────────┐
      │                       │
┌─────▼──────────┐   ┌───────▼──────────┐
│BatchTaskPanel  │   │TaskProgressCard  │
│(控制面板)       │   │(进度卡片)         │
└─────┬──────────┘   └───────┬──────────┘
      │                      │
      └──────────┬───────────┘
                 │
        ┌────────▼────────┐
        │ batchTaskStore  │
        │ (核心状态管理)   │
        └────────┬────────┘
                 │
    ┌────────────┼────────────┐
    │            │            │
┌───▼────┐  ┌───▼────┐  ┌───▼────┐
│tokenS- │  │task    │  │WebSo-  │
│tore    │  │Schedu- │  │cket    │
│        │  │ler     │  │Client  │
└────────┘  └────────┘  └────────┘
```

### 核心模块

1. **UI层**
   - `BatchTaskPanel.vue` - 批量任务控制面板
   - `TaskProgressCard.vue` - 单Token进度卡片
   - `TemplateEditor.vue` - 任务模板编辑器
   - `SchedulerConfig.vue` - 定时任务配置
   - `ExecutionHistory.vue` - 执行历史记录

2. **状态管理层**
   - `batchTaskStore.js` - 批量任务状态管理（Pinia）
   - `tokenStore.js` - Token和WebSocket管理

3. **工具层**
   - `taskScheduler.js` - 任务调度器
   - `xyzwWebSocket.js` - WebSocket客户端
   - `gameCommands.js` - 游戏指令封装

---

## 🔧 核心功能实现

### 1. 批量任务执行流程

#### 1.1 启动流程
```javascript
// batchTaskStore.js
const startBatchExecution = async (tokenIds, tasks) => {
  // 1. 验证参数
  // 2. 初始化状态
  // 3. 创建任务队列
  // 4. 执行并发控制
  // 5. 完成后清理
}
```

#### 1.2 并发控制
```javascript
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任务执行
```javascript
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）
```javascript
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
```

**一键补差包含的所有子任务：**
1. 分享一次游戏
2. 赠送好友金币
3. 免费招募
4. 免费点金（3次）
5. 福利签到
6. 领取每日礼包
7. 领取免费礼包
8. 领取永久卡礼包
9. 领取邮件奖励
10. 免费钓鱼（3次）
11. 魏国灯神免费扫荡
12. 蜀国灯神免费扫荡
13. 吴国灯神免费扫荡
14. 群雄灯神免费扫荡
15. 领取免费扫荡卷（3次）
16. 领取任务奖励1-10（10个）
17. 领取日常任务奖励
18. 领取周常任务奖励
19. 停止盐罐机器人
20. 启动盐罐机器人
21. 领取盐罐奖励

**总计：约45+个子操作**

#### 2.2 俱乐部签到（legionSignIn）
```javascript
case 'legionSignIn':
  return await client.sendWithPromise('legion_signin', {}, 2000)
```

#### 2.3 一键答题（autoStudy）
```javascript
case 'autoStudy':
  return await client.sendWithPromise('study_startgame', {}, 2000)
```

#### 2.4 领取奖励-挂机（claimHangupReward）
```javascript
case 'claimHangupReward':
  return await client.sendWithPromise('system_claimhangupreward', {}, 2000)
```

#### 2.5 加钟（addClock）
```javascript
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
```

### 进度数据结构
```javascript
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
  }
}
```

### 统计数据结构
```javascript
executionStats = {
  total: 10,        // 总Token数
  success: 8,       // 成功数
  failed: 1,        // 失败数
  skipped: 1,       // 跳过数
  startTime: timestamp,
  endTime: timestamp
}
```

---

## 🔐 WebSocket连接管理

### 连接策略
```javascript
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
}
```

### 自动断开机制
```javascript
// executeTokenTasks的finally块
finally {
  // 任务完成后自动断开WebSocket连接
  if (tokenStore.wsConnections[tokenId]) {
    tokenStore.closeWebSocketConnection(tokenId)
  }
}
```

### 连接健康检查
- 每次执行前从bin文件重新获取roleToken
- 自动处理token失效问题
- 连接失败自动跳过，不影响其他Token

---

## ⚙️ 配置管理

### 并发数配置
```javascript
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())
}
```

### 任务模板配置
```javascript
const taskTemplates = {
  '完整套餐': {
    name: '完整套餐',
    tasks: ['dailyFix', 'legionSignIn', 'autoStudy', 'claimHangupReward', 'addClock'],
    enabled: true
  },
  '快速套餐': {
    name: '快速套餐',
    tasks: ['legionSignIn', 'autoStudy', 'claimHangupReward', 'addClock'],
    enabled: true
  },
  '仅一键补差': {
    name: '仅一键补差',
    tasks: ['dailyFix'],
    enabled: true
  }
}
```

### 调度器配置
```javascript
const schedulerConfig = {
  enabled: false,
  type: 'interval' | 'daily',
  interval: 4,  // 小时
  dailyTimes: ['08:00', '12:00', '18:00', '22:00'],
  lastExecutionTime: null
}
```

---

## 💾 数据存储结构

### localStorage键值
```javascript
{
  "taskTemplates": {
    "完整套餐": { ... },
    "快速套餐": { ... },
    ...
  },
  "batchTaskHistory": [
    {
      id: "batch_1234567890",
      template: "完整套餐",
      stats: { total: 10, success: 9, ... },
      timestamp: 1234567890,
      duration: 120000
    }
  ],
  "schedulerConfig": { ... },
  "maxConcurrency": "5"
}
```

---

## 🔧 扩展性设计

### 添加新任务
只需要在 `batchTaskStore.js` 的 `executeTask` 方法中添加新case：

```javascript
case 'newTask':
  // 新任务的WebSocket指令
  return await client.sendWithPromise('command_name', { params }, 2000)
```

然后在以下位置添加任务定义：
1. `BatchTaskPanel.vue` - taskDefinitions
2. `TemplateEditor.vue` - availableTasks
3. `TaskProgressCard.vue` - taskLabels
4. 默认模板（可选）

### 修改并发数
```javascript
const maxConcurrency = ref(5)  // 改为你想要的数字
```

### 自定义任务间隔
```javascript
await new Promise(resolve => setTimeout(resolve, 500))  // 修改延迟时间
```

---

## 🐛 错误处理机制

### 单任务失败处理
```javascript
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
- 🎉 初始版本发布
- ✅ 基础批量任务功能
- ✅ 任务模板系统
- ✅ 定时调度功能
- ✅ 执行历史记录

---

## 🎯 后续优化方向

1. **性能优化**
   - 实现任务结果缓存
   - 优化大量Token的渲染性能
   - 支持虚拟滚动

2. **功能增强**
   - 支持任务条件执行（如：仅未完成的任务）
   - 添加更多游戏任务
   - 支持自定义任务参数

3. **用户体验**
   - 提供任务执行预览
   - 添加声音提示
   - 支持深色主题

4. **数据分析**
   - 任务成功率统计
   - 执行时间趋势分析
   - Token性能对比

---

## 📚 参考文档

- [Vue 3 官方文档](https://vuejs.org/)
- [Pinia 状态管理](https://pinia.vuejs.org/)
- [Naive UI 组件库](https://www.naiveui.com/)
- [WebSocket API](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)

---

**技术实现完成！** 🎉
