diff --git a/mini-program/src/pages/main/ScriptView.vue b/mini-program/src/pages/main/ScriptView.vue index 3bf1a20..eb1d273 100644 --- a/mini-program/src/pages/main/ScriptView.vue +++ b/mini-program/src/pages/main/ScriptView.vue @@ -114,7 +114,7 @@ @@ -293,6 +293,8 @@ const novelOutline = ref(null) const clarificationCard = ref(null) const currentStreamTask = ref(null) const answeringClarification = ref(false) +// 等待下一个 assistant 响应(包括 followupStream 的所有响应) +const pendingNextResponse = ref(false) const outlineFeedback = ref('') const messages = ref([]) const versions = ref([]) @@ -944,36 +946,12 @@ const generationCopy = computed(() => { // chat 视图 loading 显示条件:等待首个 assistant 响应期间 // - generationPhase === 'generating':生成流程未完成 -// 渲染层过滤:去掉"紧跟在已提交 card 后、内容等于 card.answer"的 user 消息,避免重复气泡 -// 注意:showChatLoading 必须用原始 resultMessages 判定(不能用 filteredResultMessages,否则永远 false) -const filteredResultMessages = computed(() => { - const list = resultMessages.value - if (!list || list.length < 2) return list - return list.filter((m, idx) => { - if (!(m.role === 'user' && m.kind === 'text')) return true - // 向前查找最近的 card 消息 - for (let i = idx - 1; i >= 0; i--) { - const prev = list[i] - if (prev.kind === 'card') { - // 是已提交 card 且内容相同 → 过滤 - if (prev.submitted && prev.answer && m.content === prev.answer) return false - return true - } - } - return true - }) -}) - // - generationStatus !== 'failed':非失败状态 -// - 最后一条消息是 user:说明还没收到 assistant 响应(card/outline/novel) -// 注意:使用原始 resultMessages 判定,不能用 filteredResultMessages(会被过滤掉导致永远 false) +// - pendingNextResponse:用户刚发完请求(心愿或澄清答案),等待下一个 assistant 响应 const showChatLoading = computed(() => { if (generationPhase.value !== 'generating') return false if (generationStatus.value === 'failed') return false - const list = resultMessages.value - if (!list || !list.length) return false - const lastMsg = list[list.length - 1] - return lastMsg && lastMsg.role === 'user' + return pendingNextResponse.value === true }) const generationSubcopy = computed(() => { @@ -1668,6 +1646,7 @@ const runGeneration = async ({ prompt, displayText, source = 'text', saveTheme } novelOutline.value = null clarificationCard.value = null novelSessionId.value = '' + pendingNextResponse.value = true // 标记等待下一个 assistant 响应 resumeableSessionId.value = '' outlineFeedback.value = '' generationDisplayText.value = display @@ -1719,14 +1698,17 @@ const handleShortNovelEvent = (event) => { case 'clarification_card': addResultMessage({ role: 'assistant', kind: 'card', card: payload.card || null }) generationStatus.value = 'idle' + pendingNextResponse.value = false break case 'outline_created': addResultMessage({ role: 'assistant', kind: 'outline', outline: payload.outline || null }) generationStatus.value = 'idle' + pendingNextResponse.value = false break case 'novel_start': addResultMessage({ role: 'assistant', kind: 'novel', content: '', pending: true }) generationStatus.value = 'streaming' + pendingNextResponse.value = false break case 'novel_delta': { // 往最后一条 novel 消息追加 delta @@ -1749,6 +1731,7 @@ const handleShortNovelEvent = (event) => { currentVersionMessageId.value = payload.currentVersionMessageId || '' generationPhase.value = 'done' generationStatus.value = 'idle' + pendingNextResponse.value = false persistResultMessages() break } @@ -1774,9 +1757,9 @@ const submitClarification = (answer) => { const label = option?.label || answer if (card) { card.submitted = true - card.answer = label // 显示用 label(中文);答案已在卡片中显示,但同时添加 user 消息让 loading 能正确判断等待状态 + card.answer = label // 显示用 label(中文);答案已在卡片中显示,无需额外用户气泡 } - addResultMessage({ role: 'user', kind: 'text', content: label }) + pendingNextResponse.value = true // 标记等待下一个 assistant 响应 answeringClarification.value = true currentStreamTask.value = followupStream({ sessionId: novelSessionId.value,