diff --git a/server/src/main/java/com/emotion/service/impl/ShortNovelServiceImpl.java b/server/src/main/java/com/emotion/service/impl/ShortNovelServiceImpl.java index 1840474..2ba1bc7 100644 --- a/server/src/main/java/com/emotion/service/impl/ShortNovelServiceImpl.java +++ b/server/src/main/java/com/emotion/service/impl/ShortNovelServiceImpl.java @@ -179,7 +179,8 @@ public class ShortNovelServiceImpl implements ShortNovelService { upstreamBody.put("message_id", "web_" + System.currentTimeMillis()); upstreamBody.put("query", request.getQuery()); - return forwardSse("/api/novels/daily/conversation/stream", upstreamBody, currentUserId, request.getQuery()); + return forwardSse("/api/novels/daily/conversation/stream", upstreamBody, currentUserId, + request.getQuery(), null); } @Override @@ -207,7 +208,8 @@ public class ShortNovelServiceImpl implements ShortNovelService { upstreamBody.put("action", request.getAction()); upstreamBody.put("payload", request.getPayload()); - return forwardSse("/api/novels/daily/conversation/stream", upstreamBody, currentUserId, effectiveOriginalQuery); + return forwardSse("/api/novels/daily/conversation/stream", upstreamBody, currentUserId, + effectiveOriginalQuery, request.getSessionId()); } /** @@ -218,7 +220,8 @@ public class ShortNovelServiceImpl implements ShortNovelService { * @param currentUserId 当前用户ID(从主线程捕获,避免 ThreadLocal 在异步线程中失效) * @param originalQuery 原始用户查询(首次请求时传入,用于保存) */ - private SseEmitter forwardSse(String path, Map body, String currentUserId, String originalQuery) { + private SseEmitter forwardSse(String path, Map body, String currentUserId, + String originalQuery, String knownSessionId) { SseEmitter emitter = new SseEmitter(config.getReadTimeout().longValue()); EXECUTOR.execute(() -> { @@ -229,6 +232,9 @@ public class ShortNovelServiceImpl implements ShortNovelService { final java.util.concurrent.atomic.AtomicReference stageMetaRef = new java.util.concurrent.atomic.AtomicReference<>(new JSONObject()); + // 当前流的 sessionId(stream 首次从 status 事件获取,followup 从请求参数获取) + final String[] currentSessionId = {knownSessionId}; + // 累积 novel_delta 事件的文本内容 // 上游服务通过 novel_delta 流式发送小说内容,novel_done 事件可能不含 full_text // 因此需要在后端累积所有 delta,在 novel_done 时使用累积的完整文本保存到数据库 @@ -289,8 +295,8 @@ public class ShortNovelServiceImpl implements ShortNovelService { JSONObject payload = event.getJSONObject("payload"); if (payload != null) { String sessionId = payload.getString("session_id"); - if (sessionId != null && !sessionId.isEmpty() - && originalQuery != null && !originalQuery.isEmpty()) { + if (sessionId != null && !sessionId.isEmpty()) { + currentSessionId[0] = sessionId; // 缓存原始参数:originalQuery/style/length String style = payload.getString("style"); String length = payload.getString("length"); @@ -307,11 +313,25 @@ public class ShortNovelServiceImpl implements ShortNovelService { JSONObject outline = stagePayload.getJSONObject("outline"); if (outline != null) { stageMetaRef.get().put("outline", outline); + // 累积到全局 session 缓存,供详情页还原大纲步骤 + if (currentSessionId[0] != null) { + JSONObject entry = new JSONObject(); + entry.put("kind", "outline"); + entry.put("outline", outline); + accumulateStage(currentSessionId[0], entry); + } } } else if ("clarification_card".equals(type)) { JSONObject card = stagePayload.getJSONObject("card"); if (card != null) { stageMetaRef.get().put("clarification", card); + // 累积到全局 session 缓存,供详情页还原完整澄清流程 + if (currentSessionId[0] != null) { + JSONObject entry = new JSONObject(); + entry.put("kind", "clarification_question"); + entry.put("card", card); + accumulateStage(currentSessionId[0], entry); + } } } else if ("novel_delta".equals(type)) { // 累积小说正文片段:上游通过 novel_delta 逐段发送内容