# OPT-02 任务发现

## 概述
移除前端代码中的 30s setTimeout 超时逻辑，改为监听 WebSocket 事件。

## 修改文件
- `my-uniapp-vue3/src/utils/websocket.ts` (新建)
- `my-uniapp-vue3/src/pages/book-generator/index.vue` (修改)
- `my-uniapp-vue3/src/pages/book-generator/chapter-detail.vue` (修改)

## 详细修改

### index.vue
- 导入 wsManager
- 添加 handleAudioGenerationComplete 和 handleVideoGenerationComplete 事件处理函数
- 在 onMounted 中连接 WebSocket 并订阅事件
- 在 onUnmounted 中取消订阅
- 移除两处 30s 超时 setTimeout

### chapter-detail.vue
- 导入 wsManager
- 添加事件处理函数，通过 bookId 和 chapterId 匹配当前页面
- 在 onMounted 中连接 WebSocket 并订阅事件
- 在 onUnmounted 中取消订阅
- 移除两处 30s 超时 setTimeout

### websocket.ts
- 使用 uni.connectSocket 实现，支持 H5 和小程序
- 单例模式 wsManager
- 实现 connect、on、off、send、close 方法
- 自动重连机制（最多3次）

## OPT-02 Review 修复 (2026/05/07)

### [HIGH] 问题 1：重连后事件重订阅丢失
- **文件**: `my-uniapp-vue3/src/utils/websocket.ts`
- **修复内容**:
  - 添加 `subscriptions` Set 跟踪已订阅的事件
  - `on()` 方法订阅时记录事件到 `subscriptions`，并发送 `_subscribe` 消息到服务器
  - `off()` 方法取消订阅时从 `subscriptions` 移除
  - `handleReconnect()` 重连成功后调用 `resubscribe()` 重新发送订阅消息
  - `resubscribe()` 遍历 `subscriptions` 重新发送订阅请求

### [HIGH] 问题 2：chapter-detail.vue 定时器未清理
- **文件**: `my-uniapp-vue3/src/pages/book-generator/chapter-detail.vue`
- **修复内容**:
  - 添加 `audioPollTimer` 和 `videoPollTimer` 变量存储定时器 ID
  - `handleGenerateAudio()` 和 `handleGenerateVideo()` 使用全局变量存储定时器
  - `onUnmounted()` 中添加 `clearInterval` 清理逻辑

### [MEDIUM] 问题 3：两个 onMounted 钩子
- **文件**: `my-uniapp-vue3/src/pages/book-generator/chapter-detail.vue`
- **修复内容**:
  - 合并两个 `onMounted()` 为一个
  - 第一个 `onMounted`（URL参数加载和章节加载）保留
  - 第二个 `onMounted`（WebSocket 连接）删除，代码合并到第一个中
