uniapp 实现腾讯云 IM 消息已读回执
uniapp 实现腾讯云 IM 消息已读回执处理全攻略
一、功能实现原理
腾讯云 IM 的已读回执功能通过 消息已读上报机制
实现,核心流程如下:
- 接收方阅读消息时,客户端自动上报已读状态
- 云端记录最新已读时间戳(精确到会话维度)
- 发送方通过监听事件获取接收方的已读状态
- 群聊场景支持显示已读成员列表(需开通高级功能)
二、核心实现步骤
1. 发送消息时启用已读回执
// 创建文本消息(启用已读回执)
export function createTextMessageWithReceipt(options) {const tim = initIM()return tim.createTextMessage({to: options.to,conversationType: options.type || 'C2C',payload: { text: options.content },cloudCustomData: JSON.stringify({needReadReceipt: true // 启用已读回执})})
}
2. 接收方自动上报已读
// 初始化时配置自动已读
tim = TIM.create({SDKAppID: config.SDKAppID
})// 进入会话时标记消息为已读
export async function markConversationRead(conversationID) {const tim = initIM()const conv = tim.getConversationProfile(conversationID)// 获取最后一条消息const lastMsg = conv.getLastMessage()if (!lastMsg) return// 上报已读到最新消息await tim.messageReportedRead({conversationID,lastMsgID: lastMsg.clientMsgID})
}
3. 监听已读回执通知
// 全局消息监听器
export function setupMessageListener(callback) {const tim = initIM()tim.on(tim.EVENT.MESSAGE_READ_BY_PEER, (event) => {const { data } = event// 更新本地消息状态data.forEach(receipt => {const conv = tim.getConversationProfile(receipt.conversationID)conv.setMessageRead(receipt.messageKey.clientMsgID)// 触发UI更新uni.$emit('message-read', {conversationID: receipt.conversationID,msgID: receipt.messageKey.clientMsgID,reader: receipt.reader})})})
}
4. 群聊已读成员处理
// 获取群聊已读成员列表
export async function getGroupReadMembers(groupID, msg) {const tim = initIM()try {const res = await tim.getGroupMessageReadMembersList({groupID,messageKey: tim.createMessageKey(msg.clientMsgID)})return res.data.readMemberList || []} catch (error) {console.error('获取已读成员失败:', error)return []}
}
三、关键问题处理
1. 性能优化策略
// 批量上报已读(防抖处理)
let readReportDebounce = nullexport function batchReportRead(conversationID, lastMsgID) {clearTimeout(readReportDebounce)readReportDebounce = setTimeout(async () => {try {await tim.messageReportedRead({conversationID,lastMsgID})} catch (error) {console.warn('批量上报失败:', error)}}, 500) // 500ms防抖
}
2. 隐私保护方案
// 用户隐私设置(示例)
const PRIVACY_CONFIG = {DISABLE_READ_RECEIPT: false // 用户是否关闭已读回执
}// 发送消息时动态判断
export function createMessage(options) {const tim = initIM()return tim.createTextMessage({...,cloudCustomData: JSON.stringify({needReadReceipt: !PRIVACY_CONFIG.DISABLE_READ_RECEIPT})})
}
3. 跨平台差异处理
// 微信小程序特殊处理
#ifdef MP-WEIXIN
// 修复小程序页面切换导致的已读上报延迟
Page({onHide() {const lastMsg = getCurrentPage().data.lastMsgif (lastMsg) batchReportRead(lastMsg.conversationID, lastMsg.clientMsgID)}
})
#endif
四、高级功能扩展
1. 已读状态可视化
<template><view class="message-item" :class="{ 'is-read': msg.isPeerRead }">{{ msg.payload.text }}<!-- 群聊已读状态 --><view v-if="isGroup && msg.isPeerRead" class="read-status">{{ readCount }}人已读</view></view>
</template><script>
export default {props: ['msg', 'isGroup'],computed: {readCount() {return this.msg.readCount || 0}}
}
</script>
2. 定时同步已读状态
// 定时任务配置(每5分钟同步)
setInterval(async () => {const tim = initIM()const convList = await tim.getConversationList()convList.forEach(conv => {const lastMsg = conv.getLastMessage()if (lastMsg && !lastMsg.isPeerRead) {tim.messageReportedRead({conversationID: conv.conversationID,lastMsgID: lastMsg.clientMsgID})}})
}, 5 * 60 * 1000)
3. 业务逻辑集成
// 客服场景:自动标记为已读
export function autoReadMessages(conversationID) {const tim = initIM()const conv = tim.getConversationProfile(conversationID)// 获取未读消息列表const unreadMsgs = conv.getUnreadMessageList()// 批量标记为已读unreadMsgs.forEach(msg => {conv.setMessageRead(msg.clientMsgID)})
}
五、常见问题排查
-
Q: 已读回执未触发
A: 检查消息的cloudCustomData
是否包含needReadReceipt: true
,确认接收方版本 ≥ 2.18.0 -
Q: 群聊已读人数不准确
A: 需在控制台开通「群消息已读回执」增值服务,并确保使用最新版 SDK -
Q: 已读状态同步延迟
A: 检查网络状况,已读回执默认使用长轮询,可升级到 WebSocket 连接 -
Q: 消息漫游后状态丢失
A: 确保消息漫游策略包含已读状态(需在控制台配置)
六、最佳实践建议
- 重要消息(如系统通知)强制启用已读回执
- 对长文本消息采用分片上报策略(每10条上报一次)
- 结合消息优先级实现差异化已读策略(如@消息优先处理)
- 在消息列表展示最近已读时间(使用
TIM.TYPES.CONV_LAST_MSG
)