代码改变世界

微信小程序(uniapp)搭建腾讯云 IM 消息撤回

2025-10-05 08:13  tlnshuju  阅读(0)  评论(0)    收藏  举报

uniapp 实现腾讯云 IM 消息撤回功能实战指南

一、功能实现原理

腾讯云 IM 的消息撤回功能通过 消息修订(Message Revision) 机制实现,核心流程如下:

  1. 发送方调用撤回 API 删除指定消息
  2. 云端生成撤回通知消息(类型为 TIM.TYPES.MSG_REVOKED
  3. 接收方收到通知后执行本地消息删除
  4. 全平台自动同步消息状态(需开启消息漫游)

二、核心实现步骤

1. 发送方撤回逻辑

// services/im.js
export
async
function revokeMessage(message
) {
const tim = initIM(
)
try {
// 执行消息撤回操作
const res =
await tim.revokeMessage(message)
// 更新本地消息状态(立即生效)
if (res.data.revokeMessage) {
const conv = tim.getConversationProfile(message.conversationID)
conv.setMessageRevoked(message.clientMsgID)
}
return res
}
catch (error) {
console.error('撤回失败:'
, error)
throw
new Error('消息撤回失败,请检查网络'
)
}
}

2. 接收方消息处理

// 消息监听器(全局注册)
export
function setupMessageListener(callback
) {
const tim = initIM(
)
tim.on(tim.EVENT.MESSAGE_RECEIVED
, (event
) =>
{
event.data.forEach(msg =>
{
// 处理撤回通知
if (msg.type === tim.TYPES.MSG_REVOKED
) {
handleRevokeNotice(msg)
return
}
callback(msg)
}
)
}
)
}
// 撤回通知处理
function handleRevokeNotice(notice
) {
const {
revokedMessageClientMsgID, operator
} = notice.payload
// 查找本地对应消息
const conversation = tim.getConversationProfile(notice.conversationID)
const originalMsg = conversation.getMessage(revokedMessageClientMsgID)
if (!originalMsg)
return
// 权限验证(仅允许发送者撤回)
if (originalMsg.from !== operator.userID) {
console.warn('非法撤回操作'
, operator)
return
}
// 执行本地删除
conversation.deleteMessage(revokedMessageClientMsgID)
// 触发UI更新(示例)
uni.$emit('message-revoked'
, {
conversationID: notice.conversationID,
clientMsgID: revokedMessageClientMsgID
}
)
}

3. UI 层集成示例

<template>
    <view class="message-list">
    <view
      v-for="(msg, index) in messages"
      :key="msg.clientMsgID"
      class="message-item"
    >
    <!-- 消息内容 -->
        <template v-if="!msg.isRevoked">
        {{ msg.payload.text }}
      </template>
      <!-- 撤回提示 -->
          <view v-else class="revoked-tip">
          "{{ msg.payload.description }}" 已被撤回
        </view>
        <!-- 长按操作菜单 -->
          <view
            v-if="canRevoke(msg)"
            class="action-menu"
            @longpress
          ="showActionSheet(msg)"
          ></view>
      </view>
    </view>
  </template>
  <script>
    export
    default {
    data(
    ) {
    return {
    messages: []
    }
    }
    ,
    methods: {
    // 权限校验
    canRevoke(msg
    ) {
    return msg.from ===
    this.currentUser.userID &&
    !msg.isRevoked &&
    Date.now(
    ) - msg.time <
    2 * 60 * 1000 // 2分钟内可撤回
    }
    ,
    // 执行撤回
    async handleRevoke(msg
    ) {
    try {
    await revokeMessage(msg)
    uni.showToast({
    title: '撤回成功'
    , icon: 'none'
    }
    )
    }
    catch (error) {
    uni.showToast({
    title: error.message, icon: 'none'
    }
    )
    }
    }
    }
    }
  </script>

三、关键问题处理

1. 撤回时间限制

// 配置中心(建议)
const IM_CONFIG = {
REVOKE_TIME_LIMIT: 2 * 60 * 1000 // 2分钟
}
// 权限校验时使用
if (Date.now(
) - msg.time >
IM_CONFIG.REVOKE_TIME_LIMIT
) {
throw
new Error('超过可撤回时间'
)
}

2. 消息状态同步

// 消息漫游配置(初始化时)
tim = TIM.create({
SDKAppID: config.SDKAppID
}
)
// 开启消息漫游(需在控制台配置)
tim.setMessageRevokeMode({
mode: TIM.TYPES.REVOKE_MODE_SENDER
, // 仅发送方可撤回
syncOtherMachine: true // 同步到其他端
}
)

3. 异常场景处理

// 撤回失败重试机制
export
async
function revokeWithRetry(msg, retries = 3
) {
try {
return
await revokeMessage(msg)
}
catch (error) {
if (retries <= 0
)
throw error
await
new Promise(resolve =>
setTimeout(resolve, 1000
)
)
return revokeWithRetry(msg, retries - 1
)
}
}

四、高级功能扩展

1. 富媒体消息撤回

// 自定义撤回描述(图片/文件等)
function getRevokeDescription(msg
) {
switch(msg.type) {
case TIM.TYPES.MSG_IMAGE:
return '[图片]'
case TIM.TYPES.MSG_FILE:
return '[文件]'
case TIM.TYPES.MSG_CUSTOM:
return JSON.parse(msg.payload.data).description || '[自定义消息]'
default:
return msg.payload.text || '[未知消息]'
}
}

2. 撤回动画效果

/* 添加CSS过渡 */
.message-item.revoking {
animation: fadeOut 0.3s forwards;
}
@keyframes fadeOut {
to {
opacity: 0;
transform: translateX(20px)
;
}
}

3. 服务端日志记录

// 撤回事件上报(示例)
async
function logRevokeEvent(msg, operator
) {
await axios.post('/api/im/revoke-log'
, {
sdk_app_id: process.env.SDKAppID,
group_id: msg.groupID,
operator_id: operator.userID,
target_msg_id: msg.clientMsgID,
timestamp: Date.now(
)
}
)
}

五、常见问题排查

  1. Q: 撤回后对方仍显示消息
    A: 检查消息漫游是否开启,确认双方客户端版本 ≥ 2.15.0

  2. Q: 无法撤回超过2分钟的消息
    A: 腾讯云默认限制为2分钟,需在控制台申请延长权限

  3. Q: 群聊中非群主成员撤回失败
    A: 确认群类型是否为 Private(私有群),Public 群需群主操作

  4. Q: 撤回通知不显示描述
    A: 检查自定义消息解析逻辑,确保 payload 格式正确

六、性能优化建议

  1. 使用 tim.getMessageRevokeStatus() 批量查询消息状态
  2. 对已撤回消息进行本地缓存,避免重复查询
  3. 添加防抖处理,防止快速连续撤回导致性能问题