From be39c09d2004ef6e85d34e9cb2b8a4a1850a616d Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Mon, 25 Aug 2025 16:53:25 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E6=B6=88=E6=81=AF=E7=BC=93=E5=AD=98?= =?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 | 7 +++++-- im-uniapp/store/chatStore.js | 25 +++++++++++++++++-------- im-web/src/store/chatStore.js | 26 +++++++++++++++++++------- 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/im-uniapp/App.vue b/im-uniapp/App.vue index de5c4bc..6be74ca 100644 --- a/im-uniapp/App.vue +++ b/im-uniapp/App.vue @@ -116,8 +116,11 @@ export default { this.chatStore.refreshChats(); }).catch((e) => { console.log(e) - this.$message.error("拉取离线消息失败"); - this.onExit(); + uni.showToast({ + title: "拉取离线消息失败", + icon: "none" + }) + this.exit(); }) }, pullPrivateOfflineMessage(minId) { diff --git a/im-uniapp/store/chatStore.js b/im-uniapp/store/chatStore.js index 462dca5..3321ff6 100644 --- a/im-uniapp/store/chatStore.js +++ b/im-uniapp/store/chatStore.js @@ -356,15 +356,9 @@ export default defineStore('chatStore', { cacheChats.sort((chat1, chat2) => chat2.lastSendTime - chat1.lastSendTime); // #ifndef APP-PLUS /** - * 由于h5和小程序的stroge只有5m,大约只能存储2w条消息, - * 所以这里每个会话只保留1000条消息,防止溢出 + * 由于h5和小程序的stroge只有5m,大约只能存储2w条消息,所以可能需要清理部分历史消息 */ - cacheChats.forEach(chat => { - if (chat.messages.length > 1000) { - let idx = chat.messages.length - 1000; - chat.messages = chat.messages.slice(idx); - } - }) + this.fliterMessage(cacheChats, 10000, 1000); // #endif // 记录热数据索引位置 cacheChats.forEach(chat => chat.hotMinIdx = chat.messages.length); @@ -375,6 +369,21 @@ export default defineStore('chatStore', { // 消息持久化 this.saveToStorage(true); }, + fliterMessage(chats, maxTotalSize, maxPerChatSize) { + // 每个会话只保留maxPerChatSize条消息 + let remainTotalSize = 0; + chats.forEach(chat => { + if (chat.messages.length > maxPerChatSize) { + let idx = chat.messages.length - maxPerChatSize; + chat.messages = chat.messages.slice(idx); + } + remainTotalSize += chat.messages.length; + }) + // 保证消息总数不超过maxTotalSize条,否则继续清理 + if (remainTotalSize > maxTotalSize) { + this.fliterMessage(chats, maxTotalSize, maxPerChatSize / 2); + } + }, saveToStorage(withColdMessage) { // 加载中不保存,防止卡顿 if (this.loading) { diff --git a/im-web/src/store/chatStore.js b/im-web/src/store/chatStore.js index 238e8cd..a910c68 100644 --- a/im-web/src/store/chatStore.js +++ b/im-web/src/store/chatStore.js @@ -354,14 +354,11 @@ export default defineStore('chatStore', { cacheChats.sort((chat1, chat2) => chat2.lastSendTime - chat1.lastSendTime); /** * 由于部分浏览器不支持websql或indexdb,只能使用localstorage,而localstorage大小只有10m,可能会导致缓存空间溢出 - * 解决办法:如果是使用localstorage的浏览器,每个会话只保留1000条消息,防止溢出 + * 解决办法:针对只能使用localstorage的浏览器,最多保留1w条消息,每个会话最多保留1000条消息 */ - cacheChats.forEach(chat => { - if (localForage.driver().includes("localStorage") && chat.messages.length > 1000) { - let idx = chat.messages.length - 1000; - chat.messages = chat.messages.slice(idx); - } - }) + if (localForage.driver().includes("localStorage")) { + this.fliterMessage(cacheChats, 10000, 1000) + } // 记录热数据索引位置 cacheChats.forEach(chat => chat.hotMinIdx = chat.messages.length); // 将消息一次性装载回来 @@ -371,6 +368,21 @@ export default defineStore('chatStore', { // 持久化消息 this.saveToStorage(true); }, + fliterMessage(chats, maxTotalSize, maxPerChatSize) { + // 每个会话只保留maxPerChatSize条消息 + let remainTotalSize = 0; + chats.forEach(chat => { + if (chat.messages.length > maxPerChatSize) { + let idx = chat.messages.length - maxPerChatSize; + chat.messages = chat.messages.slice(idx); + } + remainTotalSize += chat.messages.length; + }) + // 保证消息总数不超过maxTotalSize条,否则继续清理 + if (remainTotalSize > maxTotalSize) { + this.fliterMessage(chats, maxTotalSize, maxPerChatSize / 2); + } + }, saveToStorage(withColdMessage) { // 加载中不保存,防止卡顿 if (this.loading) { From c39a310e2fcd7701c6ec1c82a6d1d69561d0949c Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Mon, 25 Aug 2025 16:54:25 +0800 Subject: [PATCH 2/8] =?UTF-8?q?fix:=20=E8=8F=9C=E5=8D=95=E4=BD=8D=E7=BD=AE?= =?UTF-8?q?=E6=BA=A2=E5=87=BA=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- im-web/src/components/common/RightMenu.vue | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/im-web/src/components/common/RightMenu.vue b/im-web/src/components/common/RightMenu.vue index 7e90484..9c22341 100644 --- a/im-web/src/components/common/RightMenu.vue +++ b/im-web/src/components/common/RightMenu.vue @@ -26,9 +26,11 @@ export default { }, methods: { open(pos, items) { - this.pos = pos; + this.pos.x = pos.x; + this.pos.y = pos.y; this.items = items; this.show = true; + this.rejustPos(); }, close() { this.show = false; @@ -36,6 +38,16 @@ export default { onSelectMenu(item) { this.$emit("select", item); this.close(); + }, + rejustPos() { + let menuH = this.items.length * 36; + let menuW = 100; + if (this.pos.y > window.innerHeight - menuH) { + this.pos.y = window.innerHeight - menuH; + } + if (this.pos.x > window.innerWidth - menuW) { + this.pos.x = window.innerWidth - menuW; + } } } } @@ -75,4 +87,4 @@ export default { } } } - + \ No newline at end of file From d75d107059ee81fe517dca1e0ffd4a774563b2e3 Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Thu, 28 Aug 2025 00:56:42 +0800 Subject: [PATCH 3/8] =?UTF-8?q?h5=E6=B6=88=E6=81=AF=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E6=95=B0=E9=87=8F=E8=B0=83=E6=95=B4=E4=B8=BA5000?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- im-uniapp/store/chatStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/im-uniapp/store/chatStore.js b/im-uniapp/store/chatStore.js index 3321ff6..ad6bfce 100644 --- a/im-uniapp/store/chatStore.js +++ b/im-uniapp/store/chatStore.js @@ -358,7 +358,7 @@ export default defineStore('chatStore', { /** * 由于h5和小程序的stroge只有5m,大约只能存储2w条消息,所以可能需要清理部分历史消息 */ - this.fliterMessage(cacheChats, 10000, 1000); + this.fliterMessage(cacheChats, 5000, 1000); // #endif // 记录热数据索引位置 cacheChats.forEach(chat => chat.hotMinIdx = chat.messages.length); From d040f3c80716cf22a932b5c2b353a4d8e817f95e Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Tue, 2 Sep 2025 15:22:55 +0800 Subject: [PATCH 4/8] =?UTF-8?q?fix:=20=E6=96=87=E4=BB=B6=E5=90=8C=E6=97=B6?= =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E5=8F=AF=E8=83=BD=E9=87=8D=E5=90=8D=E7=9A=84?= =?UTF-8?q?bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../implatform/thirdparty/MinioService.java | 43 ++++++++----------- .../java/com/bx/implatform/util/FileUtil.java | 10 +++++ 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/im-platform/src/main/java/com/bx/implatform/thirdparty/MinioService.java b/im-platform/src/main/java/com/bx/implatform/thirdparty/MinioService.java index 254a8e2..d8184ea 100644 --- a/im-platform/src/main/java/com/bx/implatform/thirdparty/MinioService.java +++ b/im-platform/src/main/java/com/bx/implatform/thirdparty/MinioService.java @@ -1,6 +1,8 @@ package com.bx.implatform.thirdparty; +import cn.hutool.core.util.RandomUtil; import com.bx.implatform.util.DateTimeUtils; +import com.bx.implatform.util.FileUtil; import io.minio.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -38,9 +40,7 @@ public class MinioService { */ public void makeBucket(String bucketName) { try { - minioClient.makeBucket(MakeBucketArgs.builder() - .bucket(bucketName) - .build()); + minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build()); } catch (Exception e) { log.error("创建bucket失败,", e); } @@ -52,18 +52,9 @@ public class MinioService { public void setBucketPublic(String bucketName) { try { // 设置公开 - String sb = "{\"Version\":\"2012-10-17\"," + - "\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":" + - "{\"AWS\":[\"*\"]},\"Action\":[\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"," + - "\"s3:GetBucketLocation\"],\"Resource\":[\"arn:aws:s3:::" + bucketName + - "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:PutObject\",\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:GetObject\",\"s3:ListMultipartUploadParts\"],\"Resource\":[\"arn:aws:s3:::" + - bucketName + - "/*\"]}]}"; - minioClient.setBucketPolicy( - SetBucketPolicyArgs.builder() - .bucket(bucketName) - .config(sb) - .build()); + String sb = + "{\"Version\":\"2012-10-17\"," + "\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":" + "{\"AWS\":[\"*\"]},\"Action\":[\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"," + "\"s3:GetBucketLocation\"],\"Resource\":[\"arn:aws:s3:::" + bucketName + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:PutObject\",\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:GetObject\",\"s3:ListMultipartUploadParts\"],\"Resource\":[\"arn:aws:s3:::" + bucketName + "/*\"]}]}"; + minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(sb).build()); } catch (Exception e) { log.error("创建bucket失败,", e); } @@ -82,10 +73,10 @@ public class MinioService { if (StringUtils.isBlank(originalFilename)) { throw new RuntimeException(); } - String fileName = System.currentTimeMillis() + ""; - if (originalFilename.lastIndexOf(".") >= 0) { - fileName += originalFilename.substring(originalFilename.lastIndexOf(".")); - } + // 加入随机数,防止文件重名 + String fileName = FileUtil.excludeExtension(originalFilename); + fileName += "_" + RandomUtil.randomString(4); + fileName += "." + FileUtil.getFileExtension(originalFilename); String objectName = DateTimeUtils.getFormatDate(new Date(), DateTimeUtils.PARTDATEFORMAT) + "/" + fileName; try { InputStream stream = new ByteArrayInputStream(file.getBytes()); @@ -111,13 +102,15 @@ public class MinioService { * @return objectName */ public String upload(String bucketName, String path, String name, byte[] fileByte, String contentType) { - - String fileName = System.currentTimeMillis() + name.substring(name.lastIndexOf(".")); + // 加入随机数,防止文件重名 + String fileName = FileUtil.excludeExtension(name); + fileName += "_" + RandomUtil.randomString(4); + fileName += "." + FileUtil.getFileExtension(name); String objectName = DateTimeUtils.getFormatDate(new Date(), DateTimeUtils.PARTDATEFORMAT) + "/" + fileName; try { InputStream stream = new ByteArrayInputStream(fileByte); PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(path + "/" + objectName) - .stream(stream, fileByte.length, -1).contentType(contentType).build(); + .stream(stream, fileByte.length, -1).contentType(contentType).build(); //文件名称相同会覆盖 minioClient.putObject(objectArgs); } catch (Exception e) { @@ -127,7 +120,6 @@ public class MinioService { return objectName; } - /** * 删除 * @@ -138,7 +130,8 @@ public class MinioService { */ public boolean remove(String bucketName, String path, String fileName) { try { - minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(path + "/" + fileName).build()); + minioClient.removeObject( + RemoveObjectArgs.builder().bucket(bucketName).object(path + "/" + fileName).build()); } catch (Exception e) { log.error("删除文件失败,", e); return false; @@ -156,7 +149,7 @@ public class MinioService { */ public Boolean isExist(String bucketName, String path, String fileName) { try { - minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(path + "/" + fileName).build()); + minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(path + "/" + fileName).build()); } catch (Exception e) { return false; } diff --git a/im-platform/src/main/java/com/bx/implatform/util/FileUtil.java b/im-platform/src/main/java/com/bx/implatform/util/FileUtil.java index 78d2ab6..89aeddd 100644 --- a/im-platform/src/main/java/com/bx/implatform/util/FileUtil.java +++ b/im-platform/src/main/java/com/bx/implatform/util/FileUtil.java @@ -13,6 +13,16 @@ public final class FileUtil { return fileName.substring(fileName.lastIndexOf(".") + 1); } + /** + * 去除文件扩展名 + * + * @param fileName 文件名 + * @return + */ + public static String excludeExtension(String fileName) { + return fileName.substring(0,fileName.lastIndexOf(".")); + } + /** * 判断文件是否图片类型 * From 67622fa56547324c3a3831568f30ed5f76ddda02 Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Tue, 2 Sep 2025 15:30:05 +0800 Subject: [PATCH 5/8] =?UTF-8?q?fix:=20=E9=87=8D=E8=BF=9E=E5=90=8E=E4=BC=9A?= =?UTF-8?q?=E8=AF=9D=E9=A1=BA=E5=BA=8F=E5=BC=82=E5=B8=B8=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- im-uniapp/store/chatStore.js | 12 ++++++------ im-web/src/store/chatStore.js | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/im-uniapp/store/chatStore.js b/im-uniapp/store/chatStore.js index ad6bfce..16d3419 100644 --- a/im-uniapp/store/chatStore.js +++ b/im-uniapp/store/chatStore.js @@ -335,11 +335,11 @@ export default defineStore('chatStore', { } }, refreshChats() { - if (!cacheChats) return; + let chats = cacheChats || this.chats; // 更新会话免打扰状态 const friendStore = useFriendStore(); const groupStore = useGroupStore(); - cacheChats.forEach(chat => { + chats.forEach(chat => { if (chat.type == 'PRIVATE') { let friend = friendStore.findFriend(chat.targetId); if (friend) { @@ -353,17 +353,17 @@ export default defineStore('chatStore', { } }) // 排序 - cacheChats.sort((chat1, chat2) => chat2.lastSendTime - chat1.lastSendTime); + chats.sort((chat1, chat2) => chat2.lastSendTime - chat1.lastSendTime); // #ifndef APP-PLUS /** * 由于h5和小程序的stroge只有5m,大约只能存储2w条消息,所以可能需要清理部分历史消息 */ - this.fliterMessage(cacheChats, 5000, 1000); + this.fliterMessage(chats, 5000, 1000); // #endif // 记录热数据索引位置 - cacheChats.forEach(chat => chat.hotMinIdx = chat.messages.length); + chats.forEach(chat => chat.hotMinIdx = chat.messages.length); // 将消息一次性装载回来 - this.chats = cacheChats; + this.chats = chats; // 清空缓存,不再使用 cacheChats = null; // 消息持久化 diff --git a/im-web/src/store/chatStore.js b/im-web/src/store/chatStore.js index a910c68..046d842 100644 --- a/im-web/src/store/chatStore.js +++ b/im-web/src/store/chatStore.js @@ -333,11 +333,11 @@ export default defineStore('chatStore', { } }, refreshChats() { - if (!cacheChats) return; + let chats = cacheChats || this.chats; // 刷新免打扰状态 const friendStore = useFriendStore(); const groupStore = useGroupStore(); - cacheChats.forEach(chat => { + chats.forEach(chat => { if (chat.type == 'PRIVATE') { let friend = friendStore.findFriend(chat.targetId); if (friend) { @@ -351,18 +351,18 @@ export default defineStore('chatStore', { } }) // 排序 - cacheChats.sort((chat1, chat2) => chat2.lastSendTime - chat1.lastSendTime); + chats.sort((chat1, chat2) => chat2.lastSendTime - chat1.lastSendTime); /** * 由于部分浏览器不支持websql或indexdb,只能使用localstorage,而localstorage大小只有10m,可能会导致缓存空间溢出 * 解决办法:针对只能使用localstorage的浏览器,最多保留1w条消息,每个会话最多保留1000条消息 */ if (localForage.driver().includes("localStorage")) { - this.fliterMessage(cacheChats, 10000, 1000) + this.fliterMessage(chats, 10000, 1000) } // 记录热数据索引位置 - cacheChats.forEach(chat => chat.hotMinIdx = chat.messages.length); + chats.forEach(chat => chat.hotMinIdx = chat.messages.length); // 将消息一次性装载回来 - this.chats = cacheChats; + this.chats = chats; // 清空缓存 cacheChats = null; // 持久化消息 From 0573f0d4fddd4aceec2a17d195b8b4532fe9cac8 Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Thu, 4 Sep 2025 15:17:11 +0800 Subject: [PATCH 6/8] =?UTF-8?q?fix:=20=E7=99=BB=E5=BD=95=E9=A1=B5=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=8A=A8=E6=80=81=E8=83=8C=E6=99=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- im-web/src/view/Login.vue | 75 +++++++++++++++++--- im-web/src/view/Register.vue | 133 +++++++++++++++++++++++++---------- 2 files changed, 163 insertions(+), 45 deletions(-) diff --git a/im-web/src/view/Login.vue b/im-web/src/view/Login.vue index f3953a8..1bc8d3a 100644 --- a/im-web/src/view/Login.vue +++ b/im-web/src/view/Login.vue @@ -1,5 +1,8 @@