Compare commits

...
7 Commits
4 changed files with 142 additions and 85 deletions
+128 -80
View File
@@ -69,7 +69,8 @@
class="contact-item" class="contact-item"
:class="{ :class="{
active: active:
currentContact && currentContact.contactName === contact.contactName, currentContact &&
currentContact.contactName === contact.contactName,
}" }"
@click="selectContact(contact)" @click="selectContact(contact)"
> >
@@ -83,7 +84,7 @@
</div> </div>
<div class="last-message"> <div class="last-message">
{{ getLastMessage(contact.contactName) }} {{ contact.content }}
</div> </div>
</div> </div>
@@ -135,7 +136,7 @@
<div class="chat-user-info"> <div class="chat-user-info">
<div class="chat-user-name"> <div class="chat-user-name">
{{ currentContact.name }} {{ currentContact.contactName }}
</div> </div>
<div class="chat-user-status"> <div class="chat-user-status">
@@ -148,10 +149,11 @@
<div <div
ref="messageList" ref="messageList"
class="message-list" class="message-list"
:class="activeMenu === 'messages' ? 'active' : ''" :class="activeMenu === 'settings' ? '' : 'active'"
@scroll="handleMessageScroll"
> >
<div <div
v-for="message in currentMessages" v-for="message in contactMessages"
:key="message.id" :key="message.id"
class="message-row" class="message-row"
:class="{ :class="{
@@ -184,14 +186,6 @@
</div> </div>
</div> </div>
<div
ref="messageList"
class="message-list"
:class="activeMenu === 'contacts' ? 'empty' : ''"
>
<div class="empty-content">💬</div>
</div>
<!-- 输入消息区域 --> <!-- 输入消息区域 -->
<div v-if="activeMenu === 'messages'" class="input-panel"> <div v-if="activeMenu === 'messages'" class="input-panel">
<div class="toolbar"> <div class="toolbar">
@@ -224,7 +218,13 @@
</template> </template>
<script> <script>
import { getUserInfo, getContactInfo, getContactMessages, sendMessage } from "@/utils/user"; import {
getUserInfo,
getContactInfo,
getRecentMessages,
getContactMessages,
sendMessage,
} from "@/utils/api";
export default { export default {
name: "ChatPage", name: "ChatPage",
@@ -236,8 +236,10 @@ export default {
contactList: [], contactList: [],
// 当前聊天联系人 // 当前聊天联系人
currentContact: null, currentContact: null,
// 最近聊天列表
recentChats: [],
// 聊天消息 // 聊天消息
groupedMessages: {}, contactMessages: [],
// 搜索联系人 // 搜索联系人
searchText: "", searchText: "",
// 输入的消息内容 // 输入的消息内容
@@ -251,39 +253,41 @@ export default {
// 搜索联系人 // 搜索联系人
filteredContacts() { filteredContacts() {
if (!this.searchText.trim()) { if (!this.searchText.trim()) {
return this.contactList; return this.recentChats;
} }
const keyword = this.searchText.trim().toLowerCase(); const keyword = this.searchText.trim().toLowerCase();
return this.contactList.filter((contact) => return this.recentChats.filter((contact) =>
contact.name.toLowerCase().includes(keyword), contact.contactName.toLowerCase().includes(keyword)
); );
}, },
// 当前联系人对应的消息
currentMessages() {
if (!this.currentContact) {
return [];
}
return this.groupedMessages[this.currentContact.contactName] || [];
},
}, },
created() { created() {
this.getCurrentUser(); this.getCurrentUser();
this.getContactList(); this.getRecentMessageList();
this.getMessageList();
}, },
methods: { methods: {
// 切换菜单
changeMenu(menu) {
this.activeMenu = menu;
this.currentContact = null;
if (menu === "contacts") {
this.getContactList();
}
},
// 退出登录
logout() { logout() {
// 清除 token 和用户信息 // 清除 token 和用户信息
this.$store.commit("SET_TOKEN", ""); this.$store.commit("SET_TOKEN", "");
this.$store.commit("SET_USERNAME", ""); this.$store.commit("SET_USERNAME", "");
this.$router.push("/login"); this.$router.push("/login");
}, },
// 获取当前登录用户信息
getCurrentUser() { getCurrentUser() {
// 获取当前登录用户信息 // 获取当前登录用户信息
getUserInfo() getUserInfo()
@@ -296,60 +300,24 @@ export default {
this.$router.push("/login"); this.$router.push("/login");
}); });
}, },
getMessageList() {
// 获取当前用户的联系人消息列表 // 获取最近消息列表
getContactMessages() getRecentMessageList() {
getRecentMessages()
.then((response) => { .then((response) => {
const groupedMessages = {}; this.recentChats = response.data.recentChats || [];
const messages = response.data.messages || []; this.selectFirstContact();
// 把联系人的消息按联系人 id 分组存储
messages.forEach((item) => {
// 这个联系人的名称是和当前用户聊天消息的发送者名称或接收者名称
const contactName =
item.senderName === this.currentUser.username
? item.receiverName
: item.senderName;
// 把联系人 id 为属性进行分组,每个联系人id对应一个消息数组,内容有接收消息也有发送消息
if (!groupedMessages[contactName]) {
groupedMessages[contactName] = [];
}
groupedMessages[contactName].push({
...item,
from: item.senderName === this.currentUser.username ? "me" : "other",
time: item.time || item.createdAt,
});
});
this.groupedMessages = groupedMessages;
console.log("groupedMessages", groupedMessages);
}) })
.catch((error) => { .catch((error) => {
console.error(error); console.error(error);
this.$message.error("获取消息列表失败"); this.$message.error("获取消息列表失败");
}); });
}, },
getContactList() {
getContactInfo()
.then((response) => {
this.contactList = response.data.contacts.map((contact) => ({
...contact,
unread: contact.unread || 0,
}));
console.log("contactList", this.contactList);
this.selectFirstContact();
})
.catch((error) => {
console.error(error);
this.$message.error("获取联系人信息失败");
});
},
changeMenu(menu) {
this.activeMenu = menu;
},
// 选择联系人 // 选择联系人
selectContact(contact) { selectContact(contact) {
this.currentContact = contact; this.currentContact = contact;
this.getContactMessageList(contact.contactName, 10, 0);
// 查看联系人后清除未读数量 // 查看联系人后清除未读数量
contact.unread = 0; contact.unread = 0;
@@ -359,16 +327,60 @@ export default {
}); });
}, },
// 选择第一个联系人 // 选择最近一个联系人
selectFirstContact() { selectFirstContact() {
if (!this.currentContact && this.contactList.length > 0) { if (!this.currentContact && this.recentChats.length > 0) {
this.selectContact(this.contactList[0]); this.selectContact(this.recentChats[0]);
} }
}, },
// 获取当前联系人的消息列表
getContactMessageList(contactName, limit, offset) {
// 获取当前联系人的消息列表
getContactMessages({
contactName: contactName,
limit: limit,
offset: offset
})
.then((response) => {
const contactMessages = [];
const messages = response.data.messages || [];
messages.forEach((item) => {
contactMessages.push({
...item,
from:
item.senderName === this.currentUser.username ? "me" : "other",
time: item.time || item.createdAt,
});
});
// 将新获取的消息放到现有消息的最前面,用于按时间顺序倒序展示
this.contactMessages = contactMessages.reverse().concat(this.contactMessages);
console.log("contactMessages", contactMessages);
})
.catch((error) => {
console.error(error);
this.$message.error("获取消息列表失败");
});
},
// 获取联系人列表
getContactList() {
getContactInfo()
.then((response) => {
this.contactList = response.data.contacts.map((contact) => ({
...contact,
unread: contact.unread || 0,
}));
})
.catch((error) => {
console.error(error);
this.$message.error("获取联系人信息失败");
});
},
// 获取最后一条消息 // 获取最后一条消息
getLastMessage(contactName) { getLastMessage(contactName) {
const messageList = this.groupedMessages[contactName]; const messageList = this.contactMessages[contactName];
if (!messageList || messageList.length === 0) { if (!messageList || messageList.length === 0) {
return "暂无消息"; return "暂无消息";
@@ -385,8 +397,8 @@ export default {
return; return;
} }
if (!this.groupedMessages[this.currentContact.id]) { if (!this.contactMessages[this.currentContact.contactName]) {
this.$set(this.groupedMessages, this.currentContact.id, []); this.$set(this.contactMessages, this.currentContact.contactName, []);
} }
const newMessage = { const newMessage = {
@@ -398,10 +410,32 @@ export default {
sendMessage(newMessage) sendMessage(newMessage)
.then((response) => { .then((response) => {
console.log("发送消息成功", response.data); console.log("发送消息成功", response.data);
this.groupedMessages[this.currentContact.contactName].push({ this.contactMessages[this.currentContact.contactName].push({
...newMessage, ...newMessage,
from: "me", from: "me",
}); });
// 更新最近消息列表
const contactName = this.currentContact.contactName;
const index = this.recentChats.findIndex(
(item) => item.contactName === contactName
);
if (index !== -1) { //找到这条数据,修改内容并移除后添加到数组最前面
const chat = this.recentChats[index];
chat.content = content;
chat.createdAt = newMessage.createdAt;
this.recentChats.splice(index, 1);
this.recentChats.unshift(chat);
} else { // 没有找到这条数据,直接添加到数组最前面
this.recentChats.unshift({
contactName: contactName,
content: content,
createdAt: newMessage.createdAt,
});
}
}) })
.catch((error) => { .catch((error) => {
console.error(error); console.error(error);
@@ -424,6 +458,20 @@ export default {
messageList.scrollTop = messageList.scrollHeight; messageList.scrollTop = messageList.scrollHeight;
} }
}, },
// 处理聊天框滚动事件
handleMessageScroll() {
const el = this.$refs.messageList;
// 滚动到顶部
if (el.scrollTop === 0) {
console.log("滚动到顶部,加载更多消息");
this.getContactMessageList(this.currentContact.contactName, 10, this.contactMessages.length);
// 滚动条往下移动 500px,利于继续往上滚动
el.scrollTop = 500;
}
}
}, },
}; };
</script> </script>
+1 -1
View File
@@ -36,7 +36,7 @@
</template> </template>
<script> <script>
import { login } from "@/utils/user"; import { login } from "@/utils/api";
export default { export default {
name: "LoginPage", name: "LoginPage",
data() { data() {
+1 -1
View File
@@ -44,7 +44,7 @@
</template> </template>
<script> <script>
import { register } from "@/utils/user"; import { register } from "@/utils/api";
export default { export default {
name: "RegisterPage", name: "RegisterPage",
data() { data() {
+12 -3
View File
@@ -34,14 +34,23 @@ export function getContactInfo() {
}) })
} }
// 获取用户的联系人消息 // 获取最近消息列表
export function getContactMessages() { export function getRecentMessages() {
return request({ return request({
url: '/messagesInfo', url: '/recentChats',
method: 'get' method: 'get'
}) })
} }
// 获取用户的联系人消息
export function getContactMessages(data) {
return request({
url: '/contactMessagesInfo',
method: 'post',
data
})
}
// 发送消息 // 发送消息
export function sendMessage(data) { export function sendMessage(data) {
return request({ return request({