Client guide
Web & Mini Program development guide
A complete path through floo-web: choose a build, initialise and authenticate, manage contacts and groups, exchange every message type, receive events, and add voice & video.
Use lanying-im-web for desktop browsers, lanying-im-uniapp for H5 and multi-vendor Mini Programs, or lanying-im-miniprogram for a native WeChat Mini Program. These builds follow the same feature model, but transport and packaging settings differ.
Prerequisites and build selection
| Build | Targets | Configuration |
|---|---|---|
| lanying-im-web | Desktop browsers and traditional front-end applications | Set ws to false. |
| lanying-im-uniapp | H5 plus WeChat, Alipay, Baidu, ByteDance, QQ, DingTalk, and other uni-app targets | Set ws to true. |
| lanying-im-miniprogram | Native WeChat Mini Programs | Use the Mini Program package and platform network/storage adapters. |
- Create an application in the console and copy its App ID.
- Download the matching floo-web or floo-uniapp release.
- For voice & video, install the runtime dependencies used by the Web demo, including webrtc-adapter.
- Choose one application-wide SDK instance; do not create a separate instance per view.
Initialise the SDK
const config = {
//dnsServer: "https://dns.lanyingim.com/v2/app_dns",
appid: "YOUR_APP_ID",
ws: false, // uniapp版需要设置为true, web版需要设置为false
autoLogin: true
};The module form is the preferred integration. The script form remains available for legacy pages, but the upstream demo documents an initialisation race that requires retry handling.
import flooim from 'floo-3.0.0';
const im = flooim(config);Register, sign in, restore, and sign out
im.userManage.asyncRegister(this.user).then(() => {
console.log("注册成功");
}).catch(ex => {
console.log(ex.message);
});im.login({
name, // 用户名
password,
});With autoLogin enabled, the SDK restores the previous session from local storage. In production, clear application-specific SDK state rather than unrelated origin storage, and coordinate sign-out with push-token unbinding on mobile containers.
const list = im.userManage.getConversationList();
console.log(list);Contacts and relationship requests
| Task | API |
|---|---|
| Send a contact request | rosterManage.asyncApply({ user_id, alias }) |
| Accept or decline | rosterManage.asyncAccept / asyncDecline |
| Delete a contact | rosterManage.asyncDeleteRoster({ user_id }) |
| Read cached contacts | rosterManage.getAllRosterDetail() |
| Track changes | onRosterListUpdate |
| Block and unblock | rosterManage block-list APIs |
im.rosterManage.asyncApply({ user_id, alias })
.then(() => {
console.log("请求已发送成功!");
});Groups and membership
Group work includes the group lifecycle, membership, roles, invitations, join requests, mute and block lists, announcements, shared files, and per-group notification settings. Load group details before rendering a chat so policy and permissions are current.
im.groupManage
.asyncCreate({
name,
type, // 是否 pulbic, 0, 1
avatar,
description,
user_list, // user ids
})
.then(() => {
console.log("群创建成功");
});| Lifecycle | API |
|---|---|
| Join / leave | asyncApply({ group_id, reason }) / asyncLeave({ group_id }) |
| Destroy | asyncDestroy({ group_id }) |
| Joined groups | asyncGetJoinedGroups() |
| Group details | asyncGetGroupInfo(group_id) |
| Cached members | getGroupMembers(group_id) |
| Administration | groupManage announcement, role, mute, block-list, and shared-file APIs |
Build messages
| Content | Required fields |
|---|---|
| Text | content plus uid or gid |
| Image | type=image and attachment with dName, fLen, width, height, url |
| File | type=file and file attachment metadata |
| Location | type=location and attachment with lat, lon, addr |
| Voice & video signalling | type=rtc and config with action and callId |
| Custom | A documented custom content type plus extension payload |
const message = {
uid, // 用户id,只有单聊时使用
gid, // 群id,只有群聊时使用
content, // 消息文本内容
priority, // 设置消息的扩散优先级,取值范围0-10。普通人在聊天室发送的消息级别默认为5,可以丢弃,管理员默认为0不会丢弃。其它值可以根据业务自行设置。
}Send, forward, recall, and receive
im.sysManage.sendRosterMessage(message);
//or
im.sysManage.sendGroupMessage(message);im.on({
onRosterMessage: function(message) {
console.log(message);
}
});
im.on({
onGroupMessage: function(message) {
console.log(message);
}
});- Use onMessageStatusChanged to reconcile local pending messages with server state.
- Handle recall and deletion events by message ID and make each handler idempotent.
- Forward and recall through sysManage; enforce the server recall window in the UI.
- Persist message IDs and conversation IDs rather than relying on rendered-list indexes.
Mentions, typing, and search
im.sysManage.sendMentionMessage({
gid,
txt, // 文本消息
mentionAll, // 是否@所有人
mentionList, // [id,id ...]
mentionedMessage, // mention内容
pushMessage, // 推送
senderNickname // 发送者昵称
});Typing state is ephemeral and should not be stored as a chat message. Search results are grouped by contact and group; debounce UI input and keep the original SDK result identifiers when navigating to a message.
Voice & video lifecycle
主动发起音视频通话端
im.rtcManage.initRTCEngine(message);
//or 被动接受加入音视频通话端
im.rtcManage.joinRoom(message);- Register onRosterRTCMessage before sending or accepting an invitation.
- Use sendRTCMessage for call signalling and the engine APIs for media state.
- Publish local tracks only after room join succeeds; subscribe after remote sources arrive.
- On every exit path, unpublish, unsubscribe, leave the room, destroy the engine, and remove listeners.
Web troubleshooting
| Symptom | Check |
|---|---|
| flooim export not found | For the documented Babel setup, use sourceType: unambiguous. |
| third/long is missing | Confirm dependency installation completed; the legacy guide notes fsevents-related installation failures. |
| No default export in Vite/Vue 3 | Use the CommonJS compatibility plugins documented by the upstream demo. |
| No voice or video | Use HTTPS or localhost, verify permissions, adapter dependencies, and console feature enablement. |
| Duplicate events | Register listeners once and remove the exact handler during teardown. |