feat(chat): 优化聊天页面消息处理和滚动逻辑

This commit is contained in:
yangzhe 2025-12-17 13:49:44 +08:00
parent a9edb58d6f
commit 4737ca0feb
4 changed files with 76 additions and 87 deletions

33
App.vue
View File

@ -177,7 +177,7 @@ export default {
// //
this.reset(); this.reset();
console.log("[WebSocket] 收到消息:", e); // console.log("[WebSocket] :", e);
// //
// if (typeof e.data === "string" && e.data.indexOf("heartCheck") >= 0) { // if (typeof e.data === "string" && e.data.indexOf("heartCheck") >= 0) {
@ -195,7 +195,7 @@ export default {
const type = msgData.Type; const type = msgData.Type;
console.log("收到消息类型:", type); console.log("收到消息:", type, msgData);
// //
if (type === "pong") return; if (type === "pong") return;
@ -220,21 +220,22 @@ export default {
this.$u.vuex("vuex_tabbar", tab); this.$u.vuex("vuex_tabbar", tab);
} }
// 使 key //
let msgList = this.vuex_msgList || ""; if (type === "PrivateChatMessage") {
if (type === "ChatMessageDto") {
const data = msgData.Data || {}; const data = msgData.Data || {};
const msgUserId = data.ChatType === 1 ? data?.ToId : data?.UserId; const processData = {
const key = `chat_${msgUserId || "unknown"}`; dialogueManagementId: data.DialogueManagementId,
if (msgList.indexOf(key) < 0) { senderId: data.SenderId,
msgList += key + ","; receiverId: data.ReceiverId,
this.$u.vuex("vuex_msgList", msgList); sendDate: data.SendDate,
} message: data.Message,
} else { };
if (msgList.indexOf("WebSocketMessage") < 0) { this.$store.commit("push_Msg", {
msgList += "WebSocketMessage,"; ...processData,
this.$u.vuex("vuex_msgList", msgList); messageType: 0,
} filePath: "",
id: Math.random().toString(36).substring(2),
});
} }
}, },
// //

View File

