npm package: @msbfe/im-sdk
Description: ## 一 聊天室
Latest version: 0.0.31

# IM-SDK

## 一 聊天室

### 1. 安装

```shell
yarn add @msbfe/im-sdk
```

### 2. 初始化

```ts
import IMSDK from '@msbfe/im-sdk';
const [error, chatroom] = await IMSDk.Chatroom.initialize({
  debug: true,
  env: 'test',
  sectionId: '4454',
  token: userinfo.token, // 登录 Token
  chatroomNick: '', // 昵称
  chatroomAvatar: '', // 头像
  tags: [], // 用户标签-助教端登录必须传入 assistant
  forbiddenWordCheckedEnable: true, // 客户端开启严禁词检查，可选，默认值 true
  chatroomEnterCustom: JSON.stringify({
    avatar: 'https://joeschmoe.io/api/v1/random',
  }),
});
```

### 3. 功能

- 登录 ✅
- 查询聊天室信息 ✅
- 修改聊天室信息 ✅
- 查询成员列表 ✅
- 分页获取成员列表 ✅
- 查询全部历史消息 ✅
- 分页查询历史消息 ✅
- 进入聊天室 ✅
- 离开聊天室 ✅
- 发送文本消息 ✅
- 发送文件消息 ✅
- 接收聊天室消息 ✅
- 聊天室禁言 (调用服务端接口) ✅
- 单个禁言 ✅
- 临时禁言 ✅
- 踢出(发、收) ✅
- 更新学员备注 (调用服务端接口) ✅
- 拉黑 (自定义消息) ✅
- 取消拉黑 (自定义消息) ✅
- 根据课程查询拉黑列表 ✅
- 上报观看时长 (调用服务端接口) ✅
- 记录发言次数 (调用服务端接口) ✅
- 删除聊天消息 (删除聊天消息) ✅
- 切换聊天室 ✅
- 触发敏感检查 ✅
- 获取成员信息 ✅
- 开启连麦 ✅
- 关闭连麦 ✅
- 连麦列表更新 ✅

#### 3.1 登录

```ts
const [error, chatroom] = await IMSDk.Chatroom.initialize({
  debug: true,
  env: 'test',
  sectionId: '4454',
  token: userinfo.token, // 登录 Token
  chatroomNick: '', // 昵称
  chatroomAvatar: '', // 头像
  tags: [], // 用户标签-助教端登录必须传入 assistant
  chatroomEnterCustom: JSON.stringify({
    avatar: 'https://joeschmoe.io/api/v1/random',
  }),
});
```

#### 3.2 查询聊天室信息

- 发送请求

```ts
const [error, obj] = await chatroom.getChatroom();
if (!error) {
  console.log(obj);
}
```

- 响应结果:

```ts
{
  "id": "2302150639",
  "name": "公告更新", // 公告名称
  "announcement": "公告更新测试",  // 公告内容
  "custom": "",
  "createTime": 1663321877624,
  "updateTime": 1663741386352,
  "queuelevel": "1",
  "creator": "0",
  "onlineMemberNum": 3, // 在线人数
  "mute": false, // 聊天室禁言中，只有管理人员可以发消息
  "broadcastUrl": ""
}
```

#### 3.3 修改聊天室信息

- 请求

```ts
const [error, obj] = await chatroom.updateChatroom({
  chatroom: {
    name: '公告更新',
    announcement: '公告更新测试',
  },
  custom: JSON.stringify({
    announcement: '公告更新测试',
  }),
  needNotify: true,
});
if (error === null) {
  message.success('修改聊天室信息成功');
}
```

- 参数

| 参数         | 默认值 | 描述                                                   |
| ------------ | ------ | ------------------------------------------------------ |
| name         | ""     | 公告名称                                               |
| announcement | ""     | 公告内容                                               |
| custom       | ""     | 扩展字段                                               |
| needNotify   | false  | 默认为 false, 表示公告修改不通知聊天室其它人. 反之通知 |

- 响应结果

```ts
// obj 对应内容
{
  announcement: "公告更新测试",
  chatroomId: ""
}
```

- 学员端监听公告更新

```ts
// 聊天室信息更新
chatroom.addListener(Chatroom.EVENTS.updateChatroom, function (res) {
  console.log('updateChatroom', res);
});
```

