# backend-dev - 任务计划

> 角色: 后端开发
> 状态: pending
> 分配的任务: OPT-02, OPT-08, OPT-12, OPT-17 及相关 API

## 任务

- [ ] P0-1: OPT-02 轮询超时修复（WebSocket 推送）
- [x] P1-5: OPT-08 后端 batch-generate API
- [x] P2-4: OPT-12 后端 feedback API
- [ ] P3-3: OPT-17 歌词时间轴（LRC 格式支持）

## 后端配套

| 优化项 | 后端变更 |
|--------|----------|
| OPT-02 | WebSocket 推送 audio_generation_complete, video_generation_complete 事件 |
| OPT-03 | 提供 /api/player/recent 最近播放记录 API |
| OPT-08 | POST /api/book-generator/books/:id/batch-generate 编排接口 |
| OPT-12 | POST /api/feedback 反馈提交接口 |
| OPT-17 | TTS 生成时返回 LRC 格式时间戳 |

## 备注

- 后端项目：server/
- WebSocket 使用 ws 库
- API 设计参考 docs/api-contracts.md

---

## 后端架构优化项（2026-05-16 审查发现）

> 文本内容生成和 TTS 音频生成逻辑审查，发现以下待优化问题

| # | 分类 | 问题 | 优先级 | 文件 |
|---|------|------|--------|------|
| BK-1 | 状态机 | `safeTransitionChapter` 状态冲突时静默 return，调用方无法感知失败 | P0 | stage-manager.ts:98-121 |
| BK-2 | 状态机 | 书籍阶段计算用"最落后章节"，一坏俱坏，无法查看已完成章节 | P0 | book-generator.store.ts:24-75 |
| BK-3 | 内容生成 | 父节点完成检查只验证直接子节点，不递归检查所有后代 | P0 | content.node.ts:22-59 |
| BK-4 | 状态机 | 内容生成两阶段推进（content_generating → content_completed）存在竞态 | P1 | book-generator.store.ts:1600-1618 |
| BK-5 | TTS | realtime 长文本模式被强制禁用（shouldUseLongText 恒返 false） | P1 | tts.service.ts:95-97 |
| BK-6 | TTS | Provider 全部降级后无兜底，直接抛错无 fallback | P1 | tts.service.ts:537-538 |
| BK-7 | TTS | `processAudioGeneration` 写 audioUrl 后 onComplete 再做 advanceChapter，任一失败导致 tryAutoMerge 不触发 | P1 | book-generator.store.ts:1326-1348 |
| BK-8 | TTS | LRC 生成对无标点纯英文文本按40字硬切，LRC行数爆炸 | P2 | tts.service.ts:884-895 |

### BK-1 详情：safeTransitionChapter 静默失败

```typescript
// stage-manager.ts:98-121
if (result.count === 0) {
  // ... 状态冲突处理
  console.warn(`[safeTransition] 章节 ${chapterId} 状态冲突...`);
  return;  // ← 问题：调用方以为成功了，继续执行下游
}
```

**建议**：失败时 throw Error，或返回 `boolean` 让调用方判断。

### BK-2 详情：书籍阶段一坏俱坏

```typescript
// book-generator.store.ts:24-75
let minIdx = stageOrder.length;
for (const ch of chapters) {
  if (idx < minIdx) minIdx = idx;  // 取最小（最落后）阶段
}
```

**影响**：20章中1章 failed，整本书显示 failed，用户无法访问其他19章已完成的音频。

**建议**：增加 `book.finishedChapters` 字段，与 `genStage` 解耦；或改用 most_common 逻辑。

### BK-3 详情：父节点完成检查不递归

```typescript
// content.node.ts:22-59
const allChildrenDone = children.every(
  c => c.genStage === 'content_completed' || c.genStage === 'audio_generating' ...
);
```

只检查直接子节点（level+1），如果节（level=2）下还有小节（level=3）在 `content_generating`，节会被错误推进到 `content_completed`。

**建议**：递归检查所有后代节点，或改用 BFS 收集叶节点后统一判断。

### BK-4 详情：两阶段推进竞态

```typescript
// book-generator.store.ts:1600-1618
if (currentChapter.genStage !== 'content_generating') {
  await advanceChapter(chapterId, 'content_generating').catch(() => {});
}
await advanceChapter(chapterId, 'content_completed');
```

两次 `advanceChapter` 之间如果有并发的音频生成任务抢占了 `content_generating`，第二次调用会失败。

**建议**：合并为单次 `safeTransitionChapter(chapterId, curStage, 'content_completed')` 调用。

### BK-5 详情：realtime 模式强制禁用

```typescript
// tts.service.ts:95-97
export function shouldUseLongText(text: string): boolean {
  return false; // 强制返回 false，禁用 realtime 模式
}
```

注释说 WebSocket 连接问题导致禁用，但 MiniMax 支持100万字符异步模式，长文本应优先走异步而非分段。

**建议**：修复 WebSocket 问题，启用 MiniMax 异步长文本模式。

### BK-6 详情：无兜底 Provider

```typescript
// tts.service.ts:537-538
throw new Error('所有 TTS Provider 都已尝试，均无法生成音频');
```

**建议**：mock provider 作为最后兜底，保证服务可用性。

### BK-7 详情：onComplete 回调状态推进失败

```typescript
// book-generator.store.ts:1326-1348
async (audioUrl: string, duration: number) => {
  await advanceChapter(chapterId, 'audio_completed');  // 可能失败
  tryAutoMerge(chapterId, ...);  // 失败则不会触发
}
```

**建议**：用 `tryAutoMerge` 替换 `advanceChapter` 失败的兜底逻辑，或在 `processTtsTask` 中等待回调完成后再推进状态。

### BK-8 详情：LRC 英文硬切

```typescript
// tts.service.ts:884-895
const chunkSize = 40;  // 纯英文按40字切分，万字文本=250+行
```

**建议**：增加英文句号 `.` 作为断句依据，与中文标点一致处理。

---

## BK-* 任务分配

| 任务 | 建议处理人 |
|------|-----------|
| BK-1, BK-4 | backend-dev（状态机逻辑修复） |
| BK-2 | backend-dev（数据库 schema 变更） |
| BK-3 | backend-dev（递归检查逻辑） |
| BK-5, BK-6, BK-7, BK-8 | backend-dev（TTS 服务层） |
