From 75db96f39bc3f66f77ea27c7a424a6eaee6ae05d Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Thu, 5 Jun 2025 22:42:00 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=A8pinia=E4=BB=A3=E7=90=86vuex?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- im-web/package.json | 5 +- im-web/src/components/chat/ChatAtBox.vue | 4 +- im-web/src/components/chat/ChatBox.vue | 54 ++-- .../src/components/chat/ChatGroupReaded.vue | 2 +- im-web/src/components/chat/ChatGroupSide.vue | 8 +- im-web/src/components/chat/ChatHistory.vue | 2 +- im-web/src/components/common/UserInfo.vue | 8 +- im-web/src/components/friend/AddFriend.vue | 8 +- .../src/components/group/AddGroupMember.vue | 2 +- im-web/src/components/rtc/RtcGroupJoin.vue | 2 +- im-web/src/components/rtc/RtcPrivateVideo.vue | 2 +- im-web/src/components/setting/Setting.vue | 7 +- im-web/src/main.js | 21 +- im-web/src/store/chatStore.js | 253 ++++++++++-------- im-web/src/store/configStore.js | 27 +- im-web/src/store/friendStore.js | 117 +++----- im-web/src/store/groupStore.js | 66 +++-- im-web/src/store/uiStore.js | 31 ++- im-web/src/store/userStore.js | 50 ++-- im-web/src/view/Chat.vue | 9 +- im-web/src/view/Friend.vue | 19 +- im-web/src/view/Group.vue | 28 +- im-web/src/view/Home.vue | 107 ++++---- 23 files changed, 417 insertions(+), 415 deletions(-) diff --git a/im-web/package.json b/im-web/package.json index 50fcc26..019c50b 100644 --- a/im-web/package.json +++ b/im-web/package.json @@ -19,8 +19,7 @@ "vue": "2.7.16", "vue-axios": "3.5.2", "vue-router": "3.6.5", - "vuex": "3.6.2", - "vuex-persist": "3.1.3" + "pinia": "^2.1.7" }, "devDependencies": { "@vue/cli-plugin-babel": "~4.5.12", @@ -61,4 +60,4 @@ "last 2 versions", "not dead" ] -} +} \ No newline at end of file diff --git a/im-web/src/components/chat/ChatAtBox.vue b/im-web/src/components/chat/ChatAtBox.vue index 747f0a4..1b55965 100644 --- a/im-web/src/components/chat/ChatAtBox.vue +++ b/im-web/src/components/chat/ChatAtBox.vue @@ -42,7 +42,7 @@ export default { init() { this.$refs.scrollBox.wrap.scrollTop = 0; this.showMembers = []; - let userId = this.$store.state.userStore.userInfo.id; + let userId = this.userStore.userInfo.id; let name = "全体成员"; if (this.ownerId == userId && name.startsWith(this.searchText)) { this.showMembers.push({ @@ -108,7 +108,7 @@ export default { }, computed: { isOwner() { - return this.$store.state.userStore.userInfo.id == this.ownerId; + return this.userStore.userInfo.id == this.ownerId; } }, watch: { diff --git a/im-web/src/components/chat/ChatBox.vue b/im-web/src/components/chat/ChatBox.vue index 55788db..8d9574b 100644 --- a/im-web/src/components/chat/ChatBox.vue +++ b/im-web/src/components/chat/ChatBox.vue @@ -140,8 +140,8 @@ export default { }, methods: { moveChatToTop() { - let chatIdx = this.$store.getters.findChatIdx(this.chat); - this.$store.commit("moveTop", chatIdx); + let chatIdx = this.chatStore.findChatIdx(this.chat); + this.chatStore.moveTop(chatIdx); }, closeRefBox() { this.$refs.emoBox.close(); @@ -166,13 +166,13 @@ export default { msgInfo.loadStatus = 'ok'; msgInfo.id = m.id; this.isReceipt = false; - this.$store.commit("insertMessage", [msgInfo, file.chat]); + this.chatStore.insertMessage(msgInfo, file.chat); }) }, onImageFail(e, file) { let msgInfo = JSON.parse(JSON.stringify(file.msgInfo)); msgInfo.loadStatus = 'fail'; - this.$store.commit("insertMessage", [msgInfo, file.chat]); + this.chatStore.insertMessage(msgInfo, file.chat); }, onImageBefore(file) { // 被封禁提示 @@ -201,7 +201,7 @@ export default { // 填充对方id this.fillTargetId(msgInfo, this.chat.targetId); // 插入消息 - this.$store.commit("insertMessage", [msgInfo, this.chat]); + this.chatStore.insertMessage(msgInfo, this.chat); // 会话置顶 this.moveChatToTop(); // 滚动到底部 @@ -224,13 +224,13 @@ export default { msgInfo.id = m.id; this.isReceipt = false; this.refreshPlaceHolder(); - this.$store.commit("insertMessage", [msgInfo, file.chat]); + this.chatStore.insertMessage(msgInfo, file.chat); }) }, onFileFail(e, file) { let msgInfo = JSON.parse(JSON.stringify(file.msgInfo)); msgInfo.loadStatus = 'fail'; - this.$store.commit("insertMessage", [msgInfo, file.chat]); + this.chatStore.insertMessage(msgInfo, file.chat); }, onFileBefore(file) { // 被封禁提示 @@ -259,7 +259,7 @@ export default { // 填充对方id this.fillTargetId(msgInfo, this.chat.targetId); // 插入消息 - this.$store.commit("insertMessage", [msgInfo, this.chat]); + this.chatStore.insertMessage(msgInfo, this.chat); // 会话置顶 this.moveChatToTop(); // 滚动到底部 @@ -330,7 +330,7 @@ export default { } // 邀请成员发起通话 let ids = [this.mine.id]; - let maxChannel = this.$store.state.configStore.webrtc.maxChannel; + let maxChannel = this.configStore.webrtc.maxChannel; this.$refs.rtcSel.open(maxChannel, ids, ids, []); }, onInviteOk(members) { @@ -375,9 +375,9 @@ export default { } // 填充对方id this.fillTargetId(msgInfo, this.chat.targetId); - this.sendMessageRequest(msgInfo).then((m) => { + this.sendMessageRequest(msgInfo).then(m => { m.selfSend = true; - this.$store.commit("insertMessage", [m, this.chat]); + this.chatStore.insertMessage(m, this.chat); // 会话置顶 this.moveChatToTop(); // 保持输入框焦点 @@ -462,7 +462,7 @@ export default { this.lockMessage = true; this.sendMessageRequest(msgInfo).then((m) => { m.selfSend = true; - this.$store.commit("insertMessage", [m, this.chat]); + this.chatStore.insertMessage(m, this.chat); // 会话置顶 this.moveChatToTop(); }).finally(() => { @@ -487,7 +487,7 @@ export default { cancelButtonText: '取消', type: 'warning' }).then(() => { - this.$store.commit("deleteMessage", [msgInfo, this.chat]); + this.chatStore.deleteMessage(msgInfo, this.chat); }); }, recallMessage(msgInfo) { @@ -503,7 +503,7 @@ export default { }).then((m) => { this.$message.success("消息已撤回"); m.selfSend = true; - this.$store.commit("recallMessage", [m, this.chat]); + this.chatStore.recallMessage(m, this.chat); }) }); }, @@ -511,7 +511,7 @@ export default { if (this.chat.unreadCount == 0) { return; } - this.$store.commit("resetUnreadCount", this.chat) + this.chatStore.resetUnreadCount(this.chat) if (this.chat.type == "GROUP") { var url = `/message/group/readed?groupId=${this.chat.targetId}` } else { @@ -520,14 +520,14 @@ export default { this.$http({ url: url, method: 'put' - }).then(() => {}) + }).then(() => { }) }, loadReaded(fId) { this.$http({ url: `/message/private/maxReadedId?friendId=${fId}`, method: 'get' }).then((id) => { - this.$store.commit("readedMessage", { + this.chatStore.readedMessage({ friendId: fId, maxId: id }); @@ -539,8 +539,8 @@ export default { method: 'get' }).then((group) => { this.group = group; - this.$store.commit("updateChatFromGroup", group); - this.$store.commit("updateGroup", group); + this.chatStore.updateChatFromGroup(group); + this.groupStore.updateGroup(group); }); this.$http({ @@ -557,10 +557,10 @@ export default { friend.headImage = this.userInfo.headImageThumb; friend.nickName = this.userInfo.nickName; friend.showNickName = friend.remarkNickName ? friend.remarkNickName : friend.nickName; - this.$store.commit("updateChatFromFriend", friend); - this.$store.commit("updateFriend", friend); + this.chatStore.updateChatFromFriend(friend); + this.friendStore.updateFriend(friend); } else { - this.$store.commit("updateChatFromUser", this.userInfo); + this.chatStore.updateChatFromUser(this.userInfo); } }, loadFriend(friendId) { @@ -653,7 +653,7 @@ export default { msgInfo.groupId = this.group.id; msgInfo.content = "本群聊已被管理员封禁,原因:" + this.group.reason } - this.$store.commit("insertMessage", [msgInfo, this.chat]); + this.chatStore.insertMessage(msgInfo, this.chat); }, generateId() { // 生成临时id @@ -662,13 +662,13 @@ export default { }, computed: { mine() { - return this.$store.state.userStore.userInfo; + return this.userStore.userInfo; }, isFriend() { - return this.$store.getters.isFriend(this.userInfo.id); + return this.friendStore.isFriend(this.userInfo.id); }, friend() { - return this.$store.getters.findFriend(this.userInfo.id) + return this.friendStore.findFriend(this.userInfo.id) }, title() { let title = this.chat.showName; @@ -708,7 +708,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 = []; diff --git a/im-web/src/components/chat/ChatGroupReaded.vue b/im-web/src/components/chat/ChatGroupReaded.vue index dfe5dce..c35b96f 100644 --- a/im-web/src/components/chat/ChatGroupReaded.vue +++ b/im-web/src/components/chat/ChatGroupReaded.vue @@ -115,7 +115,7 @@ export default { type: 'GROUP', targetId: this.msgInfo.groupId } - this.$store.commit("updateMessage", [msgInfo, chatInfo]) + this.chatStore.updateMessage(msgInfo, chatInfo) }) } } diff --git a/im-web/src/components/chat/ChatGroupSide.vue b/im-web/src/components/chat/ChatGroupSide.vue index 9024315..5f4dd85 100644 --- a/im-web/src/components/chat/ChatGroupSide.vue +++ b/im-web/src/components/chat/ChatGroupSide.vue @@ -124,7 +124,7 @@ export default { data: vo }).then((group) => { this.editing = !this.editing - this.$store.commit("updateGroup", group); + this.groupStore.updateGroup(group); this.$emit('reload'); this.$message.success("修改成功"); }) @@ -139,8 +139,8 @@ export default { url: `/group/quit/${this.group.id}`, method: 'delete' }).then(() => { - this.$store.commit("removeGroup", this.group.id); - this.$store.commit("removeGroupChat", this.group.id); + this.groupStore.removeGroup(this.group.id); + this.chatStore.removeGroupChat(this.group.id); }); }) }, @@ -156,7 +156,7 @@ export default { }, computed: { mine() { - return this.$store.state.userStore.userInfo; + return this.userStore.userInfo; }, ownerName() { let member = this.groupMembers.find((m) => m.userId == this.group.ownerId); diff --git a/im-web/src/components/chat/ChatHistory.vue b/im-web/src/components/chat/ChatHistory.vue index 8ce1601..76792e4 100644 --- a/im-web/src/components/chat/ChatHistory.vue +++ b/im-web/src/components/chat/ChatHistory.vue @@ -126,7 +126,7 @@ export default { }, computed: { mine() { - return this.$store.state.userStore.userInfo; + return this.userStore.userInfo; }, histroyAction() { return `/message/${this.chat.type.toLowerCase()}/history`; diff --git a/im-web/src/components/common/UserInfo.vue b/im-web/src/components/common/UserInfo.vue index 3cdd07e..b74c262 100644 --- a/im-web/src/components/common/UserInfo.vue +++ b/im-web/src/components/common/UserInfo.vue @@ -59,8 +59,8 @@ export default { showName: user.nickName, headImage: user.headImage, }; - this.$store.commit("openChat", chat); - this.$store.commit("activeChat", 0); + this.chatStore.openChat(chat); + this.chatStore.setActiveChat(0); if (this.$route.path != "/home/chat") { this.$router.push("/home/chat"); } @@ -82,7 +82,7 @@ export default { online: this.user.online, deleted: false } - this.$store.commit("addFriend", friend); + this.friendStore.addFriend(friend); }) }, showFullImage() { @@ -93,7 +93,7 @@ export default { }, computed: { isFriend() { - return this.$store.getters.isFriend(this.user.id); + return this.friendStore.isFriend(this.user.id); } } } diff --git a/im-web/src/components/friend/AddFriend.vue b/im-web/src/components/friend/AddFriend.vue index 249cec1..074279c 100644 --- a/im-web/src/components/friend/AddFriend.vue +++ b/im-web/src/components/friend/AddFriend.vue @@ -6,7 +6,7 @@ -
+
@@ -15,7 +15,7 @@
{{ user.nickName }}
{{ - user.online ? "[在线]" :"[离线]"}}
+ user.online ? "[在线]" : "[离线]" }}
用户名:{{ user.userName }}
@@ -83,11 +83,11 @@ export default { online: user.online, deleted: false } - this.$store.commit("addFriend", friend); + this.friendStore.addFriend(friend); }) }, isFriend(userId) { - return this.$store.getters.isFriend(userId); + return this.friendStore.isFriend(userId); } } } diff --git a/im-web/src/components/group/AddGroupMember.vue b/im-web/src/components/group/AddGroupMember.vue index 181d6f0..547be76 100644 --- a/im-web/src/components/group/AddGroupMember.vue +++ b/im-web/src/components/group/AddGroupMember.vue @@ -55,7 +55,7 @@ export default { open() { this.show = true; this.friends = []; - this.$store.state.friendStore.friends.forEach((f) => { + this.friendStore.friends.forEach((f) => { if (f.deleted) { return; } diff --git a/im-web/src/components/rtc/RtcGroupJoin.vue b/im-web/src/components/rtc/RtcGroupJoin.vue index 04a8937..cad1d1a 100644 --- a/im-web/src/components/rtc/RtcGroupJoin.vue +++ b/im-web/src/components/rtc/RtcGroupJoin.vue @@ -52,7 +52,7 @@ export default { onOk() { this.isShow = false; let userInfos = this.rtcInfo.userInfos; - let mine = this.$store.state.userStore.userInfo; + let mine = this.userStore.userInfo; if (!userInfos.find((user) => user.id == mine.id)) { // 加入自己的信息 userInfos.push({ diff --git a/im-web/src/components/rtc/RtcPrivateVideo.vue b/im-web/src/components/rtc/RtcPrivateVideo.vue index 757b231..70f0ec8 100644 --- a/im-web/src/components/rtc/RtcPrivateVideo.vue +++ b/im-web/src/components/rtc/RtcPrivateVideo.vue @@ -383,7 +383,7 @@ export default { return strTime; }, configuration() { - const iceServers = this.$store.state.configStore.webrtc.iceServers; + const iceServers = this.configStore.webrtc.iceServers; return { iceServers: iceServers } diff --git a/im-web/src/components/setting/Setting.vue b/im-web/src/components/setting/Setting.vue index 03b3eac..3228613 100644 --- a/im-web/src/components/setting/Setting.vue +++ b/im-web/src/components/setting/Setting.vue @@ -56,7 +56,6 @@ export default { } }, methods: { - onClose() { this.$emit("close"); }, @@ -70,7 +69,7 @@ export default { method: "put", data: this.userInfo }).then(() => { - this.$store.commit("setUserInfo", this.userInfo); + this.userStore.setUserInfo(this.userInfo); this.$emit("close"); this.$message.success("修改成功"); }) @@ -92,9 +91,9 @@ export default { } }, watch: { - visible: function(newData, oldData) { + visible: function () { // 深拷贝 - let mine = this.$store.state.userStore.userInfo; + let mine = this.userStore.userInfo; this.userInfo = JSON.parse(JSON.stringify(mine)); } } diff --git a/im-web/src/main.js b/im-web/src/main.js index a2ed843..3672c9d 100644 --- a/im-web/src/main.js +++ b/im-web/src/main.js @@ -4,18 +4,26 @@ import router from './router' import ElementUI from 'element-ui'; import './assets/style/im.scss'; import './assets/iconfont/iconfont.css'; - +import { createPinia, PiniaVuePlugin } from 'pinia' import httpRequest from './api/httpRequest'; import * as socketApi from './api/wssocket'; import * as messageType from './api/messageType'; import emotion from './api/emotion.js'; import url from './api/url.js'; import element from './api/element.js'; -import store from './store'; import * as enums from './api/enums.js'; import * as date from './api/date.js'; import './utils/directive/dialogDrag'; +import useChatStore from './store/chatStore.js' +import useFriendStore from './store/friendStore.js' +import useGroupStore from './store/groupStore.js' +import useUserStore from './store/userStore.js' +import useConfigStore from './store/configStore.js' +import useUiStore from './store/uiStore.js' + +Vue.use(PiniaVuePlugin) +const pinia = createPinia() Vue.use(ElementUI); // 挂载全局 Vue.prototype.$wsApi = socketApi; @@ -33,7 +41,14 @@ new Vue({ el: '#app', // 配置路由 router, - store, + pinia, render: h => h(App) }) +// 挂载全局的pinia +Vue.prototype.chatStore = useChatStore(); +Vue.prototype.friendStore = useFriendStore(); +Vue.prototype.groupStore = useGroupStore(); +Vue.prototype.userStore = useUserStore(); +Vue.prototype.configStore = useConfigStore(); +Vue.prototype.uiStore = useUiStore(); \ No newline at end of file diff --git a/im-web/src/store/chatStore.js b/im-web/src/store/chatStore.js index a7f6e08..8096807 100644 --- a/im-web/src/store/chatStore.js +++ b/im-web/src/store/chatStore.js @@ -1,26 +1,42 @@ +import { defineStore } from 'pinia'; import { MESSAGE_TYPE, MESSAGE_STATUS } from "../api/enums.js" -import userStore from './userStore'; +import useUserStore from './userStore.js'; import localForage from 'localforage'; -/* 为了加速拉取离线消息效率,拉取时消息暂时存储到cacheChats,等 -待所有离线消息拉取完成后,再统一放至vuex中进行渲染*/ +/** + * 优化1(冷热消息分区): + * 热消息:登录后的消息 + * 冷消息: 登录前的消息 + * 每个会话的冷热消息分别用一个key进行存储,当有新的消息时,只更新热消息key,冷消息key保持不变 + * 由于热消息数量不会很大,所以localForage.setItem耗时很低,可以防止消息过多时出现卡顿的情况 + * + * 优化2(延迟渲染): + * 拉取消息时,如果直接用state.chats接收,页面就开始渲染,一边渲染页面一边大量接消息会导致很严重的卡顿 + * 为了加速拉取离线消息效率,拉取时消息暂时存储到cacheChats,等待所有离线消息拉取完成后,再统一放至state中进行渲染 + * + * 优化3(pinia代替vuex) + * 实测pinia的远超vuex,且语法更简洁清晰 + * + * */ + let cacheChats = []; -export default { - state: { - activeChat: null, - privateMsgMaxId: 0, - groupMsgMaxId: 0, - loadingPrivateMsg: false, - loadingGroupMsg: false, - chats: [] +export default defineStore('chatStore', { + state: () => { + return { + activeChat: null, + privateMsgMaxId: 0, + groupMsgMaxId: 0, + loadingPrivateMsg: false, + loadingGroupMsg: false, + chats: [] + } }, - - mutations: { - initChats(state, chatsData) { - state.chats = []; - state.privateMsgMaxId = chatsData.privateMsgMaxId || 0; - state.groupMsgMaxId = chatsData.groupMsgMaxId || 0; + actions: { + initChats(chatsData) { + this.chats = []; + this.privateMsgMaxId = chatsData.privateMsgMaxId || 0; + this.groupMsgMaxId = chatsData.groupMsgMaxId || 0; cacheChats = chatsData.chats || []; // 防止图片一直处在加载中状态 cacheChats.forEach((chat) => { @@ -31,15 +47,15 @@ export default { }) }) }, - openChat(state, chatInfo) { - let chats = this.getters.findChats() + openChat(chatInfo) { + let chats = this.findChats() let chat = null; for (let idx in chats) { if (chats[idx].type == chatInfo.type && chats[idx].targetId === chatInfo.targetId) { chat = chats[idx]; // 放置头部 - this.commit("moveTop", idx) + this.moveTop(idx) break; } } @@ -62,12 +78,12 @@ export default { chats.unshift(chat); } }, - activeChat(state, idx) { - let chats = this.getters.findChats(); - state.activeChat = chats[idx]; + setActiveChat(idx) { + let chats = this.findChats(); + this.activeChat = chats[idx]; }, - resetUnreadCount(state, chatInfo) { - let chats = this.getters.findChats(); + resetUnreadCount(chatInfo) { + let chats = this.findChats(); for (let idx in chats) { if (chats[idx].type == chatInfo.type && chats[idx].targetId == chatInfo.targetId) { @@ -75,13 +91,13 @@ export default { chats[idx].atMe = false; chats[idx].atAll = false; chats[idx].stored = false; - this.commit("saveToStorage"); + this.saveToStorage(); break; } } }, - readedMessage(state, pos) { - let chat = this.getters.findChatByFriend(pos.friendId); + readedMessage(pos) { + let chat = this.findChatByFriend(pos.friendId); if (!chat) return; chat.messages.forEach((m) => { if (m.id && m.selfSend && m.status < MESSAGE_STATUS.RECALL) { @@ -92,68 +108,69 @@ export default { } } }) - this.commit("saveToStorage"); + this.saveToStorage(); }, - removeChat(state, idx) { - let chats = this.getters.findChats(); - if (chats[idx] == state.activeChat) { - state.activeChat = null; + removeChat(idx) { + let chats = this.findChats(); + if (chats[idx] == this.activeChat) { + this.activeChat = null; } chats[idx].delete = true; chats[idx].stored = false; - this.commit("saveToStorage"); + this.saveToStorage(); }, - removePrivateChat(state, friendId) { - let chats = this.getters.findChats(); + removePrivateChat(friendId) { + let chats = this.findChats(); for (let idx in chats) { if (chats[idx].type == 'PRIVATE' && chats[idx].targetId === friendId) { - this.commit("removeChat", idx) + this.removeChat(idx); break; } } }, - removeGroupChat(state, groupId) { - let chats = this.getters.findChats(); + removeGroupChat(groupId) { + let chats = this.findChats(); for (let idx in chats) { if (chats[idx].type == 'GROUP' && chats[idx].targetId === groupId) { - this.commit("removeChat", idx) + this.removeChat(idx); break; } } }, - moveTop(state, idx) { + moveTop(idx) { // 加载中不移动,很耗性能 - if (this.getters.isLoading()) { + if (this.isLoading()) { return; } if (idx > 0) { - let chats = this.getters.findChats(); + let chats = this.findChats(); let chat = chats[idx]; chats.splice(idx, 1); chats.unshift(chat); chat.lastSendTime = new Date().getTime(); chat.stored = false; - this.commit("saveToStorage"); + this.saveToStorage(); } }, - insertMessage(state, [msgInfo, chatInfo]) { + insertMessage(msgInfo, chatInfo) { + let time = new Date().getTime() let type = chatInfo.type; // 记录消息的最大id - if (msgInfo.id && type == "PRIVATE" && msgInfo.id > state.privateMsgMaxId) { - state.privateMsgMaxId = msgInfo.id; + if (msgInfo.id && type == "PRIVATE" && msgInfo.id > this.privateMsgMaxId) { + this.privateMsgMaxId = msgInfo.id; } - if (msgInfo.id && type == "GROUP" && msgInfo.id > state.groupMsgMaxId) { - state.groupMsgMaxId = msgInfo.id; + if (msgInfo.id && type == "GROUP" && msgInfo.id > this.groupMsgMaxId) { + this.groupMsgMaxId = msgInfo.id; } // 如果是已存在消息,则覆盖旧的消息数据 - let chat = this.getters.findChat(chatInfo); - let message = this.getters.findMessage(chat, msgInfo); + let chat = this.findChat(chatInfo); + let message = this.findMessage(chat, msgInfo); if (message) { Object.assign(message, msgInfo); chat.stored = false; - this.commit("saveToStorage"); + this.saveToStorage(); return; } // 插入新的数据 @@ -182,7 +199,8 @@ export default { // 是否有人@我 if (!msgInfo.selfSend && chat.type == "GROUP" && msgInfo.atUserIds && msgInfo.status != MESSAGE_STATUS.READED) { - let userId = userStore.state.userInfo.id; + let userStore = useUserStore(); + let userId = userStore.userInfo.id; if (msgInfo.atUserIds.indexOf(userId) >= 0) { chat.atMe = true; } @@ -212,21 +230,22 @@ export default { } chat.messages.splice(insertPos, 0, msgInfo); chat.stored = false; - this.commit("saveToStorage"); + this.saveToStorage(); + console.log("耗时:", new Date().getTime() - time) }, - updateMessage(state, [msgInfo, chatInfo]) { + updateMessage(msgInfo, chatInfo) { // 获取对方id或群id - let chat = this.getters.findChat(chatInfo); - let message = this.getters.findMessage(chat, msgInfo); + let chat = this.findChat(chatInfo); + let message = this.findMessage(chat, msgInfo); if (message) { // 属性拷贝 Object.assign(message, msgInfo); chat.stored = false; - this.commit("saveToStorage"); + this.saveToStorage(); } }, - deleteMessage(state, [msgInfo, chatInfo]) { - let chat = this.getters.findChat(chatInfo); + deleteMessage(msgInfo, chatInfo) { + let chat = this.findChat(chatInfo); for (let idx in chat.messages) { // 已经发送成功的,根据id删除 if (chat.messages[idx].id && chat.messages[idx].id == msgInfo.id) { @@ -240,10 +259,10 @@ export default { } } chat.stored = false; - this.commit("saveToStorage"); + this.saveToStorage(); }, - recallMessage(state, [msgInfo, chatInfo]) { - let chat = this.getters.findChat(chatInfo); + recallMessage(msgInfo, chatInfo) { + let chat = this.findChat(chatInfo); if (!chat) return; // 要撤回的消息id let id = msgInfo.content; @@ -271,54 +290,54 @@ export default { } } chat.stored = false; - this.commit("saveToStorage"); + this.saveToStorage(); }, - updateChatFromFriend(state, friend) { - let chat = this.getters.findChatByFriend(friend.id); + updateChatFromFriend(friend) { + let chat = this.findChatByFriend(friend.id); // 更新会话中的群名和头像 if (chat && (chat.headImage != friend.headImage || - chat.showName != friend.nickName)) { + chat.showName != friend.nickName)) { chat.headImage = friend.headImage; chat.showName = friend.nickName; chat.stored = false; - this.commit("saveToStorage") + this.saveToStorage() } }, updateChatFromUser(user) { - let chat = this.getters.findChatByFriend(user.id); + let chat = this.findChatByFriend(user.id); // 更新会话中的昵称和头像 if (chat && (chat.headImage != user.headImageThumb || - chat.showName != user.nickName)) { + chat.showName != user.nickName)) { chat.headImage = user.headImageThumb; chat.showName = user.nickName; chat.stored = false; this.saveToStorage(); } }, - updateChatFromGroup(state, group) { - let chat = this.getters.findChatByGroup(group.id); + updateChatFromGroup(group) { + let chat = this.findChatByGroup(group.id); if (chat && (chat.headImage != group.headImageThumb || - chat.showName != group.showGroupName)) { + chat.showName != group.showGroupName)) { // 更新会话中的群名称和头像 chat.headImage = group.headImageThumb; chat.showName = group.showGroupName; chat.stored = false; - this.commit("saveToStorage") + this.saveToStorage() } }, - loadingPrivateMsg(state, loading) { - state.loadingPrivateMsg = loading; - if (!this.getters.isLoading()) { - this.commit("refreshChats") + setLoadingPrivateMsg(loading) { + this.loadingPrivateMsg = loading; + if (!this.isLoading()) { + this.refreshChats(); } }, - loadingGroupMsg(state, loading) { - state.loadingGroupMsg = loading; - if (!this.getters.isLoading()) { - this.commit("refreshChats") + setLoadingGroupMsg(loading) { + this.loadingGroupMsg = loading; + if (!this.isLoading()) { + this.refreshChats(); } }, - refreshChats(state) { + refreshChats() { if (!cacheChats) { return; } @@ -327,21 +346,22 @@ export default { return chat2.lastSendTime - chat1.lastSendTime; }); // 将消息一次性装载回来 - state.chats = cacheChats; + this.chats = cacheChats; // 清空缓存 cacheChats = null; - this.commit("saveToStorage"); + this.saveToStorage(); }, - saveToStorage(state) { + saveToStorage() { // 加载中不保存,防止卡顿 - if (this.getters.isLoading()) { + if (this.isLoading()) { return; } - let userId = userStore.state.userInfo.id; + let userStore = useUserStore(); + let userId = userStore.userInfo.id; let key = "chats-" + userId; let chatKeys = []; // 按会话为单位存储, - state.chats.forEach((chat) => { + this.chats.forEach((chat) => { // 只存储有改动的会话 let chatKey = `${key}-${chat.type}-${chat.targetId}` if (!chat.stored) { @@ -358,32 +378,27 @@ export default { }) // 会话核心信息 let chatsData = { - privateMsgMaxId: state.privateMsgMaxId, - groupMsgMaxId: state.groupMsgMaxId, + privateMsgMaxId: this.privateMsgMaxId, + groupMsgMaxId: this.groupMsgMaxId, chatKeys: chatKeys } localForage.setItem(key, chatsData) // 清理已删除的会话 - state.chats = state.chats.filter(chat => !chat.delete) + this.chats = this.chats.filter(chat => !chat.delete) }, - clear(state) { + clear() { cacheChats = [] - state.chats = []; - state.activeChat = null; - } - }, - actions: { - loadChat(context) { + this.chats = []; + this.activeChat = null; + }, + loadChat() { return new Promise((resolve, reject) => { - let userId = userStore.state.userInfo.id; + let userStore = useUserStore(); + let userId = userStore.userInfo.id; let key = "chats-" + userId; localForage.getItem(key).then((chatsData) => { if (!chatsData) { resolve(); - } else if (chatsData.chats) { - // 兼容旧版本 - context.commit("initChats", chatsData); - resolve(); } else if (chatsData.chatKeys) { const promises = []; chatsData.chatKeys.forEach(key => { @@ -391,13 +406,13 @@ export default { }) Promise.all(promises).then(chats => { chatsData.chats = chats.filter(o => o); - context.commit("initChats", chatsData); + this.initChats(chatsData); resolve(); }) } - }).catch((e) => { + }).catch(e => { console.log("加载消息失败") - reject(); + reject(e); }) }) } @@ -406,14 +421,14 @@ export default { isLoading: (state) => () => { return state.loadingPrivateMsg || state.loadingGroupMsg }, - findChats: (state, getters) => () => { - if (cacheChats && getters.isLoading()) { + findChats: (state) => () => { + if (cacheChats && state.isLoading()) { return cacheChats; } return state.chats; }, - findChatIdx: (state, getters) => (chat) => { - let chats = getters.findChats(); + findChatIdx: (state) => (chat) => { + let chats = state.findChats(); for (let idx in chats) { if (chats[idx].type == chat.type && chats[idx].targetId === chat.targetId) { @@ -422,18 +437,18 @@ export default { } } }, - findChat: (state, getters) => (chat) => { - let chats = getters.findChats(); - let idx = getters.findChatIdx(chat); + findChat: (state) => (chat) => { + let chats = state.findChats(); + let idx = state.findChatIdx(chat); return chats[idx]; }, - findChatByFriend: (state, getters) => (fid) => { - let chats = getters.findChats(); + findChatByFriend: (state) => (fid) => { + let chats = state.findChats(); return chats.find(chat => chat.type == 'PRIVATE' && chat.targetId == fid) }, - findChatByGroup: (state, getters) => (gid) => { - let chats = getters.findChats(); + findChatByGroup: (state) => (gid) => { + let chats = state.findChats(); return chats.find(chat => chat.type == 'GROUP' && chat.targetId == gid) }, @@ -454,4 +469,4 @@ export default { } } } -} \ No newline at end of file +}); \ No newline at end of file diff --git a/im-web/src/store/configStore.js b/im-web/src/store/configStore.js index baf49a9..cc18be2 100644 --- a/im-web/src/store/configStore.js +++ b/im-web/src/store/configStore.js @@ -1,26 +1,24 @@ +import { defineStore } from 'pinia'; import http from '../api/httpRequest.js' -export default { - state: { - webrtc: {} - }, - mutations: { - setConfig(state, config) { - state.webrtc = config.webrtc; - }, - clear(state) { - state.webrtc = {}; +export default defineStore('configStore', { + state: () => { + return { + webrtc: {} } }, actions: { - loadConfig(context) { + setConfig(config) { + this.webrtc = config.webrtc; + }, + loadConfig() { return new Promise((resolve, reject) => { http({ url: '/system/config', method: 'GET' - }).then((config) => { + }).then(config => { console.log("系统配置", config) - context.commit("setConfig", config); + this.setConfig(config); resolve(); }).catch((res) => { reject(res); @@ -28,5 +26,4 @@ export default { }) } } - -} \ No newline at end of file +}); \ No newline at end of file diff --git a/im-web/src/store/friendStore.js b/im-web/src/store/friendStore.js index 3ba677e..8051571 100644 --- a/im-web/src/store/friendStore.js +++ b/im-web/src/store/friendStore.js @@ -1,101 +1,62 @@ +import { defineStore } from 'pinia'; import http from '../api/httpRequest.js' import { TERMINAL_TYPE } from "../api/enums.js" -export default { - - state: { - friends: [], - timer: null +export default defineStore('friendStore', { + state: () => { + return { + friends: [], // 好友列表 + timer: null + } }, - mutations: { - setFriends(state, friends) { - friends.forEach((f) => { - f.online = false; - f.onlineWeb = false; - f.onlineApp = false; - }) - state.friends = friends; + actions: { + setFriends(friends) { + this.friends = friends; }, - updateFriend(state, friend) { - state.friends.forEach((f, index) => { + updateFriend(friend) { + this.friends.forEach((f, index) => { if (f.id == friend.id) { // 拷贝属性 - let online = state.friends[index].online; - Object.assign(state.friends[index], friend); - state.friends[index].online = online; + let online = this.friends[index].online; + Object.assign(this.friends[index], friend); + this.friends[index].online = online; } }) }, - removeFriend(state, id) { - state.friends.filter(f => f.id == id).forEach(f => f.deleted = true); + removeFriend(id) { + this.friends.filter(f => f.id == id).forEach(f => f.deleted = true); }, - addFriend(state, friend) { - if (state.friends.some((f) => f.id == friend.id)) { - this.commit("updateFriend", friend) + addFriend(friend) { + if (this.friends.some(f => f.id == friend.id)) { + this.updateFriend(friend) } else { - state.friends.unshift(friend); + this.friends.unshift(friend); } }, - refreshOnlineStatus(state) { - let userIds = state.friends.filter((f) => !f.deleted).map((f) => f.id); - if (userIds.length == 0) { - return; + updateOnlineStatus(onlineData) { + let friend = this.findFriend(onlineData.userId); + if (onlineData.terminal == TERMINAL_TYPE.WEB) { + friend.onlineWeb = onlineData.online; + } else if (onlineData.terminal == TERMINAL_TYPE.APP) { + friend.onlineApp = onlineData.online; } - http({ - url: '/user/terminal/online', - method: 'get', - params: { userIds: userIds.join(',') } - }).then((onlineTerminals) => { - this.commit("setOnlineStatus", onlineTerminals); - }) - // 30s后重新拉取 - state.timer && clearTimeout(state.timer); - state.timer = setTimeout(() => { - this.commit("refreshOnlineStatus"); - }, 30000) + friend.online = friend.onlineWeb || friend.onlineApp; }, - setOnlineStatus(state, onlineTerminals) { - state.friends.forEach((f) => { - let userTerminal = onlineTerminals.find((o) => f.id == o.userId); - if (userTerminal) { - f.online = true; - f.onlineWeb = userTerminal.terminals.indexOf(TERMINAL_TYPE.WEB) >= 0 - f.onlineApp = userTerminal.terminals.indexOf(TERMINAL_TYPE.APP) >= 0 - } else { - f.online = false; - f.onlineWeb = false; - f.onlineApp = false; - } - }); - // 在线的在前面 - state.friends.sort((f1, f2) => { - if (f1.online && !f2.online) { - return -1; - } - if (f2.online && !f1.online) { - return 1; - } - return 0; - }); + clear() { + this.timer && clearTimeout(this.timer); + this.friends = []; + this.timer = null; }, - clear(state) { - state.timer && clearTimeout(state.timer); - state.friends = []; - state.timer = null; - } - }, - actions: { - loadFriend(context) { + loadFriend() { return new Promise((resolve, reject) => { http({ url: '/friend/list', method: 'GET' - }).then((friends) => { - context.commit("setFriends", friends); - context.commit("refreshOnlineStatus"); - resolve() - }).catch(() => { - reject(); + }).then(async (friends) => { + this.setFriends(friends); + resolve(); + }).catch(e => { + reject(e); }) }); } @@ -108,4 +69,4 @@ export default { return state.friends.find((f) => f.id == userId); } } -} +}); \ No newline at end of file diff --git a/im-web/src/store/groupStore.js b/im-web/src/store/groupStore.js index f261e47..c493fea 100644 --- a/im-web/src/store/groupStore.js +++ b/im-web/src/store/groupStore.js @@ -1,53 +1,63 @@ +import { defineStore } from 'pinia'; import http from '../api/httpRequest.js' -export default { - state: { - groups: [] +export default defineStore('groupStore', { + state: () => { + return { + groups: [] + } }, - mutations: { - setGroups(state, groups) { - state.groups = groups; + actions: { + setGroups(groups) { + this.groups = groups; }, - addGroup(state, group) { - if (state.groups.some((g) => g.id == group.id)) { - this.commit("updateGroup", group) + addGroup(group) { + if (this.groups.some(g => g.id == group.id)) { + this.updateGroup(group) } else { - state.groups.unshift(group); + this.groups.unshift(group); } }, - removeGroup(state, id) { - state.groups.filter(g => g.id == id).forEach(g => g.quit = true); + removeGroup(id) { + this.groups.filter(g => g.id == id).forEach(g => g.quit = true); }, - updateGroup(state, group) { - state.groups.forEach((g, idx) => { + updateGroup(group) { + this.groups.forEach((g, idx) => { if (g.id == group.id) { // 拷贝属性 - Object.assign(state.groups[idx], group); + Object.assign(this.groups[idx], group); } }) }, - clear(state) { - state.groups = []; - } - }, - actions: { - loadGroup(context) { + updateTopMessage(id, topMessage) { + let group = this.findGroup(id); + if (group) { + group.topMessage = topMessage; + } + }, + clear() { + this.groups = []; + }, + loadGroup() { return new Promise((resolve, reject) => { http({ url: '/group/list', method: 'GET' - }).then((groups) => { - context.commit("setGroups", groups); + }).then(groups => { + this.setGroups(groups); resolve(); - }).catch((res) => { - reject(res); + }).catch(e => { + reject(e); }) }); } }, getters: { findGroup: (state) => (id) => { - return state.groups.find((g) => g.id == id); - } + return state.groups.find(g => g.id == id); + }, + isGroup: (state) => (id) => { + return state.groups.filter(g => !g.quit).some(g => g.id == id); + }, } -} \ No newline at end of file +}); \ No newline at end of file diff --git a/im-web/src/store/uiStore.js b/im-web/src/store/uiStore.js index a29a029..8d7e074 100644 --- a/im-web/src/store/uiStore.js +++ b/im-web/src/store/uiStore.js @@ -1,19 +1,22 @@ -export default { - state: { - userInfo: { // 用户信息窗口 - show: false, - user: {}, - pos: { - x: 0, - y: 0 +import { defineStore } from 'pinia'; +export default defineStore('groupStore', { + state: () => { + return { + userInfo: { // 用户信息窗口 + show: false, + user: {}, + pos: { + x: 0, + y: 0 + } + }, + fullImage: { // 全屏大图 + show: false, + url: "" } - }, - fullImage: { // 全屏大图 - show: false, - url: "" } }, - mutations: { + actions: { showUserInfoBox(state, user) { state.userInfo.show = true; state.userInfo.user = user; @@ -36,4 +39,4 @@ export default { state.fullImage.show = false; } } -} \ No newline at end of file +}) \ No newline at end of file diff --git a/im-web/src/store/userStore.js b/im-web/src/store/userStore.js index 494db35..45a5452 100644 --- a/im-web/src/store/userStore.js +++ b/im-web/src/store/userStore.js @@ -1,45 +1,43 @@ +import { defineStore } from 'pinia'; import http from '../api/httpRequest.js' import { RTC_STATE } from "../api/enums.js" -export default { - state: { - userInfo: { - - }, - rtcInfo: { - friend: {}, // 好友信息 - mode: "video", // 模式 video:视频 voice:语音 - state: RTC_STATE.FREE // FREE:空闲 WAIT_CALL:呼叫方等待 WAIT_ACCEPT: 被呼叫方等待接听 CHATING:聊天中 +export default defineStore('userStore', { + state: () => { + return { + userInfo: {}, + rtcInfo: { + friend: {}, // 好友信息 + mode: "video", // 模式 video:视频 voice:语音 + state: RTC_STATE.FREE // FREE:空闲 WAIT_CALL:呼叫方等待 WAIT_ACCEPT: 被呼叫方等待接听 CHATING:聊天中 + } } }, - - mutations: { - setUserInfo(state, userInfo) { - state.userInfo = userInfo + actions: { + setUserInfo(userInfo) { + this.userInfo = userInfo }, - setRtcInfo(state, rtcInfo) { - state.rtcInfo = rtcInfo; + setRtcInfo(rtcInfo) { + this.rtcInfo = rtcInfo; }, - setRtcState(state, rtcState) { - state.rtcInfo.state = rtcState; + setRtcState(rtcState) { + this.rtcInfo.state = rtcState; }, - clear(state) { - state.userInfo = {}; - state.rtcInfo = { + clear() { + this.userInfo = {}; + this.rtcInfo = { friend: {}, mode: "video", state: RTC_STATE.FREE }; - } - }, - actions: { - loadUser(context) { + }, + loadUser() { return new Promise((resolve, reject) => { http({ url: '/user/self', method: 'GET' }).then((userInfo) => { - context.commit("setUserInfo", userInfo); + this.setUserInfo(userInfo); resolve(); }).catch((res) => { reject(res); @@ -47,4 +45,4 @@ export default { }) } } -} \ No newline at end of file +}); \ No newline at end of file diff --git a/im-web/src/view/Chat.vue b/im-web/src/view/Chat.vue index 5234da2..f45f706 100644 --- a/im-web/src/view/Chat.vue +++ b/im-web/src/view/Chat.vue @@ -43,19 +43,16 @@ export default { }, methods: { onActiveItem(index) { - this.$store.commit("activeChat", index); + this.chatStore.setActiveChat(index); }, onDelItem(index) { - this.$store.commit("removeChat", index); + this.chatStore.removeChat(index); }, onTop(chatIdx) { - this.$store.commit("moveTop", chatIdx); + this.chatStore.moveTop(chatIdx); }, }, computed: { - chatStore() { - return this.$store.state.chatStore; - }, loading() { return this.chatStore.loadingGroupMsg || this.chatStore.loadingPrivateMsg } diff --git a/im-web/src/view/Friend.vue b/im-web/src/view/Friend.vue index 271259a..ca70564 100644 --- a/im-web/src/view/Friend.vue +++ b/im-web/src/view/Friend.vue @@ -101,8 +101,8 @@ export default { method: 'delete' }).then(() => { this.$message.success("删除好友成功"); - this.$store.commit("removeFriend", friend.id); - this.$store.commit("removePrivateChat", friend.id); + this.friendStore.removeFriend(friend.id); + this.chatStore.removePrivateChat(friend.id); }) }) }, @@ -121,7 +121,7 @@ export default { headImage: user.headImage, online: user.online } - this.$store.commit("addFriend", friend); + this.friendStore.addFriend(friend); }) }, onSendMessage(user) { @@ -131,8 +131,8 @@ export default { showName: user.nickName, headImage: user.headImageThumb, }; - this.$store.commit("openChat", chat); - this.$store.commit("activeChat", 0); + this.chatStore.openChat(chat); + this.chatStore.setActiveChat(0); this.$router.push("/home/chat"); }, showFullImage() { @@ -146,8 +146,8 @@ export default { let friend = JSON.parse(JSON.stringify(this.activeFriend)); friend.headImage = this.userInfo.headImageThumb; friend.nickName = this.userInfo.nickName; - this.$store.commit("updateChatFromFriend", friend); - this.$store.commit("updateFriend", friend); + this.chatStore.updateChatFromFriend(friend); + this.friendStore.updateFriend(friend); } }, loadUserInfo(id) { @@ -174,11 +174,8 @@ export default { } }, computed: { - friendStore() { - return this.$store.state.friendStore; - }, isFriend() { - return this.$store.getters.isFriend(this.userInfo.id); + return this.friendStore.isFriend(this.userInfo.id); }, friendMap() { // 按首字母分组 diff --git a/im-web/src/view/Group.vue b/im-web/src/view/Group.vue index 91d245e..d206332 100644 --- a/im-web/src/view/Group.vue +++ b/im-web/src/view/Group.vue @@ -50,7 +50,7 @@ + :placeholder="userStore.userInfo.nickName"> { - let userInfo = this.$store.state.userStore.userInfo; + }).then(o => { let data = { name: o.value } @@ -147,7 +146,9 @@ export default { method: 'post', data: data }).then((group) => { - this.$store.commit("addGroup", group); + this.groupStore.addGroup(group); + this.onActiveItem(group) + this.$message.success('创建成功'); }) }) }, @@ -195,7 +196,7 @@ export default { method: "put", data: vo }).then((group) => { - this.$store.commit("updateGroup", group); + this.groupStore.updateGroup(group); this.$message.success("修改成功"); }) } @@ -212,7 +213,7 @@ export default { method: 'delete' }).then(() => { this.$message.success(`群聊'${this.activeGroup.name}'已解散`); - this.$store.commit("removeGroup", this.activeGroup.id); + this.groupStore.removeGroup(this.activeGroup.id); this.reset(); }); }) @@ -228,8 +229,8 @@ export default { method: 'delete' }).then(() => { this.$message.success(`您已退出'${this.activeGroup.name}'`); - this.$store.commit("removeGroup", this.activeGroup.id); - this.$store.commit("removeGroupChat", this.activeGroup.id); + this.groupStore.removeGroup(this.activeGroup.id); + this.chatStore.removeGroupChat(this.activeGroup.id); this.reset(); }); }) @@ -241,8 +242,8 @@ export default { showName: this.activeGroup.showGroupName, headImage: this.activeGroup.headImage, }; - this.$store.commit("openChat", chat); - this.$store.commit("activeChat", 0); + this.chatStore.openChat(chat); + this.chatStore.setActiveChat(0); this.$router.push("/home/chat"); }, onScroll(e) { @@ -280,15 +281,12 @@ export default { } }, computed: { - groupStore() { - return this.$store.state.groupStore; - }, ownerName() { - let member = this.groupMembers.find((m) => m.userId == this.activeGroup.ownerId); + let member = this.groupMembers.find(m => m.userId == this.activeGroup.ownerId); return member && member.showNickName; }, isOwner() { - return this.activeGroup.ownerId == this.$store.state.userStore.userInfo.id; + return this.activeGroup.ownerId == this.userStore.userInfo.id; }, imageAction() { return `/image/upload`; diff --git a/im-web/src/view/Home.vue b/im-web/src/view/Home.vue index 845865c..f08dc3f 100644 --- a/im-web/src/view/Home.vue +++ b/im-web/src/view/Home.vue @@ -1,16 +1,14 @@