概述
最近跟朋友做了一个小程序项目,用到了即时通讯,选择了网易信Im即时通讯,不得不说,网易信的文档写的相当不友好,文档链接:https://dev.yunxin.163.com/docs/product/IM%E5%8D%B3%E6%97%B6%E9%80%9A%E8%AE%AF/%E6%96%B0%E6%89%8B%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
谁看谁懵逼。。。
长话短说,进入正题。
介绍:这里对接是小程序sdk版本
第一步
先去注册网易信账号建立应用,拿到appKey ,appSecret。理解为小程序的appid就OK,应用唯一标识码
const appKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
const appSecret = "xxxxxxxxxxxx"
export default {
appKey,
appSecret
}
第二步
先把demo拷贝下来,看看代码,这个真的要看看,很有帮助,地址:https://dev.yunxin.163.com/docs/product/IM%E5%8D%B3%E6%97%B6%E9%80%9A%E8%AE%AF/SDK%E5%BC%80%E5%8F%91%E9%9B%86%E6%88%90/Web%E5%BC%80%E5%8F%91%E9%9B%86%E6%88%90/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F
第三步
把文档过一遍,不理解跟着我往下看
第四步
去控制台打开自己的账号建立几个IM账户,注意这里是纯前端实现,IM用户体系来自网易信数据库,不通过我们自己的服务端后台,记住账户和密码用来测试的
然后跟我写下面代码试试
import config from '@/im/config.js'
let orderCounter=1
class IMController {
constructor(headers) {
this.onConnect = this.onConnect.bind(this)
/* 初始化SDk */
app.globalData.nim = NIM.getInstance({
// debug: true,
db: false, // 小程序不支持数据库
syncSessionUnread: true, // 同步会话的未读数
autoMarkRead: false, // 不开启自动标记消息已读 此时服务器下推的所有离线消息算未读,漫游消息算已读
appKey: config.appKey, // 在云信管理后台查看应用的 appKey
token: headers.token, // 帐号的唯一标识, 用于建立连接
account: headers.account, // 帐号, 应用内唯一
onconnect: this.onConnect, // 连接成功
})
}
/** 1 abnormal closure
* 连接成功
*/
onConnect() {
console.log(orderCounter++, '连接成功: ')
console.log(app.globalData.nim)
}
}
const appNim=new IMController({
token: '测试账号密码',
account: ‘测试账号’
})
//下面是一段发送消息的方法
// 他人account
let to = this.otherParam.account
let text='测试消息'
appNim.sendText({
scene: 'p2p',
to,
text,
done: (err, msg) => {
console.log('发送文本消息回调')
console.log(err)
console.log(msg)
}
})
这样一个Im账号登录连接就成功了,你可以把im类放在全局对象上以便使用,请继续看下代码,它只是一个消息Mock
// 这里我只介绍几个重点的字段及状态,
/*
* @param {string} flow 发送方 (‘out’=>自己) and (‘in’ =>他人)
* @param {string} fromNick 目标名称
* @param {string} scene 聊天类型 ‘p2p’ 点对点
* @param {string} to 发送者账户
* @param {string} sessionId 会话id
* @param {number} time 发送时间
*
*/
export default {
cc: true,
flow: "out",
from: "19b82a32aa30c50fc4c943ff398dfcae",
fromClientType: "Web",
fromDeviceId: "f1cbf57270cfe916c270a842085ce75a",
fromNick: "woshichunlogn",
idClient: "0376a3107b0d200744be4c87523b7838",
idServer: "306034218126",
isHistoryable: true,
isLocal: false,
isOfflinable: true,
isPushable: true,
isReplyMsg: true,
isRoamingable: true,
isSyncable: true,
isUnreadable: true,
needMsgReceipt: false,
needPushNick: true,
resend: false,
scene: "p2p",
sessionId: "p2p-dc46c6ede64c2c7595f0246e8cd146a7",
status: "success",
target: "dc46c6ede64c2c7595f0246e8cd146a7",
text: "fasf",
time: 1566653977065,
to: "dc46c6ede64c2c7595f0246e8cd146a7",
type: "text",
userUpdateTime: 1566543003373,
}
看了各项字段应该已经猜到对应的什么了吧,如text消息文案,time发送时间,scene点对点,等等,也可以自己去看看文档。
这里我要讲重点
离线消息与漫游消息
离线消息
只能拿到他人的消息列,漫游消息
需要在后台管理开启漫游,不然我们是拿不到漫游消息
的,漫游消息
指的是自己最近发送的消息列,当然会有本地库存储的,但是小程序里是不支持本地数据库的,当然我也是第一次对接,现在我的理解是这样,如有错误请指出。
会话
会话
指的是你最近跟某个用户产生的一次对话,他是有消息输出的,如QQ会话列表,千万不要把会话
跟消息弄混淆了,会话包括消息或多个消息
第五步
看到这里,你也大概了解这个流程是怎么建立的,你现在首要的任务是,写好UI界面,然后把我上面登录的方法调通,然后用实例发送一个消息,看看真实的数据,在把官方给的demo模板里的回调方法一个一个抽出来,我把我的例子放出来如下,有些方法和模块搜不到你不用管,因为这个都是逻辑层,自己懂了之后,每个人才会有自己的实现方式,当然我用的uni.app里的vuex....
import NIM from '@/vendors/NIM_Web_NIM_weixin_v6.7.0.js'
import NetcallController from './netcall.js'
import config from '@/im/config.js'
import store from '@/api/request/store/home.js' // 删除本地缓存
import common from '@/common/common.js'
import { hexMD5, utf8 } from '@/utils/md5-utf8'
let app = getApp()
let orderCounter = 1
export default class IMController {
constructor(headers) {
// vuex对象赋给im类
this.store = headers.$store
this.onConnect = this.onConnect.bind(this)
this.onSessions = this.onSessions.bind(this)
this.onMsg = this.onMsg.bind(this)
this.onRoamingMsgs = this.onRoamingMsgs.bind(this)
this.onUpdateSession = this.onUpdateSession.bind(this)
this.onOfflineMsgs = this.onOfflineMsgs.bind(this)
this.onMyInfo = this.onMyInfo.bind(this)
/* 初始化SDk */
app.globalData.nim = NIM.getInstance({
// debug: true,
db: false, // 小程序不支持数据库
syncSessionUnread: true, // 同步会话的未读数
autoMarkRead: false, // 不开启自动标记消息已读 此时服务器下推的所有离线消息算未读,漫游消息算已读
appKey: config.appKey, // 在云信管理后台查看应用的 appKey
token: headers.token, // 帐号的唯一标识, 用于建立连接
account: headers.account, // 帐号, 应用内唯一
onconnect: this.onConnect, // 连接成功
onwillreconnect: this.onWillReconnect, // 断开重连
ondisconnect: this.onDisconnect, // 丢失连接
onerror: this.onError, // onError
/* 收到onconnect后,链接已经建立(登录成功), SDK会开始同步数据, 在收到onsyncdone回调后表示SDK完成了数据同步工作, 此时开发者可以进行渲染 UI 等操作了。*/
onsyncdone: this.onSyncDone,
// 用户名片
onmyinfo: this.onMyInfo, // 同步登录用户资料的回调, 会传入用户资料
// onupdatemyinfo: this.onUpdateMyInfo, // 当前登录用户在其它端修改自己的个人名片之后的回调, 会传入用户资料
onusers: this.onUsers, // 同步好友用户资料的回调, 会传入用户资料数组 此回调是增量回调, 可以调用nim.mergeUsers来合并数据
// onupdateuser: this.onUpdateUser, // 用户资料更新后的回调, 会传入用户资料,请参考用户资料更新时机
// // 机器人列表的回调
// onrobots: this.onRobots, // 机器人列表事件
// // 会话
onsessions: this.onSessions, // 同步最近会话列表回调, 会传入会话列表, 按时间正序排列, 即最近聊过天的放在列表的最后面 此回调是增量回调, 可以调用nim.mergeSessions来合并数据
onupdatesession: this.onUpdateSession, // 更新会话的回调, 会传入会话对象, 以下情况会收到此回调 收到消息 发送消息 设置当前会话 重置会话未读数
// // 消息
onroamingmsgs: this.onRoamingMsgs, // 漫游消息, 对应回调
onofflinemsgs: this.onOfflineMsgs, // 离线消息, 对应回调
onmsg: this.onMsg, // 收到消息
// // 系统通知
// onofflinesysmsgs: this.onOfflineSysMsgs, // 同步离线系统通知的回调, 会传入系统通知数组
// onsysmsg: this.onSysMsg, // 收到系统通知的回调, 会传入系统通知
// onsysmsgunread: this.onSysMsgUnread, // 收到系统通知未读数的回调
// onupdatesysmsgunread: this.onUpdateSysMsgUnread, // 更新系统通知未读数的回调
// onofflinecustomsysmsgs: this.onOfflineCustomSysMsgs, // 同步离线自定义系统通知的回调, 会传入系统通知数组
// oncustomsysmsg: this.onCustomSysMsg, // 收到自定义系统通知的回调, 会传入系统通知
// // 收到广播消息
// onbroadcastmsg: this.onBroadcastMsg,
// onbroadcastmsgs: this.onBroadcastMsgs,
// // 事件订阅
// onpushevents: this.onPushEvents,
})
// 发送消息开始登陆
// store.dispatch({
// type: 'Login_StartLogin'
// })
}
/** 1 abnormal closure
* 连接成功
*/
onConnect() {
console.log(orderCounter++, '连接成功: ')
console.log(app.globalData.nim)
app.globalData.netcallController = new NetcallController({
// debug: false,
debug: true,
nim: app.globalData.nim,
store: this.store
})
}
/**
* 连接出错
*/
onError(error) {
console.log('连接出错')
common.msgHint()
toLogin()
}
/**
* 此时说明 SDK 处于断开状态, 开发者此时应该根据错误码提示相应的错误信息, 并且跳转到登录页面
*/
onDisconnect(error) {
console.log('丢失连接');
if (error) {
switch (error.code) {
// 账号或者密码错误, 请跳转到登录页面并提示错误
case 302:
common.msgHint({
title: 'im的账户或密码错误,需重新登录'
})
toLogin()
break;
// 重复登录, 已经在其它端登录了, 请跳转到登录页面并提示错误
case 417:
common.msgHint({
title: '已经在其它端登录了'
})
toLogin()
break;
// 被踢, 请提示错误后跳转到登录页面
case 'kicked':
common.msgHint({
title: '你被一名用户踢了'
})
toLogin()
break;
default:
break;
}
}
}
/** 1 abnormal closure
* 断线重连
*/
onWillReconnect(obj) {
// 此时说明 SDK 已经断开连接, 请开发者在界面上提示用户连接已断开, 而且正在重新建立连接
console.log('断线重连');
common.msgHint({
title: '断线重连中,请稍后!',
duration: 3000
})
}
/** 6
* 个人名片:存储个人信息到全局数据
*/
onMyInfo(user) {
console.log(orderCounter++, ' 个人信息: ')
console.log(user)
if (user) {
this.store.commit('setMyImData', user)
}
}
/** 7
* 包含名片的好友信息(可能某些字段不全),[{account,avatar,birth,createTime,email,gender,nick,sign,updateTime}]
*/
onUsers(friends) {
console.log(orderCounter++, ' 好友信息: ')
console.log(friends)
}
/** 9
* 同步完成
*/
onSyncDone() {
console.log(orderCounter++, '同步完成')
}
/**会话
* [ {id:"p2p-liuxuanlin",lastMsg:{from:'wujie',text:'222',to:"liuxuanlin"}} ]
*/
onSessions(session) {
console.log('会话: ')
console.log(session)
if (session) {
// 会话列表
let chatList = JSON.parse(JSON.stringify(this.store.state.chatList || []))
// 合并会话列表
let list = app.globalData.nim.mergeSessions(chatList, session);
}
}
/**
* 会话更新:收到消息、发送消息、设置当前会话、重置会话未读数 触发
* {id:'p2p-zys2',lastMsg:{},scene,to,unread,updateTime}
* {id:'team-1389946935',lastMsg:{attach:{accounts,team},type,users},scene,to,from,type,unread,updateTime}
*/
onUpdateSession(session) {
console.log('会话更新: ', session)
if (session) {
// 更新会话列表
app.globalData.netcallController.mergeChatList(session)
}
}
/**
* 收到消息
* {cc,flow:"in",from,fromClientType:"Web",fromDeviceId,fromNick,idClient,idServer:"9680840912",isHistoryable:true,isLocal,isMuted, isOfflinable,isPushable,isRoamingable,isSyncable,isUnreadable,needPushNick,resend,scene:"p2p",sessionId:"p2p-zys2",status:"success",target:"zys2",text:"[呕吐]",time,to:"wujie",type:"text",userUpdateTime}
*/
onMsg(msg) {
console.log('收到消息', msg.scene, msg.type);
console.log(msg);
if (msg) {
// 更新消息列表
app.globalData.netcallController.mergeMsg(msg)
}
}
/**
* 漫游消息:会多次收到,每次只会收到指定人的漫游消息
// {scene:"p2p",sessionId:"p2p-cs4",timetag:1513153729257,to:"cs4",msg:[{from:'wujie',text:'222',to:'cs4'}]}
// {scene:"team",sessionId:"team-3944051",timetag:1513153729257,to:"3944051",msg:[{from:'wujie',text:'222',to:'cs4'}]}
*/
onRoamingMsgs(session) {
console.log(orderCounter++, ' 漫游消息')
console.log(session)
if (session) {
// 合并漫游消息列表
app.globalData.netcallController.mergeMsgList(session)
}
}
/**
* 会话离线消息 拿到每条会话的消息列表
*/
onOfflineMsgs(session) {
console.log(orderCounter++, ' 会话离线消息')
console.log(session)
if (session) {
// 合并离线消息列表
app.globalData.netcallController.mergeMsgList(session)
}
}
}
let toLogin = res => {
setTimeout(() => {
// 删除本地缓存
store.clear()
uni.reLaunch({
url: '/pages/login/index'
})
}, 1000)
}
我是个懒人,~~喜欢把知识放在脑子里,写了这么多累了,有什么需要咨询的可以私信给我哦,bey