简介

本文主要介绍如何快速地将腾讯云 IM SDK 集成到您的 Web 项目中。
腾讯云即时通信IM SDK API 文档
示例demo下载

tim-js-sdk 功能扩展 (好友接口)

准备工作

  1. 在腾讯云官网上创建应用,获取到相应的SDKAppID和相应的秘钥信息
  2. 安装sdk

集成 SDK

// IM Web SDK
// 从v2.11.2起,SDK 支持了 WebSocket,推荐接入;v2.10.2及以下版本,使用 HTTP
npm install tim-js-sdk --save
// 发送图片、文件等消息需要腾讯云即时通信 IM 上传插件
npm install tim-upload-plugin --save

在项目脚本里引入模块。

// 从v2.11.2起,SDK 支持了 WebSocket,推荐接入;v2.10.2及以下版本,使用 HTTP
import TIM from 'tim-js-sdk';
import TIMUploadPlugin from 'tim-upload-plugin';
let options = {
 SDKAppID: xxxxxxxx // 接入时需要将0替换为您的即时通信 IM 应用的 SDKAppID
};
// 创建 SDK 实例,`TIM.create()`方法对于同一个 `SDKAppID` 只会返回同一份实例
let tim = TIM.create(options); // SDK 实例通常用 tim 表示
// 设置 SDK 日志输出级别,详细分级请参见 <a href="https://web.sdk.qcloud.com/im/doc/zh-cn//SDK.html#setLogLevel">setLogLevel 接口的说明</a>
tim.setLogLevel(0); // 普通级别,日志量较多,接入时建议使用
// tim.setLogLevel(1); // release 级别,SDK 输出关键信息,生产环境时建议使用
// 注册腾讯云即时通信 IM 上传插件
tim.registerPlugin({'tim-upload-plugin': TIMUploadPlugin});

初始化与登录(Web)

1. 创建 SDK 实例
请参考上面的集成SDK方法

2. 事件绑定

