用户名:{{ 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 @@
-
+
-
+
-
@@ -66,6 +64,7 @@ import FullImage from '../components/common/FullImage.vue';
import RtcPrivateVideo from '../components/rtc/RtcPrivateVideo.vue';
import RtcPrivateAcceptor from '../components/rtc/RtcPrivateAcceptor.vue';
import RtcGroupVideo from '../components/rtc/RtcGroupVideo.vue';
+import uiStore from '../store/uiStore';
export default {
components: {
@@ -96,7 +95,7 @@ export default {
this.$refs.rtcGroupVideo.open(rctInfo);
});
- this.$store.dispatch("load").then(() => {
+ this.loadStore().then(() => {
// ws初始化
this.$wsApi.connect(process.env.VUE_APP_WS_URL, sessionStorage.getItem("accessToken"));
this.$wsApi.onConnect(() => {
@@ -104,8 +103,8 @@ export default {
this.onReconnectWs();
} else {
// 加载离线消息
- this.pullPrivateOfflineMessage(this.$store.state.chatStore.privateMsgMaxId);
- this.pullGroupOfflineMessage(this.$store.state.chatStore.groupMsgMaxId);
+ this.pullPrivateOfflineMessage(this.chatStore.privateMsgMaxId);
+ this.pullGroupOfflineMessage(this.chatStore.groupMsgMaxId);
}
});
this.$wsApi.onMessage((cmd, msgInfo) => {
@@ -145,7 +144,7 @@ export default {
// 记录标志
this.reconnecting = true;
// 重新加载一次个人信息,目的是为了保证网络已经正常且token有效
- this.$store.dispatch("loadUser").then(() => {
+ this.userStore.loadUser().then(() => {
// 断线重连
this.$message.error("连接断开,正在尝试重新连接...");
this.$wsApi.reconnect(process.env.VUE_APP_WS_URL, sessionStorage.getItem(
@@ -160,39 +159,55 @@ export default {
this.reconnecting = false;
// 重新加载群和好友
const promises = [];
- promises.push(this.$store.dispatch("loadFriend"));
- promises.push(this.$store.dispatch("loadGroup"));
+ promises.push(this.friendStore.loadFriend());
+ promises.push(this.groupStore.loadGroup());
Promise.all(promises).then(() => {
// 加载离线消息
- this.pullPrivateOfflineMessage(this.$store.state.chatStore.privateMsgMaxId);
- this.pullGroupOfflineMessage(this.$store.state.chatStore.groupMsgMaxId);
+ this.pullPrivateOfflineMessage(this.chatStore.privateMsgMaxId);
+ this.pullGroupOfflineMessage(this.chatStore.groupMsgMaxId);
this.$message.success("重新连接成功");
}).catch(() => {
this.$message.error("初始化失败");
this.onExit();
})
},
+ loadStore() {
+ return this.userStore.loadUser().then(() => {
+ const promises = [];
+ promises.push(this.friendStore.loadFriend());
+ promises.push(this.groupStore.loadGroup());
+ promises.push(this.chatStore.loadChat());
+ promises.push(this.configStore.loadConfig());
+ return Promise.all(promises);
+ })
+ },
+ unloadStore() {
+ this.friendStore.clear();
+ this.groupStore.clear();
+ this.chatStore.clear();
+ this.userStore.clear();
+ },
pullPrivateOfflineMessage(minId) {
- this.$store.commit("loadingPrivateMsg", true)
+ this.chatStore.setLoadingPrivateMsg(true)
this.$http({
url: "/message/private/pullOfflineMessage?minId=" + minId,
method: 'GET'
}).catch(() => {
- this.$store.commit("loadingPrivateMsg", false)
+ this.chatStore.setLoadingPrivateMsg(false)
})
},
pullGroupOfflineMessage(minId) {
- this.$store.commit("loadingGroupMsg", true)
+ this.chatStore.setLoadingGroupMsg(true)
this.$http({
url: "/message/group/pullOfflineMessage?minId=" + minId,
method: 'GET'
}).catch(() => {
- this.$store.commit("loadingGroupMsg", false)
+ this.chatStore.setLoadingGroupMsg(false)
})
},
handlePrivateMessage(msg) {
// 标记这条消息是不是自己发的
- msg.selfSend = msg.sendId == this.$store.state.userStore.userInfo.id;
+ msg.selfSend = msg.sendId == this.userStore.userInfo.id;
// 好友id
let friendId = msg.selfSend ? msg.recvId : msg.sendId;
// 会话信息
@@ -202,34 +217,34 @@ export default {
}
// 消息加载标志
if (msg.type == this.$enums.MESSAGE_TYPE.LOADING) {
- this.$store.commit("loadingPrivateMsg", JSON.parse(msg.content))
+ this.chatStore.setLoadingPrivateMsg(JSON.parse(msg.content))
return;
}
// 消息已读处理,清空已读数量
if (msg.type == this.$enums.MESSAGE_TYPE.READED) {
- this.$store.commit("resetUnreadCount", chatInfo)
+ this.chatStore.resetUnreadCount(chatInfo)
return;
}
// 消息回执处理,改消息状态为已读
if (msg.type == this.$enums.MESSAGE_TYPE.RECEIPT) {
- this.$store.commit("readedMessage", {
+ this.chatStore.readedMessage({
friendId: msg.sendId
})
return;
}
// 消息撤回
if (msg.type == this.$enums.MESSAGE_TYPE.RECALL) {
- this.$store.commit("recallMessage", [msg, chatInfo])
+ this.chatStore.recallMessage(msg, chatInfo)
return;
}
// 新增好友
if (msg.type == this.$enums.MESSAGE_TYPE.FRIEND_NEW) {
- this.$store.commit("addFriend", JSON.parse(msg.content));
+ this.friendStore.addFriend(JSON.parse(msg.content));
return;
}
// 删除好友
if (msg.type == this.$enums.MESSAGE_TYPE.FRIEND_DEL) {
- this.$store.commit("removeFriend", friendId);
+ this.friendStore.removeFriend(friendId);
return;
}
// 单人webrtc 信令
@@ -251,9 +266,9 @@ export default {
headImage: friend.headImage
};
// 打开会话
- this.$store.commit("openChat", chatInfo);
+ this.chatStore.openChat(chatInfo);
// 插入消息
- this.$store.commit("insertMessage", [msg, chatInfo]);
+ this.chatStore.insertMessage(msg, chatInfo);
// 播放提示音
if (!msg.selfSend && this.$msgType.isNormal(msg.type) &&
msg.status != this.$enums.MESSAGE_STATUS.READED) {
@@ -262,20 +277,20 @@ export default {
},
handleGroupMessage(msg) {
// 标记这条消息是不是自己发的
- msg.selfSend = msg.sendId == this.$store.state.userStore.userInfo.id;
+ msg.selfSend = msg.sendId == this.userStore.userInfo.id;
let chatInfo = {
type: 'GROUP',
targetId: msg.groupId
}
// 消息加载标志
if (msg.type == this.$enums.MESSAGE_TYPE.LOADING) {
- this.$store.commit("loadingGroupMsg", JSON.parse(msg.content))
+ this.chatStore.setLoadingGroupMsg(JSON.parse(msg.content))
return;
}
// 消息已读处理
if (msg.type == this.$enums.MESSAGE_TYPE.READED) {
// 我已读对方的消息,清空已读数量
- this.$store.commit("resetUnreadCount", chatInfo)
+ this.chatStore.resetUnreadCount(chatInfo)
return;
}
// 消息回执处理
@@ -287,22 +302,22 @@ export default {
readedCount: msg.readedCount,
receiptOk: msg.receiptOk
};
- this.$store.commit("updateMessage", [msgInfo, chatInfo])
+ this.chatStore.updateMessage(msgInfo, chatInfo)
return;
}
// 消息撤回
if (msg.type == this.$enums.MESSAGE_TYPE.RECALL) {
- this.$store.commit("recallMessage", [msg, chatInfo])
+ this.chatStore.recallMessage(msg, chatInfo)
return;
}
// 新增群
if (msg.type == this.$enums.MESSAGE_TYPE.GROUP_NEW) {
- this.$store.commit("addGroup", JSON.parse(msg.content));
+ this.chatStore.addGroup(JSON.parse(msg.content));
return;
}
// 删除群
if (msg.type == this.$enums.MESSAGE_TYPE.GROUP_DEL) {
- this.$store.commit("removeGroup", msg.groupId);
+ this.groupStore.removeGroup(msg.groupId);
return;
}
// 群视频信令
@@ -326,9 +341,9 @@ export default {
headImage: group.headImageThumb
};
// 打开会话
- this.$store.commit("openChat", chatInfo);
+ this.chatStore.openChat(chatInfo);
// 插入消息
- this.$store.commit("insertMessage", [msg, chatInfo]);
+ this.chatStore.insertMessage(msg, chatInfo);
// 播放提示音
if (!msg.selfSend && msg.type <= this.$enums.MESSAGE_TYPE.VIDEO &&
msg.status != this.$enums.MESSAGE_STATUS.READED) {
@@ -341,7 +356,7 @@ export default {
this.$wsApi.close(3000);
this.$alert("您的账号已被管理员封禁,原因:" + msg.content, "账号被封禁", {
confirmButtonText: '确定',
- callback: action => {
+ callback: () => {
this.onExit();
}
});
@@ -349,13 +364,14 @@ export default {
}
},
onExit() {
+ this.unloadStore();
this.$wsApi.close(3000);
sessionStorage.removeItem("accessToken");
location.href = "/";
},
playAudioTip() {
// 离线消息不播放铃声
- if (this.$store.getters.isLoading()) {
+ if (this.chatStore.isLoading()) {
return;
}
// 防止过于密集播放
@@ -375,7 +391,7 @@ export default {
this.showSettingDialog = false;
},
loadFriendInfo(id) {
- let friend = this.$store.getters.findFriend(id);
+ let friend = this.friendStore.findFriend(id);
if (!friend) {
friend = {
id: id,
@@ -386,7 +402,7 @@ export default {
return friend;
},
loadGroupInfo(id) {
- let group = this.$store.getters.findGroup(id);
+ let group = this.groupStore.findGroup(id);
if (!group) {
group = {
id: id,
@@ -398,12 +414,9 @@ export default {
}
},
computed: {
- uiStore() {
- return this.$store.state.uiStore;
- },
unreadCount() {
let unreadCount = 0;
- let chats = this.$store.state.chatStore.chats;
+ let chats = this.chatStore.chats;
chats.forEach((chat) => {
if (!chat.delete) {
unreadCount += chat.unreadCount