fix: 心愿实现页面用 pendingNextResponse 标志修复第二轮 loading 显示
- 新增 pendingNextResponse ref 标志等待下一个 assistant 响应 - showChatLoading 改用该标志判断,替代不可靠的最后消息 role 判断 - submitClarification 移除重复 addResultMessage,消除重复用户气泡 - 规避 mp-weixin 对 v-for 中 computed 数组的错误编译导致的页面空白 - runGeneration/clarification/outline/novel_start/novel_done 正确设置标志 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -114,7 +114,7 @@
|
|||||||
|
|
||||||
<view class="conversation compact">
|
<view class="conversation compact">
|
||||||
<view
|
<view
|
||||||
v-for="(msg, idx) in filteredResultMessages"
|
v-for="msg in resultMessages"
|
||||||
:key="msg.id"
|
:key="msg.id"
|
||||||
>
|
>
|
||||||
<view v-if="msg.role === 'user' && msg.kind === 'text'" class="chat-bubble user">
|
<view v-if="msg.role === 'user' && msg.kind === 'text'" class="chat-bubble user">
|
||||||
@@ -293,6 +293,8 @@ const novelOutline = ref(null)
|
|||||||
const clarificationCard = ref(null)
|
const clarificationCard = ref(null)
|
||||||
const currentStreamTask = ref(null)
|
const currentStreamTask = ref(null)
|
||||||
const answeringClarification = ref(false)
|
const answeringClarification = ref(false)
|
||||||
|
// 等待下一个 assistant 响应(包括 followupStream 的所有响应)
|
||||||
|
const pendingNextResponse = ref(false)
|
||||||
const outlineFeedback = ref('')
|
const outlineFeedback = ref('')
|
||||||
const messages = ref([])
|
const messages = ref([])
|
||||||
const versions = ref([])
|
const versions = ref([])
|
||||||
@@ -944,36 +946,12 @@ const generationCopy = computed(() => {
|
|||||||
|
|
||||||
// chat 视图 loading 显示条件:等待首个 assistant 响应期间
|
// chat 视图 loading 显示条件:等待首个 assistant 响应期间
|
||||||
// - generationPhase === 'generating':生成流程未完成
|
// - 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':非失败状态
|
// - generationStatus !== 'failed':非失败状态
|
||||||
// - 最后一条消息是 user:说明还没收到 assistant 响应(card/outline/novel)
|
// - pendingNextResponse:用户刚发完请求(心愿或澄清答案),等待下一个 assistant 响应
|
||||||
// 注意:使用原始 resultMessages 判定,不能用 filteredResultMessages(会被过滤掉导致永远 false)
|
|
||||||
const showChatLoading = computed(() => {
|
const showChatLoading = computed(() => {
|
||||||
if (generationPhase.value !== 'generating') return false
|
if (generationPhase.value !== 'generating') return false
|
||||||
if (generationStatus.value === 'failed') return false
|
if (generationStatus.value === 'failed') return false
|
||||||
const list = resultMessages.value
|
return pendingNextResponse.value === true
|
||||||
if (!list || !list.length) return false
|
|
||||||
const lastMsg = list[list.length - 1]
|
|
||||||
return lastMsg && lastMsg.role === 'user'
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const generationSubcopy = computed(() => {
|
const generationSubcopy = computed(() => {
|
||||||
@@ -1668,6 +1646,7 @@ const runGeneration = async ({ prompt, displayText, source = 'text', saveTheme }
|
|||||||
novelOutline.value = null
|
novelOutline.value = null
|
||||||
clarificationCard.value = null
|
clarificationCard.value = null
|
||||||
novelSessionId.value = ''
|
novelSessionId.value = ''
|
||||||
|
pendingNextResponse.value = true // 标记等待下一个 assistant 响应
|
||||||
resumeableSessionId.value = ''
|
resumeableSessionId.value = ''
|
||||||
outlineFeedback.value = ''
|
outlineFeedback.value = ''
|
||||||
generationDisplayText.value = display
|
generationDisplayText.value = display
|
||||||
@@ -1719,14 +1698,17 @@ const handleShortNovelEvent = (event) => {
|
|||||||
case 'clarification_card':
|
case 'clarification_card':
|
||||||
addResultMessage({ role: 'assistant', kind: 'card', card: payload.card || null })
|
addResultMessage({ role: 'assistant', kind: 'card', card: payload.card || null })
|
||||||
generationStatus.value = 'idle'
|
generationStatus.value = 'idle'
|
||||||
|
pendingNextResponse.value = false
|
||||||
break
|
break
|
||||||
case 'outline_created':
|
case 'outline_created':
|
||||||
addResultMessage({ role: 'assistant', kind: 'outline', outline: payload.outline || null })
|
addResultMessage({ role: 'assistant', kind: 'outline', outline: payload.outline || null })
|
||||||
generationStatus.value = 'idle'
|
generationStatus.value = 'idle'
|
||||||
|
pendingNextResponse.value = false
|
||||||
break
|
break
|
||||||
case 'novel_start':
|
case 'novel_start':
|
||||||
addResultMessage({ role: 'assistant', kind: 'novel', content: '', pending: true })
|
addResultMessage({ role: 'assistant', kind: 'novel', content: '', pending: true })
|
||||||
generationStatus.value = 'streaming'
|
generationStatus.value = 'streaming'
|
||||||
|
pendingNextResponse.value = false
|
||||||
break
|
break
|
||||||
case 'novel_delta': {
|
case 'novel_delta': {
|
||||||
// 往最后一条 novel 消息追加 delta
|
// 往最后一条 novel 消息追加 delta
|
||||||
@@ -1749,6 +1731,7 @@ const handleShortNovelEvent = (event) => {
|
|||||||
currentVersionMessageId.value = payload.currentVersionMessageId || ''
|
currentVersionMessageId.value = payload.currentVersionMessageId || ''
|
||||||
generationPhase.value = 'done'
|
generationPhase.value = 'done'
|
||||||
generationStatus.value = 'idle'
|
generationStatus.value = 'idle'
|
||||||
|
pendingNextResponse.value = false
|
||||||
persistResultMessages()
|
persistResultMessages()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -1774,9 +1757,9 @@ const submitClarification = (answer) => {
|
|||||||
const label = option?.label || answer
|
const label = option?.label || answer
|
||||||
if (card) {
|
if (card) {
|
||||||
card.submitted = true
|
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
|
answeringClarification.value = true
|
||||||
currentStreamTask.value = followupStream({
|
currentStreamTask.value = followupStream({
|
||||||
sessionId: novelSessionId.value,
|
sessionId: novelSessionId.value,
|
||||||
|
|||||||
Reference in New Issue
Block a user