外观
Web / H5 接入
需要查某个方法的参数、返回值或回调时,查看 Web / H5 方法参考。
Web SDK 提供包含消息、联系人和聊天的完整工作台,支持页面内嵌和浮层。宿主可使用普通 JavaScript、Vue、React 或其他框架;SDK 自带运行时,界面及弹层放在同一个 Shadow Root 中。

环境与目录
构建使用 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。异步登录完成时仍需检查宿主组件是否存在。
接入检查
先用陈悦和林舟两个账号验证文字、竖屏图片及视频消息,再检查浮层收起与重开、窄屏返回、未读清除、断网恢复和切换账号。语音与通话需要允许及拒绝设备权限各验证一次。