接收到 `res` 内容如下:

```json
{
  "chatroomId": "2302150639",
  "idClient": "102baa94-ef75-48bb-ad83-8d0d888ef5a2",
  "from": "1",
  "fromCustom": "",
  "fromClientType": "Web",
  "time": 1663762645958,
  "type": "notification",
  "text": "",
  "resend": false,
  "status": "success",
  "attach": {
    "type": "updateChatroom",
    "from": "1",
    "fromNick": "管理员1",
    "custom": "{\"announcement\":\"公告更新测试\"}"
  },
  "flow": "in"
}
```

#### 3.4 查询成员列表

- 请求

```ts
const members = await chatroom.getAllChatroomMembers();
console.log(members);
```

- 响应

```json
[
  {
    "roomId": "2302150639", // 房间号
    "accId": "6", // 账号
    "type": "manager", // 类型 owner 房主 、manager 管理员、restricted 受限制(被拉黑或禁言) 、common 普通用户、guest 游客
    "nick": "修改成员", // 昵称
    "avatar": "https://ksimage.mashibing.com/132643d814514734bf0d5e4eb63e0e63.jpg", // 头像
    "ext": "cunstom info",
    "isOnline": true, // 在线状态
    "enterTime": 1663848190608, // 进入时间
    "isBlacklisted": false, // 黑名单
    "isMuted": false, // 禁言
    "isTempMuted": false, // 临时禁言
    "tempMuteTtl": 0, // 临时禁言时长(单位秒)
    "isRobot": false, // 是否是聊天机器人
    "isRobotExpireAt": 0 // 机器人失效的时长
  }
]
```

#### 3.5 分页获取成员列表

```ts
  const [error, members] = await chatroom.getChatroomMembers({
    guest = false,
    limit = 100,
    time = 0,
  }
  if(error!=null) {
    console.log(members)
  }
```

| 参数  | 默认值 | 描述                                                                               |
| ----- | ------ | ---------------------------------------------------------------------------------- |
| guest | false  | 只查询固定用户(非游客)                                                             |
| limit | 100    | 查询数量                                                                           |
| time  | 0      | 默认 0 代表当前服务器时间，获取固定用户传入 updateTime，获取游客用户传入 enterTime |

#### 3.6 查询全部历史消息

- 请求

```ts
chatroom
  .getAllHistoryMsgs({
    msgTypes: [], //可选, 默认值 [text、video、file、image、audio、geo、custom]，需要其他可以看下面云信消息列表
    customMsgSubTypes: [], // 可选 默认值为 []，也就是返回全部自定义消息。例如只要机器人消息，可以传递 [IMSDk.Chatroom.EVENTS.robotMessage],
    notificationMsgSubTypes: [], // 可选，默认值为 [], 用于过滤通知子类型消息，注意⚠️，默认情况下 msgTypes 不包含通知消息的
  })
  .then((res: any) => {
    history.value = res;
  });
```

- 响应

```json
[
  {
    "chatroomId": "2302150639",
    "idClient": "b82d4114588d6efb89e47f2b85b82393",
    "from": "6",
    "fromNick": "修改成员",
    "fromAvatar": "https://ksimage.mashibing.com/132643d814514734bf0d5e4eb63e0e63.jpg",
    "fromCustom": "cunstom info",
    "userUpdateTime": 1663839160317,
    "fromClientType": "Web",
    "time": 1663839167099,
    "type": "image",
    "text": "",
    "resend": false,
    "status": "success",
    "file": {
      "w": 432,
      "h": 363,
      "type": "PNG",
      "size": 51512,
      "url": "https://nim-nosdn.netease.im/MjYxNzY0Mjk=/bmltYV8xMDg1MTQyNjQzMzZfMTY2MzgzOTE2NjYzN18xYWQwZTQ5MS0yNGNkLTQzYzgtODhiOC1iNjBjMDE4YjZjOTE=?createTime=1663839167053",
      "name": "截屏2022-09-21 16.54.48.png",
      "ext": "png"
    },
    "flow": "out"
  },
  {
    "chatroomId": "2302150639",
    "idClient": "10a0d302-a093-4365-a906-113596ad1249",
    "from": "0",
    "fromNick": "管理员",
    "fromAvatar": "https://ksimage.mashibing.com/132643d814514734bf0d5e4eb63e0e63.jpg",
    "custom": "扩展信息",
    "fromClientType": "Server",
    "time": 1663828031926,
    "type": "text",
    "text": "这是发送的消息",
    "resend": false,
    "status": "success",
    "flow": "in"
  },
  {
    "chatroomId": "2302150639",
    "idClient": "7b7daf5d-2be7-4c2f-a228-5007c91700c0",
    "from": "1",
    "fromCustom": "",
    "fromClientType": "Web",
    "time": 1663818559398,
    "type": "notification",
    "text": "",
    "resend": false,
    "status": "success",
    "attach": {
      "type": "kickMember",
      "from": "1",
      "fromNick": "管理员1",
      "to": ["3"],
      "toNick": ["用户3"]
    },
    "flow": "in"
  }
]
```