// 监听事件,例如:
tim.on(TIM.EVENT.SDK_READY, function(event) {
// 收到离线消息和会话列表同步完毕通知,接入侧可以调用 sendMessage 等需要鉴权的接口
// event.name - TIM.EVENT.SDK_READY
});
tim.on(TIM.EVENT.MESSAGE_RECEIVED, function(event) {
// 收到推送的单聊、群聊、群提示、群系统通知的新消息,可通过遍历 event.data 获取消息列表数据并渲染到页面
// event.name - TIM.EVENT.MESSAGE_RECEIVED
// event.data - 存储 Message 对象的数组 - [Message]
});
tim.on(TIM.EVENT.MESSAGE_REVOKED, function(event) {
// 收到消息被撤回的通知
// event.name - TIM.EVENT.MESSAGE_REVOKED
// event.data - 存储 Message 对象的数组 - [Message] - 每个 Message 对象的 isRevoked 属性值为 true
});
tim.on(TIM.EVENT.MESSAGE_READ_BY_PEER, function(event) {
// SDK 收到对端已读消息的通知,即已读回执。使用前需要将 SDK 版本升级至 v2.7.0 或以上。仅支持单聊会话。
// event.name - TIM.EVENT.MESSAGE_READ_BY_PEER
// event.data - event.data - 存储 Message 对象的数组 - [Message] - 每个 Message 对象的 isPeerRead 属性值为 true
});
tim.on(TIM.EVENT.CONVERSATION_LIST_UPDATED, function(event) {
// 收到会话列表更新通知,可通过遍历 event.data 获取会话列表数据并渲染到页面
// event.name - TIM.EVENT.CONVERSATION_LIST_UPDATED
// event.data - 存储 Conversation 对象的数组 - [Conversation]
});
tim.on(TIM.EVENT.GROUP_LIST_UPDATED, function(event) {
// 收到群组列表更新通知,可通过遍历 event.data 获取群组列表数据并渲染到页面
// event.name - TIM.EVENT.GROUP_LIST_UPDATED
// event.data - 存储 Group 对象的数组 - [Group]
});
tim.on(TIM.EVENT.PROFILE_UPDATED, function(event) {
// 收到自己或好友的资料变更通知
// event.name - TIM.EVENT.PROFILE_UPDATED
// event.data - 存储 Profile 对象的数组 - [Profile]
});
tim.on(TIM.EVENT.BLACKLIST_UPDATED, function(event) {
// 收到黑名单列表更新通知
// event.name - TIM.EVENT.BLACKLIST_UPDATED
// event.data - 存储 userID 的数组 - [userID]
});
tim.on(TIM.EVENT.ERROR, function(event) {
// 收到 SDK 发生错误通知,可以获取错误码和错误信息
// event.name - TIM.EVENT.ERROR
// event.data.code - 错误码
// event.data.message - 错误信息
});
tim.on(TIM.EVENT.SDK_NOT_READY, function(event) {
// 收到 SDK 进入 not ready 状态通知,此时 SDK 无法正常工作
// event.name - TIM.EVENT.SDK_NOT_READY
});
tim.on(TIM.EVENT.KICKED_OUT, function(event) {
// 收到被踢下线通知
// event.name - TIM.EVENT.KICKED_OUT
// event.data.type - 被踢下线的原因,例如:
//    - TIM.TYPES.KICKED_OUT_MULT_ACCOUNT 多实例登录被踢
//    - TIM.TYPES.KICKED_OUT_MULT_DEVICE 多终端登录被踢
//    - TIM.TYPES.KICKED_OUT_USERSIG_EXPIRED 签名过期被踢 (v2.4.0起支持)。 
});
tim.on(TIM.EVENT.NET_STATE_CHANGE, function(event) { 
//  网络状态发生改变(v2.5.0 起支持)。 
// event.name - TIM.EVENT.NET_STATE_CHANGE 
// event.data.state 当前网络状态,枚举值及说明如下: 
//     \- TIM.TYPES.NET_STATE_CONNECTED - 已接入网络 
//     \- TIM.TYPES.NET_STATE_CONNECTING - 连接中。很可能遇到网络抖动,SDK 在重试。接入侧可根据此状态提示“当前网络不稳定”或“连接中” 
//    \- TIM.TYPES.NET_STATE_DISCONNECTED - 未接入网络。接入侧可根据此状态提示“当前网络不可用”。SDK 仍会继续重试,若用户网络恢复,SDK 会自动同步消息  
});
// 开始登录 
tim.login({userID: 'your userID', userSig: 'your userSig'});

3. 登录

用户登录 IM SDK 才能正常收发消息,登录需要用户提供 UserID、UserSig 等信息,具体含义请参见 登录鉴权。登录成功后,需要先等 SDK 处于 ready 状态才能调用 sendMessage 等需要鉴权的接口,您可以通过监听事件 TIM.EVENT.SDK_READY 获取 SDK 状态。

// userID [String] 用户 ID。
// userSig [String] 用户登录即时通信 IM 的密码,其本质是对 UserID 等信息加密后得到的密文。具体生成方法请参见 生成 UserSig。
tim.login({userID: xxx, userSig: xxx});

返回值

该接口返回 Promise 对象。

tim.login({userID: 'your userID', userSig: 'your userSig'})
	.then(function(imResponse) {
		console.log(imResponse.data); // 登录成功
		if (imResponse.data.repeatLogin === true) {
		  // 标识账号已登录,本次登录操作为重复登录。v2.5.1 起支持
		  console.log(imResponse.data.errorInfo);
		}
	}).catch(function(imError) {
		console.warn('login error:', imError); // 登录失败的相关信息
	});

4. 登出

// then的回调函数参数为 IMResponse,IMResponse.data为空对象。表示成功登出
tim.logout().then(function(imResponse) {
		console.log(imResponse.data); // 登出成功
	}).catch(function(imError) {
		console.warn('logout error:', imError);
	});

消息收发(Web)

一. 发送消息

发送消息需先创建消息内容对象, 再通过发送消息接口发送消息给指定用户或群组

1. 创建文本消息

tim.createTextMessage({
	// [String] 消息接收方的 userID 或 groupID
	to,
	// [String] 会话类型,取值TIM.TYPES.CONV_C2C(端到端会话)或TIM.TYPES.CONV_GROUP(群组会话)
	conversationType,
	// [String] 消息优先级(默认值: TIM.TYPES.MSG_PRIORITY_NORMAL)
	priority,
	// [Object] 消息内容的容器
	payload
})

