docs: 详情页澄清选项卡显示不全修复设计
This commit is contained in:
@@ -0,0 +1,75 @@
|
|||||||
|
---
|
||||||
|
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_card(Q1)**。
|
||||||
|
|
||||||
|
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)` 为 false,Q1 不被 `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` 编译通过
|
||||||
Reference in New Issue
Block a user