From 77fee4ea4693db26a2262c30f1103482abc0ef2d Mon Sep 17 00:00:00 2001 From: linxi <957440651@qq.com> Date: Fri, 11 Sep 2026 16:22:35 +0800 Subject: [PATCH] =?UTF-8?q?Fix=EF=BC=9A5967=20=E3=80=90=E5=95=86=E5=9F=8E?= =?UTF-8?q?=E5=B0=8F=E7=A8=8B=E5=BA=8F=E3=80=91=E5=B7=B2=E5=8F=91=E8=BF=87?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E7=9A=84=E8=81=8A=E5=A4=A9=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=EF=BC=8C=E8=BF=9B=E8=A1=8C=E5=9B=BE=E7=89=87=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E5=90=8E=E9=A1=B5=E9=9D=A2=E5=87=BA=E7=8E=B0?= =?UTF-8?q?=E7=99=BD=E5=B1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg_common/views/room.vue | 127 +++++++++++++++++++++++++++----------- 1 file changed, 90 insertions(+), 37 deletions(-) diff --git a/pkg_common/views/room.vue b/pkg_common/views/room.vue index b89bc0e..9854a38 100644 --- a/pkg_common/views/room.vue +++ b/pkg_common/views/room.vue @@ -108,8 +108,11 @@ export default { uploadToken: null, //上传token socketOpen: false, + socketConnecting: false, // 是否正在建连 socketTask: null, socketMsgQueue: [], + hasConnected: false, // 是否成功建过连接 + reconnectHistory: false, // 重连后用服务端历史整体替换本地列表,防止消息重复 roomId: null, //房间ID content: "", //消息内容 @@ -136,30 +139,22 @@ export default { }, onShow() { this.content = uni.getStorageSync(this.merName+this.uid+this.storeId) - this.connectSocketInit(); - this.list = [] + // 已连接/连接中不重复建连;清空 list 会导致图片操作(触发 onHide/onShow)后页面白屏 + if (!this.socketOpen && !this.socketConnecting) { + this.connectSocketInit(); + } }, onUnload() { - if (this.socketOpen) { - this.socketTask.close(); - } - uni.onSocketClose(res => { - console.log('WebSocket 已关闭!', res); - }); + this.closeSocket(); uni.setStorageSync(this.merName+this.uid+this.storeId, this.content) }, onHide() { - if (this.socketOpen) { - this.socketTask.close(); - } - uni.onSocketClose(res => { - console.log('WebSocket 已关闭!', res); - }); + this.closeSocket(); uni.setStorageSync(this.merName+this.uid+this.storeId, this.content) }, methods: { toGoods(item) { - const itemJson = JSON.parse(item.msg_content) + const itemJson = this.wsJson(item.msg_content) if(!itemJson.goodsId) { // 提示数据错误 // uni.showToast({ @@ -177,7 +172,12 @@ export default { }) }, wsJson(json) { - return JSON.parse(json) + // 兼容脏数据,避免渲染时报错导致白屏 + try { + return JSON.parse(json) || {} + } catch (e) { + return {} + } }, // 拼接图片完整地址:七牛上传后消息里只存 key,需要补上资源域名;http 统一转 https imgUrl(content) { @@ -255,33 +255,68 @@ export default { }); }, - // 进入这个页面的时候创建websocket连接【整个页面随时使用】 + // 进入页面时创建websocket连接【整个页面随时使用】 connectSocketInit() { + if (this.socketOpen || this.socketConnecting) return; + this.socketConnecting = true; + // 创建一个this.socketTask对象【发送、接收、关闭socket都由这个对象操作】 - this.socketTask = uni.connectSocket({ + const task = uni.connectSocket({ url: this.$SOCKET_URL, success: () => { } }) + if (!task) { + this.socketConnecting = false; + return; + } + this.socketTask = task; - uni.onSocketOpen(res => { - console.log('WebSocket连接已打开!', res); + // 任务级回调:全局 uni.onSocket* 每次进页面都会重复注册,导致消息重复处理、连接串台 + const isCurrent = () => this.socketTask === task; + + task.onOpen(() => { + if (!isCurrent()) return; this.socketOpen = true; + this.socketConnecting = false; + // 断线重连后重新加入房间;本地已有历史时用服务端历史整体替换,避免重复 + this.reconnectHistory = this.hasConnected && this.list.length > 0; + this.hasConnected = true; this.createRoom(); + // 补发连接未就绪期间排队的消息(如发图片时连接被隐藏页关闭) + if (this.socketMsgQueue.length) { + const queue = this.socketMsgQueue.splice(0); + queue.forEach(msg => this.sendSocketMessage(msg)); + } }); - uni.onSocketError(err => { - console.log('WebSocket连接打开失败,请检查!', err); - }); - - uni.onSocketMessage(res => { - console.log('收到服务器内容:', res.data); + task.onMessage(res => { + if (!isCurrent()) return; this.handleMessage(res.data); }); - uni.onSocketClose(res => { - console.log('WebSocket 已关闭!', res); + task.onError(err => { + console.log('WebSocket连接打开失败,请检查!', err); + if (!isCurrent()) return; + this.socketOpen = false; + this.socketConnecting = false; }); + + task.onClose(() => { + if (!isCurrent()) return; + this.socketOpen = false; + this.socketConnecting = false; + }); + }, + + closeSocket() { + this.socketOpen = false; + this.socketConnecting = false; + if (this.socketTask) { + try { + this.socketTask.close({}); + } catch (e) {} + } }, userInput(event) { @@ -321,11 +356,14 @@ export default { }, sendSocketMessage(msg) { - if (this.socketOpen) { - uni.sendSocketMessage({ + if (this.socketOpen && this.socketTask) { + this.socketTask.send({ data: msg, - success(res) { - console.log("消息发送成功", res,msg); + fail: () => { + // 发送失败说明连接可能已断开,重新排队并尝试重连后补发 + this.socketMsgQueue.push(msg); + this.closeSocket(); + this.connectSocketInit(); } }); } else { @@ -334,7 +372,12 @@ export default { }, handleMessage(str) { - let data = JSON.parse(str); + let data; + try { + data = JSON.parse(str); + } catch (e) { + return; + } switch (data.type) { case "room_id": this.roomId = data.msg_content; @@ -344,13 +387,23 @@ export default { case "leave": break; case "msg": - this.list.push(data.msg_content); - this.scrollLast(); + if (data.msg_content) { + this.list.push(data.msg_content); + this.scrollLast(); + } break; - case "msg_history": - this.list = data.msg_content.concat(this.list); + case "msg_history": { + const history = data.msg_content || []; + if (this.reconnectHistory) { + // 重连后服务端重发历史:整体替换,避免消息重复 + this.reconnectHistory = false; + this.list = history; + } else { + this.list = history.concat(this.list); + } this.scrollLast(); break; + } default: break; }