P1-6: WS死路由清理+结单确认断链修复 - 删ai_reply_chunk/quiz_diagnostic_answer死路由 + pending_close_request改为resolve_confirm对齐后端 + 挂载ResolveConfirmCard(修复坐席结单员工端不可见的功能断链)

This commit is contained in:
Simon
2026-07-18 02:03:13 +08:00
parent 9cbf2650e1
commit 59609b1d8d
3 changed files with 24 additions and 78 deletions
@@ -86,6 +86,16 @@
:key="msg.message_id"
:msg="msg"
/>
<!-- 坐席结单确认卡片v4.0 P1-6 修复WS resolve_confirm pendingCloseRequest 挂载此卡片 -->
<ResolveConfirmCard
v-if="store.pendingCloseRequest"
:resolve-summary="store.pendingCloseRequest.resolve_summary"
:conversation-id="store.pendingCloseRequest.conversation_id"
@confirmed="store.clearPendingCloseRequest()"
@rejected="store.clearPendingCloseRequest()"
@timeout="store.clearPendingCloseRequest()"
/>
</template>
</div>
@@ -139,6 +149,7 @@ import InputBar from './InputBar.vue'
// 2026-07-12 改造:不再 import CallAgentModal(弹窗动画已移除)
// import CallAgentModal from './CallAgentModal.vue'
import TroubleshootFlow from './TroubleshootFlow.vue'
import ResolveConfirmCard from './ResolveConfirmCard.vue'
import ParticipantStrip from './ParticipantStrip.vue'
import ParticipantList from './ParticipantList.vue'
import EvaluationDialog from './EvaluationDialog.vue'
+7 -17
View File
@@ -387,14 +387,10 @@ export function useH5WebSocket() {
break
// ==================================================================
// AI 回复流式推送(改造方案 A:发送瞬时返回,AI 经 WS 推回)
// AI 回复blocking 模式:发送瞬时返回,AI 经 WS 推回)
// ==================================================================
case 'ai_reply_chunk':
// 打字机:逐 chunk 累积到临时 AI 气泡
if (msg.data) {
store.handleAiReplyChunk(msg.data)
}
break
// v4.0 P1-6case 'ai_reply_chunk' 已删除(后端从未推送流式 chunk,
// blocking 模式下 AI 回复只走 ai_reply 完整消息)
case 'ai_reply':
// AI 终态:用真实消息替换打字机气泡
@@ -474,10 +470,10 @@ export function useH5WebSocket() {
// ==================================================================
// 坐席发起结单 — 员工端弹出确认卡片
// ==================================================================
case 'pending_close_request':
case 'resolve_confirm':
// 坐席发起了结单,会话进入 pending_close 状态
// 做什么:在消息流中插入 ResolveConfirmCard 组件
// 员工需在 5 分钟内确认或拒绝,否则系统自动关闭
// v4.0 P1-6 修复:后端实际推送类型是 resolve_confirmclosing_service._push_resolve_confirm),
// 原 case 'pending_close_request' 从未命中导致结单确认卡片不显示(功能断链)
if (msg.data) {
store.handlePendingCloseRequest(msg.data)
}
@@ -486,13 +482,7 @@ export function useH5WebSocket() {
// ==================================================================
// 诊断答题答案附加到会话上下文
// ==================================================================
case 'quiz_diagnostic_answer':
// 诊断题答案已附加到会话上下文
// 做什么:在消息流中显示一条系统消息,告知用户诊断信息已传递给坐席
if (msg.data) {
store.handleQuizDiagnosticAnswer(msg.data)
}
break
// v4.0 P1-6case 'quiz_diagnostic_answer' 已删除(后端从未推送此类型)
default:
console.warn(`[H5 WS] 未知消息类型: ${msg.type}`)
+6 -61
View File
@@ -1067,39 +1067,6 @@ export const useConversationStore = defineStore('conversation', () => {
/**
* 处理 WS 流式 AI 回复 chunk(打字机效果)
* 做什么:首个 chunk 时创建临时 AI 气泡,后续 chunk 累积到该气泡 content
* 为什么:后端 AI 推理(Dify)流式返回,逐字推送以获得打字机体验,
* 避免整段等待(原同步方案卡"发送中"3~15s
*
* @param data - { conversation_id, chunk }
*/
function handleAiReplyChunk(data: { conversation_id: string; chunk: string }): void {
// 仅处理当前会话,避免串台
if (currentConversation.value?.conversation_id !== data.conversation_id) return
if (!data.chunk) return
// 首个 chunk:创建占位气泡(不设置 status,避免误显示"发送中"
if (!streamingAiMessageId.value) {
const tempId = `ai_stream_${data.conversation_id}_${Date.now()}`
streamingAiMessageId.value = tempId
messages.value.push({
message_id: tempId,
conversation_id: data.conversation_id,
message_type: 'ai',
msg_type: 'text',
content: '',
sender_name: 'Duckula(达寇拉)',
created_at: new Date().toISOString(),
})
}
// 累积 chunkVue3 ref 深层响应式,直接改属性即可触发重渲染 → 打字机)
const idx = messages.value.findIndex(m => m.message_id === streamingAiMessageId.value)
if (idx !== -1) {
messages.value[idx].content += data.chunk
}
}
/**
* 处理 WS AI 回复终态
* 做什么:用真实 AI 消息(含 DB message_id)替换打字机占位气泡,
@@ -1457,12 +1424,15 @@ export const useConversationStore = defineStore('conversation', () => {
/**
* 处理坐席结单请求
* WS event: pending_close_request
* WS event: resolve_confirmv4.0 P1-6 修复:对齐后端 closing_service 实际推送类型)
* 后端 payload: { conversation_id, agent_id, resolve_summary, auto_close_minutes, timestamp }
*/
function handlePendingCloseRequest(data: {
conversation_id: string
resolve_summary: string
agent_name: string
agent_id?: string
agent_name?: string
auto_close_minutes?: number
}): void {
if (currentConversation.value?.conversation_id !== data.conversation_id) return
@@ -1491,29 +1461,6 @@ export const useConversationStore = defineStore('conversation', () => {
messages.value.push(systemMsg)
}
/**
* 处理诊断答题答案附加到上下文
* WS event: quiz_diagnostic_answer
*/
function handleQuizDiagnosticAnswer(data: {
question: string
selected_answer: string
conversation_id: string
}): void {
// 添加系统消息,告知用户诊断信息已传递
const systemMsg: Message = {
message_id: `quiz_diag_${data.conversation_id}_${Date.now()}`,
conversation_id: data.conversation_id,
message_type: 'system',
msg_type: 'text',
content: `📝 诊断信息已传递给坐席:${data.question}${data.selected_answer}`,
sender_name: '系统',
created_at: new Date().toISOString(),
status: 'sent',
}
messages.value.push(systemMsg)
}
/** 清除结单请求(确认或拒绝后调用) */
function clearPendingCloseRequest(): void {
pendingCloseRequest.value = null
@@ -1710,8 +1657,7 @@ export const useConversationStore = defineStore('conversation', () => {
// WS-06 消息去重(与 agent 端对齐,WebSocket 接入时使用)
handleNewMessage,
// 流式 AI 回复(改造方案 A打字机
handleAiReplyChunk,
// 流式 AI 回复(改造方案 Ablocking 模式,v4.0 P1-6 删除 handleAiReplyChunk
handleAiReply,
handleAiReplyFailed,
cancelStreamingBubble,
@@ -1737,7 +1683,6 @@ export const useConversationStore = defineStore('conversation', () => {
handleQueuePositionUpdate,
handleConversationResolved,
handlePendingCloseRequest,
handleQuizDiagnosticAnswer,
clearPendingCloseRequest,
clearResolvedInfo,
}