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

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 errorawait 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. 添加防抖处理,防止快速连续撤回导致性能问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/83055.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI入门示例

市面上有很多AI大模型&#xff0c;这里以 智谱的大模型 为示例 1.先要注册智谱AI开放平台 2.注册成功后&#xff0c;会赠送3个月的免费额度&#xff0c;如下 3.然后去控制台&#xff0c;创建一个API KEY 4.接着就可以开始写代码了 提前导入包&#xff1a; openai 示例1&…

【数据结构】单链表练习

1.链表的中间节点 https://leetcode.cn/problems/middle-of-the-linked-list/description/ 用快慢指针来解决 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode* middleNode(struct ListNode* he…

尝鲜纯血鸿蒙,华为国际版本暂时不支持升级。如mateX6 国际版?为什么不支持?什么时候支持?

一&#xff1a;mateX6 国际版支持鸿蒙吗&#xff1f; 不支持 二&#xff1a;华为国际版支持鸿蒙吗&#xff1f; 不支持 三&#xff1a;华为国际版什么时候支持&#xff1f; 2025年预期可以支持。请耐心等待。 三&#xff1a;国际版为什么不支持&#xff1f; EMUI 采用AO…

Spring Boot的启动流程,以及各个扩展点的执行顺序

目录 1. 初始化阶段执行顺序 1.1 Bean的构造方法&#xff08;构造函数&#xff09; 1.2 PostConstruct 注解方法 1.3 InitializingBean 的 afterPropertiesSet() 1.4 Bean(initMethod "自定义方法") 2. 上下文就绪后的扩展点 2.1 ApplicationContext 事件监听…

刀具问题讨论

1 刀具的问题概述 问题描述 一道工序用自动化车床连续加工某种零件&#xff0c;由于刀具损坏等原因该工序会出现故障&#xff0c;其中刀具损坏故障占95%, 其它故障仅占 5%。工序出现故障是完全随机的, 假定在生产任一零件时出现故障的机会均相同。工作人员通过检查零件来确定…

vite配置一个css插件

vite.config.js的plugins执行函数 该例子只是替换一些css,具体内容不重要,主要看形参的运用 // vite-plugin-css.js export default function cssPlugin() {return {name: vite-plugin-css-post, // 插件的名字&#xff0c;Vite 插件必须有名字enforce: post, // 设定插件执…

✨1.1.1 按位与运算替代求余运算优化场景

在计算机编程中&#xff0c;使用按位与运算&#xff08;&&#xff09;替代求余运算&#xff08;%&#xff09;可以提高效率的特殊场景是&#xff1a;当除数是 2 的整数次幂&#xff08;即 ( b 2^n )&#xff0c;其中 ( n ) 为自然数&#xff09;时。例如&#xff0c;( b …

CentOS 7 环境中部署 LNMP(Linux + Nginx + MySQL 5.7 + PHP)

在 CentOS 7 环境中部署 LNMP&#xff08;Linux Nginx MySQL 5.7 PHP&#xff09; 环境的详细步骤如下。此方案确保各组件版本兼容&#xff0c;并提供完整的配置验证流程。 1. 更新系统 sudo yum update -y 2. 安装 MySQL 5.7 2.1 添加 MySQL 官方 YUM 仓库 由于MySQL并不…

UniApp微信小程序自定义导航栏实现

UniApp微信小程序自定义导航栏 在UniApp开发微信小程序时&#xff0c;页面左上角默认有一个返回按钮&#xff08;在导航栏左侧&#xff09;&#xff0c;但有时我们需要自定义这个按钮的样式和功能&#xff0c;同时保持与导航栏中间的标题和右侧胶囊按钮&#xff08;药丸屏&…

Java大师成长计划之第35天:未来展望与个人总结

引言 作为一门历史悠久的编程语言&#xff0c;Java自1995年问世以来&#xff0c;经历了多个版本的迭代与演进&#xff0c;依然在当今技术生态中占据着重要地位。从早期的Java SE、Java EE到后来的Java Spring框架&#xff0c;再到现代的微服务架构与云原生应用&#xff0c;Jav…

