xsx 7 mesiacov pred
rodič
commit
208a560f18

+ 1 - 4
im-uniapp/components/chat-message-item/chat-message-item.vue

@@ -118,10 +118,7 @@ export default {
 	},
 	methods: {
 		onSendFail() {
-			uni.showToast({
-				title: "该消息已发送失败,目前不支持自动重新发送,建议手动重新发送",
-				icon: "none"
-			})
+			this.$emit("resend", this.msgInfo);
 		},
 		onPlayAudio() {
 			// 初始化音频播放器

+ 37 - 13
im-uniapp/pages/chat/chat-box.vue

@@ -9,10 +9,10 @@
 						<view v-for="(msgInfo, idx) in chat.messages" :key="idx">
 							<chat-message-item :ref="'message'+msgInfo.id" v-if="idx >= showMinIdx"
 								:headImage="headImage(msgInfo)" @call="onRtCall(msgInfo)" :showName="showName(msgInfo)"
-								@recall="onRecallMessage" @delete="onDeleteMessage" @copy="onCopyMessage"
-								@longPressHead="onLongPressHead(msgInfo)" @download="onDownloadFile"
-								@audioStateChange="onAudioStateChange" :id="'chat-item-' + idx" :msgInfo="msgInfo"
-								:groupMembers="groupMembers">
+								@resend="onResendMessage" @recall="onRecallMessage" @delete="onDeleteMessage"
+								@copy="onCopyMessage" @longPressHead="onLongPressHead(msgInfo)"
+								@download="onDownloadFile" @audioStateChange="onAudioStateChange"
+								:id="'chat-item-' + idx" :msgInfo="msgInfo" :groupMembers="groupMembers">
 							</chat-message-item>
 						</view>
 					</view>
@@ -338,10 +338,7 @@ export default {
 						tmpMessage = JSON.parse(JSON.stringify(tmpMessage));
 						tmpMessage.status = this.$enums.MESSAGE_STATUS.FAILED;
 						this.chatStore.insertMessage(tmpMessage, chat);
-					}).finally(() => {
-						// 滚动到底部
-						this.scrollToBottom();
-					});
+					})
 				}
 			})
 
