聊天气泡状态(发送中/失败/已读)
气泡状态由 MessageBubble 的 status、showStatus、showReadCount、readCount、totalMembers 决定;文本由 messageStatusText 统一生成。状态流转(pending → sent/failed、已读回执)由 ChatView 监听 SDK 事件后驱动,宿主只需处理 resend/tapReadDetail 等交互。
概念
| 状态 | 气泡显示 | 触发/来源 |
|---|---|---|
sending | “发送中” | 本地乐观消息,等待 send_ack |
sent | 无额外文案(群聊可显示已读 n/m) | 收到 send_ack |
failed | “发送失败”,点击重发 | 超时/网络失败/服务端错误 |
read(群聊 n/m) | messageStatusText(status,readCount,totalMembers) | 已读回执事件 |
- 单聊
conversationType=1不显示 n/m;群聊显示已读 n/m。 - 点击“已读 n/m”触发
tapReadDetail,宿主打开已读成员列表。 - 点击失败状态触发
resend,宿主应重发同内容并更新原气泡。 MessageStatusIndicator可单独用于自定义列表/通知栏。
前置条件
- 已按 快速开始 完成
init与connect,页面能收发消息。 - 使用
@ni-paas/im-web/imkit(浏览器原生 ESM,无第三方依赖);自定义代码只调用 IMKit/IMLib 公开入口。 - 已引入默认样式:调用
ensureStyles(),或自行加载 IMKit 样式表。 - 自托管版无“UI 主题商店/付费皮肤”;所有自定义均为本地代码(不适用项)。
步骤
- 乐观插入 pending 消息
发送时先用
clientMsgId插入status="sending"的气泡;ChatView.appendMessage会自动处理 pending。 - 收到 ACK 更新状态
SDK 收到
send_ack后以messageId替换 pending;失败则标failed并 emitsendFailed。 - 接线重发
监听气泡
resend或 ChatViewsendFailed,重发后把状态改回sending。 - 接线已读
群聊设置
showReadCount:true与totalMembers;收到read_receipt后更新readCount;tapReadDetail打开明细。
参数表
| Props / 事件 / 函数 | 类型 | 说明 |
|---|---|---|
status | sending|sent|failed | 气泡状态 |
showStatus | boolean | 是否显示发送状态 |
showReadCount | boolean | 群聊是否显示 n/m |
readCount / totalMembers | number | 已读人数/群成员数 |
conversationType | number | 1 单聊不显示 n/m |
messageStatusText(status,read,total) | 函数 | 统一文案 |
resend / tapReadDetail | 事件 | 重发 / 已读明细 |
示例
自定义消息列表里的状态气泡
JavaScript
import { MessageBubble, messageStatusText, ensureStyles } from '@ni-paas/im-web/imkit';
ensureStyles();
function renderMessage(message, { isMine, readCount, totalMembers }) {
const bubble = new MessageBubble({
message,
isMine,
status: message.status || 'sent',
showStatus: isMine,
showReadCount: isMine && message.conversationType !== 1,
readCount,
totalMembers,
conversationType: message.conversationType,
});
bubble.on('resend', ({ clientMsgId, message: current }) => {
current.status = 'sending';
bubble.update({ message: current, status: 'sending' });
client.sendMessage({
conversationType: current.conversationType,
targetId: current.targetId,
content: current.content,
clientMsgId,
});
});
bubble.on('tapReadDetail', ({ messageId }) => openReadList(messageId));
return bubble;
}ChatView 的 pending / sendFailed / readReceipt
JavaScript
const chat = new ChatView({
conversationType: 2,
targetId: 'g_demo',
currentUserId: 'alice',
showReadCount: true,
});
chat.on('pending', ({ message }) => {
// 乐观气泡已插入,可在这里做“发送中”动画
console.log('pending', message.clientMsgId);
});
chat.on('sendFailed', ({ message, result }) => {
console.warn('发送失败', result && result.code, result && result.msg, message.clientMsgId);
// 气泡已是 failed;用户点击会触发 resend
});
chat.on('readReceipt', ({ messageIds, result }) => {
if (result && result.code === 0) console.log('已读回执已提交', messageIds.length);
});
// 群聊 n/m 的总人数由 ChatView 在收到回执/刷新时通过
// client.getMessageReadCount(messageId) 返回的 totalMembers 自动维护;
// 如需完全自定义,使用上面的 MessageBubble 示例并自行传入 totalMembers。常见问题
发送中/失败文案能改吗?
内置文案固定为“发送中/发送失败”;需要自定义请关掉 showStatus,用自己的节点渲染,并复用 messageStatusText 的规则。
失败后重发为什么还是失败?
检查连接是否在线、服务是否开通、是否被禁言;result.code 会给出 1009/1010/1021 等具体原因。
单聊能显示“已读”吗?
气泡默认不显示单聊 n/m;可用 messageStatusText("read") 在自定义节点中展示“已读/未读”。
已读人数不更新?
确认群成员数 totalMembers 已传入,且收到 read_receipt 后更新了 readCount。