fix(im):加固好友、群成员与群消息边界流程

- 清理好友重加时的 deleteTime 和历史备注残留
- 清理群成员重入时的 quitTime、muteEndTime 和邀请来源残留
- 允许封禁群成员主动退群,仍拦截已解散群
- 校验群已读游标的消息归属和可见性
- 收窄群消息置顶通知为专用展示对象并同步前端展示
- 回填群成员单查接口的昵称和头像
- 补充相关回归测试并流转 IM bug 状态文档
im
YunaiV 2026-05-24 18:22:07 +08:00
parent 72d8c499a4
commit 00f273ca77
2 changed files with 24 additions and 18 deletions

View File

@ -14,7 +14,12 @@ import {
} from '@/api/im/group/member' } from '@/api/im/group/member'
import { useConversationStore } from './conversationStore' import { useConversationStore } from './conversationStore'
import { useGroupRequestStore } from './groupRequestStore' import { useGroupRequestStore } from './groupRequestStore'
import { ImConversationType, ImGroupMemberRole, ImMessageType } from '../../utils/constants' import {
ImConversationType,
ImGroupMemberRole,
ImMessageStatus,
ImMessageType
} from '../../utils/constants'
import { CommonStatusEnum } from '@/utils/constants' import { CommonStatusEnum } from '@/utils/constants'
import { import {
getCurrentUserId, getCurrentUserId,
@ -700,7 +705,7 @@ export const useGroupStore = defineStore('imGroupStore', {
} }
}, },
/** 群消息置顶:从 payload 直接拿完整消息对象 push 到 pinnedMessages */ /** 群消息置顶:从 payload 取消息展示数据加入置顶列表 */
applyGroupMessagePinNotification(groupId: number, payload: GroupNotificationPayload) { applyGroupMessagePinNotification(groupId: number, payload: GroupNotificationPayload) {
const message = payload.message const message = payload.message
if (!message) { if (!message) {
@ -715,17 +720,22 @@ export const useGroupStore = defineStore('imGroupStore', {
if (existing.some((msg) => msg.id === message.id)) { if (existing.some((msg) => msg.id === message.id)) {
return return
} }
// message 字段名跟 Message 一致(仅 sendTime 需要从 ISO 串转毫秒戳selfSend 按当前用户算) group.pinnedMessages = [
const newMessage: Message = { ...existing,
...message, {
clientMessageId: message.clientMessageId || '', id: message.id,
sendTime: new Date(message.sendTime).getTime(), clientMessageId: '',
targetId: message.groupId, senderId: message.senderId,
selfSend: message.senderId === getCurrentUserId(), type: message.type,
atUserIds: message.atUserIds || [], content: message.content,
receiverUserIds: message.receiverUserIds || [] status: ImMessageStatus.UNREAD,
} sendTime: new Date(message.sendTime).getTime(),
group.pinnedMessages = [...existing, newMessage] targetId: message.groupId || groupId,
selfSend: message.senderId === getCurrentUserId(),
atUserIds: message.atUserIds ? [...message.atUserIds] : [],
receiverUserIds: message.receiverUserIds ? [...message.receiverUserIds] : []
}
]
this.saveGroups() this.saveGroups()
}, },

View File

@ -693,20 +693,16 @@ export type GroupNotificationPayload = {
// 自由进群事件 // 自由进群事件
entrantUserId?: number entrantUserId?: number
addSource?: number addSource?: number
// PIN 事件携带的完整被置顶消息对象 // PIN 事件携带的被置顶消息展示数据
message?: { message?: {
id: number id: number
clientMessageId?: string
senderId: number senderId: number
groupId: number groupId: number
type: number type: number
content: string content: string
status: number
sendTime: string sendTime: string
atUserIds?: number[] atUserIds?: number[]
receiverUserIds?: number[] receiverUserIds?: number[]
receiptStatus?: number
readCount?: number
} }
} }