@@ -451,8 +448,6 @@ export default {
 			// 借助file对象保存
 			file.msgInfo = msgInfo;
 			file.chat = this.chat;
-			// 滚到最低部
-			this.scrollToBottom();
 			// 更新图片宽高
 			let chat = this.chat;
 			this.getImageSize(file).then(size => {
@@ -511,8 +506,6 @@ export default {
 			// 借助file对象保存
 			file.msgInfo = msgInfo;
 			file.chat = this.chat;
-			// 滚到最低部
-			this.scrollToBottom();
 			return true;
 		},
 		onUploadFileSuccess(file, res) {
@@ -536,6 +529,37 @@ export default {
 			msgInfo.status = this.$enums.MESSAGE_STATUS.FAILED;
 			this.chatStore.insertMessage(msgInfo, file.chat);
 		},
+		onResendMessage(msgInfo) {
+			if (msgInfo.type != this.$enums.MESSAGE_TYPE.TEXT) {
+				uni.showToast({
+					title: "该消息不支持自动重新发送,建议手动重新发送",
+					icon: "none"
+				})
+				return;
+			}
+			// 防止发送期间用户切换会话导致串扰
+			const chat = this.chat;
+			// 删除旧消息
+			this.chatStore.deleteMessage(msgInfo, chat);
+			// 重新发送
+			msgInfo.temId = this.generateId();
+			let tmpMessage = this.buildTmpMessage(msgInfo);
+			this.chatStore.insertMessage(tmpMessage, chat);
+			this.moveChatToTop();
+			this.sendMessageRequest(msgInfo).then(m => {
+				// 更新消息
+				tmpMessage = JSON.parse(JSON.stringify(tmpMessage));
+				tmpMessage.id = m.id;
+				tmpMessage.status = m.status;
+				tmpMessage.content = m.content;
+				this.chatStore.insertMessage(tmpMessage, chat);
+			}).catch(() => {
+				// 更新消息
+				tmpMessage = JSON.parse(JSON.stringify(tmpMessage));
+				tmpMessage.status = this.$enums.MESSAGE_STATUS.FAILED;
+				this.chatStore.insertMessage(tmpMessage, chat);
+			})
+		},
 		onDeleteMessage(msgInfo) {
 			uni.showModal({
 				title: '删除消息',
@@ -996,7 +1020,7 @@ export default {
 			if (newSize > oldSize && oldSize > 0) {
 				let lastMessage = this.chat.messages[newSize - 1];
 				if (this.$msgType.isNormal(lastMessage.type)) {
-					if (this.isInBottom) {
+					if (this.isInBottom || lastMessage.selfSend) {
 						// 收到消息,则滚动至底部
 						this.scrollToBottom();
 					} else {

+ 16 - 8
im-uniapp/store/chatStore.js

@@ -247,25 +247,33 @@ export default defineStore('chatStore', {
 			}
 		},
 		deleteMessage(msgInfo, chatInfo) {
-			// 获取对方id或群id
-			let chat = this.findChat(chatInfo);
 			let isColdMessage = false;
+			let chat = this.findChat(chatInfo);
+			let delIdx = -1;
 			for (let idx in chat.messages) {
 				// 已经发送成功的,根据id删除
 				if (chat.messages[idx].id && chat.messages[idx].id == msgInfo.id) {
-					chat.messages.splice(idx, 1);
-					isColdMessage = idx < chat.hotMinIdx;
+					delIdx = idx;
 					break;
 				}
 				// 正在发送中的消息可能没有id,只有临时id
 				if (chat.messages[idx].tmpId && chat.messages[idx].tmpId == msgInfo.tmpId) {
-					chat.messages.splice(idx, 1);
-					isColdMessage = idx < chat.hotMinIdx;
+					delIdx = idx;
 					break;
 				}
 			}
-			chat.stored = false;
-			this.saveToStorage(isColdMessage);
+			if (delIdx >= 0) {
+				chat.messages.splice(delIdx, 1);
+				if( delIdx < chat.hotMinIdx){
+					isColdMessage = true;
+					chat.hotMinIdx--;
+				}
+				if (delIdx < chat.readedMessageIdx) {
+					chat.readedMessageIdx--;
+				}
+				chat.stored = false;
+				this.saveToStorage(isColdMessage);
+			}
 		},
 		recallMessage(msgInfo, chatInfo) {
 			let chat = this.findChat(chatInfo);

+ 39 - 12
im-web/src/components/chat/ChatBox.vue

@@ -13,7 +13,8 @@
 								<div v-for="(msgInfo, idx) in showMessages" :key="showMinIdx + idx">
 									<chat-message-item @call="onCall(msgInfo.type)" :mine="msgInfo.sendId == mine.id"
 										:headImage="headImage(msgInfo)" :showName="showName(msgInfo)" :msgInfo="msgInfo"
-										:groupMembers="groupMembers" @delete="deleteMessage" @recall="recallMessage">
+										:groupMembers="groupMembers" @resend="onResendMessage" @delete="deleteMessage"
+										@recall="recallMessage">
 									</chat-message-item>
 								</div>
 							</div>
@@ -198,8 +199,6 @@ export default {
 			this.chatStore.insertMessage(msgInfo, this.chat);
 			// 会话置顶
 			this.moveChatToTop();
-			// 滚动到底部
-			this.scrollToBottom();
 			// 借助file对象保存
 			file.msgInfo = msgInfo;
 			file.chat = this.chat;
@@ -263,8 +262,6 @@ export default {
 			this.chatStore.insertMessage(msgInfo, this.chat);
 			// 会话置顶
 			this.moveChatToTop();
-			// 滚动到底部
-			this.scrollToBottom();
 			// 借助file对象透传
 			file.msgInfo = msgInfo;
 			file.chat = this.chat;
@@ -492,7 +489,6 @@ export default {
 					tmpMessage.status = this.$enums.MESSAGE_STATUS.FAILED;
 					this.chatStore.insertMessage(tmpMessage, chat);
 				}).finally(() => {
-					this.scrollToBottom();
 					this.isReceipt = false;
 					resolve();
 				});
@@ -506,6 +502,35 @@ export default {
 				}
 			})
 		},
+		onResendMessage(msgInfo) {
+			if (msgInfo.type != this.$enums.MESSAGE_TYPE.TEXT) {
+				this.$message.error("该消息不支持自动重新发送,建议手动重新发送")
+				return;
+			}
+			// 防止发送期间用户切换会话导致串扰
+			const chat = this.chat;
+			// 删除旧消息
+			this.chatStore.deleteMessage(msgInfo, chat);
+			// 重新推送
+			msgInfo.temId = this.generateId();
+			let tmpMessage = this.buildTmpMessage(msgInfo);
+			this.chatStore.insertMessage(tmpMessage, chat);
+			this.moveChatToTop();
+			// 发送
+			this.sendMessageRequest(msgInfo).then(m => {
+				// 更新消息
+				tmpMessage.id = m.id;
+				tmpMessage.status = m.status;
+				tmpMessage.content = m.content;
+				this.chatStore.insertMessage(tmpMessage, chat);
+			}).catch(() => {
+				// 更新消息
+				tmpMessage.status = this.$enums.MESSAGE_STATUS.FAILED;
+				this.chatStore.insertMessage(tmpMessage, chat);
+			}).finally(() => {
+				this.scrollToBottom();
+			});
+		},
 		deleteMessage(msgInfo) {
 			this.$confirm('确认删除消息?', '删除消息', {
 				confirmButtonText: '确定',
@@ -797,12 +822,14 @@ export default {
 		messageSize: {
 			handler(newSize, oldSize) {
 				if (newSize > oldSize) {
-					if (this.isInBottom) {
-						// 拉至底部
-						this.scrollToBottom();
-					} else {
-						// 增加新消息提醒
-						this.newMessageSize++;
+					// 收到普通消息,则滚动至底部
+					let lastMessage = this.chat.messages[newSize - 1];
+					if (lastMessage && this.$msgType.isNormal(lastMessage.type)) {
+						if (this.isInBottom || lastMessage.selfSend) {
+							this.scrollToBottom();
+						} else {
+							this.newMessageSize++;
+						}
 					}
 				}
 			}

+ 1 - 1
im-web/src/components/chat/ChatMessageItem.vue

@@ -119,7 +119,7 @@ export default {
 	},
 	methods: {
 		onSendFail() {
-			this.$message.error("该消息已发送失败,目前不支持自动重新发送,建议手动重新发送")
+			this.$emit("resend",this.msgInfo);
 		},
 		showFullImageBox() {
 			let imageUrl = JSON.parse(this.msgInfo.content).originUrl;

+ 16 - 7
im-web/src/store/chatStore.js

@@ -242,24 +242,33 @@ export default defineStore('chatStore', {
 			}
 		},
 		deleteMessage(msgInfo, chatInfo) {
-			let chat = this.findChat(chatInfo);
 			let isColdMessage = false;
+			let chat = this.findChat(chatInfo);
+			let delIdx = -1;
 			for (let idx in chat.messages) {
 				// 已经发送成功的,根据id删除
 				if (chat.messages[idx].id && chat.messages[idx].id == msgInfo.id) {
-					chat.messages.splice(idx, 1);
-					isColdMessage = idx < chat.hotMinIdx;
+					delIdx = idx;
 					break;
 				}
 				// 正在发送中的消息可能没有id,只有临时id
 				if (chat.messages[idx].tmpId && chat.messages[idx].tmpId == msgInfo.tmpId) {
-					chat.messages.splice(idx, 1);
-					isColdMessage = idx < chat.hotMinIdx;
+					delIdx = idx;
 					break;
 				}
 			}
-			chat.stored = false;
-			this.saveToStorage(isColdMessage);
+			if (delIdx >= 0) {
+				chat.messages.splice(delIdx, 1);
+				if (delIdx < chat.hotMinIdx) {
+					isColdMessage = true;
+					chat.hotMinIdx--;
+				}
+				if (delIdx < chat.readedMessageIdx) {
+					chat.readedMessageIdx--;
+				}
+				chat.stored = false;
+				this.saveToStorage(isColdMessage);
+			}
 		},
 		recallMessage(msgInfo, chatInfo) {
 			let chat = this.findChat(chatInfo);