diff --git a/backend/api/chat_router.py b/backend/api/chat_router.py index aab9287..9595756 100644 --- a/backend/api/chat_router.py +++ b/backend/api/chat_router.py @@ -274,11 +274,11 @@ async def websocket_chat_endpoint(websocket: WebSocket, user_id: str): ) # 余额耗尽时通知前端 remaining = charge_result.get("available_tokens", 0) - if remaining <= 0: - await websocket.send_text(json.dumps({ + # 扣费失败时也通知前端 + await websocket.send_text(json.dumps({ "type": "error", "error": "insufficient_tokens", - "message": "Token不足,请充值", + "message": "Token不足(剩余" + str(remaining) + "),请充值", "available_tokens": remaining, "timestamp": datetime.now().isoformat() })) diff --git a/backend/api/voice_chat_router.py b/backend/api/voice_chat_router.py index f1d8b80..797e2dd 100644 --- a/backend/api/voice_chat_router.py +++ b/backend/api/voice_chat_router.py @@ -1264,8 +1264,8 @@ async def receive_events_loop( })) except Exception: pass - # 余额耗尽时终止事件循环,防止火山引擎继续消费 - if remaining <= 0: + # 扣费失败时终止事件循环(余额不够最低消费也要停) + if True: logger.warning( f"[VOICE_TOKEN_EXHAUSTED] user_id={user_id} mode={charge_mode} " f"remaining={remaining}, breaking event loop and closing" diff --git a/frontend/src/stores/chatStore.js b/frontend/src/stores/chatStore.js index 1e92956..0f6f11d 100644 --- a/frontend/src/stores/chatStore.js +++ b/frontend/src/stores/chatStore.js @@ -1013,6 +1013,7 @@ export const useChatStore = defineStore('chat', () => { case 'token_update': { const remaining = data.remaining_tokens ?? data.data?.remaining_tokens ?? null + const warning = data.warning || data.data?.warning if (remaining !== null) { console.log('[ChatStore] Token update:', remaining, 'remaining') // 余额耗尽时标记并断开 @@ -1024,16 +1025,21 @@ export const useChatStore = defineStore('chat', () => { resetAudioState() break } + // 扣费失败(余额不够最低消费)也标记耗尽 + if (warning) { + console.warn('[ChatStore] Token charge failed:', warning, 'remaining:', remaining) + _realtimeTokenExhausted = true + ElMessage.error(`Token不足(剩余${remaining}),实时通话已结束`) + disconnectRealtimeWebSocket() + resetAudioState() + break + } // 充值后恢复:余额恢复时重置耗尽标记和 AI 处理状态 _realtimeTokenExhausted = false if (isAiProcessing.value) { isAiProcessing.value = false } } - const warning = data.warning || data.data?.warning - if (warning) { - console.warn('[ChatStore] Token warning:', warning) - } } break case 'error':