feat(chat): 优化聊天页面消息处理和滚动逻辑
This commit is contained in:
parent
a9edb58d6f
commit
4737ca0feb
33
App.vue
33
App.vue
|
|
@ -177,7 +177,7 @@ export default {
|
|||
// 收到任何消息都重置心跳
|
||||
this.reset();
|
||||
|
||||
console.log("[WebSocket] 收到消息:", e);
|
||||
// console.log("[WebSocket] 收到消息:", e);
|
||||
|
||||
// 心跳消息不处理
|
||||
// if (typeof e.data === "string" && e.data.indexOf("heartCheck") >= 0) {
|
||||
|
|
@ -195,7 +195,7 @@ export default {
|
|||
|
||||
const type = msgData.Type;
|
||||
|
||||
console.log("收到消息类型:", type);
|
||||
console.log("收到消息:", type, msgData);
|
||||
// 收到服务端心跳响应不处理
|
||||
if (type === "pong") return;
|
||||
|
||||
|
|
@ -220,21 +220,22 @@ export default {
|
|||
this.$u.vuex("vuex_tabbar", tab);
|
||||
}
|
||||
|
||||
// 维护消息提示队列(与原逻辑兼容,使用通用 key)
|
||||
let msgList = this.vuex_msgList || "";
|
||||
if (type === "ChatMessageDto") {
|
||||
// 收到私聊消息
|
||||
if (type === "PrivateChatMessage") {
|
||||
const data = msgData.Data || {};
|
||||
const msgUserId = data.ChatType === 1 ? data?.ToId : data?.UserId;
|
||||
const key = `chat_${msgUserId || "unknown"}`;
|
||||
if (msgList.indexOf(key) < 0) {
|
||||
msgList += key + ",";
|
||||
this.$u.vuex("vuex_msgList", msgList);
|
||||
}
|
||||
} else {
|
||||
if (msgList.indexOf("WebSocketMessage") < 0) {
|
||||
msgList += "WebSocketMessage,";
|
||||
this.$u.vuex("vuex_msgList", msgList);
|
||||
}
|
||||
const processData = {
|
||||
dialogueManagementId: data.DialogueManagementId,
|
||||
senderId: data.SenderId,
|
||||
receiverId: data.ReceiverId,
|
||||
sendDate: data.SendDate,
|
||||
message: data.Message,
|
||||
};
|
||||
this.$store.commit("push_Msg", {
|
||||
...processData,
|
||||
messageType: 0,
|
||||
filePath: "",
|
||||
id: Math.random().toString(36).substring(2),
|
||||
});
|
||||
}
|
||||
},
|
||||
// 连接关闭
|
||||
|
|
|
|||
|
|
@ -81,6 +81,9 @@
|
|||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部间距 滚动锚点 -->
|
||||
<view id="bottom-anchor" class="bottom-anchor"></view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
|
|
@ -127,25 +130,6 @@ export default {
|
|||
|
||||
// 消息列表
|
||||
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",
|
||||
message: "你知道今年的录取分数线吗",
|
||||
|
|
@ -185,14 +169,16 @@ export default {
|
|||
|
||||
// 加载历史消息
|
||||
this.getMsgList();
|
||||
|
||||
// 滚动到底部
|
||||
this.$nextTick(() => {
|
||||
this.scrollToBottom();
|
||||
});
|
||||
},
|
||||
|
||||
computed: {
|
||||
// 最后一条消息的ID
|
||||
lastMsgId() {
|
||||
const list = this.vuex_msgList || [];
|
||||
if (!list.length) return "";
|
||||
return list[list.length - 1]?.id || "";
|
||||
},
|
||||
|
||||
receiverHeadSculptureUrl() {
|
||||
if (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 "/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();
|
||||
},
|
||||
|
||||
// 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() {
|
||||
if (!this.messageValue) {
|
||||
|
|
@ -270,10 +254,10 @@ export default {
|
|||
this.$store.commit("push_Msg", msgUserData);
|
||||
// 清空输入框
|
||||
this.messageValue = "";
|
||||
// 滚动到底部
|
||||
this.$nextTick(() => {
|
||||
this.scrollToBottom();
|
||||
});
|
||||
// // 滚动到底部
|
||||
// this.$nextTick(() => {
|
||||
// this.scrollToBottom();
|
||||
// });
|
||||
}
|
||||
})
|
||||
.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() {
|
||||
this.$u.api
|
||||
|
|
@ -309,15 +277,29 @@ export default {
|
|||
const msgList = res.data.item1.reverse();
|
||||
|
||||
this.$store.commit("push_MsgList", msgList);
|
||||
// // 滚动到底部
|
||||
// this.$nextTick(() => {
|
||||
// this.scrollToBottom();
|
||||
// });
|
||||
});
|
||||
},
|
||||
|
||||
// 滚动到底部
|
||||
scrollToBottom() {
|
||||
if (this.vuex_msgList.length > 0) {
|
||||
const lastMsg = this.vuex_msgList[this.vuex_msgList.length - 1];
|
||||
this.scrollToView = "msg-" + lastMsg.id;
|
||||
// if (this.vuex_msglist.length > 0) {
|
||||
// const lastMsg = this.vuex_msglist[this.vuex_msglist.length - 1];
|
||||
// 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 {
|
||||
background-color: #ffffff;
|
||||
padding: 30rpx;
|
||||
padding: 32rpx;
|
||||
border-radius: 16rpx;
|
||||
margin: 30rpx 0;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
|
||||
|
|
@ -437,21 +419,21 @@ export default {
|
|||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 10rpx;
|
||||
margin-right: 30rpx;
|
||||
margin-right: 36rpx;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.teacher-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
gap: 8rpx;
|
||||
justify-content: space-evenly;
|
||||
gap: 16rpx;
|
||||
flex: 1;
|
||||
|
||||
.teacher-name {
|
||||
font-family: PingFang SC;
|
||||
font-weight: bold;
|
||||
font-size: 32rpx;
|
||||
font-size: 36rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
|
|
@ -538,6 +520,11 @@ export default {
|
|||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-anchor {
|
||||
height: 48rpx;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -102,15 +102,15 @@ export default {
|
|||
|
||||
// 打开聊天页面
|
||||
openChat(item) {
|
||||
// console.log('打开聊天:', item);
|
||||
console.log('打开聊天:', item);
|
||||
// uni.navigateTo({
|
||||
// url: `/pages/chat/chat-detail?userId=${item.userId}&name=${item.name}`
|
||||
// });
|
||||
const dialogueManagementId = item.dialogueManagementId
|
||||
const receiverId = item.receiverId
|
||||
// const id = item.id
|
||||
// const receiverId = item.receiverId
|
||||
this.$store.dispatch("selectTeacherChatItem", {
|
||||
dialogueManagementId,
|
||||
receiverId,
|
||||
id: item.id,
|
||||
receiverId: item.userId,
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@
|
|||
<view class="teacher-detail">
|
||||
<view class="teacher-name">
|
||||
<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>
|
||||
<text>在线</text>
|
||||
</view>
|
||||
|
|
|
|||
Loading…
Reference in New Issue