#### 3.7 分页查询历史消息

- 请求

```ts
chatroom.getHistoryMsgs({
  timetag = Date.now(), // 默认值
  limit = 100, // 查询条数
  msgTypes = [], // 查询指定类型的消息
});
```

- 参数

| 参数     | 默认值 | 描述                                        |
| -------- | ------ | ------------------------------------------- |
| timetag  | false  | 获取从 timetag 对应的时间点往前的若干条数据 |
| limit    | 100    | 查询数量                                    |
| msgTypes | []     | 可选历史消息类型，默认为即获取全部消息类型  |

#### 3.8 进入聊天室

```ts
// 成员进入
chatroom.addListener(Chatroom.EVENTS.memberEnter, function (res) {
  console.log('memberEnter', res);
  message.info(`[${res.attach.fromNick}] 进入聊天室`);
});
```

#### 3.9 离开聊天室

```ts
// 离开聊天
chatroom.addListener(Chatroom.EVENTS.memberExit, function (res) {
  console.log('memberExit', res);
  message.info(`[${res.attach.fromNick}] 离开聊天室`);
});
```

#### 3.10 发送文本消息

```ts
const handleSend = async () => {
  const [error, msg] = await chatroom.sendText(content.value);
  if (error === null) {
    message.success('发送成功');
    content.value = '';
  }
};
```

#### 3.11 发送文件消息

```html
<input id="test" type="file" />
```

```ts
chatroom.sendFile({
  type: "image", // "image" | "audio" | "video" | "file";
  fileInput: document.getElementById('test'), // blob | HTMLInputElement | base64
  uploadprogress: (obj) => {},
  uploaddone: (error, file) => {},
  beforesend: (msg) => {},
  done: (error, msg) => {};
});
```

#### 3.12 发送自定义消息

```ts
chatroom.sendCustomMsg({
  type: 'hyperLinks', // 超链接
  data: {
    title: '',
    subtitle: '',
    href: '',
  },
});
```

#### 3.13 接收聊天室消息

#### 3.13.1 云信消息分类

| 事件名称     | 描述   |
| ------------ | ------ |
| text         | 文本   |
| video        | 视频   |
| file         | 视频   |
| image        | 视频   |
| audio        | 音频   |
| geo          | 未知   |
| custom       | 自定义 |
| notification | 通知类 |

根据业务需要把消息按类型进行划分。

#### 3.13.2 基于云信的消息，再划分成 4 类

