✨ feat(im): 群聊免打扰接入后端,完善免打扰失败回滚 + ContextMenu 微调
- groupStore.setMuted 改 async,调 /im/group-member/update 推后端 - GroupMember.muted 在类型层补齐;convertGroupMember 保留 muted; loadGroupMembers 拉完成员后用当前用户那条 member.muted 回填 group.muted 与 conversation.muted,避免冷启动后服务端已免打扰的群在会话列表里仍显示为 未免打扰 - ConversationItem.handleMuted 失败回滚:catch 后 ElMessage.error 并反向 setMuted 把 conversationStore(已 saveConversations 落盘)拽回正确状态 - ContextMenu 分割线改用 h-[1px] + bg(UnoCSS 不带 border-style preflight, border-t 在空内容 div 上不显形),文案 text-center → text-left 贴近微信 - groupStore.setMuted 改 async 后,ConversationItem 里两路 setMuted 调用 都用 void 显式 fire-and-forget,风格统一im
parent
45a530e8c7
commit
a0ed0d800c
|
|
@ -11,6 +11,7 @@ import {
|
||||||
updateGroupMember as apiUpdateGroupMember,
|
updateGroupMember as apiUpdateGroupMember,
|
||||||
type ImGroupMemberRespVO
|
type ImGroupMemberRespVO
|
||||||
} from '@/api/im/group/member'
|
} from '@/api/im/group/member'
|
||||||
|
import { useUserStore } from '@/store/modules/user'
|
||||||
import { useConversationStore } from './conversationStore'
|
import { useConversationStore } from './conversationStore'
|
||||||
import { ImConversationType } from '../../utils/constants'
|
import { ImConversationType } from '../../utils/constants'
|
||||||
import type { Group, GroupMember } from '../types'
|
import type { Group, GroupMember } from '../types'
|
||||||
|
|
@ -81,17 +82,28 @@ export const useGroupStore = defineStore('imGroupStore', {
|
||||||
// 拉取该群所有成员(聚合自 AdminUser,含 nickname / avatar / displayUserName)
|
// 拉取该群所有成员(聚合自 AdminUser,含 nickname / avatar / displayUserName)
|
||||||
const list = await apiGetGroupMemberList(groupId)
|
const list = await apiGetGroupMemberList(groupId)
|
||||||
const members = (list || []).map((member) => convertGroupMember(member, groupId))
|
const members = (list || []).map((member) => convertGroupMember(member, groupId))
|
||||||
|
// 后端只在成员维度返回当前用户的 muted(apiGetMyGroupList 不带),借这次拉成员一起回填
|
||||||
|
// 否则冷启动 / 清缓存后,服务端已免打扰的群在会话列表里仍显示为未免打扰
|
||||||
|
const userStore = useUserStore()
|
||||||
|
const currentUserId = Number(userStore.getUser?.id) || 0
|
||||||
|
const me = members.find((m) => m.userId === currentUserId)
|
||||||
|
const muted = !!me?.muted
|
||||||
// 成员列表可能在群列表之前触发,此时需要占位一个 group
|
// 成员列表可能在群列表之前触发,此时需要占位一个 group
|
||||||
if (!group) {
|
if (!group) {
|
||||||
this.upsertGroup({
|
this.upsertGroup({
|
||||||
id: groupId,
|
id: groupId,
|
||||||
name: String(groupId),
|
name: String(groupId),
|
||||||
members,
|
members,
|
||||||
memberCount: members.length
|
memberCount: members.length,
|
||||||
|
muted
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
group.members = members
|
group.members = members
|
||||||
group.memberCount = members.length
|
group.memberCount = members.length
|
||||||
|
group.muted = muted
|
||||||
|
// 已有 group 分支没走 upsertGroup,单独把 muted 推回 conversation 保证会话列表展示一致
|
||||||
|
const conversationStore = useConversationStore()
|
||||||
|
conversationStore.updateConversation(ImConversationType.GROUP, groupId, { muted })
|
||||||
}
|
}
|
||||||
return members
|
return members
|
||||||
},
|
},
|
||||||
|
|
@ -158,7 +170,8 @@ function convertGroupMember(member: ImGroupMemberRespVO, groupId: number): Group
|
||||||
avatar: member.avatar,
|
avatar: member.avatar,
|
||||||
displayUserName: member.displayUserName,
|
displayUserName: member.displayUserName,
|
||||||
displayGroupName: member.displayGroupName,
|
displayGroupName: member.displayGroupName,
|
||||||
status: member.status
|
status: member.status,
|
||||||
|
muted: member.muted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,7 @@ export interface GroupMember {
|
||||||
displayUserName?: string // 组内显示名(不与 nickname 合并,由消费方按需取舍)
|
displayUserName?: string // 组内显示名(不与 nickname 合并,由消费方按需取舍)
|
||||||
displayGroupName?: string // 群显示备注(当前用户对该群的自定义名)
|
displayGroupName?: string // 群显示备注(当前用户对该群的自定义名)
|
||||||
status?: number // 在群 / 退群状态,对齐 CommonStatusEnum
|
status?: number // 在群 / 退群状态,对齐 CommonStatusEnum
|
||||||
|
muted?: boolean // 当前成员对该群的免打扰开关(loadGroupMembers 用它回填 Group.muted)
|
||||||
|
|
||||||
// ========== 前端扩展字段 ==========
|
// ========== 前端扩展字段 ==========
|
||||||
isOwner?: boolean // 是否群主(前端从 Group.ownerUserId 计算)
|
isOwner?: boolean // 是否群主(前端从 Group.ownerUserId 计算)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue