2021-02-26 Web-im js-sdk开发打包流程
年前初步的完成了im基本版,像单聊,群聊,消息的收发,图片视频,消息右键撤回等功能,年后就开始主要集中精力进行sdk的开发了。
说下我个人的开发思路:
第一步 新建一个工程不使用脚手架编译js文件,执行npm init -y 生成package.json文件
第二步 由于我原来的im工程代码是用的ts+mobx+react开发的im,所以我这边需要新建一个tsconfig.json来进行响应的配置。具体示例参考官方文档(这里给出链接):
https://www.tslang.cn/docs/handbook/compiler-options.html
如果对官方文档给出的选项可能不理解,这里给出更详细的说明链接:
https://my.oschina.net/u/4564900/blog/4893389
接下来给出我这边的webpack.config.js文件的配置示例代码如下:
const path = require("path");
module.exports = {
entry: ["./src/index.ts"],
output: {
path: path.join(__dirname, "dist"), //打包输出文件的路径跟文件夹目录
filename: "bundle.js", //打包输出的文件名字
library: "webpackNumbers", //表示支持的类型 最终会在打出的js文件下
libraryTarget: "this",
umdNamedDefine: true,
globalObject: "this",
},
mode: "production",
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/,
},
],
},
resolve: {
// Add ".ts" and ".tsx" as resolvable extensions.
extensions: [".ts", ".tsx", ".js"],
},
};
webpack配置library等参考文章https://zhuanlan.zhihu.com/p/108216236
接下来给出tsconfig.json文件配置的示例代码如下:
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"outDir": "./outDir/",
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"experimentalDecorators": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noImplicitAny":false,
"noImplicitThis":false,
"noEmit": false,
"jsx": "react",
"baseUrl": "."
},
"exclude": [ // 排除那些文件不打包
"node_modules",
"*.test.ts"
]
}
接下来简单给出我的项目入口文件index.ts示例代码如下:
import HomeStore from './routes/ZxHome/store'
var store=new HomeStore()
然后再进入store文件看下示例代码:
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';
const currentTime = moment().valueOf();
let sendHeartTimer: any; //心跳包的定时器
const WEB_SOCKET_TIMEOUT = 50000; //50秒
export default class Store {
public arrayBufferUtil: ArrayBufferUtil = new ArrayBufferUtil();
public parseMsgUtil: ParseMsgUtil = new ParseMsgUtil();
// 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
webWocketUrl: string = '';//服务器地址
appId: string = '9eb745a14c44b7f5badbbb92092ee8e9#Jiao-IM-Demo';
//用户id
userId: string = '';
//设备id
deviceId: string = 'deviceId1'
private isFirstActiveChatData: boolean = false;
public sdkacctLogin: any;
public aes = new AesUtil()
constructor() {
this.init()
}
public async init() {
await this.getNewFriends()
await this.getFriendList()
await this.getLocalChatList()
await this.getChatGroupLists()
//await this.setDemoKvDataSet([])
this.getDemoKvDataGet()
this.initWebSocket()
await this.getChatTopData()
const userInfo = await storage.getF(StringKey.USER_INFO)
if (!userInfo) {
navigate('/zxlogin')
} else {
this.userInfo = userInfo
}
}
//获取本地的会话列表
public getLocalChatList = async () => {
let cacheChats = await storage.getF(this.CACHE_CHATS_KEY)
if (!cacheChats) {
console.log('当前没有离线缓存列表')
return;
}
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;
}
}
public getPullOfflineMessageList = async ({
communicationId,
count = 20,
deviceType = 2, //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
console.log('开始取消置顶', chatItem)
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
}
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 () => {
const sdkLogin = await storage.getF(this.SDK_ACCT_LOGIN_KEY)
if (!!sdkLogin) {
this.sdkacctLogin = sdkLogin;
if (!!this.sdkacctLogin) {
const { user_id, access_token } = this.sdkacctLogin
this.userId = user_id;
this.token = access_token;
this.sendReqBindUserChannel()
}
}
}
public async sendReqBindUserChannel() {
const params = {
appId: this.appId, //应用ID
userId: this.userId, //用户ID
token: this.token, //验证码
manufacturer: 'web', // 手机厂商
deviceId: this.deviceId, // 手机厂商
osVersion: 'web', // 系统版本
}
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 = 1,
communicationType = CommunicationTypeEnum.PERSON_MESSAGE,
communicationId = '',
toUserId = ''
}: any) => {
if (!this.activeChatData || !this.activeChatData[StringKey.COMMUNICATIONID]) {
return;
}
if (process.env.NODE_ENV === 'development') {
console.log('激活的会话数据', this.activeChatData)
}
const {
conversationId,
userId,
}: any = this.activeChatData
const userInfo = await storage.getF('userInfo')
const { avatar, nickname } = userInfo
const otherInfo = {
userInfo: {
"userId": userInfo['userId'],
"avatarUrl": avatar,
"username": nickname
}
}
if (!communicationId && this.activeChatData[StringKey.COMMUNICATIONID]) {
communicationId = this.activeChatData[StringKey.COMMUNICATIONID]
}
if (!toUserId) {
if (userId) {
toUserId = userId
} else {
toUserId = ''
}
}
if (this.activeChatData[StringKey.COMMUNICATION_Type]
&& communicationType !== this.activeChatData[StringKey.COMMUNICATION_Type]) {
communicationType = this.activeChatData[StringKey.COMMUNICATION_Type]
}
if (!communicationId || !this.userId) {
console.log('发送消息有参数为空了')
return;
}
let tag = getRandomKey(16)
const params = {
appId: this.appId, //string 对应平台产品APP_ID
communicationId: communicationId, //string 所在会话ID
fromUserId: this.userId, // 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
//console.log('proto', proto)
const { CommunicationMessageProto }: any = proto
let protoName = 'CommunicationMessageProto';
let command = CommandEnum.COMMAND_SEND_MSG_REQ
storage.setF(tag, params)
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 = () => {
this.connect = 0;
}
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)
if (command == CommandEnum.COMMAND_BIND_USER_RESP) {
//绑定成功
//console.log('websocket绑定成功', JSON.stringify(protoData))
const { lastMsgReceiveTime, lastMsgSequenceId } = protoData
storage.setF(this.LAST_MESSAGE_KEY, {
lastMsgReceiveTime: lastMsgReceiveTime,
lastMsgSequenceId: lastMsgSequenceId,
});
}
if (command == CommandEnum.COMMAND_SEND_MSG_REQ) { //10
console.log('command10', JSON.stringify(protoData))
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)
}
}
}
////假设在发消息的时候跟收到消息之前这段时间突然删除会话 几乎不可能发生的情况
//发出消息如果还没收到消息之前突然删除 执行创建的逻辑
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
//console.log("toJsActiveChatData" + command, toJsActiveChatData)
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
//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 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('联系人中找不到该好友')
}
}
}
}
}
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;
}
// 消息类型: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 = () => {
console.log('连接成功,开始发心跳', this)
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;
if (code == '0' && !hasError) {
return data;
} else {
return {}
}
}
//sdk 获取新的好友
public async getNewFriends() {
const res = await request({
method: 'GET',
url: api.GET.zxSdkNewFriendList,
data: {}
})
//console.log('newFriendList', res)
const { code, data, hasError } = res;
if (code == '0' && !hasError) {
if (data && Array.isArray(data)) {
data.forEach((item, index) => {
item[StringKey.COMMUNICATIONID] = item[StringKey.CONVERSATIONID]
})
this.newFriends = data;
}
}
}
//sdk 获取联系人列表
public async getFriendList() {
const res = await request({
method: 'GET',
url: api.GET.zxSdkGetFriendList,
data: {}
})
//console.log('getFriendList', res)
let { code, data, hasError } = res;
if (code == '0' && !hasError) {
if (Array.isArray(data)) {
const userInfo = await storage.getF('userInfo')
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;
}
}
}
}
//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,
}
})
console.log('params', userId)
console.log('接受好友成功', res)
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
}
}
}
整个项目的大部分逻辑都在这个store文件里面
最后给出我这边sdk的package.json文件的配置代码如下:
{
"name": "ImSdk",
"version": "1.0.0",
"description": "ImSdk",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"proto": "pbjs -t static-module -w commonjs -o src/proto/proto.js src/proto/*.proto"
},
"keywords": [],
"author": "gdchent",
"license": "ISC",
"dependencies": {
"@babel/core": "^7.13.1",
"ali-oss": "^6.13.2",
"axios": "^0.21.1",
"babel-plugin-named-asset-import": "^0.3.7",
"crypto-js": "4.0.0",
"html-webpack-plugin": "^5.2.0",
"js-base64": "^3.6.0",
"jsencrypt": "3.0.0-rc.1",
"localforage": "^1.9.0",
"moment": "^2.29.1",
"postcss-preset-env": "6.7.0",
"protobufjs": "^6.10.2",
"typescript": "3.7.2",
"webpack": "4.42.0",
"webpack-cli": "^4.5.0",
"webpack-dev-server": "3.10.3",
"webpack-manifest-plugin": "2.2.0",
"workbox-webpack-plugin": "4.3.1"
},
"devDependencies": {
"@babel/plugin-proposal-decorators": "^7.13.5",
"@babel/plugin-proposal-optional-chaining": "^7.13.0",
"@babel/preset-env": "^7.13.5",
"awesome-typescript-loader": "^5.2.1",
"babel-loader": "^8.2.2",
"babel-plugin-import": "^1.13.3",
"source-map-loader": "^2.0.1",
"ts-loader": "^8.0.17"
}
}
通过上述配置可以看到,执行npm run build 就可以愉快的正常的打包了,然后就是坐等打包成功了...
示例效果如下:
打包输出效果图.png
由于我在webpack.config.js文件里面配置了LibraryTarget为umd模式,也就是通用,所以我这里可以直接用index.html引入,接下来我们看下刚刚打包成功的dist文件夹截图如下:
bundleJs.png
接下来我们在dist文件夹下新建index.html文件引入js,示例代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>测试打包出来的js文件</title>
<script type="text/javascript" src="./bundle.js"></script>
</head>
<body>
</body>
</html>
接下来运行当前html文件,按下f12,由于我这里调用了我公司的后台接口,这个时候肯定会出现跨域之类的,没关系,说明目的达到了就成,截图如下:
js-sdk打包运行效果.png