payload 内容格式如下:

NameTypeDescription
textString消息文本内容

示例

// 发送文本消息,Web 端与小程序端相同
// 1. 创建消息实例,接口返回的实例可以上屏
let message = tim.createTextMessage({
	to: 'user1',
	conversationType: TIM.TYPES.CONV_C2C,
	// 消息优先级,用于群聊(v2.4.2起支持)。如果某个群的消息超过了频率限制,后台会优先下发高优先级的消息,详细请参考:https://cloud.tencent.com/document/product/269/3663#.E6.B6.88.E6.81.AF.E4.BC.98.E5.85.88.E7.BA.A7.E4.B8.8E.E9.A2.91.E7.8E.87.E6.8E.A7.E5.88.B6)
	// 支持的枚举值:TIM.TYPES.MSG_PRIORITY_HIGH, TIM.TYPES.MSG_PRIORITY_NORMAL(默认), TIM.TYPES.MSG_PRIORITY_LOW, TIM.TYPES.MSG_PRIORITY_LOWEST
	// priority: TIM.TYPES.MSG_PRIORITY_NORMAL,
	payload: {
	  text: 'Hello world!'
	}
});
// 2. 发送消息
tim.sendMessage(message).then(function(imResponse) {
	// 发送成功
	console.log(imResponse);
}).catch(function(imError) {
	// 发送失败
	console.warn('sendMessage error:', imError);
});

2. 创建图片消息

tim.createImageMessage({
	// [String] 消息接收方的 userID 或 groupID
	to,
	// [String] 会话类型,取值TIM.TYPES.CONV_C2C(端到端会话)或TIM.TYPES.CONV_GROUP(群组会话)
	conversationType,
	// [String] 消息优先级(默认值: TIM.TYPES.MSG_PRIORITY_NORMAL)
	priority,
	// [Object] 消息内容的容器
	payload
	// [function] 获取上传进度的回调函数
	onProgress
})

payload 内容格式如下:

NameTypeDescription
textHTMLInputElement | Object用于选择图片的 DOM 节点(Web)或者 File 对象(Web)或者微信小程序 wx.chooseImage 接口的 success 回调参数。SDK 会读取其中的数据并上传图片

示例

// Web 端发送图片消息示例1 - 传入 DOM 节点
// 1. 创建消息实例,接口返回的实例可以上屏
let message = tim.createImageMessage({
  to: 'user1',
  conversationType: TIM.TYPES.CONV_C2C,
  // 消息优先级,用于群聊(v2.4.2起支持)。如果某个群的消息超过了频率限制,后台会优先下发高优先级的消息,详细请参考 消息优先级与频率控制
  // 支持的枚举值:TIM.TYPES.MSG_PRIORITY_HIGH, TIM.TYPES.MSG_PRIORITY_NORMAL(默认), TIM.TYPES.MSG_PRIORITY_LOW, TIM.TYPES.MSG_PRIORITY_LOWEST
  // priority: TIM.TYPES.MSG_PRIORITY_NORMAL,
  payload: {
    file: document.getElementById('imagePicker'),
  },
  onProgress: function(event) { console.log('file uploading:', event) }
});
// 2. 发送消息
let promise = tim.sendMessage(message);
promise.then(function(imResponse) {
  // 发送成功
  console.log(imResponse);
}).catch(function(imError) {
  // 发送失败
  console.warn('sendMessage error:', imError);
});
// Web 端发送图片消息示例2- 传入 File 对象
// 先在页面上添加一个 ID 为 "testPasteInput" 的消息输入框,例如 <input type="text" id="testPasteInput" placeholder="截图后粘贴到输入框中" size="30" />
document.getElementById('testPasteInput').addEventListener('paste', function(e) {
  let clipboardData = e.clipboardData;
  let file;
  let fileCopy;
  if (clipboardData && clipboardData.files && clipboardData.files.length > 0) {
    file = clipboardData.files[0];
    // 图片消息发送成功后,file 指向的内容可能被浏览器清空,如果接入侧有额外的渲染需求,可以提前复制一份数据
    fileCopy = file.slice();
  }
  if (typeof file === 'undefined') {
    console.warn('file 是 undefined,请检查代码或浏览器兼容性!');
    return;
  }
   // 1. 创建消息实例,接口返回的实例可以上屏
  let message = tim.createImageMessage({
    to: 'user1',
    conversationType: TIM.TYPES.CONV_C2C,
    payload: {
      file: file
    },
    onProgress: function(event) { console.log('file uploading:', event) }
  });  
  // 2. 发送消息
  let promise = tim.sendMessage(message);
  promise.then(function(imResponse) {
    // 发送成功
    console.log(imResponse);
  }).catch(function(imError) {
    // 发送失败
    console.warn('sendMessage error:', imError);
  });
});

