微信小程序(uniapp)搭建腾讯云 IM 消息撤回
2025-10-05 08:13 tlnshuju 阅读(0) 评论(0) 收藏 举报uniapp 实现腾讯云 IM 消息撤回功能实战指南
一、功能实现原理
腾讯云 IM 的消息撤回功能通过 消息修订(Message Revision) 机制实现,核心流程如下:
- 发送方调用撤回 API 删除指定消息
- 云端生成撤回通知消息(类型为
TIM.TYPES.MSG_REVOKED
) - 接收方收到通知后执行本地消息删除
- 全平台自动同步消息状态(需开启消息漫游)
二、核心实现步骤
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(
)
}
)
}
五、常见问题排查
Q: 撤回后对方仍显示消息
A: 检查消息漫游是否开启,确认双方客户端版本 ≥ 2.15.0Q: 无法撤回超过2分钟的消息
A: 腾讯云默认限制为2分钟,需在控制台申请延长权限Q: 群聊中非群主成员撤回失败
A: 确认群类型是否为 Private(私有群),Public 群需群主操作Q: 撤回通知不显示描述
A: 检查自定义消息解析逻辑,确保 payload 格式正确
六、性能优化建议
- 使用
tim.getMessageRevokeStatus()
批量查询消息状态 - 对已撤回消息进行本地缓存,避免重复查询
- 添加防抖处理,防止快速连续撤回导致性能问题