chore:ws通信成功
This commit is contained in:
@@ -61,54 +61,104 @@ export default {
|
|||||||
* 流式消息入口(自动适配平台)
|
* 流式消息入口(自动适配平台)
|
||||||
*/
|
*/
|
||||||
async sendStreamMessage(message, onChunk, onComplete) {
|
async sendStreamMessage(message, onChunk, onComplete) {
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-WEIXIN
|
||||||
// 微信小程序:降级为普通请求 + 前端打字模拟
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
const socketTask = wx.connectSocket({
|
||||||
const result = await this.sendMessage(message);
|
url: 'wss://dev.aigc-quickapp.com/ws/aikefu',
|
||||||
const content = result.content || '';
|
header: {
|
||||||
const conversationId = result.conversationId || '';
|
}
|
||||||
|
|
||||||
// 保存会话ID(确保连续对话)
|
|
||||||
if (conversationId) {
|
|
||||||
this.setConversationId(conversationId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 模拟打字效果
|
|
||||||
let index = 0;
|
|
||||||
const chunkSize = 2; // 每次显示2个字符
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
const timer = setInterval(() => {
|
|
||||||
if (index < content.length) {
|
|
||||||
const chunk = content.substring(index, index + chunkSize);
|
|
||||||
index += chunkSize;
|
|
||||||
if (onChunk) onChunk(chunk);
|
|
||||||
} else {
|
|
||||||
clearInterval(timer);
|
|
||||||
if (onComplete) {
|
|
||||||
onComplete({
|
|
||||||
content: content,
|
|
||||||
conversation_id: conversationId
|
|
||||||
});
|
|
||||||
}
|
|
||||||
resolve({ content, conversation_id: conversationId });
|
|
||||||
}
|
|
||||||
}, 80); // 打字速度:80ms/次
|
|
||||||
});
|
});
|
||||||
} catch (error) {
|
|
||||||
console.error('小程序流式消息降级失败:', error);
|
|
||||||
if (onComplete) {
|
|
||||||
onComplete({ error: error.message || '发送失败' });
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifdef H5
|
let content = '';
|
||||||
// H5:使用真实流式(EventSource / Fetch)
|
let conversationId = '';
|
||||||
return this.sendHttpStream(message, onChunk, onComplete);
|
let isAuthenticated = false;
|
||||||
// #endif
|
|
||||||
},
|
|
||||||
|
|
||||||
|
// 连接成功
|
||||||
|
socketTask.onOpen(() => {
|
||||||
|
console.log('WebSocket 连接成功,开始认证...');
|
||||||
|
// 第一步:发送 auth 认证
|
||||||
|
socketTask.send({
|
||||||
|
data: JSON.stringify({
|
||||||
|
action: 'auth',
|
||||||
|
uniacid: store.state.uniacid || '1',
|
||||||
|
token: store.state.token || 'test_token',
|
||||||
|
user_id: store.state.memberInfo?.id || 'anonymous'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 接收消息
|
||||||
|
socketTask.onMessage((res) => {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(res.data);
|
||||||
|
console.log('收到 WebSocket 消息:', data);
|
||||||
|
|
||||||
|
// 处理认证响应
|
||||||
|
if (data.type === 'auth_success') {
|
||||||
|
console.log('认证成功,发送聊天消息...');
|
||||||
|
isAuthenticated = true;
|
||||||
|
socketTask.send({
|
||||||
|
data: JSON.stringify({
|
||||||
|
action: 'chat',
|
||||||
|
uniacid: store.state.uniacid || '1',
|
||||||
|
query: message,
|
||||||
|
user_id: store.state.memberInfo?.id || 'anonymous',
|
||||||
|
conversation_id: this.getConversationId() || ''
|
||||||
|
})
|
||||||
|
});
|
||||||
|
} else if (data.type === 'auth_failed') {
|
||||||
|
const errorMsg = '认证失败,请重新登录';
|
||||||
|
console.error(errorMsg, data);
|
||||||
|
reject(new Error(errorMsg));
|
||||||
|
if (onComplete) onComplete({ error: errorMsg });
|
||||||
|
socketTask.close();
|
||||||
|
}
|
||||||
|
// 处理聊天流式响应
|
||||||
|
else if (data.action === 'chat_response') {
|
||||||
|
if (data.type === 'chunk') {
|
||||||
|
const text = data.content || '';
|
||||||
|
content += text;
|
||||||
|
if (onChunk) onChunk(text);
|
||||||
|
} else if (data.type === 'end') {
|
||||||
|
conversationId = data.conversation_id || '';
|
||||||
|
if (conversationId) {
|
||||||
|
this.setConversationId(conversationId);
|
||||||
|
}
|
||||||
|
if (onComplete) {
|
||||||
|
onComplete({ content, conversation_id: conversationId });
|
||||||
|
}
|
||||||
|
resolve({ content, conversation_id: conversationId });
|
||||||
|
socketTask.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('WebSocket 消息解析失败:', e, '原始数据:', res.data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 连接错误
|
||||||
|
socketTask.onError((err) => {
|
||||||
|
const errorMsg = 'WebSocket 连接失败';
|
||||||
|
console.error(errorMsg, err);
|
||||||
|
reject(new Error(errorMsg));
|
||||||
|
if (onComplete) onComplete({ error: errorMsg });
|
||||||
|
});
|
||||||
|
|
||||||
|
// 连接关闭
|
||||||
|
socketTask.onClose(() => {
|
||||||
|
console.log('WebSocket 连接已关闭');
|
||||||
|
});
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
if (!isAuthenticated || content === '') {
|
||||||
|
console.warn('WebSocket 超时,强制关闭');
|
||||||
|
socketTask.close();
|
||||||
|
reject(new Error('AI服务响应超时'));
|
||||||
|
if (onComplete) onComplete({ error: 'AI服务响应超时' });
|
||||||
|
}
|
||||||
|
}, 10000);
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* HTTP 流式请求(仅 H5 使用)
|
* HTTP 流式请求(仅 H5 使用)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -65,6 +65,10 @@ export default {
|
|||||||
componentRefresh() {
|
componentRefresh() {
|
||||||
return this.$store.state.componentRefresh;
|
return this.$store.state.componentRefresh;
|
||||||
},
|
},
|
||||||
|
// AI客服配置
|
||||||
|
globalAIKefuConfig() {
|
||||||
|
return this.$store.state.globalAIKefuConfig;
|
||||||
|
},
|
||||||
// 客服配置
|
// 客服配置
|
||||||
servicerConfig() {
|
servicerConfig() {
|
||||||
return this.$store.state.servicerConfig;
|
return this.$store.state.servicerConfig;
|
||||||
|
|||||||
Reference in New Issue
Block a user