Skip to content

互动消息聊天指南

本文介绍互动消息相关功能的使用方法,包括消息收发、历史消息、消息撤回和私聊。

发送消息

文本消息

typescript
const result = await classroom.sendTextMessage('大家好!');
if (!result.ok) {
  console.error('发送失败:', result.message);
}

图片消息

typescript
// 选择文件后发送(自动上传 COS)
const fileInput = document.querySelector<HTMLInputElement>('#image-input');
const file = fileInput?.files?.[0];
if (file) {
  const result = await classroom.sendImageMessage(file);
  if (!result.ok) console.error('图片发送失败:', result.message);
}

文件消息

typescript
const file = fileInput.files[0];
const result = await classroom.sendFileMessage(file);
if (!result.ok) {
  console.error('文件发送失败:', result.message);
}

自定义消息

typescript
// 发送自定义消息(content 会被序列化为 JSON 字符串)
const result = await classroom.sendCustomMessage({
  type: 'emoji',
  emojiId: 'thumbs_up',
});

私聊消息

typescript
// 发送定向私聊消息(仅目标用户可见)
const result = await classroom.sendDirectedMessage('user_002', '你好,有问题想请教');
if (!result.ok) {
  console.error('私聊发送失败:', result.message);
}

接收消息

通过响应式状态订阅消息列表

订阅完整消息列表(包含历史消息 + 实时新消息)

typescript
classroom.state.messageList$.subscribe(messages => {
  renderMessageList(messages);
});

通过事件监听新消息

监听新消息(用于触发通知/滚动等 UI 操作)

typescript
import { TEvent } from '@tencent-classroom/sdk';

classroom.on(TEvent.RECV_MESSAGE, (message) => {
  console.log('新消息:', message.content);
  scrollToBottom();
  showNotification(message);
});

解析展示私聊消息标识

messageList$ 中包含公聊消息 + 与自己相关的私聊消息。

私聊消息通过 message.ext(即 IM 的 cloudCustomData)中的字段标识:

typescript
interface MessageExt {
  IsPrivateMsg?: boolean;      // 是否为私聊消息
  PrivateInfo?: {
    From: { ID: string };      // 发送者 userId
    To: { ID: string };        // 接收者 userId
  };
}

解析示例:

typescript
classroom.state.messageList$.subscribe((messages) => {
  for (const msg of messages) {
    // 解析 ext 字段
    const ext = typeof msg.ext === 'string' ? JSON.parse(msg.ext || '{}') : (msg.ext || {});

    if (ext.IsPrivateMsg) {
      // 这是一条私聊消息
      const fromId = ext.PrivateInfo?.From?.ID;
      const toId = ext.PrivateInfo?.To?.ID;
      renderPrivateMessage(msg, fromId, toId);
    } else {
      // 普通公聊消息
      renderPublicMessage(msg);
    }
  }
});

messageList$ 的过滤规则

SDK 内部已确保 messageList$ 只包含:

  • 所有公聊消息(Text / Image / File 类型)
  • 与当前用户相关的私聊消息(自己是发送者 From 或接收者 To)

其他用户之间的私聊消息不会出现在列表中,业务层无需再做可见性判断。

历史消息

typescript
// 拉取历史消息(增量拉取,不重复)
const result = await classroom.fetchHistoryMessages(20); // 默认 20 条
if (result.ok) {
  console.log('历史消息:', result.data);
}

// 继续拉取更多
const moreResult = await classroom.fetchHistoryMessages(20);

提示:进房时 SDK 会自动拉取一次历史消息并写入 state.messageList$,通常无需手动调用。

消息撤回

typescript
// 撤回自己的消息(所有角色可撤回自己的消息)
const result = await classroom.revokeMessage(message.id);
if (!result.ok) {
  console.error('撤回失败:', result.message);
}

// 老师/助教撤回他人消息(按 IM 序列号)
await classroom.revokeClassMessage(message.seq);

监听消息撤回事件:

typescript
classroom.on(TEvent.MESSAGE_REVOKED, ({ msgId }) => {
  console.log('消息已被撤回:', msgId);
});

未读管理

typescript
// 订阅未读消息数
classroom.state.messageUnreadCount$.subscribe(count => {
  updateBadge(count);
});

// 标记全部已读
classroom.markAllMessagesAsRead();

// 标记指定序列号以前的消息为已读
classroom.markMessageAsRead(latestSeq);

聊天模式控制

老师/助教可控制课堂聊天模式:

typescript
// 设置聊天模式
await classroom.setSilenceMode('freeChat');      // 自由聊天
await classroom.setSilenceMode('publicOnly');    // 仅公开消息
await classroom.setSilenceMode('privateOnly');   // 仅私聊
await classroom.setSilenceMode('muteAll');       // 全员禁言

// 订阅禁言模式变化
classroom.state.silenceMode$.subscribe(mode => {
  console.log('当前聊天模式:', mode);
});

检查发送权限

typescript
// 检查当前用户是否可发送消息
if (classroom.canSendChatMessage()) {
  // 可以发送
} else {
  showToast('当前处于禁言状态');
}

相关 API