Browse Source

优化消息列表排序

master
xie.bx 2 years ago
parent
commit
5009eebf4b
  1. 4
      im-ui/src/App.vue
  2. 2
      im-ui/src/components/chat/ChatPrivateVideo.vue
  3. 3
      im-ui/src/components/common/RightMenu.vue
  4. 43
      im-ui/src/components/group/AddGroupMember.vue
  5. 68
      im-ui/src/store/chatStore.js
  6. 27
      im-ui/src/store/friendStore.js
  7. 19
      im-ui/src/store/groupStore.js
  8. 19
      im-ui/src/view/Chat.vue
  9. 23
      im-ui/src/view/Friend.vue
  10. 11
      im-ui/src/view/Group.vue
  11. 1
      im-ui/src/view/Register.vue

4
im-ui/src/App.vue

@ -26,4 +26,8 @@ export default {
height: 100%;
width: 100%;
}
.el-message {
z-index: 99999999 !important;
}
</style>

2
im-ui/src/components/chat/ChatPrivateVideo.vue

@ -67,7 +67,7 @@
methods: {
init() {
if (!this.hasUserMedia() || !this.hasRTCPeerConnection()) {
this.$message.error("您的浏览器不支持WebRTC");
this.$message.error("初始化失败,原因可能是: 1.未部署ssl证书 2.您的浏览器不支持WebRTC");
if (!this.master) {
this.sendFailed("对方浏览器不支持WebRTC")
}

3
im-ui/src/components/common/RightMenu.vue

@ -3,7 +3,7 @@
<div class="right-menu" :style="{'left':pos.x+'px','top':pos.y+'px'}">
<el-menu text-color="#333333">
<el-menu-item v-for="(item) in items" :key="item.key" :title="item.name"
@click="onSelectMenu(item)">
@click.native.stop="onSelectMenu(item)">
<span :class="item.icon"></span>
<span>{{item.name}}</span>
@ -33,6 +33,7 @@
},
onSelectMenu(item) {
this.$emit("select", item);
this.close();
}
}
}

43
im-ui/src/components/group/AddGroupMember.vue