@ -81,6 +81,9 @@
</view> </view>
</view> </view>
</view> </view>
<!-- 底部间距 滚动锚点 -->
<view id="bottom-anchor" class="bottom-anchor"></view>
</scroll-view> </scroll-view>
</view> </view>
@ -127,25 +130,6 @@ export default {
// //
messageList: [ messageList: [
{
id: "9cac8661-bf09-4b63-ab15-1a0a36b921e0",
message: "你知道今年的录取分数线吗",
sendDate: "2025-07-10T15:11:32.886075",
isSend: true,
isRead: false,
interactMode: 0,
messageType: 0,
},
{
id: "02306fc3-c821-4a23-ad66-0bd77d154105",
message:
"目前2025年的录取分数线还没有正式公布因为学校需要等招生工作结束后才会公布最终的录取分数线。不过你可以参考2023-2024年的录取分数线作为大致的参考。\n\n如果你想知道具体专业的录取分数线可以告诉我你所在省份和科类历史类或物理类我可以根据往年数据给你一些参考建议。如果需要更准确的信息建议关注江西新能源科技职业学院的官网www.jxnee.edu.cn或者直接联系招生办电话0790-6764666/6765666。",
sendDate: "2025-07-10T15:11:32.88644",
isSend: true,
isRead: false,
interactMode: 1,
messageType: 0,
},
{ {
id: "9cac8661-bf09-4b63-ab15-1a0a36b91110", id: "9cac8661-bf09-4b63-ab15-1a0a36b91110",
message: "你知道今年的录取分数线吗", message: "你知道今年的录取分数线吗",
@ -185,14 +169,16 @@ export default {
// //
this.getMsgList(); this.getMsgList();
//
this.$nextTick(() => {
this.scrollToBottom();
});
}, },
computed: { computed: {
// ID
lastMsgId() {
const list = this.vuex_msgList || [];
if (!list.length) return "";
return list[list.length - 1]?.id || "";
},
receiverHeadSculptureUrl() { receiverHeadSculptureUrl() {
if (this.vuex_msgUser.headSculptureUrl) { if (this.vuex_msgUser.headSculptureUrl) {
return this.baseUrl + "/" + this.vuex_msgUser.headSculptureUrl; return this.baseUrl + "/" + this.vuex_msgUser.headSculptureUrl;
@ -206,7 +192,17 @@ export default {
return this.baseUrl + "/" + this.vuex_user.HeadSculptureUrl; return this.baseUrl + "/" + this.vuex_user.HeadSculptureUrl;
} }
return "/static/common/images/avatar.png"; return "/static/common/images/avatar_default2.png";
},
},
watch: {
// ID
lastMsgId(val) {
if (!val) return;
this.$nextTick(() => {
this.scrollToBottom();
});
}, },
}, },
@ -216,18 +212,6 @@ export default {
uni.navigateBack(); uni.navigateBack();
}, },
// this.vuex_msgUser = {
// dialogueManagementId: "08de36ed-8bc0-4b79-86e7-0128010ccc4b",
// receiverId: "08de33d5-b517-4801-8474-4a4ad5642691",
// receiverName: "",
// receiverHeadSculptureUrl: "tx.jpg",
// title: "",
// startTime: "2025-12-09T14:38:21.295504",
// lastMessageTime: "0001-01-01T00:00:00",
// isOverhead: false,
// unReadCount: 0,
// };
// //
handleSend() { handleSend() {
if (!this.messageValue) { if (!this.messageValue) {
@ -270,10 +254,10 @@ export default {
this.$store.commit("push_Msg", msgUserData); this.$store.commit("push_Msg", msgUserData);
// //
this.messageValue = ""; this.messageValue = "";
// // //
this.$nextTick(() => { // this.$nextTick(() => {
this.scrollToBottom(); // this.scrollToBottom();
}); // });
} }
}) })
.catch((error) => { .catch((error) => {
@ -281,22 +265,6 @@ export default {
}); });
}, },
//
receiveMessage(content) {
const message = {
id: Date.now(),
content: content,
isSelf: false,
timestamp: this.formatTime(new Date()),
};
this.messageList.push(message);
this.$nextTick(() => {
this.scrollToBottom();
});
},
// //
getMsgList() { getMsgList() {
this.$u.api this.$u.api
@ -309,15 +277,29 @@ export default {
const msgList = res.data.item1.reverse(); const msgList = res.data.item1.reverse();
this.$store.commit("push_MsgList", msgList); this.$store.commit("push_MsgList", msgList);
// //
// this.$nextTick(() => {
// this.scrollToBottom();
// });
}); });
}, },
// //
scrollToBottom() { scrollToBottom() {
if (this.vuex_msgList.length > 0) { // if (this.vuex_msglist.length > 0) {
const lastMsg = this.vuex_msgList[this.vuex_msgList.length - 1]; // const lastMsg = this.vuex_msglist[this.vuex_msglist.length - 1];
this.scrollToView = "msg-" + lastMsg.id; // this.scrollToView = "msg-" + lastMsg.id;
// }
//
if (this.scrollToView === "bottom-anchor") {
this.scrollToView = "";
this.$nextTick(() => {
this.scrollToView = "bottom-anchor";
});
return;
} }
this.scrollToView = "bottom-anchor";
}, },
// //
@ -424,7 +406,7 @@ export default {
.teacher-info-card { .teacher-info-card {
background-color: #ffffff; background-color: #ffffff;
padding: 30rpx; padding: 32rpx;
border-radius: 16rpx; border-radius: 16rpx;
margin: 30rpx 0; margin: 30rpx 0;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1); box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
@ -437,21 +419,21 @@ export default {
width: 120rpx; width: 120rpx;
height: 120rpx; height: 120rpx;
border-radius: 10rpx; border-radius: 10rpx;
margin-right: 30rpx; margin-right: 36rpx;
object-fit: cover; object-fit: cover;
} }
.teacher-info { .teacher-info {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-evenly;
gap: 8rpx; gap: 16rpx;
flex: 1; flex: 1;
.teacher-name { .teacher-name {
font-family: PingFang SC; font-family: PingFang SC;
font-weight: bold; font-weight: bold;
font-size: 32rpx; font-size: 36rpx;
color: #333333; color: #333333;
} }
@ -538,6 +520,11 @@ export default {
text-align: left; text-align: left;
} }
} }
.bottom-anchor {
height: 48rpx;
width: 100%;
}
} }
} }

View File

@ -102,15 +102,15 @@ export default {
// //
openChat(item) { openChat(item) {
// console.log(':', item); console.log('打开聊天:', item);
// uni.navigateTo({ // uni.navigateTo({
// url: `/pages/chat/chat-detail?userId=${item.userId}&name=${item.name}` // url: `/pages/chat/chat-detail?userId=${item.userId}&name=${item.name}`
// }); // });
const dialogueManagementId = item.dialogueManagementId // const id = item.id
const receiverId = item.receiverId // const receiverId = item.receiverId
this.$store.dispatch("selectTeacherChatItem", { this.$store.dispatch("selectTeacherChatItem", {
dialogueManagementId, id: item.id,
receiverId, receiverId: item.userId,
}); });
}, },

View File

@ -32,7 +32,8 @@
<view class="teacher-detail"> <view class="teacher-detail">
<view class="teacher-name"> <view class="teacher-name">
<text>{{ teacher.name }}</text> <text>{{ teacher.name }}</text>
<view v-if="teacher.presence" class="online-status"> <!-- presence 0在线 1离线 -->
<view v-if="teacher.presence == 0" class="online-status">
<view class="online-dot"></view> <view class="online-dot"></view>
<text>在线</text> <text>在线</text>
</view> </view>