最近忙于在公司做关于im方面sdk开发,由于也是第一次做sdk方面的开发,参考环信web-sdk集成文档
:http://docs-im.easemob.com/im/web/intro/basic
接下来给出我的websocket的封装示例,首先看看我的GdchentWebsocket.ts文件,示例代码如下:
/*
* @Author: chentao
* @Date: 2020-12-15 16:33:08
* @Last Modified by: chentao
* @Last Modified time: 2021-03-15 16:31:57
* 封装WebSocket
*/
class GdchentWebSocket {
private messageCallBack: Function;
private connectSuccessCallBack: Function;
private connectErrorCallBack: Function;
// websocket实例
public ws: WebSocket;
// 最大收到消息的时间
public maxSendTime: number = 0;
// 最大收到消息的序列id
public maxSequenceId: string = '0';
// 当前用户的id
public defaultId: string;
// 当前用户的名称
public fromName: string;
// 当前用户的头像
public fromHeadUrl: string;
// 当前登录的token
public token: string;
public ret: any;
constructor(
webSocketMessageCallBack: Function,
connectSuccessCallBack: Function,
connectErrorCallBack: Function
) {
this.messageCallBack = webSocketMessageCallBack;
this.connectSuccessCallBack = connectSuccessCallBack;
this.connectErrorCallBack = connectErrorCallBack;
}
public createSocket = (url: string, ret: any) => {
if (!this.ws) {
console.log('websocketUrl:', url)
this.ws = new WebSocket(url);
//ws.binaryType = 'arraybuffer';
this.ws.binaryType = 'blob';
this.ws.onopen = () => {
console.log('WebSocket已连接');
this.ws.send(ret);
this.connectSuccessCallBack();
};
this.ws.onmessage = (event) => {
console.log('收到消息', event)
this.messageCallBack(event)
};
this.ws.onclose = (e) => {
console.log(`WebSocket已关闭,状态码:${e.code}`);
this.connectErrorCallBack(e)
if (e.code === 1006) {
console.log(`服务器或网络已断开,正在尝试重新连接...`);
setTimeout(() => {
this.createSocket(url, ret);
}, 1000);
}
};
this.ws.onerror = (e) => {
console.log('WebSocket连接失败', e);
this.connectErrorCallBack()
};
} else {
console.log("websocket实例存在", this.ws.readyState);
switch (this.ws.readyState) {
case WebSocket.CONNECTING:
// do something
console.log('websocket正在连接')
break;
case WebSocket.OPEN:
// do something
//发送消息
console.log("websocket的readyState状态是否为1:", this.ws.readyState);
console.log("发送的消息", ret);
this.ws.send(ret);
break;
case WebSocket.CLOSING:
// 断开 web socket 连接成功触发事件
// do something
console.log("websocket正在关闭:", this.ws.readyState);
break;
case WebSocket.CLOSED:
// do something
console.log("websocket已经关闭:", this.ws.readyState);
console.log(`服务器或网络已断开,正在尝试重新连接...`);
setTimeout(() => {
this.createSocket(url, ret);
}, 1000);
break;
default:
// this never happens
break;
}
}
}
// 关闭连接
public close() {
if (this.ws) {
this.ws.close();
this.ws = null;
}
}
}
export default GdchentWebSocket;
接下来进入我自己封装的处理消息所有逻辑的示例代码如下:
/*
* @Author: chentao
* @Date: 2020-12-18 10:39:22
* @Last Modified by: chentao
* @Last Modified time: 2021-03-18 10:39:42
*/
import { storage, pinyin, navigate, getSensitiveMsg, getRandomKey, StringKey } from '../../../utils';
import moment from 'moment';
import GdchentWebSocket from './GdchentWebSocket';
import { request } from '../../../config/zxAxios';
import api from '../../../config/apiConfig';
import proToObject from '../../../proto/proto';
import ParseMsgUtil from "../../../utils/ParseMsgUtil";
import ArrayBufferUtil from '../../../utils/ArrayBufferUtil'
import AesUtil from '../../../utils/AesUtil'
import { randomKey } from '../../../utils/secret';
import ChatItemEnum from '../../../enum/ChatItemEnum';
import CommunicationTypeEnum from '../../../enum/CommunicationTypeEnum'
import CommandEnum from '../../../enum/CommandEnum'
import CreateChatGroup from '../../../interface/CreateChatGroup';
import LoginStore from '../../ZxLogin/store'
import PullOfflineMessageListEnum from '../../../enum/PullOfflineMessageListEnum';
import MessageTypeEnum from '../../../enum/MessageTypeEnum';
import ConnectEnum from '../../../enum/ConnectEnum';
import StorageKeyEnum from '../../../enum/StorageKeyEnum';
const currentTime = moment().valueOf();
let sendHeartTimer: any; //心跳包的定时器
const WEB_SOCKET_TIMEOUT = 50000; //50秒
class Store {
public websocketCallBack: Object;
public arrayBufferUtil: ArrayBufferUtil = new ArrayBufferUtil();
public parseMsgUtil: ParseMsgUtil = new ParseMsgUtil();
public loginStore: LoginStore = new LoginStore(this);
// Socket实例
gdchentWebSocket: GdchentWebSocket = null;
// 当前用户的id
defaultId: string = storage.get('im_defaultId');
// 当前登录的token
token: string = '';
// 当前时间
currentDate: string = moment(currentTime).format('YYYY-MM-DD');
// 已收到消息缓存,用于检测消息是否重复,key为msgId
cacheMessages: { [key: string]: boolean } = {};
// 可展示聊天消息的类型
messageTypes = [
1, // 文字
2, // 语音
3, // 图片
4, // 视频
5, // 表情
6, // 链接
7, // 位置
8, // 聊天记录
9, // 文件
10, // 发红包
12, // 名片
20, // 位置共享
48, // 回复
51, // 邀请加入群聊
77, // 群公告
];
// 根据好友id获取好友信息
friendData = {};
// 是否触发接收好友,当有值时,跳转到聊天模块,并打新好友的聊天
acceptFriendDefaultId: any = null;
// 敏感词
sensitiveKeywords: any = [];
// 用户信息
userInfo: any = {};
userInfoList: any = [];
// 聊天列表
chats: any[] = [];
// 选中菜单数据
activeChatData: any = {};
// 新的好友列表
newFriends: any[] = [];
// 好友列表
friends: any[] = [];
creatChatGroupsList: any[] = [];
allGroupMembers: any[] = [];
// 群组列表
groups: any = [];
// 好友列表id和备注名键值对
remarkNameData = {};
contextMessage: any = null;
// 表情列表
emojis: any = [{ icon: 'love', data: [] }];
// 用于更新收藏列表
collectKey: number = 0;
// 敏感词发送次数
sensitiveCount: number = 0;
// 禁止聊天
disabled: number = 0;
// websocket连接状态 0表示断开连接
connect: number = 1;
//联系人分组的key
contact_tag: string = 'CONTACT_TAG'
topList: any[] = []
//storage的key的常量
public SDK_ACCT_LOGIN_KEY = 'sdkacctLogin'
public CACHE_CHATS_KEY = `im_${this.defaultId}_chats`
public LAST_MESSAGE_KEY: string = 'lastmessageKey'
public ACTIVE_CHAT_DATA_KEY: string = 'activeChatDataKey'
public CHAT_TOP_DATA = 'CONVERSATION_PIN_TAG'
//websocket
public webWocketUrl: string = '';//服务器地址
public appId: string = ''
//用户id
public userId: string = '';
//设备id
public deviceId: string = 'deviceId1'
private isFirstActiveChatData: boolean = false;
public sdkacctLogin: any;
public aes = new AesUtil()
constructor() { }
public getLoginInstance():LoginStore{
return this.loginStore;
}
//获取二维码信息 同时sdk这边会开启轮询
public async getScanLoginCode() {
const scanLoginCode = await this.loginStore.getQRCodeUrl()
return scanLoginCode
}
//获取本地的会话列表
public getLocalChatList = async () => {
return new Promise(async (resolve, reject) => {
//每次在调用接口之前判断sdk方面是否已经登陆
let cacheChats = await storage.getF(this.CACHE_CHATS_KEY)
if (!cacheChats) {
console.log('当前没有离线缓存列表')
return reject({ message: '获取本地缓存会话失败!' });
}
if (cacheChats) {
this.chats = cacheChats;
if (!this.isFirstActiveChatData && Array.isArray(cacheChats) && cacheChats.length > 0) {
cacheChats[0][StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_ACTIVE
cacheChats[0][StringKey.UN_READ_COUNT] = ChatItemEnum.CHAT_ITEM_UN_READ_COUNT_DEFAULT_ZERO
this.activeChatData = cacheChats[0]
let newChats: any = []
newChats = newChats.concat(cacheChats)
cacheChats.forEach(async (item, index) => {
const { conversationId }: any = cacheChats[index];
if (conversationId) {
//console.log('获取的离线消息id', conversationId)
//通过会话id拉取离线消息
await this.getPullOfflineMessageList({
communicationId: conversationId
})
}
})
}
this.isFirstActiveChatData = true;
}
if (cacheChats && Array.isArray(cacheChats)) {
resolve(cacheChats)
}
})
}
public getPullOfflineMessageList = async ({
communicationId,
count = PullOfflineMessageListEnum.COUNT,
deviceType = PullOfflineMessageListEnum.DEVICE_TYPE, //2表示web端
}: any) => {
//拉取离线消息
const protoTime = await storage.getF(this.LAST_MESSAGE_KEY);
if (protoTime) {
const { lastMsgReceiveTime, lastMsgSequenceId }: any = protoTime
const params = {
count: count,
deviceType: deviceType,
lastMsgReceiveTime: lastMsgReceiveTime,
endMsgId: lastMsgSequenceId,
communicationId: communicationId,
}
const messageRes = await request({
method: 'GET',
url: api.GET.zxGetPullOfflineMessageList,
data: params
})
const { code, hasError, data } = messageRes
if (code == '0' && !hasError) {
//清理7天前会话
// 截取20条
if (data) {
let { msgList } = data;
if (!msgList || msgList.length <= 0) {
console.log('拉取的离线消息为空')
return;
}
//将离线消息拼接入本地在线消息
let cacheChats = await storage.getF(this.CACHE_CHATS_KEY)
if (cacheChats && Array.isArray(cacheChats)) {
const findCacheChat: any = cacheChats.find((item, index) => {
return item['conversationId'] === communicationId
})
if (findCacheChat) {
if (findCacheChat && Array.isArray(findCacheChat[StringKey.MESSAGES_KEY])) {
findCacheChat.messages.forEach((itemMessage: any, index: number) => {
msgList = msgList.filter((itemMsg: any, index: number) => {
return itemMsg['messageId'] !== itemMessage['messageId']
})
})
findCacheChat.messages = findCacheChat.messages.concat(msgList)
if (findCacheChat['conversationId'] === this.activeChatData['conversationId']) {
//console.log('findCacheChat',JSON.stringify(findCacheChat))
this.setRefreshActiveChatData(findCacheChat)
}
this.setObserverChatList(findCacheChat, false)
} else {
console.log('搞操作前不是数组')
}
}
}
}
}
}
}
public getCacheActiveGroupToActiveData = async (contactItem: any) => {
let cacheChats: any = await storage.getF(this.CACHE_CHATS_KEY)
if (cacheChats && Array.isArray(cacheChats) && cacheChats.length > 0) {
let cacheItem = cacheChats.find((item, index) => {
return item[StringKey.COMMUNICATIONID] === contactItem[StringKey.COMMUNICATIONID]
})
if (cacheItem) {
return cacheItem;
}
}
return contactItem
}
public getCacheActiveToActiveData = async (contactItem: any) => {
let cacheChats: any = await storage.getF(this.CACHE_CHATS_KEY)
if (cacheChats && Array.isArray(cacheChats) && cacheChats.length > 0) {
let cacheItem = cacheChats.find((item, index) => {
return item['userId'] === contactItem['userId'] && item[StringKey.CONVERSATIONID] === contactItem[StringKey.CONVERSATIONID]
})
if (cacheItem) {
return cacheItem;
}
}
return contactItem
}
//联系人到会话
public setActiveContactAndRefreshChatList = async (chatItem: any, isCreateTop = false) => {
if (!chatItem) {
if (process.env.NODE_ENV === 'development') {
console.log('setActiveContactAndRefreshChatList——chatItem传入有问题', chatItem)
}
return;
}
chatItem[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_ACTIVE
chatItem[StringKey.UN_READ_COUNT] = ChatItemEnum.CHAT_ITEM_UN_READ_COUNT_DEFAULT_ZERO
const createChatTime = new Date().getTime()
chatItem[StringKey.CREATE_CHAT_TIME] = createChatTime
let cacheChats: any = await storage.getF(this.CACHE_CHATS_KEY)
if (cacheChats && Array.isArray(cacheChats) && cacheChats.length > 0) {
let newActiveIndex = cacheChats.findIndex((value, index) => {
if (value[StringKey.ACTIVE] == ChatItemEnum.CHAT_ITEM_ACTIVE) {
value[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_NO_ACTIVE;
}
return chatItem[StringKey.COMMUNICATIONID] === value[StringKey.COMMUNICATIONID]
//return chatItem['userId'] === value['userId']
})
if (newActiveIndex != -1) {
this.activeChatData = cacheChats[newActiveIndex]
this.activeChatData[StringKey.UN_READ_COUNT] = ChatItemEnum.CHAT_ITEM_UN_READ_COUNT_DEFAULT_ZERO
this.activeChatData[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_ACTIVE
if (!this.activeChatData[StringKey.CREATE_CHAT_TIME]) {
this.activeChatData[StringKey.CREATE_CHAT_TIME] = createChatTime
}
this.setRefreshActiveChatData(this.activeChatData)
} else {
cacheChats.unshift(chatItem)
await storage.setF(this.CACHE_CHATS_KEY, cacheChats)
this.getLocalChatList()
}
} else {
cacheChats = []
cacheChats.unshift(chatItem)
await storage.setF(this.CACHE_CHATS_KEY, cacheChats)
this.getLocalChatList()
}
}
public deleteChatItem = async (chatItem: any) => {
let cacheChats: any = await storage.getF(this.CACHE_CHATS_KEY)
if (cacheChats && cacheChats.length > 0) {
cacheChats = cacheChats.filter((item: any, index: number) => {
return chatItem['conversationId'] !== item['conversationId']
})
await storage.setF(this.CACHE_CHATS_KEY, cacheChats)
this.getLocalChatList()
}
}
public setObserverChatList =
async (chatItem: any, isCreateTop = false, isUpdateMessage = false) => {
let cacheChats: any = await storage.getF(this.CACHE_CHATS_KEY)
if (cacheChats && cacheChats.length > 0) {
cacheChats.forEach((item: any, index: number) => {
if (item[StringKey.ACTIVE] === ChatItemEnum.CHAT_ITEM_ACTIVE) {
item[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_NO_ACTIVE
}
})
let existIndex = -1
let cacheConversationChat: any;
cacheChats.forEach((item: any, index: number) => {
if (chatItem[StringKey.COMMUNICATIONID] === item[StringKey.COMMUNICATIONID]) {
cacheConversationChat = item
existIndex = index;
}
})
if (isCreateTop) {
if (!cacheConversationChat) {
chatItem[StringKey.IS_TOP] = isCreateTop
cacheChats.unshift(chatItem)
} else {
chatItem[StringKey.IS_TOP] = isCreateTop
let deleteChat = cacheChats.splice(existIndex, 1)
cacheChats.unshift(chatItem)
}
this.addRefreshTopList(chatItem)
} else {
chatItem[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_ACTIVE
chatItem[StringKey.UN_READ_COUNT] = ChatItemEnum.CHAT_ITEM_UN_READ_COUNT_DEFAULT_ZERO
if (!cacheConversationChat) {
cacheChats.unshift(chatItem)
} else {
cacheConversationChat[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_ACTIVE
cacheConversationChat[StringKey.UN_READ_COUNT] = ChatItemEnum.CHAT_ITEM_UN_READ_COUNT_DEFAULT_ZERO
let jsChatMessages = chatItem[StringKey.MESSAGES_KEY]
if (jsChatMessages && Array.isArray(jsChatMessages) && jsChatMessages.length > 0) {
// console.log('cacheConversationChat:', cacheConversationChat)
cacheConversationChat[StringKey.MESSAGES_KEY] = jsChatMessages
if (isUpdateMessage) {
let deleteChat = cacheChats.splice(existIndex, 1)
cacheChats.unshift(chatItem)
}
}
}
}
} else {
chatItem[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_ACTIVE
chatItem[StringKey.UN_READ_COUNT] = ChatItemEnum.CHAT_ITEM_UN_READ_COUNT_DEFAULT_ZERO
cacheChats = []
cacheChats.unshift(chatItem)
}
const topArray: any = []
const sendTimeSortArray: any = []
cacheChats.forEach((cacheChatItem: any, index: number) => {
const { isPin } = cacheChatItem
if (isPin) {
topArray.push(cacheChatItem)
} else {
sendTimeSortArray.push(cacheChatItem)
}
})
sendTimeSortArray.sort((itemA: any, itemB: any) => {
const { sendTime: sendTimeA } = itemA
const { sendTime: sendTimeB } = itemB
if (sendTimeA > sendTimeB) {
return -1;
}
return 0;
})
cacheChats = topArray.concat(sendTimeSortArray)
await storage.setF(this.CACHE_CHATS_KEY, cacheChats)
this.getLocalChatList()
}
//添加多端同步置顶数据
public addRefreshTopList = async (chatItem: any) => {
if (chatItem) {
let findHaveItem = this.topList.find((item, index) => {
return chatItem[StringKey.COMMUNICATIONID] === item[StringKey.COMMUNICATIONID]
})
if (!findHaveItem) {
this.topList.unshift(chatItem)
}
this.setChatTopData()
}
}
public deleteTopItemData = async (chatItem: any) => {
if (chatItem) {
this.topList = this.topList.filter((item, index) => {
return chatItem[StringKey.COMMUNICATIONID] !== item[StringKey.COMMUNICATIONID]
})
let cacheChats: any = await storage.getF(this.CACHE_CHATS_KEY)
if (cacheChats && cacheChats.length > 0) {
let existIndex = -1
const findActiveChat = cacheChats.find((item: any, index: number) => {
if (chatItem[StringKey.COMMUNICATIONID] === item[StringKey.COMMUNICATIONID]) {
existIndex = index;
}
return chatItem[StringKey.COMMUNICATIONID] === item[StringKey.COMMUNICATIONID];
})
if (findActiveChat) {
chatItem[StringKey.IS_TOP] = false
let deleteChat = cacheChats.splice(existIndex, 1)
cacheChats.push(chatItem)
cacheChats = this.chatSort(cacheChats)
await storage.setF(this.CACHE_CHATS_KEY, cacheChats)
this.getLocalChatList()
}
}
}
}
public chatSort = (cacheChats: any[]) => {
const topArray: any = []
const sendTimeSortArray: any = []
cacheChats.forEach((cacheChatItem, index) => {
const { isPin } = cacheChatItem
if (isPin) {
topArray.push(cacheChatItem)
} else {
sendTimeSortArray.push(cacheChatItem)
}
})
sendTimeSortArray.sort((itemA: any, itemB: any) => {
const { sendTime: sendTimeA } = itemA
const { sendTime: sendTimeB } = itemB
if (sendTimeA > sendTimeB) {
return -1;
}
return 0;
})
cacheChats = topArray.concat(sendTimeSortArray)
return cacheChats
}
public groupExit = async (groupId: string) => {
const res = await request({
method: 'POST',
url: api.POST.zxGroupExit,
data: {
groupId: groupId
}
})
const { code, hasError, data } = res;
if (code === '0' && !hasError) {
this.getChatGroupLists()
}
}
//选中会话
public setRefreshActiveChatData = async (activeChatData: any) => {
if (!activeChatData) {
if (process.env.NODE_ENV === 'development') {
console.log('保存的activeChatData为空')
}
return
}
activeChatData[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_ACTIVE
activeChatData[StringKey.UN_READ_COUNT] = ChatItemEnum.CHAT_ITEM_UN_READ_COUNT_DEFAULT_ZERO
await storage.setF(this.ACTIVE_CHAT_DATA_KEY, activeChatData);
this.activeChatData = activeChatData
return new Promise((resolve, reject) => {
if (typeof activeChatData === 'object') {
resolve(activeChatData)
} else {
reject({
message: '刷新会话数据失败!'
})
}
})
}
public recallMessage = async ({ conversationId = '', messageId = '' }) => {
const dataParams = {
conversationId: conversationId,
messageId: messageId
}
const res = await request({
method: 'POST',
url: api.POST.zxMsgRecall,
data: dataParams
})
const { code, hasError, data } = res
if (code == '0' && !hasError) {
this.deleteMessages(messageId)
} else {
const { error } = res
}
}
// 删除消息
public deleteMessages = async (messageIds: string | string[]) => {
messageIds = [].concat(messageIds);
this.chats = this.chats.map((item) => {
if (item.active === ChatItemEnum.CHAT_ITEM_ACTIVE) {
let messages = item.messages.filter(({ messageId }: any) => {
return !messageIds.includes(messageId)
})
let itemObject = {
...item, messages: messages
}
this.setRefreshActiveChatData(itemObject)
return itemObject;
}
return item;
});
await storage.setF(this.CACHE_CHATS_KEY, this.chats)
this.getLocalChatList()
}
// 初始化websocket
public initWebSocket = async (
websocketCallBack: Object,
appId,
) => {
this.appId = appId
this.websocketCallBack = websocketCallBack
await storage.setF(StorageKeyEnum.APP_ID, appId)
}
public sendReqBindUserChannel = async (config: any) => {
const params = config
const proto: any = proToObject
const { ReqBindUserChannel }: any = proto
let protoName = 'ReqBindUserChannel';
let command = CommandEnum.COMMAND_BIND_USER_REQ
this.sendWebSocketMessage(
params,
ReqBindUserChannel,
protoName,
command
)
}
public sendMessage = async ({
content,
messageType = MessageTypeEnum.TEXT_MESSAGE,
communicationType = CommunicationTypeEnum.PERSON_MESSAGE,
appId: string,
communicationId = '',
fromUserId = '',
toUserId = ''
}) => {
if (process.env.NODE_ENV === 'development') {
console.log('激活的会话数据', this.activeChatData)
}
const userInfo = await storage.getF('userInfo')
const { avatar, nickname } = userInfo
const otherInfo = {
userInfo: {
"userId": userInfo['userId'],
"avatarUrl": avatar,
"username": nickname
}
}
let tag = getRandomKey(16)
const params = {
appId: this.appId, //string 对应平台产品APP_ID
communicationId: communicationId, //string 所在会话ID
fromUserId: fromUserId, // string 发送方用户ID
toUserId: toUserId, // string接收方用户ID
sendTime: new Date().getTime(), //int64 发送时间 时间戳
communicationType: communicationType, // int32 消息类型:1=个人消息;2=群组消息;3=公众号消息
messageType: messageType, // 消息类型:1=文本消息;2=表情消息;3=文件;4=图片;5=语音消息;6=视频消息;7=位置消息;8=命令;9=自定义消息;10=系统消息;11=音视频消息;12=红包消息
content: content, // string消息文本
setting: '', //string 消息设置
other: JSON.stringify(otherInfo),
tag: tag,
}
const proto: any = proToObject
const { CommunicationMessageProto }: any = proto
let protoName = 'CommunicationMessageProto';
let command = CommandEnum.COMMAND_SEND_MSG_REQ
storage.setF(tag, params)//这个是发送前的对象
//在这里返回给demo层一个发送前的状态
await this.createSendMessageChats(params, command)
let that = this;
setTimeout(() => {
that.sendWebSocketMessage(
params,
CommunicationMessageProto,
protoName,
command,
)
}, 1000);
}
public createSendMessageChats = async (sendData: any, command: number) => {
const {
appId, //string 对应平台产品APP_ID
communicationId, //string 所在会话ID
fromUserId, // string 发送方用户ID
toUserId, // string接收方用户ID
sendTime, //int64 发送时间 时间戳
communicationType, // int32 消息类型:1=个人消息;2=群组消息;3=公众号消息
messageType, // 消息类型:1=文本消息;2=表情消息;3=文件;4=图片;5=语音消息;6=视频消息;7=位置消息;8=命令;9=自定义消息;10=系统消息;11=音视频消息;12=红包消息
content, // string消息文本
setting, //string 消息设置
other,
tag,
} = sendData
const itemMessage = JSON.parse(JSON.stringify(sendData))
itemMessage[StringKey.SEND_MESSAGE_STATUS] = StringKey.SEND_MESSAGE_FAIRED
itemMessage[StringKey.COMMAND_KEY] = command
this.chats.forEach((value, index) => {
if (value[StringKey.ACTIVE] == ChatItemEnum.CHAT_ITEM_ACTIVE) {
value[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_NO_ACTIVE
}
})
if (communicationType == CommunicationTypeEnum.PERSON_MESSAGE
|| communicationType == CommunicationTypeEnum.GROUP_MESSAGE) {
// 检测聊天列表是否存在
const findChatIndex = this.chats.findIndex((item) => item.communicationId === communicationId);
//console.log('findChatIndex', findChatIndex)
const findChat = this.chats[findChatIndex];
//console.log('findChatIndex', findChat)
if (findChat) {
// 创建聊天后,选中聊天
// 设置未读数量
// 自己发的消息不计算
// 非选中聊天才展示未读数量
// 追加消息
let messages = []
itemMessage[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_ACTIVE
messages.push(itemMessage)
if (findChat.messages) {
findChat.messages?.push(...messages)
} else {
findChat.messages = messages
}
//让当前激活的active会话item插入消息列表数据
this.activeChatData.messages = findChat.messages
let toJsActiveChatData = this.activeChatData
console.log("toJsActiveChatData" + command, toJsActiveChatData)
await this.setRefreshActiveChatData(toJsActiveChatData)
// 聊天已经置顶则不做处理,如果未置顶则将其移动至置顶的后面
//this.chats.splice(findChatIndex, 1);
//this.chats.unshift(findChat);
this.setObserverChatList(findChat, false)
} else {
//会话聊天列表不存在 创建会话
const findFriendChatIndex = this.friends.findIndex((item) => item.communicationId === communicationId);
const findFriendChat = this.friends[findFriendChatIndex];
//console.log('command11-联系人找会话消息', findFriendChat)
if (findFriendChat) {
let messages = []
messages.push(itemMessage)
findFriendChat[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_ACTIVE
findFriendChat[StringKey.UN_READ_COUNT] = ChatItemEnum.CHAT_ITEM_UN_READ_COUNT_DEFAULT_ZERO
findFriendChat[StringKey.MESSAGES_KEY] = messages
this.activeChatData.messages = messages
let toJsActiveChatData = this.activeChatData
//console.log(toJsActiveChatData)
this.setRefreshActiveChatData(toJsActiveChatData)
this.setObserverChatList(findFriendChat, true)
} else {
if (communicationType == CommunicationTypeEnum.GROUP_MESSAGE) {
let messages = []
messages.push(itemMessage)
itemMessage[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_ACTIVE
itemMessage[StringKey.UN_READ_COUNT] = ChatItemEnum.CHAT_ITEM_UN_READ_COUNT_DEFAULT_ZERO
itemMessage[StringKey.MESSAGE_ID] = itemMessage[StringKey.MESSAGE_ID]
itemMessage[StringKey.MESSAGES_KEY] = messages
this.activeChatData.messages = messages
let toJsActiveChatData = this.activeChatData
//console.log(toJsActiveChatData)
this.setRefreshActiveChatData(toJsActiveChatData)
this.setObserverChatList(findFriendChat, true)
} else if (communicationType == CommunicationTypeEnum.PERSON_MESSAGE) {
console.log('command联系人中找不到该好友')
} else {
console.log('command联系人中找不到该好友else情况')
}
}
}
}
}
public sendWebSocketMessage = async (
params: any,
method: any,
protoName: string,
command: number
) => {
const sdkacctLogin = await storage.getF(this.SDK_ACCT_LOGIN_KEY)
if (!!sdkacctLogin) {
const { im_module } = sdkacctLogin
if (!!im_module) {
//console.log('im_module', im_module)
const { server_addr, wssocket_port, }: any = im_module
this.webWocketUrl = `ws://${server_addr}:${wssocket_port}`
if (this.webWocketUrl) {
const ret: ArrayBuffer = this.templateFun(
this.appId,
this.userId,
this.deviceId,
params,
method,
protoName,
command
)
this.getWebSocketInstance().createSocket(this.webWocketUrl, ret)
}
} else {
console.log('sdk登录信息-json数据解析异常!')
}
} else {
console.log('获取登录信息失败-跳到登录页面')
navigate('/zxlogin')
}
}
//proto模板函数
public templateFun(
appId: string,
userId: string,
deviceId: string,
param: string,
method: any,
protoName: any,
command: number,
): ArrayBuffer {
//console.log("methodName", methodName, protoName);
// 函数模板
let createProto = method.create(param); // 开始创建
console.log("编码前createProto", createProto);
let encodeProto = method.encode(createProto).finish(); // 对proto对象进行编码
console.log("编码后的东西", encodeProto);
const proto: any = proToObject;
let protoData = proto[protoName].decode(encodeProto);
console.log("解码protoData", protoData);
let encryptionResult = encodeProto;
// if (command !== COMMAND_PING) {
// console.log("aes解密", this.aes.socketDecrypt(encryptionResult));
// }
//改交由后台来处理加密了 主要这里会出现前端加密图片地址之类 后端那边会出现解密出错情况
//let encryptionResult = aes.socketEncrypt(encodeProto); // 编码后的结果拿来加密
//console.log("encryptionResult解码前的长度", encryptionResult.length);
//console.log("encryptionResult加密后", encryptionResult);
//let Base64 = require("js-base64").Base64;
//encryptionResult = Base64.decode(encryptionResult); //Base64解密
//console.log("base64解码后", encryptionResult);
//console.log("encryptionResult解码后的长度",encryptionResult.length);
//ParseMsgUtil.bindUserDecodeMessage(encryptionResult); //解密消息
const ret = this.arrayBufferUtil.generateDataPacket(
protoName,
encryptionResult,
appId,
userId,
deviceId,
command
);
return ret;
}
public getWebSocketInstance(): GdchentWebSocket {
if (!this.gdchentWebSocket) {
this.gdchentWebSocket = new GdchentWebSocket(
this.webSocketMessageCallBack,
this.connectSuccessCallBack,
this.connectErrorCallBack
)
}
return this.gdchentWebSocket;
}
public connectErrorCallBack = (e) => {
const { onError }: any = this.websocketCallBack
if (this.websocketCallBack && typeof onError === 'function') {
onError(e, ConnectEnum.CONNECT_FAIRED)
}
this.connect = ConnectEnum.CONNECT_FAIRED;
}
public webSocketMessageCallBack = (event: any) => {
this.connect = 1
if (this.parseMsgUtil) {
console.log('接收到服务器消息', event)
this.parseMsgUtil.parseMsg(event.data, (protoData: any, command: number) => {
console.log('接收到消息页面', protoData, command)
const { onOpened }: any = this.websocketCallBack
if (command == CommandEnum.COMMAND_BIND_USER_RESP) {
//绑定成功
//console.log('websock-et绑定成功', JSON.stringify(protoData))
const { lastMsgReceiveTime, lastMsgSequenceId } = protoData
storage.setF(this.LAST_MESSAGE_KEY, {
lastMsgReceiveTime: lastMsgReceiveTime,
lastMsgSequenceId: lastMsgSequenceId,
});
if (this.websocketCallBack && typeof onOpened === 'function') {
onOpened(protoData, command)
}
}
if (command == CommandEnum.COMMAND_SEND_MSG_REQ) { //10
const {
appId,
communicationId,
fromUserId,
toUserId,
sendTime,
communicationType,
messageType,
content,
setting,//json字符串
messageId,
updateTime,
} = protoData;
storage.setF(this.LAST_MESSAGE_KEY, {
lastMsgReceiveTime: updateTime,
lastMsgSequenceId: messageId,
});
this.createChats(protoData, command)
}
if (command == CommandEnum.COMMAND_SEND_MSG_RSP) {
//11
console.log('command' + command, JSON.stringify(protoData))
this.createChatsByCommand11(protoData, command)
}
if (command == CommandEnum.COMMAND_PULL_MSG_RESP) {
console.log('websocket心跳消息' + command, protoData)
this.createChatsByHeart(protoData, command)
}
})
} else {
console.log('this.parseUtil不存在', this)
}
}
public createChatsByCommand11 = async (protoData: any, command: number) => {
/**
* "resp":{
"ret":1218,
"errorCode":"用户给自己发送消息"
},
*/
const {
resp,
appId,
userId,
communicationId,
sendTime,
toUserId,
tag,
communicationType,
messageType
} = protoData
if (resp && resp['ret'] == 1218) {
const { errorCode }: any = resp
return;
}
const itemMessage = JSON.parse(JSON.stringify(protoData))
const tagInfo = await storage.getF(tag)
const { content } = tagInfo
itemMessage['content'] = content
console.log('发出去的消息自己响应', JSON.stringify(itemMessage))
this.chats.forEach((value, index) => {
if (value[StringKey.ACTIVE] == ChatItemEnum.CHAT_ITEM_ACTIVE) {
value[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_NO_ACTIVE
}
})
if (communicationType == CommunicationTypeEnum.PERSON_MESSAGE
|| communicationType == CommunicationTypeEnum.GROUP_MESSAGE) {
// 检测聊天列表是否存在
const findChat = this.chats.find((item) => item.communicationId === communicationId);
//console.log('findChatIndex', findChat)
if (findChat && findChat[StringKey.MESSAGES_KEY]) {
findChat[StringKey.SEND_TIME] = sendTime
let messages = []
messages = findChat[StringKey.MESSAGES_KEY]
let itemFindMessage = messages.find((value: any, index: number) => {
return value[StringKey.TAG] === tag
})
console.log('发出去的消息', itemFindMessage)
if (itemFindMessage) {
itemFindMessage[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_ACTIVE
itemFindMessage[StringKey.SEND_TIME] = sendTime
itemFindMessage[StringKey.SEND_MESSAGE_STATUS] = StringKey.SEND_MESSAGE_SUCCESS
itemFindMessage[StringKey.COMMAND_KEY] = command
itemFindMessage[StringKey.MESSAGE_ID] = itemMessage[StringKey.MESSAGE_ID]
this.activeChatData[StringKey.SEND_TIME] = sendTime
//让当前激活的active会话item插入消息列表数据
this.activeChatData.messages = findChat.messages
let toJsActiveChatData = this.activeChatData
console.log("发出前toJsActiveChatData" + command, toJsActiveChatData)
await this.setRefreshActiveChatData(toJsActiveChatData)
// 聊天已经置顶则不做处理,如果未置顶则将其移动至置顶的后面
//this.chats.splice(findChatIndex, 1);
//this.chats.unshift(findChat);
this.setObserverChatList(findChat, false, true)
} else {
//假设用户在发送消息的时候删除本地会话的情况的业务逻辑 保存发送消息 也是几乎不可能发生的情况 预防万一
//导致本地消息tag找不到
this.createNewChatByNoCurrentChat(protoData, command)
}
} else {
this.createNewChatByNoCurrentChat(protoData, command)
}
const { onTextMessage, onCmdMessage, onPictureMessage }: any = this.websocketCallBack
if (messageType === MessageTypeEnum.TEXT_MESSAGE) {
if (onTextMessage && typeof onTextMessage === 'function') {
onTextMessage(protoData)
}
}
if (messageType === MessageTypeEnum.PICTURE_MESSAGE) {
if (onPictureMessage && typeof onPictureMessage === 'function') {
onPictureMessage(protoData)
}
}
if (messageType === MessageTypeEnum.COMMAND_MESSAGE) {
if (onCmdMessage && typeof onCmdMessage === 'function') {
onCmdMessage(protoData)
}
}
}
}
////假设在发消息的时候跟收到消息之前这段时间突然删除会话 几乎不可能发生的情况
//发出消息如果还没收到消息之前突然删除 执行创建的逻辑
createNewChatByNoCurrentChat = async (protoData: any, command: number) => {
const {
resp,
appId,
userId,
communicationId,
sendTime,
toUserId,
tag,
communicationType,
messageType
} = protoData
const itemMessage = JSON.parse(JSON.stringify(protoData))
const tagInfo = await storage.getF(tag)
const { content } = tagInfo
const userInfo = await storage.getF('userInfo')
const { avatar, nickname } = userInfo
const otherInfo = {
userInfo: {
"userId": userInfo['userId'],
"avatarUrl": avatar,
"username": nickname
}
}
itemMessage['other'] = JSON.stringify(otherInfo)
itemMessage['content'] = content
itemMessage[StringKey.COMMAND_KEY] = command
itemMessage[StringKey.SEND_TIME] = sendTime
itemMessage[StringKey.SEND_MESSAGE_STATUS] = StringKey.SEND_MESSAGE_SUCCESS
// 检测聊天列表是否存在
const findChatIndex = this.chats.findIndex((item) => item.communicationId === communicationId);
//console.log('findChatIndex', findChatIndex)
const findChat = this.chats[findChatIndex];
//console.log('findChatIndex', findChat)
if (findChat) {
// 创建聊天后,选中聊天
// 设置未读数量
// 自己发的消息不计算
// 非选中聊天才展示未读数量
// 追加消息
let messages = []
messages.push(itemMessage)
//[]
if (findChat.messages) {
findChat.messages?.push(...messages)
} else {
findChat.messages = messages
}
//让当前激活的active会话item插入消息列表数据
this.activeChatData.messages = findChat.messages
let toJsActiveChatData = this.activeChatData
await this.setRefreshActiveChatData(toJsActiveChatData)
this.setObserverChatList(findChat, false)
} else {
//会话聊天列表不存在 创建会话
const findFriendChatIndex = this.friends.findIndex((item) => item.userId === toUserId);
const findFriendChat = this.friends[findFriendChatIndex];
if (findFriendChat) {
let messages = []
messages.push(itemMessage)
findFriendChat[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_ACTIVE
findFriendChat[StringKey.UN_READ_COUNT] = ChatItemEnum.CHAT_ITEM_UN_READ_COUNT_DEFAULT_ZERO
findFriendChat[StringKey.MESSAGE_ID] = itemMessage[StringKey.MESSAGE_ID]
findFriendChat[StringKey.MESSAGES_KEY] = messages
this.activeChatData.messages = messages
let toJsActiveChatData = this.activeChatData
//console.log(toJsActiveChatData)
this.setRefreshActiveChatData(toJsActiveChatData)
this.setObserverChatList(findFriendChat, true)
} else {
if (communicationType == CommunicationTypeEnum.GROUP_MESSAGE) {
let messages = []
messages.push(itemMessage)
itemMessage[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_ACTIVE
itemMessage[StringKey.UN_READ_COUNT] = ChatItemEnum.CHAT_ITEM_UN_READ_COUNT_DEFAULT_ZERO
itemMessage[StringKey.MESSAGE_ID] = itemMessage[StringKey.MESSAGE_ID]
itemMessage[StringKey.MESSAGES_KEY] = messages
this.activeChatData.messages = messages
let toJsActiveChatData = this.activeChatData
this.setRefreshActiveChatData(toJsActiveChatData)
this.setObserverChatList(findFriendChat, true)
} else if (communicationType == CommunicationTypeEnum.PERSON_MESSAGE) {
console.log('command联系人中找不到该好友')
} else {
console.log('command联系人中找不到该好友else情况')
}
}
}
}
public createChatsByHeart = (protoData: any, command: number) => {
const { lastMsgSequenceId, lastMsgReceiveTime, chatMsg } = protoData
if (lastMsgSequenceId && lastMsgReceiveTime) {
storage.setF(this.LAST_MESSAGE_KEY, {
lastMsgReceiveTime: lastMsgReceiveTime,
lastMsgSequenceId: lastMsgSequenceId,
});
}
if (!chatMsg) {
return;
}
for (let i = 0; i < chatMsg.length; i++) {
let itemMessage = chatMsg[i];
const {
resp,
appId,
userId,
communicationId,
messageId,
sendTime,
toUserId,
communicationType,
messageType,
tag,
deviceType,
content,
} = itemMessage
itemMessage[StringKey.COMMAND_KEY] = command
itemMessage[StringKey.SEND_TIME] = sendTime
if (messageType == 1101) {
this.getChatTopData()
return;
}
if (communicationType == CommunicationTypeEnum.PERSON_MESSAGE
|| communicationType == CommunicationTypeEnum.GROUP_MESSAGE) {
// 检测聊天列表是否存在
const findChatIndex = this.chats.findIndex((item) => {
return item.communicationId === communicationId
});
const findChat = this.chats[findChatIndex];
if (findChat) {
// 创建聊天后,选中聊天
// 设置未读数量
// 自己发的消息不计算
// 非选中聊天才展示未读数量
// 追加消息
let messages = []
messages.push(itemMessage)
console.log('心跳接收到的消息', itemMessage)
if (findChat.messages) {
let findChatItemMessage = findChat.messages.find((item: any) => item.tag = itemMessage['tag'])
//let findChatItemMessage = findChat.messages.find((item) => item.messageId = itemMessage['messageId'])
if (findChatItemMessage) {
console.log('心跳消息已经存在终止本轮消息', findChatItemMessage)
continue;
}
console.log('消息不存在开始插入消息')
findChat.messages = findChat.messages.concat(messages)
} else {
findChat.messages = messages
}
//心跳有重复 所以要放在后面一点
if (this.chats.length <= 0 || (userId !== this.defaultId && findChat['conversationId'] !== this.activeChatData['conversationId'])) {
findChat.active = ChatItemEnum.CHAT_ITEM_ACTIVE
findChat.unReadCount = ChatItemEnum.CHAT_ITEM_UN_READ_COUNT_DEFAULT_ZERO
} else {
findChat.active = ChatItemEnum.CHAT_ITEM_NO_ACTIVE;
findChat.unReadCount += 1;
}
// this.activeChatData.messages = findChat.messages
//let toJsActiveChatData = toJS(this.activeChatData)
//console.log(toJsActiveChatData)
//this.setRefreshActiveChatData(toJsActiveChatData)
// 聊天已经置顶则不做处理,如果未置顶则将其移动至置顶的后面
//this.chats.splice(findChatIndex, 1);
//this.chats.unshift(findChat);
this.setObserverChatList(findChat, false)
} else {
//会话聊天列表不存在 创建会话
const findFriendChatIndex = this.friends.findIndex((item) => item.userId === toUserId);
const findFriendChat = this.friends[findFriendChatIndex];
console.log('联系人找会话消息', findFriendChat)
if (findFriendChat) {
let messages = []
messages.push(itemMessage)
findFriendChat[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_ACTIVE
findFriendChat[StringKey.UN_READ_COUNT] = ChatItemEnum.CHAT_ITEM_UN_READ_COUNT_DEFAULT_ZERO
findFriendChat[StringKey.MESSAGES_KEY] = messages
this.activeChatData.messages = messages
let toJsActiveChatData = this.activeChatData
//console.log(toJsActiveChatData)
this.setRefreshActiveChatData(toJsActiveChatData)
this.setObserverChatList(findFriendChat, true)
} else {
console.log('联系人中找不到该好友')
}
}
}
const { onTextMessage, onCmdMessage, onPictureMessage }: any = this.websocketCallBack
if (messageType === MessageTypeEnum.TEXT_MESSAGE) {
if (onTextMessage && typeof onTextMessage === 'function') {
onTextMessage(protoData)
}
}
if (messageType === MessageTypeEnum.PICTURE_MESSAGE) {
if (onPictureMessage && typeof onPictureMessage === 'function') {
onPictureMessage(protoData)
}
}
if (messageType === MessageTypeEnum.COMMAND_MESSAGE) {
if (onCmdMessage && typeof onCmdMessage === 'function') {
onCmdMessage(protoData)
}
}
}
}
public createChats = async (protoData: any, command: number) => {
const {
appId,
communicationId,
fromUserId,
toUserId,
sendTime,
communicationType, // 消息类型:1=个人消息;2=群组消息;3=公众号消息
messageType,//1=文本消息;2=表情消息;3=文件;4=图片;5=语音消息;6=视频消息;7=位置消息;8=命令;9=自定义消息;10=红包消息
content,
setting,//json字符串
messageId,
updateTime,
tag,
} = protoData;
const itemMessage = JSON.parse(JSON.stringify(protoData))
itemMessage[StringKey.COMMAND_KEY] = command
itemMessage[StringKey.SEND_TIME] = sendTime
if (messageType == 1101) {
this.getChatTopData()
return;
}
let cacheTag = await storage.getF(tag)
if (cacheTag) {
return;
}
const { onTextMessage, onCmdMessage, onPictureMessage }: any = this.websocketCallBack
if (messageType === MessageTypeEnum.TEXT_MESSAGE) {
if (onTextMessage && typeof onTextMessage === 'function') {
onTextMessage(protoData)
}
}
if (messageType === MessageTypeEnum.PICTURE_MESSAGE) {
if (onPictureMessage && typeof onPictureMessage === 'function') {
onPictureMessage(protoData)
}
}
if (messageType === MessageTypeEnum.COMMAND_MESSAGE) {
if (onCmdMessage && typeof onCmdMessage === 'function') {
onCmdMessage(protoData)
}
}
// 消息类型:1=个人消息;2=群组消息;3=公众号消息
if (communicationType == CommunicationTypeEnum.PERSON_MESSAGE ||
communicationType == CommunicationTypeEnum.GROUP_MESSAGE
) {
// 检测聊天列表是否存在
const findChatIndex = this.chats.findIndex((item) => item.communicationId === communicationId);
//console.log('findChatIndex', findChatIndex)
const findChat = this.chats[findChatIndex];
//console.log('findChatIndex', findChat)
if (findChat) {
// 创建聊天后,选中聊天
// 设置未读数量
// 自己发的消息不计算
// 非选中聊天才展示未读数量
let isCreateTop = false;
//如果会话列表长度是1个 并且选中的userId跟
if (this.chats.length <= 0 || (fromUserId !== this.defaultId && findChat[StringKey.COMMUNICATIONID] !== this.activeChatData[StringKey.COMMUNICATIONID])) {
isCreateTop = true
findChat[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_ACTIVE
findChat[StringKey.UN_READ_COUNT] = ChatItemEnum.CHAT_ITEM_UN_READ_COUNT_DEFAULT_ZERO;
} else {
findChat[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_NO_ACTIVE;
findChat[StringKey.UN_READ_COUNT] += 1
}
// 追加消息
let messages = []
messages.push(itemMessage)
if (findChat.messages) {
findChat.messages = findChat.messages.concat(messages)
} else {
findChat.messages = messages
}
findChat[StringKey.IS_TOP] = false;
this.activeChatData = findChat;
let toJsActiveChatData = this.activeChatData
//console.log(toJsActiveChatData)
this.setRefreshActiveChatData(toJsActiveChatData)
// 聊天已经置顶则不做处理,如果未置顶则将其移动至置顶的后面
//this.chats.splice(findChatIndex, 1);
//this.chats.unshift(findChat);
this.setObserverChatList(findChat, false, true)
} else {
//会话聊天列表不存在 创建会话
const findFriendChatIndex = this.friends.findIndex((item) => item.userId === fromUserId);
const findFriendChat = this.friends[findFriendChatIndex];
//console.log('联系人找会话消息', findFriendChat)
if (findFriendChat) {
let messages = []
messages.push(itemMessage)
findFriendChat[StringKey.MESSAGES_KEY] = messages
findFriendChat[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_ACTIVE
findFriendChat[StringKey.UN_READ_COUNT] = ChatItemEnum.CHAT_ITEM_UN_READ_COUNT_DEFAULT_ZERO
findFriendChat[StringKey.IS_TOP] = false;
this.activeChatData = findFriendChat
let toJsActiveChatData = this.activeChatData
//console.log(toJsActiveChatData)
this.setRefreshActiveChatData(toJsActiveChatData)
this.setObserverChatList(findFriendChat, false, true)
} else {
console.log('联系人中找不到该好友')
}
}
}
}
//websocket请求成功
public connectSuccessCallBack = () => {
this.connect = 1
sendHeartTimer = setInterval(() => {
if (sendHeartTimer) {
if (this.sendHeart && typeof this.sendHeart === 'function') {
this.sendHeart(); //发送心跳包
//this.sendHeartEmpty()
} else {
console.log('this.sendHeart不是一个函数')
}
}
}, WEB_SOCKET_TIMEOUT);
}
//发websocket心跳包
public sendHeartEmpty = async () => {
//console.log("开始发送心跳包");
const protoName = "EmptyResp";
const protoData = await storage.getF(this.LAST_MESSAGE_KEY)
let params: any = {
}
if (!protoData) {
params = {
lastMsgSequenceId: '',
lastMsgReceiveTime: '',
}
} else {
const { lastMsgSequenceId, lastMsgReceiveTime } = protoData
params = {
lastMsgSequenceId: lastMsgSequenceId ? lastMsgSequenceId : '',
lastMsgReceiveTime: lastMsgReceiveTime ? lastMsgReceiveTime : '',
};
}
//区分全局变量 改成局部变量
let command: number = CommandEnum.COMMAND_PING; //发出指令码 98
const proto: any = proToObject;
const { EmptyResp }: any = proto;
const ret: ArrayBuffer = this.templateFun(
this.appId,
this.userId,
this.deviceId,
params,
EmptyResp,
protoName,
command
);
this.getWebSocketInstance().createSocket(this.webWocketUrl, ret)
}
//发websocket心跳包
public sendHeart = async () => {
//console.log("开始发送心跳包");
const protoName = "HeartBeatMsg";
const protoData = await storage.getF(this.LAST_MESSAGE_KEY)
let params: any = {}
if (!protoData) {
params = {
lastMsgSequenceId: '',
lastMsgReceiveTime: '',
}
} else {
const { lastMsgSequenceId, lastMsgReceiveTime } = protoData
params = {
lastMsgSequenceId: lastMsgSequenceId ? lastMsgSequenceId : '',
lastMsgReceiveTime: lastMsgReceiveTime ? lastMsgReceiveTime : '',
};
}
//区分全局变量 改成局部变量
const command = CommandEnum.COMMAND_PULL_MSG_REQ;
const proto: any = proToObject;
const { HeartBeatMsg }: any = proto;
const ret: ArrayBuffer = this.templateFun(
this.appId,
this.userId,
this.deviceId,
params,
HeartBeatMsg,
protoName,
command
);
this.getWebSocketInstance().createSocket(this.webWocketUrl, ret)
}
public setChatTopData = async () => {
/**
* //会话置顶
key : "CONVERSATION_PIN_TAG"
value :
[
{
"communicationId": "179qa90yburad3k7gjiuk",
"isPin": true,
"pinTime": 1608190636682
},
{
"communicationId": "aaaaa90yburad3k7wwwww",
"isPin": true,
"pinTime": 1608190612345
}
]
*/
const jsonDataArray = this.topList
const res = await request({
method: 'POST',
url: api.POST.zxSetChatTopData,
data: {
data: JSON.stringify(jsonDataArray),
dataType: this.CHAT_TOP_DATA
}
})
const { code, hasError, data } = res;
if (code === '0' && !hasError) {
storage.setF(this.CHAT_TOP_DATA, jsonDataArray)
}
}
//获取顶部数据
public getChatTopData = async () => {
const res: any = await request({
method: 'GET',
url: api.GET.zxGetChatTopData,
data: {
dataType: this.CHAT_TOP_DATA
}
})
const { code, hasError, data }: any = res;
if (code == '0' && !hasError) {
const { dataValue } = data;
if (dataValue && typeof dataValue === 'string') {
let topArray = JSON.parse(dataValue)
if (topArray) {
let cacheChats: any = await storage.getF(this.CACHE_CHATS_KEY)
if (cacheChats && Array.isArray(cacheChats) && cacheChats.length > 0) {
topArray.forEach((element: any) => {
cacheChats.forEach((item: any, index: number) => {
if (item['conversationId'] === element['communicationId']) {
if (item[StringKey.IS_TOP] != element[StringKey.IS_TOP]) {
item[StringKey.IS_TOP] = true
item['communicationId'] = element['communicationId']
this.setObserverChatList(item, item[StringKey.IS_TOP])
}
}
})
});
}
this.topList = topArray
}
}
}
}
//添加用户到指定的联系组
public addUserToContactGroup = async (groupId: string, userId: string) => {
//通过groupId找到对应的组
let jsGroups = this.groups
let groupList = this.userInfoList
if (jsGroups) {
for (let i in jsGroups) {
let value = jsGroups[i]
if (value['groupId'] == groupId) {
let { userIds } = value;
if (userIds) {
let itemUserId = userIds.find((itemUserId: string, index: number) => {
return userId === itemUserId
})
if (!itemUserId) {
userIds.push(userId);
value['userIds'] = userIds
let itemUser = await this.getUserInfoById(userId)
if (itemUser && itemUser['userId']) {
itemUser[StringKey.COMMUNICATIONID] = itemUser[StringKey.CONVERSATIONID]
}
//添加到groupArray中
for (let m in groupList) {
let groupItem = groupList[m]
if (groupItem['groupId'] === groupId) {
let itemInfo = groupItem['groups'].find((itemInfo: any, index: number) => {
return itemInfo['userId'] === userId
})
if (!itemInfo) {
groupItem['groups'].push(itemUser)
}
}
}
}
}
}
}
this.userInfoList = groupList
this.groups = jsGroups
this.setDemoKvDataSet(this.groups)
}
}
//删除用户到指定的联系组
public async deleteUserToContactGroup(groupId: string, userId: string) {
//通过groupId找到对应的组
if (this.groups) {
this.groups.forEach((value: any, index: number) => {
if (value['groupId'] == groupId) {
let { userIds } = value;
if (userIds) {
userIds = userIds.filter((itemUserId: string, index: number) => {
return userId != itemUserId;
})
value['userIds'] = userIds;
}
}
})
this.setDemoKvDataSet(
this.groups
)
}
}
//通过分组名字来创建分组
public createGroupByName = async (groupName: string) => {
if (this.groups) {
let isHave: boolean = false;
//如果数组里面有该数组就创建数组
this.groups.forEach((item: any, index: number) => {
if (item['groupName'] == groupName) {
isHave = true
}
})
if (!isHave) {
const item: any = {
groupId: randomKey(16),
groupName: groupName,
userIds: []
}
this.groups.push(item)
//console.log('groups', this.groups)
this.setDemoKvDataSet(this.groups)
} else {
console.log('已经创建过该组了')
}
}
}
//创建分组
public async createContactGroup(item: any) {
if (this.groups) {
let isHave: boolean = false;
this.groups.forEach((itemValue: any, index: number) => {
if (item['groupId'] == itemValue['groupId']) {
isHave = true;
}
})
if (!isHave) {
this.groups.push(item)
} else {
console.log('该用户组已经创建了')
}
await this.setDemoKvDataSet(this.groups)
this.getDemoKvDataGet()
}
}
//通过id删除联系组
public async deleteContactGroupById(groupId: string) {
//如果当前数组中有该元素那就删除
if (this.groups) {
this.groups = this.groups.filter((value: any, index: number) => {
return value['groupId'] != groupId
})
this.setDemoKvDataSet(this.groups)
}
}
//设置好友分组
public async setDemoKvDataSet(groupArray: any) {
const dataParams = {
key: this.contact_tag,
protocolVersion: 1,
value: JSON.stringify(groupArray)
};
const res = await request({
method: 'POST',
url: api.POST.zxPostDemoKvDataSet,
data: dataParams
})
const { code, hasError, data } = res;
if (code == '0' && !hasError) {
this.getDemoKvDataGet()
}
}
//获取或者更新好友分组
public getDemoKvDataGet = async () => {
const res = await request({
method: 'GET',
url: api.GET.zxGetDemoKvDataGet,
data: {
key: this.contact_tag
}
})
const { code, hasError, data } = res;
if (code == '0' && !hasError) {
const { key, value, version, userId } = data;
if (value && typeof value == 'string') {
let groups = JSON.parse(value)
if (groups && Array.isArray(groups)) {
this.groups = groups
let groupList = []
for (let m in groups) {
let item = groups[m]
let userIds = item['userIds']
let groupId = item['groupId']
let groupName = item['groupName']
let promiseList = []
if (userIds && Array.isArray(userIds) && userIds.length > 0) {
for (let itemId of userIds) {
if (itemId) {
let itemUser = await this.getUserInfoById(itemId)
if (itemUser && itemUser['userId']) {
itemUser[StringKey.COMMUNICATIONID] = itemUser[StringKey.CONVERSATIONID]
}
promiseList.push(itemUser)
}
}
}
const groupItem = {
groupId: groupId,
groupName: groupName,
groups: promiseList
}
groupList.push(groupItem)
}
this.userInfoList = groupList
}
}
}
}
public getUserInfoById = async (user_id: string) => {
const res = await request({
method: 'GET',
url: api.GET.zxGetUserInfoById,
data: {
userId: user_id
}
})
const { code, hasError, data } = res;
return new Promise((resolve, reject) => {
if (code == '0' && !hasError) {
resolve(data)
} else {
return reject({})
}
})
}
//sdk 获取新的好友
public async getNewFriends() {
const res = await request({
method: 'GET',
url: api.GET.zxSdkNewFriendList,
data: {}
})
console.log('newFriendList', res)
const { code, data, hasError } = res;
return new Promise((resolve, reject) => {
if (code == '0' && !hasError) {
if (data && Array.isArray(data)) {
data.forEach((item, index) => {
item[StringKey.COMMUNICATIONID] = item[StringKey.CONVERSATIONID]
})
this.newFriends = data;
resolve(data)
} else {
reject({
code,
message: '获取新朋友失败!'
})
}
} else {
reject({
code,
message: '获取新朋友失败!'
})
}
})
}
//sdk 获取联系人列表
public async getFriendList() {
const res = await request({
method: 'GET',
url: api.GET.zxSdkGetFriendList,
data: {}
})
//console.log('getFriendList', res)
let { code, data, hasError } = res;
const userInfo = await storage.getF('userInfo')
return new Promise((resolve, reject) => {
if (code == '0' && !hasError) {
if (Array.isArray(data)) {
if (userInfo) {
const { userId } = userInfo
data = data.filter((item, index, array) => {
if (!item[StringKey.MESSAGES_KEY]) {
item[StringKey.MESSAGES_KEY] = []
}
if (!item[StringKey.ACTIVE]) {
item[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_NO_ACTIVE
}
if (!item[StringKey.UN_READ_COUNT]) {
item[StringKey.UN_READ_COUNT] = ChatItemEnum.CHAT_ITEM_UN_READ_COUNT_DEFAULT_ZERO
}
if (!item[StringKey.IS_TOP]) {
item[StringKey.IS_TOP] = false;
}
if (!item[StringKey.COMMUNICATIONID]) {
item[StringKey.COMMUNICATIONID] = item[StringKey.CONVERSATIONID]
}
if (!item[StringKey.COMMUNICATION_TYPE]) {
item[StringKey.COMMUNICATION_TYPE] = CommunicationTypeEnum.PERSON_MESSAGE
}
return userId != item.userId
})
this.friends = data;
resolve(data)
}
}
} else {
reject({
code,
message: '获取联系人列表失败!'
})
}
})
}
//sdk 添加好友
public async addFriend({ remark, userId }: any) {
//12618400093 179gxkj9wg3g3hhvij9n6
//12618400094 179gxkjhisvwn56zrzdeb
//12618400095 179gxkjoo9vh5lcaf8y38
//zxSdkPostAddFriend
const res = await request({
method: 'POST',
url: api.POST.zxSdkPostAddFriend,
data: {
remark: remark,
userId: userId,
}
})
//console.log('添加好友成功', res)
const { code, data, hasError } = res;
if (code == '0' && !hasError) {
}
}
//sdk 接受好友邀请
public async acceptFriend(userId: string) {
///sdk/v1/user/friend/add/accept
const res = await request({
method: 'POST',
url: api.POST.zxSdkAcceptFriend,
data: {
userId: userId,
}
})
const { code, data, hasError } = res;
if (code == '0' && !hasError) {
}
}
public getChatGroupLists = async (isCreateChat = false) => {
const res = await request({
method: 'GET',
url: api.GET.zxgroupLists,
data: {}
})
const { code, data, hasError } = res;
if (code == '0' && !hasError) {
if (data && Array.isArray(data)) {
this.creatChatGroupsList = data;
this.allGroupMembers = []
for (let i in data) {
const item = data[i]
await this.getAllChatGroupMember(item)
}
if (isCreateChat && this.allGroupMembers.length > 0) {
let length = this.allGroupMembers.length
this.setRefreshActiveChatData(this.allGroupMembers[length - 1])
this.setObserverChatList(this.allGroupMembers[length - 1], false, true)
}
}
}
}
public getAllChatGroupMember = async (item: any) => {
const {
communicationId,
managerList,//群管理员ID列表
} = item;
const res: any = await request({
method: 'GET',
url: api.GET.zxGetAllGroupMember,
data: {
groupId: communicationId
},
})
const { code, hasError, data } = res
if (res.code === '0' && !hasError) {
if (!item[StringKey.MESSAGES_KEY]) {
item[StringKey.MESSAGES_KEY] = []
}
if (!item[StringKey.ACTIVE]) {
item[StringKey.ACTIVE] = ChatItemEnum.CHAT_ITEM_NO_ACTIVE
}
if (!item[StringKey.UN_READ_COUNT]) {
item[StringKey.UN_READ_COUNT] = ChatItemEnum.CHAT_ITEM_UN_READ_COUNT_DEFAULT_ZERO
}
if (!item[StringKey.IS_TOP]) {
item[StringKey.IS_TOP] = false;
}
if (!item[StringKey.COMMUNICATIONID]) {
item[StringKey.COMMUNICATIONID] = item[StringKey.CONVERSATIONID]
}
if (!item[StringKey.COMMUNICATION_TYPE]) {
item[StringKey.COMMUNICATION_TYPE] = CommunicationTypeEnum.GROUP_MESSAGE
}
let chatGroupItem = {
...item,
members: data
}
this.allGroupMembers.push(chatGroupItem);
}
}
public createChatGroup = async (chatGroup: CreateChatGroup, isCreateChat: boolean) => {
const res = await request({
method: 'POST',
url: api.POST.createChatGroup,
data: chatGroup
})
const { code, hasError, data } = res
if (code === '0' && !hasError) {
console.log('创建群组成功', res, chatGroup)
this.getChatGroupLists(isCreateChat)
}
}
//demo 分组
public async postTagList() {
const res = await request({
method: 'POST',
url: api.POST.zxPostDemoTagList,
data: {}
})
}
//demo 创建分组
public async postTagCreate() {
let userIdArray = [
'179gxkics21lq1qedh4ej',
'179gxkigcsjdz9t1p3wr0',
'179gxkijxj168hvp0qp3h',
'179gxkio9p7ejoq1yx3f2',
'179gxkisdfh6u9si4087j',
'179gxkiw2dx73sr3u6nbk',
'179gxkj0tbx7g1pb79rbl',
'179gxkj9wg3g3hhvij9n6',
'179gxkjhisvwn56zrzdeb',
'179gxkjoo9vh5lcaf8y38',
'179gxkjtf7vhhuahsc239'
];
let userIdsString = '';
for (let i = 0; i < userIdArray.length; i++) {
if (i < userIdArray.length - 1) {
userIdsString = userIdsString + userIdArray[i] + ','
} else {
userIdsString = userIdsString + userIdArray[i];
}
}
//let arrayString=JSON.stringify(userIdArray)
const res = await request({
method: 'POST',
url: api.POST.zxPostDemoTagCreate,
data: {
name: 'test1',
userIds: userIdsString,
}
})
const { code, hasError, data } = res
if (code == '0' && !hasError) {
const { members } = data
}
}
}
export default Store
我这里先给出我自己调用sdk的示例代码如下:
import React from 'react'
import './index.css'
import QRCode from 'qrcode.react';
import HomeStore from '../ZxHome/store'
import DemoLogin from '../ZxDemoLogin/components/Layout'
import { storage, pinyin, navigate, getSensitiveMsg, getRandomKey, StringKey } from '../../utils';
import MessageTypeEnum from '../../enum/MessageTypeEnum';
import CommunicationTypeEnum from '../../enum/CommunicationTypeEnum';
import StorageKeyEnum from '../../enum/StorageKeyEnum';
const homeStore = new HomeStore()
const loginStore = homeStore.getLoginInstance()
/**
*
* 第一步 比如demo完成初始化 传入 appid之类的
* init
*/
class App extends React.PureComponent {
constructor(props) {
super(props)
this.state = {
code: '',
friendList: []
}
}
//刷新或者是获取扫码登陆信息
refreshCode = async () => {
const code = await loginStore.getQRCodeUrl()
console.log('刷新获取验证码', code)
this.setState({
code: code
})
}
// componentDidMount() {
// this.initConfig()
// //this.refreshCode()
// }
/**
* 初始化配置 需要demo传入appId
*/
initConfig = async () => {
const callBack = {
onOpened: (protoData, command) => {
console.log('收到sdk绑定成功', protoData, command)
},
onTextMessage: (protoData) => {
console.log('收到sdk文本消息', protoData)
},
onCmdMessage: (protoData) => {
console.log('收到命令码!')
},
onPictureMessage: (protoData) => {
console.log('收到sdk图片消息', protoData)
},
onError: (e, connectStatus) => {
console.log('websocket的连接状态', e, connectStatus)
}
}
let appId = '9eb745a14c44b7f5badbbb92092ee8e9#Jiao-IM-Demo'
console.log('开始初始化配置')
//demo层调用的init初始化方法
homeStore.initWebSocket(callBack, appId)
}
//获取联系人列表
getFriendList = async () => {
//调用联系人列表方法
const friendList = await homeStore.getFriendList();
if (Array.isArray(friendList) && friendList.length > 0) {
this.setState({
friendList: friendList
})
}
}
//demo层调用sdk示例
login = async () => {
const res = await loginStore.mgacctLoginByDemo({
zxSdkLoginToken: 'zxSdkLoginToken',
userId: 'userId',
homeStore: homeStore
})
console.log('res', res)
}
//获取会话列表
getSdkChatList = async () => {
const chatList = await homeStore.getLocalChatList()
return chatList;
}
friendItemOnClick = (item, index) => {
this.initConfig()
}
//发送消息
sendMessage = async () => {
homeStore.sendMessage({
content: 'send',
messageType: MessageTypeEnum.TEXT_MESSAGE,
communicationType: CommunicationTypeEnum.PERSON_MESSAGE,
appId: '9eb745a14c44b7f5badbbb92092ee8e9#Jiao-IM-Demo',
communicationId: 'communicationId',
fromUserId: "",
toUserId: 'userId'
})
}
render() {
return (
获取联系人列表
{
this.state.friendList.map((item, index) => {
return (
{
this.friendItemOnClick(item, index)
}}
>
{JSON.stringify(item)}
)
})
}
获取会话列表
发送文本消息
)
}
}
export default App
js-sdk是我自己基于webpack打包 然后以对象导出,调用思路其实就在initWebSocket的时候传入对象里面包含像appId跟回调函数这类东西,作为该sdk内部的全局变量,只要每次接收消息或者处理消息就会触发initWebSocket传入的回调函数,这样用户就可以实时的监听到消息!