Эх сурвалжийг харах

优化:web端缓存存储以会话为单位

xsx 1 жил өмнө
parent
commit
f28571a6f8

+ 4 - 0
im-uniapp/App.vue

@@ -356,6 +356,10 @@
 					url: "/pages/chat/chat"
 				})
 			} else {
+				uni.showToast({
+					title: '您的登陆信息已失效,请重新登陆',
+					icon: 'none'
+				})
 				// 跳转到登录页
 				// #ifdef H5
 				uni.navigateTo({

+ 14 - 1
im-uniapp/components/chat-item/chat-item.vue

@@ -17,7 +17,7 @@
 			</view>
 			<view class="chat-content">
 				<view class="chat-at-text">{{atText}}</view>
-				<view class="chat-send-name" v-show="chat.sendNickName">{{chat.sendNickName+':&nbsp;'}}</view>
+				<view class="chat-send-name" v-if="isShowSendName">{{chat.sendNickName+':&nbsp;'}}</view>
 				<rich-text class="chat-content-text" :nodes="$emo.transform(chat.lastContent)"></rich-text>
 				<uni-badge v-if="chat.unreadCount>0" size="small" :max-num="99" :text="chat.unreadCount" />
 			</view>
@@ -44,6 +44,7 @@
 			}
 		},
 		methods: {
+			
 			showChatBox() {
 				uni.navigateTo({
 					url: "/pages/chat/chat-box?chatIdx=" + this.index
@@ -51,6 +52,18 @@
 			}
 		},
 		computed: {
+			isShowSendName() {
+				if (!this.chat.sendNickName) {
+					return false;
+				}
+				let size = this.chat.messages.length;
+				if (size == 0) {
+					return false;
+				}
+				// 只有群聊的普通消息需要显示名称
+				let lastMsg = this.chat.messages[size - 1];
+				return this.$msgType.isNormal(lastMsg.type)
+			},
 			atText() {
 				if (this.chat.atMe) {
 					return "[有人@我]"

+ 1 - 1
im-uniapp/pages/common/user-info.vue

@@ -81,7 +81,7 @@
 			onDelFriend(){
 				uni.showModal({
 					title: "确认删除",
-					content: `确认要删除与 '${this.userInfo.nickName}'的好友关系吗?`,
+					content: `确认删除 '${this.userInfo.nickName}',并删除聊天记录吗?`,
 					success: (res)=> {
 						if(res.cancel)
 							return;

+ 17 - 13
im-uniapp/store/chatStore.js

@@ -92,11 +92,11 @@ export default defineStore('chatStore', {
 		readedMessage(pos) {
 			let chat = this.findChatByFriend(pos.friendId);
 			chat.messages.forEach((m) => {
-				if (m.selfSend && m.status < MESSAGE_STATUS.RECALL) {
+				if (m.id && m.selfSend && m.status < MESSAGE_STATUS.RECALL) {
 					// pos.maxId为空表示整个会话已读
 					if (!pos.maxId || m.id <= pos.maxId) {
 						m.status = MESSAGE_STATUS.READED
-						chats.stored = false;
+						chat.stored = false;
 					}
 				}
 			})
@@ -137,9 +137,10 @@ export default defineStore('chatStore', {
 				let chat = chats[idx];
 				chats.splice(idx, 1);
 				chats.unshift(chat);
+				chat.lastSendTime = new Date().getTime();
+				chat.stored = false;
 				this.saveToStorage();
 			}
-			
 		},
 		insertMessage(msgInfo) {
 			// 获取对方id或群id
@@ -171,12 +172,14 @@ export default defineStore('chatStore', {
 				chat.lastContent = "[文件]";
 			} else if (msgInfo.type == MESSAGE_TYPE.AUDIO) {
 				chat.lastContent = "[语音]";
-			} else if (msgInfo.type == MESSAGE_TYPE.TEXT || msgInfo.type == MESSAGE_TYPE.RECALL) {
-				chat.lastContent = msgInfo.content;
 			} else if (msgInfo.type == MESSAGE_TYPE.ACT_RT_VOICE) {
 				chat.lastContent = "[语音通话]";
 			} else if (msgInfo.type == MESSAGE_TYPE.ACT_RT_VIDEO) {
 				chat.lastContent = "[视频通话]";
+			} else if (msgInfo.type == MESSAGE_TYPE.TEXT ||
+				msgInfo.type == MESSAGE_TYPE.RECALL ||
+				msgInfo.type == MESSAGE_TYPE.TIP_TEXT) {
+				chat.lastContent = msgInfo.content;
 			}
 			chat.lastSendTime = msgInfo.sendTime;
 			chat.sendNickName = msgInfo.sendNickName;
@@ -313,22 +316,23 @@ export default defineStore('chatStore', {
 			// 按会话为单位存储,只存储有改动的会话
 			this.chats.forEach((chat)=>{
 				let chatKey = `${key}-${chat.type}-${chat.targetId}`
-				if(chat.delete){
-					uni.removeStorageSync(chatKey);
-					return;
-				}
 				if(!chat.stored){
-					uni.setStorageSync(chatKey,chat);
+					if(chat.delete){
+						uni.removeStorageSync(chatKey);
+					}else{
+						uni.setStorageSync(chatKey,chat);
+					}
+					chat.stored = true;
+				}
+				if(!chat.delete){
+					chatKeys.push(chatKey);	
 				}
-				chat.stored = true;
-				chatKeys.push(chatKey);	
 			})
 			// 会话核心信息
 			let chatsData = {
 				privateMsgMaxId: this.privateMsgMaxId,
 				groupMsgMaxId: this.groupMsgMaxId,
 				chatKeys: chatKeys
-				//chats: this.chats
 			}
 			uni.setStorageSync(key, chatsData)
 		},

+ 111 - 59
im-web/src/store/chatStore.js

@@ -21,7 +21,7 @@ export default {
 			state.chats = [];
 			state.privateMsgMaxId = chatsData.privateMsgMaxId || 0;
 			state.groupMsgMaxId = chatsData.groupMsgMaxId || 0;
-			cacheChats = chatsData.chats||[];
+			cacheChats = chatsData.chats || [];
 			// 防止图片一直处在加载中状态
 			cacheChats.forEach((chat) => {
 				chat.messages.forEach((msg) => {
@@ -55,7 +55,9 @@ export default {
 					unreadCount: 0,
 					messages: [],
 					atMe: false,
-					atAll: false
+					atAll: false,
+					stored: false,
+					delete: false
 				};
 				chats.unshift(chat);
 			}
@@ -72,26 +74,23 @@ export default {
 					chats[idx].unreadCount = 0;
 					chats[idx].atMe = false;
 					chats[idx].atAll = false;
+					chats[idx].stored = false;
+					this.commit("saveToStorage");
+					break;
 				}
 			}
-			this.commit("saveToStorage");
 		},
 		readedMessage(state, pos) {
-			let chats = this.getters.findChats();
-			for (let idx in chats) {
-				if (chats[idx].type == 'PRIVATE' &&
-					chats[idx].targetId == pos.friendId) {
-					chats[idx].messages.forEach((m) => {
-						if (m.selfSend && m.status != MESSAGE_STATUS.RECALL) {
-							// pos.maxId为空表示整个会话已读
-							if (!pos.maxId || m.id <= pos.maxId) {
-								m.status = MESSAGE_STATUS.READED
-							}
-
-						}
-					})
+			let chat = this.getters.findChatByFriend(pos.friendId);
+			chat.messages.forEach((m) => {
+				if (m.id && m.selfSend && m.status != MESSAGE_STATUS.RECALL) {
+					// pos.maxId为空表示整个会话已读
+					if (!pos.maxId || m.id <= pos.maxId) {
+						m.status = MESSAGE_STATUS.READED
+						chat.stored = false;
+					}
 				}
-			}
+			})
 			this.commit("saveToStorage");
 		},
 		removeChat(state, idx) {
@@ -99,9 +98,30 @@ export default {
 			if (chats[idx] == state.activeChat) {
 				state.activeChat = null;
 			}
-			chats.splice(idx, 1);
+			chats[idx].delete = true;
+			chats[idx].stored = false;
 			this.commit("saveToStorage");
 		},
+		removePrivateChat(state,friendId){
+			let chats = this.getters.findChats();
+			for (let idx in chats) {
+				if (chats[idx].type == 'PRIVATE' &&
+					chats[idx].targetId === friendId) {
+					this.commit("removeChat",idx)
+					break;
+				}
+			}
+		},
+		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)
+					break;
+				}
+			}
+		},
 		moveTop(state, idx) {
 			// 加载中不移动,很耗性能
 			if (this.getters.isLoading()) {
@@ -112,18 +132,11 @@ export default {
 				let chat = chats[idx];
 				chats.splice(idx, 1);
 				chats.unshift(chat);
+				chat.lastSendTime = new Date().getTime();
+				chat.stored = false;
 				this.commit("saveToStorage");
 			}
 		},
-		removePrivateChat(state, friendId) {
-			let chats = this.getters.findChats();
-			for (let idx in chats) {
-				if (chats[idx].type == 'PRIVATE' &&
-					chats[idx].targetId == friendId) {
-					this.commit("removeChat", idx);
-				}
-			}
-		},
 		insertMessage(state, msgInfo) {
 			let type = msgInfo.groupId ? 'GROUP' : 'PRIVATE';
 			// 记录消息的最大id
@@ -142,6 +155,7 @@ export default {
 				if (msgInfo.type == MESSAGE_TYPE.RECALL) {
 					chat.lastContent = msgInfo.content;
 				}
+				chat.stored = false;
 				this.commit("saveToStorage");
 				return;
 			}
@@ -152,14 +166,14 @@ export default {
 				chat.lastContent = "[文件]";
 			} else if (msgInfo.type == MESSAGE_TYPE.AUDIO) {
 				chat.lastContent = "[语音]";
-			} else if (msgInfo.type == MESSAGE_TYPE.TEXT ||
-				msgInfo.type == MESSAGE_TYPE.RECALL ||
-				msgInfo.type == MESSAGE_TYPE.TIP_TEXT) {
-				chat.lastContent = msgInfo.content;
 			} else if (msgInfo.type == MESSAGE_TYPE.ACT_RT_VOICE) {
 				chat.lastContent = "[语音通话]";
 			} else if (msgInfo.type == MESSAGE_TYPE.ACT_RT_VIDEO) {
 				chat.lastContent = "[视频通话]";
+			} else if (msgInfo.type == MESSAGE_TYPE.TEXT ||
+				msgInfo.type == MESSAGE_TYPE.RECALL ||
+				msgInfo.type == MESSAGE_TYPE.TIP_TEXT) {
+				chat.lastContent = msgInfo.content;
 			}
 			chat.lastSendTime = msgInfo.sendTime;
 			chat.sendNickName = msgInfo.sendNickName;
@@ -199,6 +213,7 @@ export default {
 				}
 			}
 			chat.messages.splice(insertPos, 0, msgInfo);
+			chat.stored = false;
 			this.commit("saveToStorage");
 		},
 		updateMessage(state, msgInfo) {
@@ -208,6 +223,7 @@ export default {
 			if (message) {
 				// 属性拷贝
 				Object.assign(message, msgInfo);
+				chat.stored = false;
 				this.commit("saveToStorage");
 			}
 		},
@@ -226,31 +242,30 @@ export default {
 					break;
 				}
 			}
+			chat.stored = false;
 			this.commit("saveToStorage");
 		},
 		updateChatFromFriend(state, friend) {
-			let chats = this.getters.findChats();
-			for (let i in chats) {
-				let chat = chats[i];
-				if (chat.type == 'PRIVATE' && chat.targetId == friend.id) {
-					chat.headImage = friend.headImageThumb;
-					chat.showName = friend.nickName;
-					break;
-				}
+			let chat = this.getters.findChatByFriend(friend.id);
+			// 更新会话中的群名和头像
+			if (chat && (chat.headImage != friend.headImageThumb ||
+					chat.showName != friend.nickName)) {
+				chat.headImage = friend.headImageThumb;
+				chat.showName = friend.nickName;
+				chat.stored = false;
+				this.commit("saveToStorage")
 			}
-			this.commit("saveToStorage");
 		},
 		updateChatFromGroup(state, group) {
-			let chats = this.getters.findChats();
-			for (let i in chats) {
-				let chat = chats[i];
-				if (chat.type == 'GROUP' && chat.targetId == group.id) {
-					chat.headImage = group.headImageThumb;
-					chat.showName = group.showGroupName;
-					break;
-				}
+			let chat = this.getters.findChatByGroup(group.id);
+			if (chat && (chat.headImage != group.headImageThumb ||
+					chat.showName != group.showGroupName)) {
+				// 更新会话中的群名称和头像
+				chat.headImage = group.headImageThumb;
+				chat.showName = group.showGroupName;
+				chat.stored = false;
+				this.commit("saveToStorage")
 			}
-			this.commit("saveToStorage");
 		},
 		loadingPrivateMsg(state, loading) {
 			state.loadingPrivateMsg = loading;
@@ -282,10 +297,28 @@ export default {
 			}
 			let userId = userStore.state.userInfo.id;
 			let key = "chats-" + userId;
+			let chatKeys = [];
+			// 按会话为单位存储,
+			state.chats.forEach((chat) => {
+				// 只存储有改动的会话
+				let chatKey = `${key}-${chat.type}-${chat.targetId}`
+				if (!chat.stored) {
+					if (chat.delete) {
+						localForage.removeItem(chatKey);
+					} else {
+						localForage.setItem(chatKey, chat);
+					}
+					chat.stored = true;
+				}
+				if (!chat.delete) {
+					chatKeys.push(chatKey);
+				}
+			})
+			// 会话核心信息
 			let chatsData = {
 				privateMsgMaxId: state.privateMsgMaxId,
 				groupMsgMaxId: state.groupMsgMaxId,
-				chats: state.chats
+				chatKeys: chatKeys
 			}
 			localForage.setItem(key, chatsData)
 		},
@@ -293,7 +326,6 @@ export default {
 			cacheChats = []
 			state.chats = [];
 			state.activeChat = null;
-			
 		}
 	},
 	actions: {
@@ -301,17 +333,27 @@ export default {
 			return new Promise((resolve, reject) => {
 				let userId = userStore.state.userInfo.id;
 				let key = "chats-" + userId;
-				localForage.getItem(key).then((item)=>{
-					let chatsData = item;
-					// 兼容历史数据,以后要删除
-					if(!chatsData){
-						chatsData = JSON.parse(localStorage.getItem(key));
+				localForage.getItem(key).then((chatsData) => {
+					if (!chatsData) {
+						resolve();
 					}
-					if (chatsData) {
+					else if(chatsData.chats){
+						// 兼容旧版本
 						context.commit("initChats", chatsData);
+						resolve();
+					}else if (chatsData.chatKeys) {
+						const promises = [];
+						chatsData.chatKeys.forEach(key => {
+							promises.push(localForage.getItem(key))
+						})
+						Promise.all(promises).then(chats => {
+							chatsData.chats = chats.filter(o => o);
+							context.commit("initChats", chatsData);
+							resolve();
+						})
 					}
-					resolve();
-				}).catch(()=>{
+				}).catch((e) => {
+					console.log("加载消息失败")
 					reject();
 				})
 			})
@@ -349,6 +391,16 @@ export default {
 			}
 			return chat;
 		},
+		findChatByFriend: (state, getters) => (fid) => {
+			let chats = getters.findChats();
+			return chats.find(chat => chat.type == 'PRIVATE' &&
+				chat.targetId == fid)
+		},
+		findChatByGroup: (state, getters) => (gid) => {
+			let chats = getters.findChats();
+			return chats.find(chat => chat.type == 'GROUP' &&
+				chat.targetId == gid)
+		},
 		findMessage: (state) => (chat, msgInfo) => {
 			if (!chat) {
 				return null;

+ 1 - 1
im-web/src/view/Chat.vue

@@ -12,7 +12,7 @@
 			</div>
 			<el-scrollbar class="chat-list-items">
 				<div v-for="(chat,index) in chatStore.chats" :key="index">
-					<chat-item v-show="chat.showName.includes(searchText)" :chat="chat" :index="index"
+					<chat-item v-show="!chat.delete&&chat.showName.includes(searchText)" :chat="chat" :index="index"
 						@click.native="onActiveItem(index)" @delete="onDelItem(index)" @top="onTop(index)"
 						:active="chat === chatStore.activeChat"></chat-item>
 				</div>

+ 1 - 1
im-web/src/view/Friend.vue

@@ -89,7 +89,7 @@
 				this.loadUserInfo(friend, idx);
 			},
 			onDelItem(friend, idx) {
-				this.$confirm(`确认要解除与 '${friend.nickName}'的好友关系吗?`, '确认解除?', {
+				this.$confirm(`确认删除'${friend.nickName}',并清空聊天记录吗?`, '确认解除?', {
 					confirmButtonText: '确定',
 					cancelButtonText: '取消',
 					type: 'warning'

+ 4 - 2
im-web/src/view/Group.vue

@@ -172,7 +172,7 @@
 				});
 			},
 			onDissolve() {
-				this.$confirm('确认要解散群聊吗?', '确认解散?', {
+				this.$confirm(`确认要解散'${this.activeGroup.name}'吗?`, '确认解散?', {
 					confirmButtonText: '确定',
 					cancelButtonText: '取消',
 					type: 'warning'
@@ -183,6 +183,7 @@
 					}).then(() => {
 						this.$message.success(`群聊'${this.activeGroup.name}'已解散`);
 						this.$store.commit("removeGroup", this.activeGroup.id);
+						this.$store.commit("removeGroupChat", this.activeGroup.id);
 						this.reset();
 					});
 				})
@@ -208,7 +209,7 @@
 
 			},
 			onQuit() {
-				this.$confirm('退出群聊后将不再接受群里的消息,确认退出吗?', '确认退出?', {
+				this.$confirm(`确认退出'${this.activeGroup.showGroupName}',并清空聊天记录吗?`, '确认退出?', {
 					confirmButtonText: '确定',
 					cancelButtonText: '取消',
 					type: 'warning'
@@ -217,6 +218,7 @@
 						url: `/group/quit/${this.activeGroup.id}`,
 						method: 'delete'
 					}).then(() => {
+						this.$message.success(`您已退出'${this.activeGroup.name}'`);
 						this.$store.commit("removeGroup", this.activeGroup.id);
 						this.$store.commit("removeGroupChat", this.activeGroup.id);
 						this.reset();