import Vue from "vue"; import GLOBAL_OBJ from "./global"; import "./EventHub"; import { setMsgData } from "./message"; // 心跳间隔 const HEART_BEAT_TIME = 15000; // 心跳最大失败次数(超过此次数重连) const HEART_BEAT_FAIL_NUM = 1; // 重连间隔 const RECONNECT_TIME = 3000; export default class Socket { constructor(option) { this.socket = null; this._options = option; this.timeoutObj = null; this.robotObj = {}; this.selfCloseStatus = false this.reconnectLock = false console.log("Socket init", GLOBAL_OBJ); // 失败回答 this.failMsg = {} } getToken() { return new Promise((resolve, reject) => { console.log('-----开始请求token-----') uni.request({ method: "GET", dataType: "json", // url: `http://192.168.124.118:8083/xcx/framework/agent/${this._options.agentId}`, // url: `https://des.js-dyyj.com/getDemoToken?id=${this._options.agentId}`, url: `https://des.dayunyuanjian.cn/getDemoToken?id=${this._options.agentId}`, success: (res) => { console.log("请求token成功", res); resolve(res); }, fail: (err) => { wx.showToast({ title: "创建失败", icon: "none", }); console.log("请求token失败", err); reject() }, }); }); } async init() { return this.createSocket(); } async createSocket(options) { return new Promise(async (resolve, reject) => { const origin = "wss://wss.lke.cloud.tencent.com"; // const origin = "wss://des.dayunyuanjian.cn"; let path = "/v1/qbot/chat/conn/"; let initSocket = 1; let mainToken const res = await this.getToken(); if ( res && res.data && res.data.apiResponse && res.data.apiResponse.Token ) { mainToken = res.data.apiResponse.Token; } // 机器人信息 this.robotObj = res.data.requestInfo; console.log("获取token:", mainToken); if (this.selfCloseStatus) {return} // 建立连接 const socket = wx.connectSocket({ url: `${origin}${path}?EIO=4&transport=websocket`, success: (e) => { console.log("创建长链接成功", e); }, complete: (e) => { console.log("socket - complete", e); }, }); this.socket = socket; GLOBAL_OBJ.SOCKET = this; socket.onOpen((e) => { // 监听发送 if (initSocket === 1) { const token = mainToken || ""; if (token) { // cb({ token: token }); this.send({ data: "40" + JSON.stringify({ token: token, }), }); } else { // cb({ token: '' }); this.send({ data: JSON.stringify({ token: "", }), }); } initSocket++; } else { const token = mainToken || ""; // cb({ token: token }); this.send({ data: JSON.stringify({ token: token, }), }); initSocket++; } options && options.complete && options.complete() if (this.selfCloseStatus) { this.destroy() } }); socket.onMessage((e) => { console.log("socket.onMessage", e); const { data } = e; if (data == 2) { // 触发浪涌 this.send({ data: '3', }); } const params = this.getMsgData(data); const { type } = params ?? {}; this.on(type, params); const num = "" + data.substring(0, 2); if (num == "40") { console.log("创建对话成功", e); // 发送失败信息 this.sendFailMsg() resolve(); // 链接成功 } this.createInter(); }); // 失败 socket.onError((e) => { console.log("websocket error 长链接报错", e); // 失败重建 this.doConnectTimeout(); // }); // 关闭 socket.onClose((e) => { console.log("websocket close 长链接关闭", e); this.connectSocketTimeOut && clearTimeout(this.connectSocketTimeOut); //非自动关闭重连 if (e.code != 1000) { this.doConnectTimeout(); } }); }); } doConnectTimeout() { if (this.selfCloseStatus){ // 主动退出 不在重连 return } // 重连一次 console.log("websocket 异常关闭 开始重连"); this.connectSocketTimeOut = setTimeout(() => { this.createSocket({ complete: function (res) { // this.reconnectLock = false; }, }); }, RECONNECT_TIME); } onConnect(e) { console.log("websocket connect", e); } send(e, t) { console.log("开始请求 websocket send", e); this.socket && this.socket.send(e); this.createInter(); } sendFailMsg() { const content = Object.values(this.failMsg) const lastFailMsgIndex = content.findLastIndex(it => !it.status) if (lastFailMsgIndex > -1) { const msg = content[lastFailMsgIndex] console.log('开始重新发送失败信息', msg) // 重新发送失败的信息 this.send(msg.data.socketParams,msg.data.contentType) } } getMsgData(e) { if (e && typeof e == "string") { const status = e.indexOf("42"); const index = e.indexOf("["); if (status > -1 && index > -1) { const txt = e.substring(index); const item = JSON.parse(txt); const [type, obj] = item; const payload = obj.payload ? obj.payload : {}; const params = { chatId: this._options.agentId, type, contentType: "text", //默认文字 timestamp: new Date().getTime(), ...payload, }; // 缓存聊天记录 return params; } } return null; } emit(type, params, contentType) { console.log("emit", type, params); const tmpParams = params tmpParams.incremental = true const data = { //incremental:true, payload: tmpParams }; switch (type) { case "send": // 发送消息 const socketParams = { data: "42" + JSON.stringify(["send", data]) }; this.send(socketParams, contentType); console.log(params.request_id + '发送内容', data) if (!params.is_msg_status) { // 不写入缓存中 return; } const msgParams = { chatId: this._options.agentId, contentType, type, timestamp: new Date().getTime(), ...params, content: params.realContent ? params.realContent : params.content, }; msgParams && setMsgData(msgParams); this.failMsg[params.request_id] = { data: { socketParams, contentType }, statue: false } break; } } // 监听 on(type, params) { switch (type) { case "reply": // 回复结束 const tmpParams = { ...params, name: this.robotObj.name, headImage: this.robotObj.headImage, }; if ( params && params.type === "reply" && !params.is_from_self && params.can_rating ) { // 回复消息 console.log('reply回复内容', tmpParams.content, tmpParams) this._options.onMessage && this._options.onMessage(tmpParams); } if (!params.is_from_self && params.is_final) { if (this.failMsg[tmpParams.request_id]) { this.failMsg[tmpParams.request_id].status = true // 已回复 状态为true } // 回复结束 写入缓存 // setMsgData(tmpParams); } // 回复 break; } } // 关闭socket destroy() { if (this.socket && this.socket.readyState == 1) { this.socket && this.socket.close(); this.socket = null; } this.failMsg={} } createInter() { if (this.timeoutObj) { clearTimeout(this.timeoutObj); } return this.timeoutObj = setTimeout(() => { this.socket && this.socket.send && this.socket.send({ data: 3 }); }, HEART_BEAT_TIME); } }