二. 撤回消息

撤回单聊消息或者群聊消息。撤回成功后,消息对象的 isRevoked 属性值为 true。

示例

// 主动撤回消息
let promise = tim.revokeMessage(message);
promise.then(function(imResponse) {
// 消息撤回成功
}).catch(function(imError) {
// 消息撤回失败
console.warn('revokeMessage error:', imError);
});
tim.on(TIM.EVENT.MESSAGE_REVOKED, function(event) {
// 收到消息被撤回的通知。使用前需要将 SDK 版本升级至v2.4.0或以上。
// event.name - TIM.EVENT.MESSAGE_REVOKED
// event.data - 存储 Message 对象的数组 - [Message] - 每个 Message 对象的 isRevoked 属性值为 true
});
// 获取会话的消息列表时遇到被撤回的消息
let promise = tim.getMessageList({conversationID: 'C2Ctest', count: 15});
promise.then(function(imResponse) {
const messageList = imResponse.data.messageList; // 消息列表
messageList.forEach(function(message) {
  if (message.isRevoked) {
    // 处理被撤回的消息
  } else {
    // 处理普通消息
  }
});
});

三. 接收消息

接收消息需要通过事件监听实现

let onMessageReceived = function(event) {
// event.data - 存储 Message 对象的数组 - [Message]
};
tim.on(TIM.EVENT.MESSAGE_RECEIVED, onMessageReceived);

1. 解析文本消息
如果您的文本消息只含有文字,则可以直接在 UI 上渲染出'xxxxxxx'文字。
含有 [呲牙] 内容需要解析为的文本参考下方

const emojiMap = {         // 根据[呲牙]可匹配的路径地址
'[微笑]': 'emoji_0.png',
'[呲牙]': 'emoji_1.png',
'[下雨]': 'emoji_2.png'
}
const emojiUrl = 'http://xxxxxxxx/emoji/'   // 为<img src="https://main.qcloudimg.com/raw/6be88c30a4552b5eb93d8eec243b6593.png"  style="margin:0;">图片的地址
function parseText (payload) {
let renderDom = []
// 文本消息
 let temp = payload.text
 let left = -1
 let right = -1
 while (temp !== '') {
   left = temp.indexOf('[')
   right = temp.indexOf(']')
   switch (left) {
     case 0:
       if (right === -1) {
         renderDom.push({
           name: 'text',
           text: temp
         })
         temp = ''
       } else {
         let _emoji = temp.slice(0, right + 1)
         if (emojiMap[_emoji]) {    // 如果您需要渲染表情包,需要进行匹配您对应[呲牙]的表情包地址
           renderDom.push({
             name: 'img',
             src: emojiUrl + emojiMap[_emoji]
           })
           temp = temp.substring(right + 1)
         } else {
           renderDom.push({
             name: 'text',
             text: '['
           })
           temp = temp.slice(1)
         }
       }
       break
     case -1:
       renderDom.push({
         name: 'text',
         text: temp
       })
       temp = ''
       break
     default:
       renderDom.push({
         name: 'text',
         text: temp.slice(0, left)
       })
       temp = temp.substring(left)
       break
   }
 }
return renderDom
}
// 最后的 renderDom 结构为[{name: 'text', text: 'XXX'}, {name: 'img', src: 'http://xxx'}......]
// 渲染当前数组即可得到想要的 UI 结果,如:XXX<img src="https://main.qcloudimg.com/raw/6be88c30a4552b5eb93d8eec243b6593.png"  style="margin:0;">XXX<img src="https://main.qcloudimg.com/raw/6be88c30a4552b5eb93d8eec243b6593.png"  style="margin:0;">XXX[呲牙XXX]

