2021-03-12 js-sdk封装思路跟示例

最近忙于在公司做关于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传入的回调函数,这样用户就可以实时的监听到消息!

你可能感兴趣的:(2021-03-12 js-sdk封装思路跟示例)