4.1 KiB
4.1 KiB
author, created_at, purpose
| author | created_at | purpose |
|---|---|---|
| AI Assistant | 2026-07-26 | 修复详情页只显示 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 | ... |
根因链:
- 上游 SSE 事件结构:
session_id字段在事件顶层(与type同级),不在payload内。前端从顶层取(ScriptView.vue:1800const { type, session_id, payload } = event)且工作正常。 - 后端 status 事件处理:
ShortNovelServiceImpl.forwardSse行 312-314 从payload.getString("session_id")取,取不到。 - 首次 stream 的 currentSessionId[0] 初始为 null:
forwardSse行 253final String[] currentSessionId = {knownSessionId},首次 stream 调用时knownSessionId=null。 - 首次 stream 的 Q1 不累积:首次 stream 里第一个
clarification_card事件到达时currentSessionId[0]仍为 null,行 346 的if (currentSessionId[0] != null)为 false,Q1 不被accumulateStage累积。 - followup 流正常:followup 调用
forwardSse时knownSessionId = request.getSessionId()(前端传的,非 null),后续 Q2/Q3 都正确累积。 - drainStages 取到不完整的 stagesHistory:novel_done 时 drainStages 取到
[A1, Q2, A2, Q3, A3, outline](缺 Q1),saveNovelResult 创建 2 question + 3 answer。 - 详情页只能渲染 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)) 之前):
// 从事件顶层取 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 已永久丢失,无法真实恢复。
验收标准
- 在 H5 手动完成一次新的小说生成(包含至少 2 轮澄清)
- 进入该剧本的详情页
- 验证选项卡数量与生成页完全一致(生成 N 个,详情显示 N 个)
- Console 无新增错误
- 本地
mvn clean install编译通过