From 8707b24e2fa7db72c72a91726216ea33831aa076 Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Sat, 29 Jun 2024 01:44:09 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E8=A1=A5=E5=85=85=E5=BF=83=E8=B7=B3?= =?UTF-8?q?=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/bx/imserver/netty/IMChannelHandler.java | 2 +- .../com/bx/imserver/netty/processor/HeartbeatProcessor.java | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/im-server/src/main/java/com/bx/imserver/netty/IMChannelHandler.java b/im-server/src/main/java/com/bx/imserver/netty/IMChannelHandler.java index d985867..dd9e30e 100644 --- a/im-server/src/main/java/com/bx/imserver/netty/IMChannelHandler.java +++ b/im-server/src/main/java/com/bx/imserver/netty/IMChannelHandler.java @@ -74,7 +74,7 @@ public class IMChannelHandler extends SimpleChannelInboundHandler { RedisTemplate redisTemplate = SpringContextHolder.getBean("redisTemplate"); String key = String.join(":", IMRedisKey.IM_USER_SERVER_ID, userId.toString(), terminal.toString()); redisTemplate.delete(key); - log.info("断开连接,userId:{},终端类型:{}", userId, terminal); + log.info("断开连接,userId:{},终端类型:{},{}", userId, terminal, ctx.channel().id().asLongText()); } } diff --git a/im-server/src/main/java/com/bx/imserver/netty/processor/HeartbeatProcessor.java b/im-server/src/main/java/com/bx/imserver/netty/processor/HeartbeatProcessor.java index bf9bf3c..2a0e997 100644 --- a/im-server/src/main/java/com/bx/imserver/netty/processor/HeartbeatProcessor.java +++ b/im-server/src/main/java/com/bx/imserver/netty/processor/HeartbeatProcessor.java @@ -30,7 +30,7 @@ public class HeartbeatProcessor extends AbstractMessageProcessor heartBeatAttr = AttributeKey.valueOf(ChannelAttrKey.HEARTBEAT_TIMES); Long heartbeatTimes = ctx.channel().attr(heartBeatAttr).get(); @@ -44,6 +44,9 @@ public class HeartbeatProcessor extends AbstractMessageProcessor userIdAttr = AttributeKey.valueOf(ChannelAttrKey.USER_ID); + Long userId = ctx.channel().attr(userIdAttr).get(); + log.info("心跳,userId:{},{}",userId,ctx.channel().id().asLongText()); } @Override From 1cb3fed3cde5b6d7710c4ad421c0977981f948d6 Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Sat, 29 Jun 2024 09:40:24 +0800 Subject: [PATCH 2/6] =?UTF-8?q?fix:=20ws=E6=96=AD=E7=BA=BF=E9=87=8D?= =?UTF-8?q?=E8=BF=9E=E5=A4=B1=E8=B4=A5=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- im-uniapp/App.vue | 38 ++++++++++++++++++++++++++---------- im-uniapp/common/wssocket.js | 9 +++++++-- im-uniapp/store/chatStore.js | 2 ++ 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/im-uniapp/App.vue b/im-uniapp/App.vue index 72cb7d5..06664b8 100644 --- a/im-uniapp/App.vue +++ b/im-uniapp/App.vue @@ -49,16 +49,11 @@ } }); wsApi.onClose((res) => { - console.log("ws断开",res); - // 1000是客户端正常主动关闭 - if (res.code != 1000) { + console.log("ws断开", res); + // 3099是客户端正常主动关闭 + if (res.code != 3099) { // 重新连接 - uni.showToast({ - title: '连接已断开,尝试重新连接...', - icon: 'none', - }) - let loginInfo = uni.getStorageSync("loginInfo") - wsApi.reconnect(UNI_APP.WS_URL, loginInfo.accessToken); + this.reconnectWs(); } }) }, @@ -96,7 +91,9 @@ } // 消息回执处理,改消息状态为已读 if (msg.type == enums.MESSAGE_TYPE.RECEIPT) { - store.commit("readedMessage", { friendId: msg.sendId }) + store.commit("readedMessage", { + friendId: msg.sendId + }) return; } // 标记这条消息是不是自己发的 @@ -280,6 +277,27 @@ return true; } return loginInfo.expireTime < new Date().getTime(); + }, + reconnectWs() { + // 重新加载一次个人信息,主要是防止断线太久导致token已经过期 + this.reloadUserInfo().then((userInfo) => { + store.commit("setUserInfo", userInfo); + // 重新连接 + uni.showToast({ + title: '连接已断开,尝试重新连接...', + icon: 'none', + }) + let loginInfo = uni.getStorageSync("loginInfo") + wsApi.reconnect(UNI_APP.WS_URL, loginInfo.accessToken); + }).catch(() => { + this.exit(); + }) + }, + reloadUserInfo() { + return http({ + url: '/user/self', + method: 'GET' + }) } }, onLaunch() { diff --git a/im-uniapp/common/wssocket.js b/im-uniapp/common/wssocket.js index 7c6acff..d7cce1a 100644 --- a/im-uniapp/common/wssocket.js +++ b/im-uniapp/common/wssocket.js @@ -6,6 +6,7 @@ let connectCallBack = null; let isConnect = false; //连接标识 避免重复连接 let rec = null; let isInit = false; +let lastConnectTime = new Date(); // 最后一次连接时间 let init = () => { // 防止重复初始化 @@ -64,6 +65,7 @@ let connect = (url, token) => { if (isConnect) { return; } + lastConnectTime = new Date(); uni.connectSocket({ url: wsurl, success: (res) => { @@ -86,10 +88,13 @@ let reconnect = (wsurl, accessToken) => { //如果已经连上就不在重连了 return; } + // 延迟10秒重连 避免过多次过频繁请求重连 + let timeDiff = new Date().getTime() - lastConnectTime.getTime() + let delay = timeDiff < 10000 ? 10000 - timeDiff : 0; rec && clearTimeout(rec); - rec = setTimeout(function() { // 延迟15秒重连 避免过多次过频繁请求重连 + rec = setTimeout(function() { connect(wsurl, accessToken); - }, 15000); + }, delay); }; //设置关闭连接 diff --git a/im-uniapp/store/chatStore.js b/im-uniapp/store/chatStore.js index a89fae7..f889660 100644 --- a/im-uniapp/store/chatStore.js +++ b/im-uniapp/store/chatStore.js @@ -294,6 +294,8 @@ export default { }); // 将消息一次性装载回来 state.chats = cacheChats; + // 断线重连后不能使用缓存模式,否则会导致聊天窗口的消息不刷新 + cacheChats = state.chats; this.commit("saveToStorage"); }, saveToStorage(state) { From 3c716caa374c7f42037c513fda314d50d50636c1 Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Sat, 29 Jun 2024 09:46:47 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E9=80=80=E7=BE=A4=E5=90=8E=E5=90=8C?= =?UTF-8?q?=E6=97=B6=E5=88=A0=E9=99=A4=E4=BC=9A=E8=AF=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- im-uniapp/App.vue | 62 ++++++++++++++-------------- im-uniapp/pages/group/group-info.vue | 2 + im-uniapp/store/chatStore.js | 9 ++++ 3 files changed, 42 insertions(+), 31 deletions(-) diff --git a/im-uniapp/App.vue b/im-uniapp/App.vue index 06664b8..02f6ee4 100644 --- a/im-uniapp/App.vue +++ b/im-uniapp/App.vue @@ -5,7 +5,7 @@ import * as enums from './common/enums'; import * as wsApi from './common/wssocket'; import UNI_APP from '@/.env.js' - + export default { data() { return { @@ -58,21 +58,21 @@ }) }, pullPrivateOfflineMessage(minId) { - store.commit("loadingPrivateMsg",true) + store.commit("loadingPrivateMsg", true) http({ url: "/message/private/pullOfflineMessage?minId=" + minId, method: 'GET' - }).catch(()=>{ - store.commit("loadingPrivateMsg",false) + }).catch(() => { + store.commit("loadingPrivateMsg", false) }) }, pullGroupOfflineMessage(minId) { - store.commit("loadingGroupMsg",true) + store.commit("loadingGroupMsg", true) http({ url: "/message/group/pullOfflineMessage?minId=" + minId, method: 'GET' - }).catch(()=>{ - store.commit("loadingGroupMsg",false) + }).catch(() => { + store.commit("loadingGroupMsg", false) }) }, handlePrivateMessage(msg) { @@ -109,17 +109,17 @@ // 单人视频信令 if (msgType.isRtcPrivate(msg.type)) { // #ifdef MP-WEIXIN - // 小程序不支持音视频 - return; + // 小程序不支持音视频 + return; // #endif // 被呼叫,弹出视频页面 let delayTime = 100; - if(msg.type == enums.MESSAGE_TYPE.RTC_CALL_VOICE - || msg.type == enums.MESSAGE_TYPE.RTC_CALL_VIDEO){ - let mode = msg.type == enums.MESSAGE_TYPE.RTC_CALL_VIDEO? "video":"voice"; + if (msg.type == enums.MESSAGE_TYPE.RTC_CALL_VOICE || + msg.type == enums.MESSAGE_TYPE.RTC_CALL_VIDEO) { + let mode = msg.type == enums.MESSAGE_TYPE.RTC_CALL_VIDEO ? "video" : "voice"; let pages = getCurrentPages(); - let curPage = pages[pages.length-1].route; - if(curPage != "pages/chat/chat-private-video"){ + let curPage = pages[pages.length - 1].route; + if (curPage != "pages/chat/chat-private-video") { const friendInfo = encodeURIComponent(JSON.stringify(friend)); uni.navigateTo({ url: `/pages/chat/chat-private-video?mode=${mode}&friend=${friendInfo}&isHost=false` @@ -128,8 +128,8 @@ } } setTimeout(() => { - uni.$emit('WS_RTC_PRIVATE',msg); - },delayTime) + uni.$emit('WS_RTC_PRIVATE', msg); + }, delayTime) return; } let chatInfo = { @@ -149,7 +149,7 @@ handleGroupMessage(msg) { // 消息加载标志 if (msg.type == enums.MESSAGE_TYPE.LOADING) { - store.commit("loadingGroupMsg",JSON.parse(msg.content)) + store.commit("loadingGroupMsg", JSON.parse(msg.content)) return; } // 消息已读处理 @@ -186,15 +186,15 @@ // 群视频信令 if (msgType.isRtcGroup(msg.type)) { // #ifdef MP-WEIXIN - // 小程序不支持音视频 - return; + // 小程序不支持音视频 + return; // #endif // 被呼叫,弹出视频页面 let delayTime = 100; - if(msg.type == enums.MESSAGE_TYPE.RTC_GROUP_SETUP){ + if (msg.type == enums.MESSAGE_TYPE.RTC_GROUP_SETUP) { let pages = getCurrentPages(); - let curPage = pages[pages.length-1].route; - if(curPage != "pages/chat/chat-group-video"){ + let curPage = pages[pages.length - 1].route; + if (curPage != "pages/chat/chat-group-video") { const userInfos = encodeURIComponent(msg.content); const inviterId = msg.sendId; const groupId = msg.groupId @@ -207,11 +207,11 @@ } // 消息转发到chat-group-video页面进行处理 setTimeout(() => { - uni.$emit('WS_RTC_GROUP',msg); - },delayTime) + uni.$emit('WS_RTC_GROUP', msg); + }, delayTime) return; } - + let chatInfo = { type: 'GROUP', targetId: group.id, @@ -272,8 +272,8 @@ // this.audioTip.src = "/static/audio/tip.wav"; // this.audioTip.play(); }, - isExpired(loginInfo){ - if(!loginInfo || !loginInfo.expireTime){ + isExpired(loginInfo) { + if (!loginInfo || !loginInfo.expireTime) { return true; } return loginInfo.expireTime < new Date().getTime(); @@ -311,12 +311,12 @@ uni.switchTab({ url: "/pages/chat/chat" }) - } else{ + } else { // 跳转到登录页 // #ifdef H5 - uni.navigateTo({ - url: "/pages/login/login" - }) + uni.navigateTo({ + url: "/pages/login/login" + }) // #endif } } diff --git a/im-uniapp/pages/group/group-info.vue b/im-uniapp/pages/group/group-info.vue index 60cff9b..fe4b4e1 100644 --- a/im-uniapp/pages/group/group-info.vue +++ b/im-uniapp/pages/group/group-info.vue @@ -112,6 +112,7 @@ url:"/pages/group/group" }); this.$store.commit("removeGroup", this.groupId); + this.$store.commit("removeGroupChat",this.groupId); },100) } }) @@ -141,6 +142,7 @@ url:"/pages/group/group" }); this.$store.commit("removeGroup", this.groupId); + this.$store.commit("removeGroupChat",this.groupId); },100) } }) diff --git a/im-uniapp/store/chatStore.js b/im-uniapp/store/chatStore.js index f889660..7e2e1a2 100644 --- a/im-uniapp/store/chatStore.js +++ b/im-uniapp/store/chatStore.js @@ -133,6 +133,15 @@ export default { } } }, + removeGroupChat(state, groupId) { + let chats = this.getters.findChats(); + for (let idx in chats) { + if (chats[idx].type == 'GROUP' && + chats[idx].targetId == groupId) { + this.commit("removeChat", idx); + } + } + }, moveTop(state, idx) { let chats = this.getters.findChats(); let chat = chats[idx]; From a2b5b7745e23bff5ea64a1c805efc47386dd5006 Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Sun, 30 Jun 2024 13:30:43 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=B0=8F=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- im-ui/package.json | 2 +- im-uniapp/common/request.js | 1 + .../group-member-selector/group-member-selector.vue | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/im-ui/package.json b/im-ui/package.json index 7c85713..c10926b 100644 --- a/im-ui/package.json +++ b/im-ui/package.json @@ -13,7 +13,7 @@ "element-ui": "^2.15.10", "js-audio-recorder": "^1.0.7", "sass": "^1.47.0", - "sass-loader": "^7.3.1", + "sass-loader": "^10.1.1", "vue": "^2.6.11", "vue-axios": "^3.5.0", "vue-router": "^3.3.3", diff --git a/im-uniapp/common/request.js b/im-uniapp/common/request.js index ea9ed94..878adf1 100644 --- a/im-uniapp/common/request.js +++ b/im-uniapp/common/request.js @@ -62,6 +62,7 @@ const request = (options) => { fail(error) { uni.showToast({ title: "网络似乎有点不给力,请稍后重试", + icon: "none", duration: 1500 }) return reject(error) diff --git a/im-uniapp/components/group-member-selector/group-member-selector.vue b/im-uniapp/components/group-member-selector/group-member-selector.vue index cced730..1d3cb6a 100644 --- a/im-uniapp/components/group-member-selector/group-member-selector.vue +++ b/im-uniapp/components/group-member-selector/group-member-selector.vue @@ -4,7 +4,7 @@ 选择成员 - @@ -120,7 +120,7 @@ display: flex; align-items: center; height: 70rpx; - padding: 10rpx; + padding: 10rpx 30rpx; .top-tip { flex: 1; @@ -135,7 +135,7 @@ display: flex; align-items: center; height: 90rpx; - + padding: 0 30rpx; .user-item { padding: 3rpx; } From ed0a9a177225b46c74c450f4b1542981f69212cc Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Sun, 30 Jun 2024 13:56:40 +0800 Subject: [PATCH 5/6] =?UTF-8?q?ws=E6=96=AD=E7=BA=BF=E9=87=8D=E8=BF=9E?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- im-uniapp/App.vue | 24 +++++++++++++++++++----- im-uniapp/common/request.js | 2 +- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/im-uniapp/App.vue b/im-uniapp/App.vue index 02f6ee4..549bf4e 100644 --- a/im-uniapp/App.vue +++ b/im-uniapp/App.vue @@ -9,7 +9,8 @@ export default { data() { return { - audioTip: null + audioTip: null, + reconnecting: false // 正在重连标志 } }, methods: { @@ -28,6 +29,14 @@ wsApi.init(); wsApi.connect(UNI_APP.WS_URL, loginInfo.accessToken); wsApi.onConnect(() => { + // 重连成功提示 + if(this.reconnecting){ + this.reconnecting = false; + uni.showToast({ + title: "已重新连接", + icon: 'none' + }) + } // 加载离线消息 this.pullPrivateOfflineMessage(store.state.chatStore.privateMsgMaxId); this.pullGroupOfflineMessage(store.state.chatStore.groupMsgMaxId); @@ -279,18 +288,23 @@ return loginInfo.expireTime < new Date().getTime(); }, reconnectWs() { - // 重新加载一次个人信息,主要是防止断线太久导致token已经过期 + // 记录标志 + this.reconnecting = true; + // 重新加载一次个人信息,目的是为了保证网络已经正常且token有效 this.reloadUserInfo().then((userInfo) => { - store.commit("setUserInfo", userInfo); - // 重新连接 uni.showToast({ title: '连接已断开,尝试重新连接...', icon: 'none', }) + store.commit("setUserInfo", userInfo); + // 重新连接 let loginInfo = uni.getStorageSync("loginInfo") wsApi.reconnect(UNI_APP.WS_URL, loginInfo.accessToken); }).catch(() => { - this.exit(); + // 5s后重试 + setTimeout(()=>{ + this.reconnectWs(); + },5000) }) }, reloadUserInfo() { diff --git a/im-uniapp/common/request.js b/im-uniapp/common/request.js index 878adf1..481c6be 100644 --- a/im-uniapp/common/request.js +++ b/im-uniapp/common/request.js @@ -61,7 +61,7 @@ const request = (options) => { }, fail(error) { uni.showToast({ - title: "网络似乎有点不给力,请稍后重试", + title: "网络似乎有点不给力哟", icon: "none", duration: 1500 }) From d79e6c3df4a79951e6159ef8269986aedf20b79e Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Sun, 30 Jun 2024 14:10:38 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=9B=9E=E6=89=A7?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E7=9A=84=E5=9B=BE=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- im-uniapp/static/icon/iconfont.css | 10 +++++----- im-uniapp/static/icon/iconfont.ttf | Bin 7216 -> 7176 bytes 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/im-uniapp/static/icon/iconfont.css b/im-uniapp/static/icon/iconfont.css index c3ed695..4adf106 100644 --- a/im-uniapp/static/icon/iconfont.css +++ b/im-uniapp/static/icon/iconfont.css @@ -1,6 +1,6 @@ @font-face { font-family: "iconfont"; /* Project id 4272106 */ - src: url('iconfont.ttf?t=1711870080646') format('truetype'); + src: url('iconfont.ttf?t=1719727774055') format('truetype'); } .iconfont { @@ -11,6 +11,10 @@ -moz-osx-font-smoothing: grayscale; } +.icon-receipt:before { + content: "\e601"; +} + .icon-pause:before { content: "\e669"; } @@ -35,10 +39,6 @@ content: "\e685"; } -.icon-receipt:before { - content: "\e61a"; -} - .icon-ok:before { content: "\e65a"; } diff --git a/im-uniapp/static/icon/iconfont.ttf b/im-uniapp/static/icon/iconfont.ttf index 060b3e5346d29bdd346959bb39b8a845be259ff3..926d0b1f1c450ea869e73169d5e65ea2a103ae6a 100644 GIT binary patch delta 524 zcmXv}T}YEr7=F&*w{PD*r_=qkR?W{1XC~j)W@;@E4JnEsA|it*tEEBUEN{{%3W^0o zn&&>csV=ez>_P}6q$|6OuDXdXmKU-hD!N(quF-*q_dV}jVX`=VZFZ!%c?Q_} zy|R+oc7A;A=-Jl&Kj4#SoX=05?)YD|WHnu5DIMj9Q@vn~IZHzP>-wl#q}U4yvWAOJ z>il|@XLuF*4IdW_uFi;<9v1fAEV8uJMpPeyMC>5Cfp%;`1SU9IU=uxrFgyrA!3#fH z$Z=8_u+#a!B{k2>zOuR}?5!FBkmldiw8SIWKiDmV(*xkPkXmLIO delta 538 zcmX|+O=uHA9L3*!?QXW#W}7eB4Q)1Y(?e=Zx8?&YB4RH+6e|VsBvsQYXbswfo>Z*T zgNLMZvUXu{v{M=*BzIm>xF#s%0gK!WFY`IKxgvyunOs}e;@Ndf$%N+0(DvTaP6(a&26axL&hXf3j?ZqBNk0A~X z7I<@><%oRD3$6_WN~(Y$wJTLcFuE%U`JImuBC{exn4D0jCg(+haCu+k4o;$uEiypr zWSgewZQ5q1*a{!u5BLWW7B#V=Y1*28!l)P@L&?x=b6R`KZYg}{Gh1V6ILNDySWzwG zrn5!sP-%=5-Lw|7qVZAJFBL6Miw=@_xl|^lJk`liHqB40m@mfzz zbG0uV5@cMbk%ZBHzi8UzQTvUZ&D!+1;~n#y*3oX7+&LWy+2-nAjj6Dah;Y5Vy=XQ& Wp$SV)IliG^tDdi3sx8R7&b`0OOmx!#