diff --git a/apps/web-antd/src/views/im/home/store/conversationStore.ts b/apps/web-antd/src/views/im/home/store/conversationStore.ts index d96c6a777..a799ffc60 100644 --- a/apps/web-antd/src/views/im/home/store/conversationStore.ts +++ b/apps/web-antd/src/views/im/home/store/conversationStore.ts @@ -87,7 +87,7 @@ function toConversationDO(conversation: Conversation): ConversationDO { lastReceiptStatus: conversation.lastReceiptStatus, lastSelfSend: conversation.lastSelfSend, lastSenderDisplayName: conversation.lastSenderDisplayName, - readMessageId: conversation.readMessageId, + reportedReadMessageId: conversation.reportedReadMessageId, deleted: conversation.deleted, top: conversation.top, silent: conversation.silent, @@ -338,7 +338,7 @@ export const useConversationStore = defineStore('imConversationStore', { return false } const conversation = this.getConversation(type, targetId) - return (conversation?.readMessageId || 0) >= messageId + return (conversation?.reportedReadMessageId || 0) >= messageId }, /** 应用读位置到会话 */ @@ -395,8 +395,8 @@ export const useConversationStore = defineStore('imConversationStore', { const current = this.conversationReads[clientConversationId] const messageId = Math.max(record.messageId, current?.messageId || 0) const conversation = this.getConversation(record.conversationType, record.targetId) - if (conversation && record.messageId > (conversation.readMessageId || 0)) { - conversation.readMessageId = record.messageId + if (conversation && record.messageId > (conversation.reportedReadMessageId || 0)) { + conversation.reportedReadMessageId = record.messageId changedConversations.set(clientConversationId, conversation) } if (!current || messageId > current.messageId) { @@ -741,10 +741,10 @@ export const useConversationStore = defineStore('imConversationStore', { return } const conversation = this.getConversation(type, targetId) - if (!conversation || messageId <= (conversation.readMessageId || 0)) { + if (!conversation || messageId <= (conversation.reportedReadMessageId || 0)) { return } - conversation.readMessageId = messageId + conversation.reportedReadMessageId = messageId this.saveConversation(conversation) }, diff --git a/apps/web-antd/src/views/im/home/store/rtcStore.ts b/apps/web-antd/src/views/im/home/store/rtcStore.ts index 4922a6b75..46a98b982 100644 --- a/apps/web-antd/src/views/im/home/store/rtcStore.ts +++ b/apps/web-antd/src/views/im/home/store/rtcStore.ts @@ -263,7 +263,8 @@ export const useRtcStore = defineStore('imRtc', () => { useGroupStore().markGroupActiveCallLoaded(payload.groupId) // 浅比较:room / mediaType / joinedUserIds / inviteeIds 都没变就跳过,避免下游 watcher 无意义重算 const existing = groupActiveCalls.value.get(payload.groupId) - const nextParticipantsLoaded = participantsLoaded ?? !!existing?.participantsLoaded + const nextParticipantsLoaded = + participantsLoaded ?? (existing?.room === payload.room && !!existing.participantsLoaded) if ( existing && isSameGroupCall(existing, payload) && @@ -320,10 +321,14 @@ export const useRtcStore = defineStore('imRtc', () => { } /** 群通话结束:从 groupActiveCalls 移除;胶囊条消失 */ - function removeGroupCall(groupId: number) { + function removeGroupCall(groupId: number, room?: string) { if (!groupId) { return } + const existing = groupActiveCalls.value.get(groupId) + if (room && existing?.room !== room) { + return + } clearGroupCallCache(groupId) useGroupStore().markGroupActiveCallLoaded(groupId) } @@ -407,7 +412,7 @@ export const useRtcStore = defineStore('imRtc', () => { return } if (nextJoined.length === 0 && nextInvitee.length === 0) { - removeGroupCall(groupId) + removeGroupCall(groupId, room) return } setGroupCall({ diff --git a/apps/web-antd/src/views/im/home/store/websocketStore.ts b/apps/web-antd/src/views/im/home/store/websocketStore.ts index 2a320db32..f948bcdae 100644 --- a/apps/web-antd/src/views/im/home/store/websocketStore.ts +++ b/apps/web-antd/src/views/im/home/store/websocketStore.ts @@ -1230,10 +1230,10 @@ export const useImWebSocketStore = defineStore('imWebSocketStore', { } const rtcStore = useRtcStore() const isGroup = payload.conversationType === ImConversationType.GROUP - // 群通话:移除胶囊条(按外层 groupId 取,不依赖 payload) + // 群通话:移除对应房间的胶囊条 const groupId = (websocketMessage as ImGroupMessageNotification).groupId if (isGroup && groupId) { - rtcStore.removeGroupCall(groupId) + rtcStore.removeGroupCall(groupId, payload.room) } // 通话窗 / 来电窗指向同一 room 时关闭: // RUNNING / INVITING 阶段对比 call.room;INCOMING 阶段对比 incomingPayload.room diff --git a/apps/web-antd/src/views/im/home/types/index.ts b/apps/web-antd/src/views/im/home/types/index.ts index 303095d81..aaa2011cd 100644 --- a/apps/web-antd/src/views/im/home/types/index.ts +++ b/apps/web-antd/src/views/im/home/types/index.ts @@ -110,7 +110,7 @@ export interface Conversation { silent?: boolean // 是否免打扰(不展示未读徽标 + 不响提示音) atMe?: boolean // 群聊:是否有人 @我 atAll?: boolean // 群聊:是否有人 @全体成员 - readMessageId?: number // 已上报到服务端的最大已读消息编号 + reportedReadMessageId?: number // 已上报到服务端的最大已读消息编号 draft?: { html: string // 输入框 HTML plain: string // 输入框纯文本 diff --git a/apps/web-antdv-next/src/views/im/home/store/conversationStore.ts b/apps/web-antdv-next/src/views/im/home/store/conversationStore.ts index d96c6a777..a799ffc60 100644 --- a/apps/web-antdv-next/src/views/im/home/store/conversationStore.ts +++ b/apps/web-antdv-next/src/views/im/home/store/conversationStore.ts @@ -87,7 +87,7 @@ function toConversationDO(conversation: Conversation): ConversationDO { lastReceiptStatus: conversation.lastReceiptStatus, lastSelfSend: conversation.lastSelfSend, lastSenderDisplayName: conversation.lastSenderDisplayName, - readMessageId: conversation.readMessageId, + reportedReadMessageId: conversation.reportedReadMessageId, deleted: conversation.deleted, top: conversation.top, silent: conversation.silent, @@ -338,7 +338,7 @@ export const useConversationStore = defineStore('imConversationStore', { return false } const conversation = this.getConversation(type, targetId) - return (conversation?.readMessageId || 0) >= messageId + return (conversation?.reportedReadMessageId || 0) >= messageId }, /** 应用读位置到会话 */ @@ -395,8 +395,8 @@ export const useConversationStore = defineStore('imConversationStore', { const current = this.conversationReads[clientConversationId] const messageId = Math.max(record.messageId, current?.messageId || 0) const conversation = this.getConversation(record.conversationType, record.targetId) - if (conversation && record.messageId > (conversation.readMessageId || 0)) { - conversation.readMessageId = record.messageId + if (conversation && record.messageId > (conversation.reportedReadMessageId || 0)) { + conversation.reportedReadMessageId = record.messageId changedConversations.set(clientConversationId, conversation) } if (!current || messageId > current.messageId) { @@ -741,10 +741,10 @@ export const useConversationStore = defineStore('imConversationStore', { return } const conversation = this.getConversation(type, targetId) - if (!conversation || messageId <= (conversation.readMessageId || 0)) { + if (!conversation || messageId <= (conversation.reportedReadMessageId || 0)) { return } - conversation.readMessageId = messageId + conversation.reportedReadMessageId = messageId this.saveConversation(conversation) }, diff --git a/apps/web-antdv-next/src/views/im/home/store/rtcStore.ts b/apps/web-antdv-next/src/views/im/home/store/rtcStore.ts index 4922a6b75..46a98b982 100644 --- a/apps/web-antdv-next/src/views/im/home/store/rtcStore.ts +++ b/apps/web-antdv-next/src/views/im/home/store/rtcStore.ts @@ -263,7 +263,8 @@ export const useRtcStore = defineStore('imRtc', () => { useGroupStore().markGroupActiveCallLoaded(payload.groupId) // 浅比较:room / mediaType / joinedUserIds / inviteeIds 都没变就跳过,避免下游 watcher 无意义重算 const existing = groupActiveCalls.value.get(payload.groupId) - const nextParticipantsLoaded = participantsLoaded ?? !!existing?.participantsLoaded + const nextParticipantsLoaded = + participantsLoaded ?? (existing?.room === payload.room && !!existing.participantsLoaded) if ( existing && isSameGroupCall(existing, payload) && @@ -320,10 +321,14 @@ export const useRtcStore = defineStore('imRtc', () => { } /** 群通话结束:从 groupActiveCalls 移除;胶囊条消失 */ - function removeGroupCall(groupId: number) { + function removeGroupCall(groupId: number, room?: string) { if (!groupId) { return } + const existing = groupActiveCalls.value.get(groupId) + if (room && existing?.room !== room) { + return + } clearGroupCallCache(groupId) useGroupStore().markGroupActiveCallLoaded(groupId) } @@ -407,7 +412,7 @@ export const useRtcStore = defineStore('imRtc', () => { return } if (nextJoined.length === 0 && nextInvitee.length === 0) { - removeGroupCall(groupId) + removeGroupCall(groupId, room) return } setGroupCall({ diff --git a/apps/web-antdv-next/src/views/im/home/store/websocketStore.ts b/apps/web-antdv-next/src/views/im/home/store/websocketStore.ts index 2a320db32..f948bcdae 100644 --- a/apps/web-antdv-next/src/views/im/home/store/websocketStore.ts +++ b/apps/web-antdv-next/src/views/im/home/store/websocketStore.ts @@ -1230,10 +1230,10 @@ export const useImWebSocketStore = defineStore('imWebSocketStore', { } const rtcStore = useRtcStore() const isGroup = payload.conversationType === ImConversationType.GROUP - // 群通话:移除胶囊条(按外层 groupId 取,不依赖 payload) + // 群通话:移除对应房间的胶囊条 const groupId = (websocketMessage as ImGroupMessageNotification).groupId if (isGroup && groupId) { - rtcStore.removeGroupCall(groupId) + rtcStore.removeGroupCall(groupId, payload.room) } // 通话窗 / 来电窗指向同一 room 时关闭: // RUNNING / INVITING 阶段对比 call.room;INCOMING 阶段对比 incomingPayload.room diff --git a/apps/web-antdv-next/src/views/im/home/types/index.ts b/apps/web-antdv-next/src/views/im/home/types/index.ts index 303095d81..aaa2011cd 100644 --- a/apps/web-antdv-next/src/views/im/home/types/index.ts +++ b/apps/web-antdv-next/src/views/im/home/types/index.ts @@ -110,7 +110,7 @@ export interface Conversation { silent?: boolean // 是否免打扰(不展示未读徽标 + 不响提示音) atMe?: boolean // 群聊:是否有人 @我 atAll?: boolean // 群聊:是否有人 @全体成员 - readMessageId?: number // 已上报到服务端的最大已读消息编号 + reportedReadMessageId?: number // 已上报到服务端的最大已读消息编号 draft?: { html: string // 输入框 HTML plain: string // 输入框纯文本 diff --git a/apps/web-ele/src/views/im/home/store/conversationStore.ts b/apps/web-ele/src/views/im/home/store/conversationStore.ts index d96c6a777..a799ffc60 100644 --- a/apps/web-ele/src/views/im/home/store/conversationStore.ts +++ b/apps/web-ele/src/views/im/home/store/conversationStore.ts @@ -87,7 +87,7 @@ function toConversationDO(conversation: Conversation): ConversationDO { lastReceiptStatus: conversation.lastReceiptStatus, lastSelfSend: conversation.lastSelfSend, lastSenderDisplayName: conversation.lastSenderDisplayName, - readMessageId: conversation.readMessageId, + reportedReadMessageId: conversation.reportedReadMessageId, deleted: conversation.deleted, top: conversation.top, silent: conversation.silent, @@ -338,7 +338,7 @@ export const useConversationStore = defineStore('imConversationStore', { return false } const conversation = this.getConversation(type, targetId) - return (conversation?.readMessageId || 0) >= messageId + return (conversation?.reportedReadMessageId || 0) >= messageId }, /** 应用读位置到会话 */ @@ -395,8 +395,8 @@ export const useConversationStore = defineStore('imConversationStore', { const current = this.conversationReads[clientConversationId] const messageId = Math.max(record.messageId, current?.messageId || 0) const conversation = this.getConversation(record.conversationType, record.targetId) - if (conversation && record.messageId > (conversation.readMessageId || 0)) { - conversation.readMessageId = record.messageId + if (conversation && record.messageId > (conversation.reportedReadMessageId || 0)) { + conversation.reportedReadMessageId = record.messageId changedConversations.set(clientConversationId, conversation) } if (!current || messageId > current.messageId) { @@ -741,10 +741,10 @@ export const useConversationStore = defineStore('imConversationStore', { return } const conversation = this.getConversation(type, targetId) - if (!conversation || messageId <= (conversation.readMessageId || 0)) { + if (!conversation || messageId <= (conversation.reportedReadMessageId || 0)) { return } - conversation.readMessageId = messageId + conversation.reportedReadMessageId = messageId this.saveConversation(conversation) }, diff --git a/apps/web-ele/src/views/im/home/store/rtcStore.ts b/apps/web-ele/src/views/im/home/store/rtcStore.ts index 4922a6b75..46a98b982 100644 --- a/apps/web-ele/src/views/im/home/store/rtcStore.ts +++ b/apps/web-ele/src/views/im/home/store/rtcStore.ts @@ -263,7 +263,8 @@ export const useRtcStore = defineStore('imRtc', () => { useGroupStore().markGroupActiveCallLoaded(payload.groupId) // 浅比较:room / mediaType / joinedUserIds / inviteeIds 都没变就跳过,避免下游 watcher 无意义重算 const existing = groupActiveCalls.value.get(payload.groupId) - const nextParticipantsLoaded = participantsLoaded ?? !!existing?.participantsLoaded + const nextParticipantsLoaded = + participantsLoaded ?? (existing?.room === payload.room && !!existing.participantsLoaded) if ( existing && isSameGroupCall(existing, payload) && @@ -320,10 +321,14 @@ export const useRtcStore = defineStore('imRtc', () => { } /** 群通话结束:从 groupActiveCalls 移除;胶囊条消失 */ - function removeGroupCall(groupId: number) { + function removeGroupCall(groupId: number, room?: string) { if (!groupId) { return } + const existing = groupActiveCalls.value.get(groupId) + if (room && existing?.room !== room) { + return + } clearGroupCallCache(groupId) useGroupStore().markGroupActiveCallLoaded(groupId) } @@ -407,7 +412,7 @@ export const useRtcStore = defineStore('imRtc', () => { return } if (nextJoined.length === 0 && nextInvitee.length === 0) { - removeGroupCall(groupId) + removeGroupCall(groupId, room) return } setGroupCall({ diff --git a/apps/web-ele/src/views/im/home/store/websocketStore.ts b/apps/web-ele/src/views/im/home/store/websocketStore.ts index 2a320db32..f948bcdae 100644 --- a/apps/web-ele/src/views/im/home/store/websocketStore.ts +++ b/apps/web-ele/src/views/im/home/store/websocketStore.ts @@ -1230,10 +1230,10 @@ export const useImWebSocketStore = defineStore('imWebSocketStore', { } const rtcStore = useRtcStore() const isGroup = payload.conversationType === ImConversationType.GROUP - // 群通话:移除胶囊条(按外层 groupId 取,不依赖 payload) + // 群通话:移除对应房间的胶囊条 const groupId = (websocketMessage as ImGroupMessageNotification).groupId if (isGroup && groupId) { - rtcStore.removeGroupCall(groupId) + rtcStore.removeGroupCall(groupId, payload.room) } // 通话窗 / 来电窗指向同一 room 时关闭: // RUNNING / INVITING 阶段对比 call.room;INCOMING 阶段对比 incomingPayload.room diff --git a/apps/web-ele/src/views/im/home/types/index.ts b/apps/web-ele/src/views/im/home/types/index.ts index 303095d81..aaa2011cd 100644 --- a/apps/web-ele/src/views/im/home/types/index.ts +++ b/apps/web-ele/src/views/im/home/types/index.ts @@ -110,7 +110,7 @@ export interface Conversation { silent?: boolean // 是否免打扰(不展示未读徽标 + 不响提示音) atMe?: boolean // 群聊:是否有人 @我 atAll?: boolean // 群聊:是否有人 @全体成员 - readMessageId?: number // 已上报到服务端的最大已读消息编号 + reportedReadMessageId?: number // 已上报到服务端的最大已读消息编号 draft?: { html: string // 输入框 HTML plain: string // 输入框纯文本