跳转到正文

Web / H5 接入 ​

需要查某个方法的参数、返回值或回调时,查看 Web / H5 方法参考。

Web SDK 提供包含消息、联系人和聊天的完整工作台,支持页面内嵌和浮层。宿主可使用普通 JavaScript、Vue、React 或其他框架;SDK 自带运行时,界面及弹层放在同一个 Shadow Root 中。

Web SDK:工作伙伴讨论秋日出游

环境与目录 ​

构建使用 Node.js 22.12 或更新版本。保留源码中的相邻目录关系,共享二维码和视频处理模块参与本地构建:

text
workspace/
├── sdk-web/
├── uniapp/uni_modules/popo-im/
│   ├── browser-video/
│   └── browser-qr/
└── your-web-app/
sh
npm --prefix sdk-web ci
npm --prefix sdk-web run build

构建生成 sdk-web/dist/im-kit.iife.js、im-kit.es.js 和类型声明。普通网页可将 IIFE 脚本放入自己的静态目录;ESM 接入需要保留整个 dist/,包括按需加载的分块。

如使用现有前端构建工具,可在宿主 package.json 引用本地模块,执行安装后导入:

json
{
  "dependencies": {
    "@im/web-kit": "file:../sdk-web"
  }
}
js
import { createIM } from '@im/web-kit'

初始化与认证 ​

先按认证与 Token准备宿主取票接口。以下 /api/im-auth 是宿主自行实现的接口;它在服务端验证当前用户并取得 IM 凭证。

html
<div id="chat" style="height: 720px"></div>
<script src="/kit/im-kit.iife.js"></script>
<script>
const client = IMKit.createIM({
  serverUrl: 'https://example.com',
  // 可省略,默认由 serverUrl 派生 wss://example.com/ws
  webSocketUrl: 'wss://example.com/ws',
  authProvider: async () => {
    const response = await fetch('/api/im-auth', {
      method: 'POST',
      credentials: 'same-origin',
      cache: 'no-store'
    })
    const result = await response.json()
    if (!response.ok || result.code !== 0) {
      throw Object.assign(new Error('暂时无法连接聊天'), {
        status: response.status,
        code: result.code
      })
    }
    const data = result.data
    return {
      token: data.token,
      expireAt: data.expire_at,
      user: {
        userId: data.user.user_id,
        username: data.user.username,
        nickname: data.user.nickname,
        avatar: data.user.avatar,
        signature: data.user.signature
      }
    }
  }
})
</script>

serverUrl 是部署根地址,SDK 自行追加 /app/sdk/*,不要填成某一个业务接口。生产环境推荐将宿主认证、SDK HTTP、WebSocket 和媒体代理到同源 HTTPS 地址;跨域部署还需由服务端配置正确的来源与资源访问策略。

两种 UI 入口 ​

页面内嵌 ​

js
client.mount({ container: document.querySelector('#chat') })
await client.login()

容器必须已插入页面且具有明确高度。SDK 自动在桌面多栏工作台与手机全屏导航之间适配;消息和联系人入口已包含在工作台中,无需另建两个根实例。

浮层 ​

js
client.mount({ mode: 'floating' })
await client.login()

// 宿主自己的聊天按钮
document.querySelector('#open-chat').onclick = () => client.show()

同一实例只挂载一次。show()、hide() 控制可见性;浮层中的“收起”保留连接和当前页面。移动端浮层自动铺满视口。需要把顶部头像或退出入口接到宿主时,在 mount 配置 onProfile、onLogout 回调。

登录、退出与切换账号 ​

js
// 可选:宿主已经确认本机账号时,先展示该用户的可读缓存。
client.restoreCachedSession({
  userId: 'chenyue', nickname: '陈悦', avatar: ''
})
await client.login()

// 用户在宿主切换账号,Provider 的身份来源更新后:
await client.login()

// 用户退出宿主:
client.logout()

// 组件卸载或离开整个工作台:
client.destroy()

缓存恢复返回 boolean,不发网络请求。断网可读状态为 state.session === 'offline',login() 网络失败仍会拒绝,宿主应保留已有界面并显示适当提示。destroy() 保留可恢复缓存;显式 logout() 清理当前账号缓存。销毁后需重新 createIM。

常用公开操作 ​

js
await client.openConversation({ type: 'friend', id: 'linzhou' })
await client.openConversation({ type: 'group', id: '6655312956' })

const stopUnread = client.onUnreadChange(({ conversation, contact }) => {
  // 更新宿主自己的消息角标和申请角标。
  renderUnread(conversation, contact)
})
const stopState = client.onStateChange(state => {
  renderConnection(state.connection, state.session)
})

client.setTheme('system') // 'system' | 'light' | 'dark'
await client.refresh()

// 宿主后端已保存并同步资料后,更新 SDK 本地展示。
client.refreshCurrentUser({
  userId: 'chenyue', nickname: '陈悦', avatar: '/media/chenyue.webp'
})

// 组件销毁前解除订阅。
stopUnread()
stopState()

上例 renderUnread、renderConnection 是宿主自己的展示逻辑。onStateChange 立即通知当前状态,适用于各前端框架;不要依赖 SDK 内部 Vue 的响应式对象驱动宿主。

通话由工作台处理,也可使用 await client.calls.start('linzhou', 'video')、accept()、end();语音类型为 'audio'。服务端需已配置 TRTC 和相应能力。

浏览器注意事项 ​

  • 录音、扫码和音视频采集需要 HTTPS 与浏览器授权,本机 localhost 可用于开发。
  • 浏览器可能限制来电铃声或远端音频自动播放,界面会提供点击恢复声音入口;需用真实浏览器验证。
  • 相机或编解码能力取决于设备。视频无法规范化时可能按原文件发送,不能假定每个浏览器均支持转码。
  • 手机全屏宿主建议设置 viewport-fit=cover,并验证顶部、底部安全区和软键盘。
  • 通话期间 hide() 不会隐藏正在使用的通话界面;使用通话窗口内的最小化入口。
  • Vue 2 在 mounted 挂载、beforeDestroy 销毁;Vue 3 对应 onMounted、onBeforeUnmount。异步登录完成时仍需检查宿主组件是否存在。

接入检查 ​

先用陈悦和林舟两个账号验证文字、竖屏图片及视频消息,再检查浮层收起与重开、窄屏返回、未读清除、断网恢复和切换账号。语音与通话需要允许及拒绝设备权限各验证一次。