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
YunaiV 2026-04-27 09:03:18 +08:00
parent 7f84c428a5
commit 6add0b0600
1 changed files with 17 additions and 10 deletions

View File

@ -71,7 +71,7 @@
<script lang="ts" setup>
import { computed } from 'vue'
import { ElMessageBox } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
import dayjs from 'dayjs'
import Icon from '@/components/Icon/src/Icon.vue'
@ -146,19 +146,26 @@ function handleTop() {
}
/**
* 切换免打扰会话级 muted 立刻同步friend / group 侧在后台异步推后端 + 落本地
* 切换免打扰乐观 UI先落本地再异步推后端失败回滚 + 提示
*
* await friend / group setMutedUI 已经通过 conversationStore.setMuted 完成视觉切换
* 后台 /im/friend/update / /im/group-member/update void fire-and-forget
* awaitUI 已经通过 conversationStore.setMuted 完成视觉切换菜单立即关闭
* 后端 /im/friend/update / /im/group-member/update conversationStore
* 避免本地已经 saveConversations IndexedDB跟服务端长期不一致
* friend / group 自身的 setMuted await 失败时不会落本地只有 conversation 需要回滚
*/
function handleMuted() {
const next = !props.conversation.muted
conversationStore.setMuted(props.conversation.type, props.conversation.targetId, next)
if (props.conversation.type === ImConversationType.PRIVATE) {
void friendStore.setMuted(props.conversation.targetId, next)
} else {
void groupStore.setMuted(props.conversation.targetId, next)
}
const { type, targetId } = props.conversation
conversationStore.setMuted(type, targetId, next)
const sync =
type === ImConversationType.PRIVATE
? friendStore.setMuted(targetId, next)
: groupStore.setMuted(targetId, next)
sync.catch((e) => {
console.error('[IM] 切换免打扰失败', e)
ElMessage.error('切换免打扰失败')
conversationStore.setMuted(type, targetId, !next)
})
}
/** 删除会话:二次确认后软删(用户取消走 catch 静默) */