From f2ffda5e7a3260f2c3b026e43272c4e626db2455 Mon Sep 17 00:00:00 2001
From: xsx <825657193@qq.com>
Date: Thu, 16 Oct 2025 00:12:29 +0800
Subject: [PATCH 1/6] =?UTF-8?q?=E7=BB=86=E8=8A=82=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../chat-message-item/chat-message-item.vue | 5 ++++-
im-uniapp/pages/chat/chat-box.vue | 12 +++++++++++-
im-web/src/components/chat/ChatBox.vue | 6 ++++++
3 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/im-uniapp/components/chat-message-item/chat-message-item.vue b/im-uniapp/components/chat-message-item/chat-message-item.vue
index 5b1a43d..f35dd7b 100644
--- a/im-uniapp/components/chat-message-item/chat-message-item.vue
+++ b/im-uniapp/components/chat-message-item/chat-message-item.vue
@@ -65,7 +65,7 @@
{{ msgInfo.content }}
-
+
{
// 更新消息
+ tmpMessage = JSON.parse(JSON.stringify(tmpMessage));
tmpMessage.id = m.id;
tmpMessage.status = m.status;
this.chatStore.updateMessage(tmpMessage, chat);
@@ -194,7 +195,10 @@ export default {
// 滚动到底部
this.scrollToBottom();
this.isReceipt = false;
-
+ }).catch(() => {
+ tmpMessage = JSON.parse(JSON.stringify(tmpMessage));
+ tmpMessage.status = this.$enums.MESSAGE_STATUS.FAILED;
+ this.chatStore.updateMessage(tmpMessage, chat);
})
},
onRtCall(msgInfo) {
@@ -474,6 +478,9 @@ export default {
msgInfo.status = m.status;
this.isReceipt = false;
this.chatStore.updateMessage(msgInfo, file.chat);
+ }).catch(() => {
+ msgInfo.status = this.$enums.MESSAGE_STATUS.FAILED;
+ this.chatStore.updateMessage(msgInfo, file.chat);
})
},
onUploadImageFail(file, err) {
@@ -527,6 +534,9 @@ export default {
msgInfo.status = m.status;
this.isReceipt = false;
this.chatStore.updateMessage(msgInfo, file.chat);
+ }).catch(() => {
+ msgInfo.status = this.$enums.MESSAGE_STATUS.FAILED;
+ this.chatStore.updateMessage(msgInfo, file.chat);
})
},
onUploadFileFail(file, res) {
diff --git a/im-web/src/components/chat/ChatBox.vue b/im-web/src/components/chat/ChatBox.vue
index 69152a1..3318a81 100644
--- a/im-web/src/components/chat/ChatBox.vue
+++ b/im-web/src/components/chat/ChatBox.vue
@@ -164,6 +164,9 @@ export default {
msgInfo.status = m.status;
this.isReceipt = false;
this.chatStore.updateMessage(msgInfo, file.chat);
+ }).catch(() => {
+ msgInfo.status = this.$enums.MESSAGE_STATUS.FAILED;
+ this.chatStore.updateMessage(msgInfo, file.chat);
})
},
onImageFail(e, file) {
@@ -227,6 +230,9 @@ export default {
this.isReceipt = false;
this.refreshPlaceHolder();
this.chatStore.updateMessage(msgInfo, file.chat);
+ }).catch(() => {
+ msgInfo.status = this.$enums.MESSAGE_STATUS.FAILED;
+ this.chatStore.updateMessage(msgInfo, file.chat);
})
},
onFileFail(e, file) {
From 13d496741d2e807c2cc4e00d5b8cfe3e7c622e13 Mon Sep 17 00:00:00 2001
From: xsx <825657193@qq.com>
Date: Thu, 16 Oct 2025 00:15:21 +0800
Subject: [PATCH 2/6] =?UTF-8?q?=E7=BB=86=E8=8A=82=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../chat-message-item/chat-message-item.vue | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/im-uniapp/components/chat-message-item/chat-message-item.vue b/im-uniapp/components/chat-message-item/chat-message-item.vue
index f35dd7b..dbcecc3 100644
--- a/im-uniapp/components/chat-message-item/chat-message-item.vue
+++ b/im-uniapp/components/chat-message-item/chat-message-item.vue
@@ -11,7 +11,7 @@
:name="showName" size="small">
- {{ showName }}
+ {{ showName }}
@@ -294,10 +294,17 @@ export default {
.top {
display: flex;
flex-wrap: nowrap;
- color: $im-text-color-lighter;
- font-size: $im-font-size-smaller;
- line-height: $im-font-size-smaller;
- height: $im-font-size-smaller;
+ align-items: center;
+
+ .name {
+ color: $im-text-color-lighter;
+ font-size: $im-font-size-smaller;
+ line-height: $im-font-size-smaller;
+ height: $im-font-size-smaller;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
}
.bottom {
From 8f355d5a7388f0606098f8deb1df398c2e228606 Mon Sep 17 00:00:00 2001
From: xsx <825657193@qq.com>
Date: Mon, 20 Oct 2025 16:05:59 +0800
Subject: [PATCH 3/6] =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=90=8D=E9=95=BF?=
=?UTF-8?q?=E5=BA=A6=E9=99=90=E5=88=B6128=E5=AD=97=E7=AC=A6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../main/java/com/bx/implatform/contant/Constant.java | 5 +++++
.../bx/implatform/service/impl/FileServiceImpl.java | 10 ++++++++++
2 files changed, 15 insertions(+)
diff --git a/im-platform/src/main/java/com/bx/implatform/contant/Constant.java b/im-platform/src/main/java/com/bx/implatform/contant/Constant.java
index 3884cd7..d255ba3 100644
--- a/im-platform/src/main/java/com/bx/implatform/contant/Constant.java
+++ b/im-platform/src/main/java/com/bx/implatform/contant/Constant.java
@@ -15,6 +15,11 @@ public final class Constant {
*/
public static final Long MAX_FILE_SIZE = 20 * 1024 * 1024L;
+ /**
+ * 最大文件名长度
+ */
+ public static final Long MAX_FILE_NAME_LENGTH = 128L;
+
/**
* 大群人数上限
*/
diff --git a/im-platform/src/main/java/com/bx/implatform/service/impl/FileServiceImpl.java b/im-platform/src/main/java/com/bx/implatform/service/impl/FileServiceImpl.java
index 761f2dc..9eb4ce5 100644
--- a/im-platform/src/main/java/com/bx/implatform/service/impl/FileServiceImpl.java
+++ b/im-platform/src/main/java/com/bx/implatform/service/impl/FileServiceImpl.java
@@ -60,6 +60,8 @@ public class FileServiceImpl extends ServiceImpl imple
public String uploadFile(MultipartFile file) {
try {
Long userId = SessionContext.getSession().getUserId();
+ // 文件名长度校验
+ checkFileNameLength(file);
// 大小校验
if (file.getSize() > Constant.MAX_FILE_SIZE) {
throw new GlobalException(ResultCode.PROGRAM_ERROR, "文件大小不能超过20M");
@@ -95,6 +97,8 @@ public class FileServiceImpl extends ServiceImpl imple
public UploadImageVO uploadImage(MultipartFile file, Boolean isPermanent,Long thumbSize) {
try {
Long userId = SessionContext.getSession().getUserId();
+ // 文件名长度校验
+ checkFileNameLength(file);
// 大小校验
if (file.getSize() > Constant.MAX_IMAGE_SIZE) {
throw new GlobalException(ResultCode.PROGRAM_ERROR, "图片大小不能超过20M");
@@ -170,6 +174,7 @@ public class FileServiceImpl extends ServiceImpl imple
LambdaQueryWrapper wrapper = Wrappers.lambdaQuery();
wrapper.eq(FileInfo::getMd5, md5);
wrapper.eq(FileInfo::getFileType, fileType);
+ wrapper.last("limit 1");
return getOne(wrapper);
}
@@ -199,4 +204,9 @@ public class FileServiceImpl extends ServiceImpl imple
this.save(fileInfo);
}
+ private void checkFileNameLength(MultipartFile file){
+ if(file.getOriginalFilename().length() > Constant.MAX_FILE_NAME_LENGTH){
+ throw new GlobalException("文件名长度不能超过" + Constant.MAX_FILE_NAME_LENGTH);
+ }
+ }
}
From 0457e706ee43a0fdca59bf5cd7d555b5113f87b3 Mon Sep 17 00:00:00 2001
From: xsx <825657193@qq.com>
Date: Mon, 20 Oct 2025 16:12:11 +0800
Subject: [PATCH 4/6] =?UTF-8?q?fix:=20=E5=90=8C=E6=97=B6=E4=B8=8A=E4=BC=A0?=
=?UTF-8?q?=E6=96=87=E4=BB=B6=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/pages/chat/chat-box.vue | 13 +++++++++++--
im-web/src/components/chat/ChatBox.vue | 27 +++++++++++++++++---------
2 files changed, 29 insertions(+), 11 deletions(-)
diff --git a/im-uniapp/pages/chat/chat-box.vue b/im-uniapp/pages/chat/chat-box.vue
index 7c0a7c6..296a497 100644
--- a/im-uniapp/pages/chat/chat-box.vue
+++ b/im-uniapp/pages/chat/chat-box.vue
@@ -152,7 +152,8 @@ export default {
isInBottom: true, // 滚动条是否在底部
newMessageSize: 0, // 滚动条不在底部时新的消息数量
scrollTop: 0, // 用于ios h5定位滚动条
- scrollViewHeight: 0 // 滚动条总长度
+ scrollViewHeight: 0, // 滚动条总长度
+ maxTmpId: 0 // 最后生成的临时id
}
},
methods: {
@@ -983,7 +984,13 @@ export default {
},
generateId() {
// 生成临时id
- return String(new Date().getTime()) + String(Math.floor(Math.random() * 1000));
+ const id = String(new Date().getTime()) + String(Math.floor(Math.random() * 1000));
+ // 必须保证id是递增
+ if (this.maxTmpId > id) {
+ return this.generateId();
+ }
+ this.maxTmpId = id;
+ return id;
}
},
computed: {
@@ -1108,6 +1115,8 @@ export default {
// 清空底部标志
this.isInBottom = true;
this.newMessageSize = 0;
+ // 清空消息临时id
+ this.maxTmpId = 0;
// 监听键盘高度
this.listenKeyBoard();
// 计算聊天窗口高度
diff --git a/im-web/src/components/chat/ChatBox.vue b/im-web/src/components/chat/ChatBox.vue
index 3318a81..c6e2322 100644
--- a/im-web/src/components/chat/ChatBox.vue
+++ b/im-web/src/components/chat/ChatBox.vue
@@ -132,7 +132,8 @@ export default {
reqQueue: [], // 等待发送的请求队列
isSending: false, // 是否正在发消息
isInBottom: false, // 滚动条是否在底部
- newMessageSize: 0 // 滚动条不在底部时新的消息数量
+ newMessageSize: 0, // 滚动条不在底部时新的消息数量
+ maxTmpId: 0 // 最后生成的临时ID
}
},
methods: {
@@ -573,7 +574,7 @@ export default {
this.$http({
url: url,
method: 'put'
- }).then(() => { })
+ }).then(() => {})
this.chatStore.resetUnreadCount(this.chat)
}
},
@@ -724,25 +725,31 @@ export default {
getImageSize(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
- reader.onload = function (event) {
+ reader.onload = function(event) {
const img = new Image();
- img.onload = function () {
+ img.onload = function() {
resolve({ width: img.width, height: img.height });
};
- img.onerror = function () {
+ img.onerror = function() {
reject(new Error('无法加载图片'));
};
img.src = event.target.result;
};
- reader.onerror = function () {
+ reader.onerror = function() {
reject(new Error('无法读取文件'));
};
reader.readAsDataURL(file);
});
},
generateId() {
- // 生成临时id
- return String(new Date().getTime()) + String(Math.floor(Math.random() * 1000));
+ // 生成临时id
+ const id = String(new Date().getTime()) + String(Math.floor(Math.random() * 1000));
+ // 必须保证id是递增
+ if (this.maxTmpId > id) {
+ return this.generateId();
+ }
+ this.maxTmpId = id;
+ return id;
}
},
computed: {
@@ -799,7 +806,7 @@ export default {
chat: {
handler(newChat, oldChat) {
if (newChat.targetId > 0 && (!oldChat || newChat.type != oldChat.type ||
- newChat.targetId != oldChat.targetId)) {
+ newChat.targetId != oldChat.targetId)) {
this.userInfo = {}
this.group = {};
this.groupMembers = [];
@@ -822,6 +829,8 @@ export default {
this.resetEditor();
// 复位回执消息
this.isReceipt = false;
+ // 清空消息临时id
+ this.maxTmpId = 0;
// 更新placeholder
this.refreshPlaceHolder();
}
From c328524c9f08300328b0c6ea2efc8019f858f2b1 Mon Sep 17 00:00:00 2001
From: xsx <825657193@qq.com>
Date: Sun, 2 Nov 2025 17:08:32 +0800
Subject: [PATCH 5/6] =?UTF-8?q?fix:=20=E6=B6=88=E6=81=AF=E9=80=81=E8=BE=BE?=
=?UTF-8?q?=E7=8A=B6=E6=80=81=E5=BC=82=E5=B8=B8=E7=9A=84bug?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../implatform/listener/PrivateMessageListener.java | 12 ++++++++----
.../service/impl/PrivateMessageServiceImpl.java | 6 +++---
2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java b/im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java
index d75ab86..ba61cd2 100644
--- a/im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java
+++ b/im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java
@@ -26,19 +26,23 @@ public class PrivateMessageListener implements MessageListener
@Lazy
@Autowired
private PrivateMessageService privateMessageService;
+
@Override
public void process(List> results) {
Set messageIds = new HashSet<>();
- for(IMSendResult result : results){
+ for (IMSendResult result : results) {
PrivateMessageVO messageInfo = result.getData();
// 更新消息状态,这里只处理成功消息,失败的消息继续保持未读状态
if (result.getCode().equals(IMSendCode.SUCCESS.code()) && !Objects.isNull(messageInfo.getId())) {
- messageIds.add(messageInfo.getId());
- log.info("消息送达,消息id:{},发送者:{},接收者:{},终端:{}", messageInfo.getId(), result.getSender().getId(), result.getReceiver().getId(), result.getReceiver().getTerminal());
+ if (result.getReceiver().getId().equals(messageInfo.getRecvId())) {
+ messageIds.add(messageInfo.getId());
+ log.info("消息送达,消息id:{},发送者:{},接收者:{},终端:{}", messageInfo.getId(),
+ result.getSender().getId(), result.getReceiver().getId(), result.getReceiver().getTerminal());
+ }
}
}
// 批量修改状态
- if(CollUtil.isNotEmpty(messageIds)){
+ if (CollUtil.isNotEmpty(messageIds)) {
UpdateWrapper updateWrapper = new UpdateWrapper<>();
updateWrapper.lambda().in(PrivateMessage::getId, messageIds)
.eq(PrivateMessage::getStatus, MessageStatus.PENDING.code())
diff --git a/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java b/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java
index 24c4972..3401f8a 100644
--- a/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java
+++ b/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java
@@ -189,9 +189,9 @@ public class PrivateMessageServiceImpl extends ServiceImpl messages = this.list(wrapper);
// 更新消息为送达状态
- List messageIds =
- messages.stream().filter(m -> m.getStatus().equals(MessageStatus.PENDING.code())).map(PrivateMessage::getId)
- .collect(Collectors.toList());
+ List messageIds = messages.stream().filter(m -> m.getRecvId().equals(session.getUserId()))
+ .filter(m -> m.getStatus().equals(MessageStatus.PENDING.code())).map(PrivateMessage::getId)
+ .collect(Collectors.toList());
if (!messageIds.isEmpty()) {
LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate();
updateWrapper.in(PrivateMessage::getId, messageIds);
From aa18f59f4c7f6a92305a839b2584cbb1128fe278 Mon Sep 17 00:00:00 2001
From: xsx <825657193@qq.com>
Date: Sun, 2 Nov 2025 17:11:35 +0800
Subject: [PATCH 6/6] =?UTF-8?q?fix:=20ios=E9=83=A8=E5=88=86=E8=AE=BE?=
=?UTF-8?q?=E5=A4=87=E5=87=BA=E7=8E=B0=E7=99=BD=E5=B1=8F=E7=9A=84bug?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
im-uniapp/pages/chat/chat-box.vue | 32 ++++++++++++++++++-------------
1 file changed, 19 insertions(+), 13 deletions(-)
diff --git a/im-uniapp/pages/chat/chat-box.vue b/im-uniapp/pages/chat/chat-box.vue
index 296a497..ff3b7e7 100644
--- a/im-uniapp/pages/chat/chat-box.vue
+++ b/im-uniapp/pages/chat/chat-box.vue
@@ -642,13 +642,21 @@ export default {
});
},
onClickToBottom() {
- this.scrollToBottom();
- // 有些设备滚到底部时会莫名触发滚动到顶部的事件
- // 所以这里延迟100s保证能准确设置底部标志
+ /**
+ * 有些ios设备在点击回到底部后页面会卡住,原因不详
+ * 解决方式: 延迟300ms再滚动
+ */
setTimeout(() => {
- this.isInBottom = true;
- this.newMessageSize = 0;
- }, 100)
+ this.scrollToBottom();
+ /**
+ * 有些设备滚到底部时会莫名触发滚动到顶部的事件
+ * 解决方式: 延迟100ms保证能准确设置底部标志
+ */
+ setTimeout(() => {
+ this.isInBottom = true;
+ this.newMessageSize = 0;
+ }, 100)
+ }, 300)
},
onScroll(e) {
// 记录当前滚动条高度
@@ -656,16 +664,14 @@ export default {
},
onScrollToTop() {
if (this.showMinIdx > 0) {
- // #ifndef H5
- // 防止滚动条定格在顶部,不能一直往上滚,app和小程序采用scroll-into-view定位
- this.scrollToMsgIdx(this.showMinIdx);
- // #endif
- // #ifdef H5
- // 防止滚动条定格在顶部,不能一直往上滚,h5采用scroll-top定位
+ // 防止滚动条定格在顶部,不能一直往上滚
if (uni.getSystemInfoSync().platform == 'ios') {
+ // ios采用scroll-top定位,否则可能会出现白屏
this.holdingScrollBar(this.scrollViewHeight);
+ } else {
+ // 安卓采用scroll-into-view定位
+ this.scrollToMsgIdx(this.showMinIdx);
}
- // #endif
// 多展示20条信息
this.showMinIdx = this.showMinIdx > 20 ? this.showMinIdx - 20 : 0;
}