| 事件名称     | 描述                                                                                                                                                                                                                                                                                                                                                               |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| normal       | 普通消息(text、image、audio、video、file、geo)                                                                                                                                                                                                                                                                                                                     |
| tip          | 提醒消息(如进入会话时出现的欢迎消息，或者会话命中敏感词后的提示消息等等)                                                                                                                                                                                                                                                                                           |
| notification | 通知消息(memberEnter(进入)、memberExit(离开)、gagMember(成员禁言)、ungagMember(成员解除禁言)、updateChatroom(聊天室信息更新)、addTempMute(临时禁言)、removeTempMute(移除临时禁言)、muteRoom(聊天室禁言)、unmuteRoom(移除聊天室禁言))                                                                                                                               |
| custom       | 自定义 normal (正常消息)、loginSuccess(登录成功)、loginFail(登录失败）、black(拉黑)、unblack(取消拉黑)、updateRemark(更新备注)、liveStart(直播开始)、liveEnd(直播结束) 、kicked(被踢出)、error(错误) 、reconnect(重连) 、memberIn(进入)、memberOut(离开)、 robotMessage（机器人消息）、openCall（打开连麦）、closeCall（关闭连麦）、callStatusUpdate(连麦状态更新) |

> 禁言分为三种模式: `聊天室禁言`、`成员禁言`、`成员临时禁言`

#### 3.13.3 接收普通消息

```ts
chatroom.addListener(Chatroom.EVENTS.normal, function (msg) {});
chatroom.addListener(Chatroom.EVENTS.tip, function (msg) {});
```

#### 3.14 聊天室禁言

```ts
chatroom.addListener(Chatroom.EVENTS.muteRoom, function (msg) {}); // 聊天室被禁言
chatroom.addListener(Chatroom.EVENTS.unmuteRoom, function (msg) {}); // 聊天室解除禁言
```

#### 3.15 单禁言

```ts
const [error, obj] = chatroom.markChatroomGaglist({
  account: '****',
  isAdd: true, // 添加禁言：true、移除禁言：false
});
if (error === null) {
  console.log('禁言|取消禁言成功');
}

// 禁言
chatroom.addListener(Chatroom.EVENTS.gagMember, function () {});
// 移除禁言
chatroom.addListener(Chatroom.EVENTS.ungagMember, function () {});
```

#### 3.16 临时禁言

```ts
const [error, obj] = chatroom.updateChatroomMemberTempMute({
  account: '****',
  duration: 1000, // 禁言时长: 单位为秒 移除禁言：0
  needNotify: true, // 禁言：true、移除禁言：false
  custom: '', // 对应消息的扩展字段
});

if (error === null) {
  console.log('禁言|取消禁言成功');
}
// 禁言
chatroom.addListener(Chatroom.EVENTS.addTempMute, function () {});
// 移除禁言
chatroom.addListener(Chatroom.EVENTS.removeTempMute, function () {});
```

#### 3.17 踢出 (聊天室中踢出，刷新还可以继续进入，状态是瞬时的)

```ts
const handlekickChatroomMember = async () => {
  const [error, result] = await chatroom.kickChatroomMember({
    account: '3',
  });
  console.log(error, result); //  {account: '3', custom: ''}
};

// 学员端监听踢出消息
chatroom.addListener(Chatroom.EVENTS.kicked, function (res) {
  message.error(res.message);
});
```

#### 3.18 更新备注

- 请求

```ts
const [error, result] = await chatroom.updateRemark({
  courseId: 44,
  userId: 'user_00000068',
  nickName: '测试',
});
console.log(error, result);
```

- 响应

```json
{
  "code": "SUCCESS",
  "message": "操作成功",
  "traceId": "",
  "data": true
}
```

#### 3.19 拉黑

- 请求

```js
const [error, result] = chatroom.black({
  courseId: '',
  userId: '',
});
```

- 响应

```json
{
  "code": "SUCCESS",
  "message": "操作成功",
  "traceId": "",
  "data": true
}
```

#### 3.20 取消拉黑

- 请求

```js
const [error, result] = chatroom.unblack({
  courseId: '',
  userId: '',
});
```

- 响应

```json
{
  "code": "SUCCESS",
  "message": "操作成功",
  "traceId": "",
  "data": true
}
```

#### 3.21 根据课程查询拉黑列表

##### 3.21.1 支持分页

- 请求

```js
const [error, result] = chatroom.queryBlackList({
  courseId: '41',
  length: 10,
  pageIndex: 1,
});
```

- 响应

```json
{
  "code": "SUCCESS",
  "message": "操作成功",
  "traceId": "",
  "data": {
    "current": 1,
    "pages": 10,
    "records": [],
    "size": 10,
    "total": 100
  }
}
```

##### 3.21.2 查询全量

- 请求

```js
const [error, result] = chatroom.queryAllBlackList({
  courseId: '41',
});
```

- 响应

```json
{
  "code": "SUCCESS",
  "message": "操作成功",
  "traceId": "",
  "data": [
    {
      "blacklistedTime": "",
      "blacklistedUser": "",
      "blacklistedUserRealName": "",
      "courseId": 0,
      "id": 0,
      "userId": "",
      "userNickname": "",
      "wechatNickname": ""
    }
  ]
}
```

#### 3.22 聊天室禁言

- 请求

```js
const [error, result] = await chatroom.muteRoom({
  mute: true, // 禁言: true  取消禁言: false
});
console.log(error, result);
```

- 响应

```json
{
  "code": "SUCCESS",
  "message": "操作成功",
  "traceId": "",
  "data": true
}
```

#### 3.23 上报观看时长

- 请求

```js
const [error, result] = await chatroom.reportWatchTime();
```

- 响应

```json
{
  "code": "SUCCESS",
  "message": "操作成功",
  "traceId": "",
  "data": true
}
```

#### 3.24 记录发言次数

- 请求

```js
const [error, result] = await chatroom.reportStatementsNum({ count: 1 });
```

- 响应

```json
{
  "code": "SUCCESS",
  "message": "操作成功",
  "traceId": "",
  "data": true
}
```

#### 3.25 删除聊天消息

```js
// 撤回消息
const recall = async () => {
  const [error, res] = await chatroom.recall({
    fromUserId: 'user_00000068',
    msgId: 'd39f037bb2c6ae35add99877a475b43d',
    msgTimeTag: 1664347261676,
  });
  console.log(error, res);
};

// 监听删除消息回调
chatroom.addListener(
  Chatroom.EVENTS.deleteChatroomMsg,
  function ({ idClient }) {
    console.log(idClient);
  }
);
```

#### 3.26 切换聊天室

```js
// 先销毁
chatroom.destroy();
// 重新执行初始化
IMSDk.Chatroom.initialize({
  ...
})
```

#### 3.27 触发敏感检查

```js
const handleSend = async () => {
  const [error, msg] = await chatroom.sendText('草');
  if (error === null) {
    message.success('发送成功');
    content.value = '';
  } else {
    console.log(error); // { code: "hasForbidden", message: "聊天内容包含敏感词" },
  }
};
```

#### 3.28 设置聊天室普通成员

```js
const [error, result] = await chatroom.markChatroomCommonMember({
  account: '13305',
});
```

#### 3.29 获取成员信息

- 请求

```js
const getChatroomMembersInfo = async () => {
  const [error, result] = await chatroom.getChatroomMembersInfo({
    accounts: ['42909'],
  });
  console.log(error, result);
};
```

- 响应

```js
 {
  accounts: ['42909'],
  members: [
    {
      "type": "common",
      "roomId": "2457143158",
      "nick": "Nets",
      "accId": "42909",
      "avatar": "http://ksimage.mashibing.com/132643d814514734bf0d5e4eb63e0e63.jpg",
      "enterTime": 1665403446414,
      "isBlacklisted": false,
      "isMuted": false,
      "ext": {
          "banChat": 0,
          "blacklisted": 0,
          "globalSpeakCount": 43,
          "globalViewDuration": 257,
          "inTime": 1665403511595,
          "nickName": "应届生  21 对Java感兴趣的",
          "phone": "13055199735",
          "role": 0,
          "saleTeacherBzId": "32767",
          "saleTeacherNickName": "栀晓",
          "source": 1
      },
      "isOnline": true,
      "isRobot": false,
      "isTempMuted": false
    }
  ]
 }
```

## 二 私聊

### 1. 初始化

- env 环境变量
- token 登录凭证

```js
import IMSDK from '@msbfe/im-sdk';
const [error, im] = await IMSDk.NIM.initialize({
  env: 'test',
  token: userinfo.token,
});

if (!error) {
  // im 创建成功
  im.addListener(IMSDK.NIM.EVENTS.connect, () => {
    console.log('登录成功');
  });
  // 监听会话列表更新
  im.addListener(IMSDK.NIM.EVENTS.updateSessions, (arr: Session[]) => {
    console.log('会话更新', sessions);
    sessions.value = arr;
  });
} else {
  console.log(error);
}
```

### 2. 创建本地会话

- `to` 聊天对象, 账号或群 ID

```js
const [error, session] = await im.insertLocalSession({
  to: id, // 用户ID
});
```

### 3. 删除本地会话

- `sessionId` 会话 ID

```js
const [error, session] = im.deleteLocalSession(sessionId);
```

### 4. 同时删除本地和服务端会话

```js
const [error, session] = im.syncDeleteSession({
  sessionId: item.id,
  to: item.to,
});
```

### 5. 切换会话

#### 5.1 设置当前会话

- 如果是已经存在的会话记录, 会将此会话未读数置为 0, 开发者会收到 onupdatesession 回调
- 之后此会话在收到消息之后不会更新未读数

```js
im.setCurrSession('sessionid');
```

#### 5.2 重置会话未读数

- 如果是已经存在的会话记录, 会将此会话未读数置为 0, 那么会收到 onupdatesession 回调
- 之后此会话在收到消息之后依然会更新未读数

```js
im.resetCurrSession();
```

### 6. 获取会话历史消息

```js
const [error, result] = await im.getMsgs({
  scene: 'p2p', // 点对点
  to: item.to, //
  limit: 10, // 限制条数
});
```

#### 响应

```json
[
  {
    "id": "p2p-13187", // 会话ID
    "scene": "p2p", // 会话场景
    "to": "13187", // 用户ID
    "updateTime": 1666267793516, // 会话更新时间
    // 会话最近一条消息
    "lastMsg": {
      "scene": "p2p",
      "from": "13305",
      "fromNick": "Nets",
      "fromClientType": "Web",
      "fromDeviceId": "a018a1f6f66044b5ed3d392b31acb209",
      "to": "13187",
      "time": 1666267793516,
      "type": "text",
      "text": "121212121212122323",
      "isHistoryable": true,
      "isRoamingable": true,
      "isSyncable": true,
      "cc": true,
      "isPushable": true,
      "isOfflinable": true,
      "isUnreadable": true,
      "isReplyMsg": true,
      "needPushNick": true,
      "needMsgReceipt": false,
      "isLocal": false,
      "resend": false,
      "idClient": "640077c0b7976f0b7cd394990fe6dc91",
      "userUpdateTime": 1663925973486,
      "status": "success",
      "target": "13187",
      "sessionId": "p2p-13187",
      "flow": "out",
      "idServer": "4379177879259"
    },
    "unread": 0, // 未读消息
    "nick": "邓澎波", // 聊天对象昵称
    "avatar": "https://oss-cdn.mashibing.cn/user/afca7d8dbd2a375b7a1f3765b4fee370.jpg" // 聊天对象头像
  }
]
```

### 7. 分页查询历史消息

查询分页消息时，需要传入两个参数 `lastMsgId`、`endTime` 或 `beginTime`，具体传入 `endTime` 或 `beginTime`, 取决于传入的 `reverse`.

- reverse: false (默认)

```js
lastMsgId: item.idServer;
endTime: item.time;
```

- reverse: true

```js
lastMsgId: item.idServer;
endTime: item.time;
```

根据前面返回值，案例如下:

```js
const [error, result] = await im.getMsgs({
  scene: 'p2p', // 点对点
  to: item.to, // 用户
  limit: 10, // 限制条数
  lastMsgId: 4379177879259, // 消息 idServer
  time: 1666267793516, // 消息时间 time
});
```

### 8. 发送消息

```js
// 发送消息之前消息具柄
const msg = im.sendText({
  to: 'userNo',
  text: imContent.value,
  done: (error, msg) => {
    if (!error) {
      history.value.unshift(msg);
    }
  },
});
```

### 9. 发送图片

```js
const input = document.querySelector('#input');
im.sendFile({
  to: accid,
  fileInput: input,
  beginupload(upload) {
    // 通过这个 upload 对象来中断上传  upload.abort()
  },
  uploadprogress(obj) {
    console.log(obj);
  },
  beforesend(obj) {},
  uploaddone(error, file) {},
  done(error, msg) {
    console.log(error, msg);
  },
});
```

### 10. 未读消息

```js
const unread = computed(() => {
  return sessions.value.reduce((prev, current) => {
    prev += current.unread;
    return prev;
  }, 0);
});
```

### 11. 更新备注

```js
const [error, result] = await im.updateRemark({
  courseId: '', // 课程ID
  userId: '', // 用户ID
  nickName: '', // 昵称(可选)
  label: '', // 用户标签(可选)
});
```

### 12. 获取用户详情

```js
const [error, result] = await im.getUserInfo({
  userId: '', // 用户ID
});
```

- 响应

```json
{
  "speakCount": 0,
  "viewDuration": 0,
  "nickName": ""
}
```

### 13. 注销

```js
im.destroy();
```