Ubuntu开机自动运行Docker容器中的Qt UI程序

Ubuntu开机自动运行Docker容器中的Qt UI程序 引言为什么需要这样配置?解决方案概览详细实现步骤1. 创建容器启动脚本2. 创建系统服务3. 配置自动登录和显示设置常见问题解决方案1. 程序无法显示(X11权限问题)2. 分辨率设置不生效3. 服务启动失败安全注意事项结语附录:完整文…

Scratch节日 | 龙舟比赛 | 端午节

端午节快乐&#xff01; 这款专为孩子们打造的Scratch游戏——《龙舟比赛》&#xff0c;让你在掌控龙舟的竞速中&#xff0c;沉浸式体验中华传统节日的魅力&#xff01; &#x1f3ae; 游戏亮点 节日氛围浓厚&#xff1a;化身龙舟选手&#xff0c;在波涛汹涌的河流中展开刺激竞…

(五)MMA(OpenTelemetry/Rabbit MQ/ApiGateway/MongoDB)

文章目录 项目地址一、OpenTelemetry1.1 配置OpenTelemetry1. 服务添加2. 添加服务标识3. 添加请求的标识4. 添加中间价 二、Rabbit MQ2.1 配置Rabbit MQ1. docker-compose2. 添加Rabbit MQ的Connect String 2.2 替换成Rabbit MQ1. 安装所需要的包2. 使用 三、API Gateways3.1 …

格恩朗超声波水表 助力农业精准灌溉与振兴​

在农业现代化的征程中&#xff0c;水资源的精准利用至关重要&#xff0c;而这离不开高精度计量设备的支持。大连格恩朗品牌积极响应国家全面推进乡村振兴、加快农业农村现代化的号召&#xff0c;精心打造的超声波水表&#xff0c;凭借其超高精度&#xff0c;成为绿色灌溉领域的…

微信小程序页面嵌套web-view点击系统导航返回时进行弹窗处理

实现效果&#xff1a;微信小程序页面嵌套web-view点击系统导航返回时进行弹窗处理 首先在web-view里是不可实现的&#xff08;据我了解下来&#xff09; 参考小程序文档&#xff1a;page-container 大致逻辑&#xff1a; 1、page-container可实现页面离开前拦截 2、由于web-vie…

设计模式25——中介者模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 中介者模式&#xff08;Mediat…

Java基础 Day25

一、线程通信 1、简介 确保线程能够按照预定的顺序执行并且能够安全地访问共享资源 使多条线程更好的进行协同工作 2、常用方法 void wait() 使当前线程进入等待状态 void notify(); 随机唤醒单个等待的线程&#xff08;可以空唤醒&#xff09; void notifyAll(); 唤醒…

WebSocket与实时对话式AI服务的集成

WebSocket与实时对话式AI服务的集成 在现代对话式AI系统中,传统的HTTP请求-响应模型已难以满足实时交互的体验需求。特别是用户对响应速度、逐字输出、会话上下文保持等方面提出更高要求时,需要一种能够建立持久连接并支持双向通信的协议。WebSocket正是在这一背景下,成为A…

iOS 集成网易云信IM

云信官方文档在这 看官方文档的时候&#xff0c;版本选择最新的V10。 1、CocoPods集成 pod NIMSDK_LITE 2、AppDelegate.m添加头文件 #import <NIMSDK/NIMSDK.h> 3、初始化 NIMSDKOption *mrnn_option [NIMSDKOption optionWithAppKey:"6f6568e354026d2d658a…

人工智能100问☞第37问:什么是扩散模型?

目录 ​​一、通俗解释 二、专业解析​​ 三、权威参考 扩散模型是一种​​通过系统性地添加再去除噪声来生成新数据(如图像)的生成式AI技术​​,其核心机制分为两个阶段:正向扩散​​:对原始数据(如清晰图片)逐步添加噪声,直至完全变成随机噪点(类似老照片逐渐模糊…