2. 解析系统消息

function parseGroupSystemNotice (payload) {
const groupName =
    payload.groupProfile.groupName || payload.groupProfile.groupID
switch (payload.operationType) {
  case 1:
    return `${payload.operatorID} 申请加入群组:${groupName}`
  case 2:
    return `成功加入群组:${groupName}`
  case 3:
    return `申请加入群组:${groupName}被拒绝`
  case 4:
    return `被管理员${payload.operatorID}踢出群组:${groupName}`
  case 5:
    return `群:${groupName} 已被${payload.operatorID}解散`
  case 6:
    return `${payload.operatorID}创建群:${groupName}`
  case 7:
    return `${payload.operatorID}邀请你加群:${groupName}`
  case 8:
    return `你退出群组:${groupName}`
  case 9:
    return `你被${payload.operatorID}设置为群:${groupName}的管理员`
  case 10:
    return `你被${payload.operatorID}撤销群:${groupName}的管理员身份`
  case 255:
    return '自定义群系统通知'
}
}

3. 解析群提示消息

function parseGroupTipContent (payload) {
switch (payload.operationType) {
  case this.TIM.TYPES.GRP_TIP_MBR_JOIN:
    return `群成员:${payload.userIDList.join(',')},加入群组`
  case this.TIM.TYPES.GRP_TIP_MBR_QUIT:
    return `群成员:${payload.userIDList.join(',')},退出群组`
  case this.TIM.TYPES.GRP_TIP_MBR_KICKED_OUT:
    return `群成员:${payload.userIDList.join(',')},被${payload.operatorID}踢出群组`
  case this.TIM.TYPES.GRP_TIP_MBR_SET_ADMIN:
    return `群成员:${payload.userIDList.join(',')},成为管理员`
  case this.TIM.TYPES.GRP_TIP_MBR_CANCELED_ADMIN:
    return `群成员:${payload.userIDList.join(',')},被撤销管理员`
  default:
    return '[群提示消息]'
}
}

会话相关

1. 获取某会话的消息列表

// 打开某个会话时,第一次拉取消息列表
let promise = tim.getMessageList({conversationID: 'C2Ctest', count: 15});
promise.then(function(imResponse) {
const messageList = imResponse.data.messageList; // 消息列表。
const nextReqMessageID = imResponse.data.nextReqMessageID; // 用于续拉,分页续拉时需传入该字段。
const isCompleted = imResponse.data.isCompleted; // 表示是否已经拉完所有消息。
});
// 打开某个会话时,第一次拉取消息列表
// 下拉查看更多消息
let promise = tim.getMessageList({conversationID: 'C2Ctest', nextReqMessageID, count: 15});
promise.then(function(imResponse) {
const messageList = imResponse.data.messageList; // 消息列表。
const nextReqMessageID = imResponse.data.nextReqMessageID; // 用于续拉,分页续拉时需传入该字段。
const isCompleted = imResponse.data.isCompleted; // 表示是否已经拉完所有消息。
});

2. 将会话设置为已读

// 将某会话下所有未读消息已读上报
tim.setMessageRead({conversationID: 'C2Cexample'});

3. 获取会话列表

// 拉取会话列表
let promise = tim.getConversationList();
promise.then(function(imResponse) {
const conversationList = imResponse.data.conversationList; // 会话列表,用该列表覆盖原有的会话列表
}).catch(function(imError) {
console.warn('getConversationList error:', imError); // 获取会话列表失败的相关信息
});

4. 删除会话

let promise = tim.deleteConversation('C2CExample');
promise.then(function(imResponse) {
//删除成功。
const { conversationID } = imResponse.data;// 被删除的会话 ID。
}).catch(function(imError) {
console.warn('deleteConversation error:', imError); // 删除会话失败的相关信息
});
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