@ -1,27 +1,29 @@
<template>
<el-dialog title="邀请好友" :visible.sync="visible" width="50%" :before-close="onClose">
<el-dialog title="邀请好友" :visible.sync="visible" width="50%" :before-close="onClose">
<div class="agm-container">
<div class="agm-l-box">
<el-input width="200px" placeholder="搜索好友" class="input-with-select" v-model="searchText" @keyup.enter.native="onSearch()">
<el-input width="200px" placeholder="搜索好友" class="input-with-select" v-model="searchText"
@keyup.enter.native="onSearch()">
<el-button slot="append" icon="el-icon-search" @click="onSearch()"></el-button>
</el-input>
<el-scrollbar style="height:400px;">
<div v-for="(friend,index) in friends" :key="friend.id">
<friend-item v-show="friend.nickName.startsWith(searchText)" :showDelete="false" @click.native="onSwitchCheck(friend)"
:menu="false" :friend="friend" :index="index" :active="index === activeIndex">
<el-checkbox :disabled="friend.disabled" @click.native.stop="" class="agm-friend-checkbox" v-model="friend.isCheck"
size="medium"></el-checkbox>
<friend-item v-show="friend.nickName.startsWith(searchText)" :showDelete="false"
@click.native="onSwitchCheck(friend)" :menu="false" :friend="friend" :index="index"
:active="false">
<el-checkbox :disabled="friend.disabled" @click.native.stop="" class="agm-friend-checkbox"
v-model="friend.isCheck" size="medium"></el-checkbox>
</friend-item>
</div>
</el-scrollbar>
</div>
<div class="agm-arrow el-icon-d-arrow-right"></div>
<div class="agm-r-box">
<div class="agm-select-tip"> 已勾选{{checkCount}}位好友</div>
<el-scrollbar style="height:400px;">
<div v-for="(friend,index) in friends" :key="friend.id">
<friend-item v-if="friend.isCheck && !friend.disabled" :friend="friend"
:index="index" :active="false" @del="onRemoveFriend(friend,index)"
:menu="false">
<friend-item v-if="friend.isCheck && !friend.disabled" :friend="friend" :index="index"
:active="false" @del="onRemoveFriend(friend,index)" :menu="false">
</friend-item>
</div>
</el-scrollbar>
@ -45,7 +47,6 @@
data() {
return {
searchText: "",
activeIndex: -1,
friends: []
}
},
@ -130,11 +131,11 @@
<style lang="scss">
.agm-container {
display: flex;
.agm-l-box {
flex: 1;
border: #dddddd solid 1px;
border: #53a0e79c solid 1px;
border-radius: 5px;
overflow: hidden;
.el-checkbox {
display: flex;
align-items: center;
@ -164,14 +165,22 @@
.agm-friend-checkbox {
margin-right: 20px;
}
}
.agm-arrow {
display: flex;
align-items: center;
font-size: 20px;
padding: 5px;
font-weight: 600;
color: #53a0e7cc;
}
.agm-r-box {
flex: 1;
border: #dddddd solid 1px;
border: #53a0e79c solid 1px;
border-radius: 5px;
.agm-select-tip {
text-align: left;
@ -181,4 +190,4 @@
}
}
}
</style>
</style>

68
im-ui/src/store/chatStore.js

@ -6,7 +6,7 @@ import userStore from './userStore';
export default {
state: {
activeIndex: -1,
activeChat: null,
privateMsgMaxId: 0,
groupMsgMaxId: 0,
loadingPrivateMsg: false,
@ -30,14 +30,12 @@ export default {
},
openChat(state, chatInfo) {
let chat = null;
let activeChat = state.activeIndex >= 0 ? state.chats[state.activeIndex] : null;
for (let i in state.chats) {
if (state.chats[i].type == chatInfo.type &&
state.chats[i].targetId === chatInfo.targetId) {
chat = state.chats[i];
for (let idx in state.chats) {
if (state.chats[idx].type == chatInfo.type &&
state.chats[idx].targetId === chatInfo.targetId) {
chat = state.chats[idx];
// 放置头部
state.chats.splice(i, 1);
state.chats.unshift(chat);
this.commit("moveTop", idx)
break;
}
}
@ -55,18 +53,9 @@ export default {
};
state.chats.unshift(chat);
}
// 选中会话保持不变
if (activeChat) {
state.chats.forEach((chat, idx) => {
if (activeChat.type == chat.type &&
activeChat.targetId == chat.targetId) {
state.activeIndex = idx;
}
})
}
},
activeChat(state, idx) {
state.activeIndex = idx;
state.activeChat = state.chats[idx];
},
resetUnreadCount(state, chatInfo) {
for (let idx in state.chats) {
@ -74,7 +63,7 @@ export default {
state.chats[idx].targetId == chatInfo.targetId) {
state.chats[idx].unreadCount = 0;
state.chats[idx].atMe = false;
state.chats[idx].atAll = false;
state.chats[idx].atAll = false;
}
}
this.commit("saveToStorage");
@ -93,18 +82,23 @@ export default {
this.commit("saveToStorage");
},
removeChat(state, idx) {
state.chats.splice(idx, 1);
if (state.activeIndex >= state.chats.length) {
state.activeIndex = state.chats.length - 1;
if (state.chats[idx] == state.activeChat) {
state.activeChat = null;
}
state.chats.splice(idx, 1);
this.commit("saveToStorage");
},
moveTop(state, idx) {
let chat = state.chats[idx];
// 放置头部
state.chats.splice(idx, 1);
state.chats.unshift(chat);
this.commit("saveToStorage");
// 加载中不移动,很耗性能
if(state.loadingPrivateMsg || state.loadingGroupMsg){
return ;
}
if (idx > 0) {
let chat = state.chats[idx];
state.chats.splice(idx, 1);
state.chats.unshift(chat);
this.commit("saveToStorage");
}
},
removeGroupChat(state, groupId) {
for (let idx in state.chats) {
@ -131,6 +125,7 @@ export default {
if (state.chats[idx].type == type &&
state.chats[idx].targetId === targetId) {
chat = state.chats[idx];
this.commit("moveTop", idx)
break;
}
}
@ -151,13 +146,13 @@ export default {
chat.unreadCount++;
}
// 是否有人@我
if(!msgInfo.selfSend && chat.type=="GROUP" && msgInfo.atUserIds
&& msgInfo.status != MESSAGE_STATUS.READED){
if (!msgInfo.selfSend && chat.type == "GROUP" && msgInfo.atUserIds &&
msgInfo.status != MESSAGE_STATUS.READED) {
let userId = userStore.state.userInfo.id;
if(msgInfo.atUserIds.indexOf(userId)>=0){
if (msgInfo.atUserIds.indexOf(userId) >= 0) {
chat.atMe = true;
}
if(msgInfo.atUserIds.indexOf(-1)>=0){
if (msgInfo.atUserIds.indexOf(-1) >= 0) {
chat.atAll = true;
}
}
@ -248,9 +243,18 @@ export default {
loadingPrivateMsg(state, loadding) {
state.loadingPrivateMsg = loadding;
if(!state.loadingPrivateMsg && !state.loadingGroupMsg){
this.commit("sort")
}
},
loadingGroupMsg(state, loadding) {
state.loadingGroupMsg = loadding;
if(!state.loadingPrivateMsg && !state.loadingGroupMsg){
this.commit("sort")
}
},
sort(state){
state.chats.sort((c1,c2)=>c2.lastSendTime-c1.lastSendTime);
},
saveToStorage(state) {
let userId = userStore.state.userInfo.id;
@ -263,7 +267,7 @@ export default {
localStorage.setItem(key, JSON.stringify(chatsData));
},
clear(state) {
state.activeIndex = -1;
state.activeChat = null;
state.chats = [];
}
},

27
im-ui/src/store/friendStore.js

@ -5,7 +5,7 @@ export default {
state: {
friends: [],
activeIndex: -1,
activeFriend: null,
timer: null
},
mutations: {
@ -22,12 +22,14 @@ export default {
}
})
},
activeFriend(state, index) {
state.activeIndex = index;
activeFriend(state, idx) {
state.activeFriend = state.friends[idx];
},
removeFriend(state, index) {
state.friends.splice(index, 1);
state.activeIndex = -1;
removeFriend(state, idx) {
if (state.friends[idx] == state.activeFriend) {
state.activeFriend = null;
}
state.friends.splice(idx, 1);
},
addFriend(state, friend) {
state.friends.push(friend);
@ -67,7 +69,7 @@ export default {
f.onlineApp = false;
}
});
let activeFriend = state.friends[state.activeIndex];
// 在线的在前面
state.friends.sort((f1,f2)=>{
if(f1.online&&!f2.online){
return -1;
@ -77,21 +79,12 @@ export default {
}
return 0;
});
// 重新排序后,activeIndex指向的好友可能会变化,需要重新指定
if(state.activeIndex >=0){
state.friends.forEach((f,i)=>{
if(f.id == activeFriend.id){
state.activeIndex = i;
}
})
}
},
clear(state) {
clearTimeout(state.timer);
state.friends = [];
state.timer = null;
state.activeIndex = -1;
state.activeFriend = [];
}
},
actions: {

19
im-ui/src/store/groupStore.js

@ -4,26 +4,27 @@ export default {
state: {
groups: [],
activeIndex: -1,
activeGroup: null,
},
mutations: {
setGroups(state, groups) {
state.groups = groups;
},
activeGroup(state, index) {
state.activeIndex = index;
activeGroup(state, idx) {
state.activeGroup = state.groups[idx];
},
addGroup(state, group) {
state.groups.unshift(group);
},
removeGroup(state, groupId) {
state.groups.forEach((g, index) => {
state.groups.forEach((g, idx) => {
if (g.id == groupId) {
state.groups.splice(index, 1);
state.activeIndex = -1;
state.groups.splice(idx, 1);
}
})
if (state.activeGroup.id == groupId) {
state.activeGroup = null;
}
},
updateGroup(state, group) {
state.groups.forEach((g, idx) => {
@ -33,9 +34,9 @@ export default {
}
})
},
clear(state){
clear(state) {
state.groups = [];
state.activeGroup = -1;
state.activeGroup = null;
}
},
actions: {

19
im-ui/src/view/Chat.vue

@ -14,12 +14,12 @@
<div v-for="(chat,index) in chatStore.chats" :key="index">
<chat-item v-show="chat.showName.startsWith(searchText)" :chat="chat" :index="index"
@click.native="onActiveItem(index)" @delete="onDelItem(index)" @top="onTop(index)"
:active="index === chatStore.activeIndex"></chat-item>
:active="chat === chatStore.activeChat"></chat-item>
</div>
</el-scrollbar>
</el-aside>
<el-container class="chat-box">
<chat-box v-show="activeChat.targetId>0" :chat="activeChat"></chat-box>
<chat-box v-if="chatStore.activeChat" :chat="chatStore.activeChat"></chat-box>
</el-container>
</el-container>
</template>
@ -57,21 +57,6 @@
chatStore() {
return this.$store.state.chatStore;
},
activeChat() {
let index = this.chatStore.activeIndex;
let chats = this.chatStore.chats
if (index >= 0 && chats.length > 0) {
return chats[index];
}
//
let emptyChat = {
targetId: -1,
showName: "",
headImage: "",
messages: []
}
return emptyChat;
},
loading(){
return this.chatStore.loadingGroupMsg || this.chatStore.loadingPrivateMsg
}

23
im-ui/src/view/Friend.vue

@ -15,7 +15,7 @@
<el-scrollbar class="friend-list-items">
<div v-for="(friend,index) in $store.state.friendStore.friends" :key="index">
<friend-item v-show="friend.nickName.startsWith(searchText)" :index="index"
:active="index === $store.state.friendStore.activeIndex" @chat="onSendMessage(friend)"
:active="friend === $store.state.friendStore.activeFriend" @chat="onSendMessage(friend)"
@delete="onDelItem(friend,index)" @click.native="onActiveItem(friend,index)">
</friend-item>
</div>
@ -46,7 +46,7 @@
<div class="frient-btn-group">
<el-button v-show="isFriend" icon="el-icon-chat-dot-round" type="primary" @click="onSendMessage(userInfo)">发送消息</el-button>
<el-button v-show="!isFriend" icon="el-icon-plus" type="primary" @click="onAddFriend(userInfo)">加为好友</el-button>
<el-button v-show="isFriend" icon="el-icon-delete" type="danger" @click="onDelItem(userInfo,friendStore.activeIndex)">删除好友</el-button>
<el-button v-show="isFriend" icon="el-icon-delete" type="danger" @click="onDelItem(userInfo,activeIdx)">删除好友</el-button>
</div>
</div>
</div>
@ -74,6 +74,7 @@
return {
searchText: "",
showAddFriend: false,
activeIdx: -1,
userInfo: {}
}
},
@ -84,11 +85,12 @@
onCloseAddFriend() {
this.showAddFriend = false;
},
onActiveItem(friend, index) {
this.$store.commit("activeFriend", index);
this.loadUserInfo(friend, index);
onActiveItem(friend, idx) {
this.$store.commit("activeFriend", idx);
this.activeIdx = idx
this.loadUserInfo(friend, idx);
},
onDelItem(friend, index) {
onDelItem(friend, idx) {
this.$confirm(`确认要解除与 '${friend.nickName}'的好友关系吗?`, '确认解除?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
@ -99,7 +101,7 @@
method: 'delete'
}).then((data) => {
this.$message.success("删除好友成功");
this.$store.commit("removeFriend", index);
this.$store.commit("removeFriend", idx);
this.$store.commit("removePrivateChat", friend.id);
})
})
@ -173,14 +175,7 @@
isFriend(){
return this.friendStore.friends.find((f)=>f.id==this.userInfo.id);
}
},
mounted() {
if (this.friendStore.activeIndex >= 0) {
let friend = this.friendStore.friends[this.friendStore.activeIndex];
this.loadUserInfo(friend, this.friendStore.activeIndex);
}
}
}
</script>

11
im-ui/src/view/Group.vue

@ -13,7 +13,7 @@
<el-scrollbar class="group-list-items">
<div v-for="(group,index) in groupStore.groups" :key="index">
<group-item v-show="group.remark.startsWith(searchText)" :group="group"
:active="index === groupStore.activeIndex" @click.native="onActiveItem(group,index)">
:active="group === groupStore.activeGroup" @click.native="onActiveItem(group,index)">
</group-item>
</div>
</el-scrollbar>
@ -269,15 +269,6 @@
imageAction() {
return `/image/upload`;
}
},
mounted() {
if (this.groupStore.activeIndex >= 0) {
let activeGroup = this.groupStore.groups[this.groupStore.activeIndex];
// store
this.activeGroup = JSON.parse(JSON.stringify(activeGroup));
//
this.loadGroupMembers();
}
}
}
</script>

1
im-ui/src/view/Register.vue

@ -56,7 +56,6 @@
};
var checkConfirmPassword = (rule, value, callback) => {
console.log("checkConfirmPassword");
if (value === '') {
return callback(new Error('请输入密码'));
}

Loading…
Cancel
Save