feat: 会话列表实时同步未读与最新消息

This commit is contained in:
JiXinHui 2025-12-17 16:52:22 +08:00
parent 5b0a14ae57
commit 890a3cee94
3 changed files with 226 additions and 25 deletions

11
App.vue
View File

@ -236,6 +236,17 @@ export default {
filePath: "",
id: Math.random().toString(36).substring(2),
});
// / /
if (processData.dialogueManagementId) {
this.$store.commit("apply_RealtimeMessageToList", {
dialogueId: processData.dialogueManagementId,
message: processData.message,
sendDate: processData.sendDate,
senderId: processData.senderId,
receiverId: processData.receiverId,
});
}
}
},
//

View File

@ -63,12 +63,120 @@ export default {
},
computed: {
// 便使
unreadMap() {
const map = {};
const list = this.$store?.state?.vuex_userMsgList || [];
list.forEach((item) => {
const id = this.getDialogueId(item);
const count =
item?.unReadCount ??
item?.unreadCount ??
item?.unread ??
null;
if (id && typeof count === "number") {
map[id] = count;
}
});
return map;
},
displayChatList() {
return (this.chatList || []).map((item) => ({
// + id
const realtime = this.$store?.state?.vuex_userMsgList || [];
const baseList = this.chatList || [];
const rtMap = {};
realtime.forEach((item) => {
const id = this.getDialogueId(item);
if (id) rtMap[id] = item;
});
const merged = baseList.map((item) => {
const id = this.getDialogueId(item);
const rt = id ? rtMap[id] : null;
const source = rt || item;
const unread =
typeof this.unreadMap[id] === "number"
? this.unreadMap[id]
: source?.unReadCount ??
source?.unreadCount ??
source?.unread ??
0;
return {
...item,
displayTime: item.lastMessageTime || "",
displayPreview: item.lastMessage || "暂无消息",
}));
...rt,
id,
dialogueManagementId: id,
DialogueManagementId: id,
userId:
source?.receiverId ||
source?.friendId ||
source?.userId ||
item?.userId ||
"",
avatar:
source?.receiverHeadSculptureUrl ||
source?.avatar ||
source?.friendAvatar ||
"/static/avatar/default-avatar.png",
displayTime: this.formatTime(
source?.lastMessageTime ||
source?.lastSendTime ||
source?.sendDate ||
item?.lastMessageTime ||
""
),
displayPreview:
source?.lastMessage ||
source?.message ||
item?.lastMessage ||
"暂无消息",
unreadCount: unread,
};
});
// 线
realtime.forEach((item) => {
const id = this.getDialogueId(item);
if (!id) return;
const exists = merged.some((row) => row.id === id);
if (!exists) {
const unread =
typeof this.unreadMap[id] === "number"
? this.unreadMap[id]
: item?.unReadCount ??
item?.unreadCount ??
item?.unread ??
0;
merged.unshift({
...item,
id,
dialogueManagementId: id,
DialogueManagementId: id,
userId:
item?.receiverId ||
item?.friendId ||
item?.userId ||
"",
avatar:
item?.receiverHeadSculptureUrl ||
item?.avatar ||
item?.friendAvatar ||
"/static/avatar/default-avatar.png",
displayTime: this.formatTime(
item?.lastMessageTime ||
item?.lastSendTime ||
item?.sendDate ||
""
),
displayPreview:
item?.lastMessage || item?.message || "暂无消息",
unreadCount: unread,
});
}
});
return merged;
},
},
data() {
@ -130,6 +238,8 @@ export default {
const list = (res && res.data && res.data.item1) || [];
this.chatList = this.normalizeDialogueList(list);
// 便
this.$store.commit("set_UserMsgList", this.chatList);
this.totalCount = res?.data?.item2 || list.length;
} catch (error) {
console.error("[在线咨询] 获取会话列表失败", error);
@ -155,9 +265,20 @@ export default {
? item.unReadCount
: item?.unreadCount || 0;
const id =
item?.dialogueManagementId ||
item?.DialogueManagementId ||
item?.dialogueId ||
item?.friendId ||
item?.id ||
index;
return {
id: item?.dialogueManagementId || item?.dialogueId || item?.id || index,
id,
dialogueManagementId: id,
DialogueManagementId: id,
userId: item?.receiverId || item?.friendId || item?.userId || "",
friendId: item?.receiverId || item?.friendId || item?.userId || "",
name:
item?.receiverName ||
item?.friendName ||
@ -202,6 +323,18 @@ export default {
// 退
return String(timeStr).replace("T", " ").slice(5, 16);
},
//
getDialogueId(item) {
return (
item?.dialogueManagementId ||
item?.DialogueManagementId ||
item?.dialogueId ||
item?.friendId ||
item?.id ||
""
);
},
},
};
</script>

View File

@ -186,6 +186,63 @@ const store = new Vuex.Store({
return item;
});
},
// WebSocket 实时消息:更新会话列表的未读数、文案与时间
apply_RealtimeMessageToList(
state,
{ dialogueId, message, sendDate, senderId, receiverId }
) {
if (!dialogueId) return;
const activeId =
state.vuex_msgUser?.dialogueManagementId ||
state.vuex_msgUser?.friendId ||
state.vuex_msgUser?.id;
const isActive = activeId && activeId === dialogueId;
let found = false;
state.vuex_userMsgList = (state.vuex_userMsgList || []).map((item) => {
const itemId =
item?.dialogueManagementId ||
item?.DialogueManagementId ||
item?.friendId ||
item?.id;
if (itemId === dialogueId) {
found = true;
const currentUnread =
Number(
item?.unReadCount ??
item?.unreadCount ??
item?.unread ??
0
) || 0;
const nextUnread = isActive ? 0 : currentUnread + 1;
return {
...item,
lastMessage: message ?? item?.lastMessage ?? "",
lastMessageTime: sendDate ?? item?.lastMessageTime ?? "",
unReadCount: nextUnread,
unreadCount: nextUnread,
};
}
return item;
});
// 未在列表中则插入一条最小信息的会话(保持实时感知)
if (!found) {
const nextUnread = isActive ? 0 : 1;
state.vuex_userMsgList.unshift({
id: dialogueId,
dialogueManagementId: dialogueId,
DialogueManagementId: dialogueId,
friendId: receiverId || senderId || dialogueId,
name: "",
avatar: "",
lastMessage: message || "",
lastMessageTime: sendDate || "",
unReadCount: nextUnread,
unreadCount: nextUnread,
});
}
},
// 更新消息窗口滚动位置
set_MsgScrollTop(state, top) {
state.vuex_msgScrollTop = Number(top) || 0;