Files
happy-life-star/docs/superpowers/specs/2026-07-26-detail-clarification-card-count-fix-design.md
T

76 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
author: AI Assistant
created_at: 2026-07-26
purpose: 修复详情页只显示 2 个澄清选项卡(应为 N 个)的后端累积丢失 bug
---
# 详情页澄清选项卡显示不全修复设计
## 问题
生成小说时,生成页显示 N 个澄清选项卡(clarification cards),但进入详情页后只显示前 2 个。必须保证详情页选项卡数量与生成页完全一致。
## 根因分析
通过数据库查询(t_message 按 conversation_id 分组统计)确认:3 个有 clarification 的 conversation 全部是 **clarification_question=2 + clarification_answer=3**。即用户回答了 3 次(3 个 answer),但后端只保存了 2 个 question。**丢失的是第一个 clarification_cardQ1**。
DB 中 conversation `339751895901937665` 的 messageOrder 分布:
| order | type | content |
|---|---|---|
| 1 | clarification_answer | 同事/上司 |
| 2 | clarification_question | 是什么具体事件让你决定不再讨好? |
| 3 | clarification_answer | 功劳被抢 |
| 4 | clarification_question | 你希望主角如何反击? |
| 5 | clarification_answer | 暗中布局 |
| 6 | outline | ... |
**根因链**
1. **上游 SSE 事件结构**`session_id` 字段在事件**顶层**(与 `type` 同级),不在 `payload` 内。前端从顶层取(`ScriptView.vue:1800` `const { type, session_id, payload } = event`)且工作正常。
2. **后端 status 事件处理**`ShortNovelServiceImpl.forwardSse` 行 312-314 从 `payload.getString("session_id")` 取,**取不到**。
3. **首次 stream 的 currentSessionId[0] 初始为 null**`forwardSse` 行 253 `final String[] currentSessionId = {knownSessionId}`,首次 stream 调用时 `knownSessionId=null`
4. **首次 stream 的 Q1 不累积**:首次 stream 里第一个 `clarification_card` 事件到达时 `currentSessionId[0]` 仍为 null,行 346 的 `if (currentSessionId[0] != null)` 为 falseQ1 不被 `accumulateStage` 累积。
5. **followup 流正常**followup 调用 `forwardSse``knownSessionId = request.getSessionId()`(前端传的,非 null),后续 Q2/Q3 都正确累积。
6. **drainStages 取到不完整的 stagesHistory**novel_done 时 drainStages 取到 `[A1, Q2, A2, Q3, A3, outline]`(缺 Q1),saveNovelResult 创建 2 question + 3 answer。
7. **详情页只能渲染 2 个 card**:从 DB 读到的 clarification_question 只有 2 条。
## 修复方案
**修改文件**`server/src/main/java/com/emotion/service/impl/ShortNovelServiceImpl.java`
**修改点**`forwardSse` 方法的事件循环(行 305 附近),在解析 event 后、status 处理之前,**从事件顶层取 `session_id` 同步 `currentSessionId[0]`**(与前端 `ScriptView.vue:1805-1806` 取 sessionId 的方式对齐)。
**新增代码**(放在 `String type = event.getString("type");` 之后、status 事件 `if ("status".equals(type))` 之前):
```java
// 从事件顶层取 session_id 同步 sessionId
// 上游事件结构与前端对齐:session_id 与 type 同级,不在 payload 内
// 修复:首次 stream 里 status 处理从 payload 取不到 session_id,导致 currentSessionId 保持 null
// 第一个 clarification_card 因 sessionId 为 null 不累积,详情页少显示第一个选项卡
String topSessionId = event.getString("session_id");
if (topSessionId != null && !topSessionId.isEmpty()) {
currentSessionId[0] = topSessionId;
}
```
## 影响范围
-`forwardSse` 方法新增 5 行代码
- 零现有逻辑改动(status 处理保留原样作为次选,顶层取 sessionId 优先覆盖)
- 零数据库变更
- 零前端改动
## 预期效果
- **新剧本**:首次 stream 的 Q1 不再丢失,详情页显示全部 N 个选项卡(与生成页完全一致)
- **老剧本**3 个已有 conversation):保持现状,仍显示 2 个 card。DB 中 stagesHistory 缺失的 Q1 已永久丢失,无法真实恢复。
## 验收标准
1. 在 H5 手动完成一次新的小说生成(包含至少 2 轮澄清)
2. 进入该剧本的详情页
3. 验证选项卡数量与生成页完全一致(生成 N 个,详情显示 N 个)
4. Console 无新增错误
5. 本地 `mvn clean install` 编译通过