feature/im-0602-ch
ch 3 years ago
parent 0bdab1c4bf
commit 51ee94d573

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-05-05 14:40:00
* @LastEditors: ch
* @LastEditTime: 2022-06-02 15:09:46
* @LastEditTime: 2022-06-09 11:25:44
* @Description: 根据git分支生成对应环境的环境变量
* 开发时如果环境变量换了可以不用重启服务直接运行node env.config.js即可
*/
@ -13,8 +13,8 @@ const envConfig = {
dev : {
baseUrl: 'https://k8s-horse-gateway.mashibing.cn',
staticUrl : 'https://k8s-shop-app.mashibing.cn',
imUrl : 'ws://192.168.10.94:8090'
// imUrl : 'wss://k8s-horse-gateway.mashibing.cn'
// imUrl : 'ws://192.168.10.94:8090'
imUrl : 'wss://k8s-horse-gateway.mashibing.cn'
},
test : {
baseUrl: 'https://k8s-horse-gateway.mashibing.cn',

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-05-27 17:44:36
* @LastEditors: ch
* @LastEditTime: 2022-06-02 14:45:51
* @LastEditTime: 2022-06-09 11:34:36
* @Description: file content
*/
import {ToAsyncAwait, MsbRequestTk} from '@/common/utils';
@ -11,4 +11,6 @@ const BASE_URL = '/mall/im';
/**
* 获取soket登录秘钥
*/
export const ApiGetSoketTicket = () => ToAsyncAwait(MsbRequestTk.get(`${BASE_URL}/ticket`));
export const ApiGetSoketTicket = () => ToAsyncAwait(MsbRequestTk.get(`${BASE_URL}/ticket`, {
ticketType: 'CONNECT_TICKET'
}));

@ -2,18 +2,15 @@
* @Author: ch
* @Date: 2022-05-18 14:54:47
* @LastEditors: ch
* @LastEditTime: 2022-06-07 19:28:14
* @LastEditTime: 2022-06-09 11:38:48
* @Description: file content
*/
import { CreateUUID, FormatDate, ToAsyncAwait } from "@/common/utils";
import './potoReq';
import './protoRsp'
const connect = Symbol('connect'),
send = Symbol('send'),
onResponse = Symbol('onResponse'),
onMessage = Symbol('onMessage'),
updateData = Symbol('updateData')
;
const connect = Symbol('connect');
const send = Symbol('send');
const onMessage = Symbol('onMessage');
const fromatPotoReq = (traceId, traceType, content) => {
let messageModel = new proto.ReqModel();
messageModel.setTraceid(traceId);
@ -26,86 +23,101 @@ fromatPotoRsp = (data)=>{
let ctx = res.getContent();
ctx = ctx ? JSON.parse(ctx) : {};
if (ctx.payload) {
ctx.payload = JSON.parse(ctx.payload)
ctx.payload = JSON.parse(ctx.payload);
}
return {
content: ctx,
traceId: res.getTraceid(),
traceType: res.getTracetype(),
code: res.getCode(),
message : res.getMessage()
}
}
export default class MsbIm {
option = {
message: res.getMessage(),
};
};
class MsbIm {
defaultOption = {
ioKey: 'traceId',
reconnect: true,
logout : false
}
};
socket = null;
isOpen = false;
queue = {};
interceptors = {
dataChangeBefore: null,
dataChangeAfter: null,
onLogout : null,
onMessage: null
onClose: null,
onMessage: null,
};
sessionData = [];
curSessionId = null;
constructor(option) {
this.option = {
...this.option,
...option
}
...this.defaultOption,
...option,
};
}
/**
* 创建连接返回一个Promise 创建成功并成功打开连接算连接成功
* @param {*} option
*/
[connect](option) {
return new Promise((resolve, reject) => {
this.socket = uni.connectSocket({
...option,
fail(e){
reject(e);
}
});
this.socket.onOpen(() => {
this.socket.onMessage(async (res) => {
console.log(res.data,'apppppppp');
const open = () => {
console.log('[im] open');
this.isOpen = true;
resolve(this.socket);
};
const message = async (res) => {
const result = fromatPotoRsp(res.data);
// if (result.content?.payload) {
// result.content.payload = JSON.parse(result.content.payload);
// }
// 401主动退出
if (result.code === 401) {
this.logout();
return false;
}
this.interceptors.onMessage && this.interceptors.onMessage(result);
// 处理服务端主动推送的消息
this[onMessage](result);
// 如果再消息堆里有此消息回调,则执行回调,并删除
const cbk = this.queue[result[this.option.ioKey]];
if (cbk) {
cbk(result.code !== 200 ? { error: result } : { result: result });
delete this.queue[result[this.option.ioKey]];
}
})
resolve(this.socket);
};
const close = () => {
console.log('[im] close');
this.interceptors.onClose && this.interceptors.onClose();
};
if (uni) {
this.socket = uni.connectSocket({
...this.option,
fail(e) {
reject(e);
},
});
this.socket.onOpen(() => {
open();
this.socket.onMessage((res) => {
message(res);
});
});
this.socket.onClose(() => {
if (this.option.reconnect && !this.option.logout) {
this[connect]();
}
this.option.logout = false;
close();
});
} else if (WebSocket) {
try {
this.socket = new WebSocket(this.option.url);
this.socket.binaryType = 'arraybuffer';
this.socket.onopen = () => {
open();
};
this.socket.onmessage = (res) => {
message(res);
};
this.socket.onclose = () => {
close();
};
} catch (e) {
reject(e);
}
}
});
}
/**
@ -114,6 +126,9 @@ export default class MsbIm {
*/
[send](data) {
return new Promise((resolve, reject) => {
if (!this.isOpen) {
return reject('连接未打开');
}
this.queue[data[this.option.ioKey]] = ({ result, error }) => {
if (result) {
resolve(result);
@ -122,13 +137,18 @@ export default class MsbIm {
}
};
const par = fromatPotoReq(data.traceId, data.traceType, data.content);
if (uni) {
this.socket.send({
data : fromatPotoReq(data.traceId, data.traceType, data.content),
data: par,
fail(e) {
reject({ error: e });
},
});
} else if (WebSocket) {
this.socket.send(par);
}
});
})
}
/**
* 服务端推送消息只处理服务端主动推送的消息
@ -142,7 +162,7 @@ export default class MsbIm {
let ctx = data.content;
let historyData = [...this.sessionData],
newData = [];
const hisIndex = historyData.findIndex(i => i.id === ctx.sessionId);
const hisIndex = historyData.findIndex((i) => i.id === ctx.sessionId);
if (hisIndex >= 0) {
// 存在会话往现有会话增加一条消息,并修改最后一条消息为当前消息
const curHisData = historyData[hisIndex];
@ -155,51 +175,57 @@ export default class MsbIm {
newData = historyData;
} else {
// 会话列表不存在,则创建一个会话
newData = [...historyData, {
newData = [
...historyData,
{
fromAvatar: ctx.fromAvatar,
fromId: ctx.fromId,
fromNickname: ctx.fromNickname,
id: ctx.id,
lastMessage: ctx,
messageList: [ctx],
unreadCount : 1
}]
unreadCount: 1,
},
];
}
this.setSessionData(newData)
this.setSessionData(newData);
}
init(config) {
return new Promise((resolve, reject) => {
const heart = () => {
// 要优化 心跳没回复需要重连
setTimeout(async () => {
if (this.isOpen) {
await this[send]({
traceId: CreateUUID(),
traceType: 0,
content: { text: "ping" }
}).catch((e)=>{});
heart();
},1000)
content: { text: 'ping' },
});
}
this[connect]({
heart();
}, 1000);
};
this.option = {
...this.option,
...config,
}).then(() => {
};
this[connect]()
.then((res) => {
resolve(res);
heart();
resolve(this);
}).catch((e)=>{});
})
}
logout() {
this.option.logout = true;
this.socket.close();
this.interceptors.onLogout && this.interceptors.onLogout();
.catch((e) => {
console.log('eeeee', e);
});
});
}
/**
* 设置数据
*/
setSessionData(data) {
this.interceptors.dataChangeBefore && this.interceptors.dataChangeBefore(data, this.sessionData);
this.sessionData = data;
let newData = JSON.parse(JSON.stringify(data));
this.interceptors.dataChangeBefore && this.interceptors.dataChangeBefore(newData, this.sessionData);
this.sessionData = newData;
this.interceptors.dataChangeAfter && this.interceptors.dataChangeAfter(this.sessionData);
}
/**
@ -218,29 +244,30 @@ export default class MsbIm {
const par = {
traceId: CreateUUID(),
traceType: 1,
...params
...params,
};
console.log('[im] 获取会话列表--start', par);
let { error, result } = await ToAsyncAwait(this[send](par));
console.log('[im] 获取会话列表--end', result, error);
if (error) {
return Promise.reject(error);
}
const { content } = result;
console.log('获取会话列表', par, result);
content.sessionVOS.forEach(item => {
content.sessionVOS.forEach((item) => {
if (item.lastMessage) {
item.lastMessage.payload = JSON.parse(item.lastMessage.payload || {});
}
let historyData = this.sessionData;
let hisIndex = historyData.findIndex(i => i.id === item.id);
let hisIndex = historyData.findIndex((i) => i.id === item.id);
if (hisIndex >= 0) {
historyData[hisIndex].lastMessage = item.lastMessage;
historyData[hisIndex].unreadCount++;
this.setSessionData(historyData)
this.setSessionData(historyData);
} else {
item.messageList = [];
const newData = [...historyData, item]
const newData = [...historyData, item];
this.setSessionData(newData);
}
});
@ -251,33 +278,33 @@ export default class MsbIm {
* @param {*} params
*/
async getHistoryMsg() {
const curSessionIdx = this.sessionData.findIndex(i => i.id === this.curSessionId);
const curSessionIdx = this.sessionData.findIndex((i) => i.id === this.curSessionId);
const curSession = this.sessionData[curSessionIdx];
const msgList = curSession.messageList || [];
const par = {
traceId: CreateUUID(),
traceType: 23,
traceType: 2,
content: {
sessionId: this.curSessionId,
topMessageId: msgList.length ? msgList[0].id : null
}
topMessageId: msgList.length ? msgList[0].id : null,
},
};
console.log('[im] 获取会话历史消息--start', par);
const { error, result } = await ToAsyncAwait(this[send](par));
console.log('[im] 获取会话历史消息--end', result, error);
if (error) {
return Promise.reject(error);
}
const { content } = result;
console.log('获取会话历史消息',par, result);
if (content.length) {
let newData = this.sessionData;
content.forEach(item => {
item.payload = JSON.parse(item.payload)
})
content.forEach((item) => {
item.payload = JSON.parse(item.payload);
});
newData[curSessionIdx].messageList = content.concat(newData[curSessionIdx].messageList);
this.setSessionData(newData);
}
return Promise.resolve(result);
}
/**
* 会话已读
@ -286,14 +313,14 @@ export default class MsbIm {
async setRead(params) {
const par = {
traceId: CreateUUID(),
traceType : "6",
...params
}
traceType: '6',
...params,
};
console.log('[im] 会话已读--start', par);
const { error, result } = await this[send](par);
console.log('[im] 会话已读--end', result, error);
console.log('会话已读', par, result);
let newData = this.sessionData.map(item => {
let newData = this.sessionData.map((item) => {
if (item.id == params.content.sessionId) {
item.unreadCount = 0;
}
@ -307,28 +334,28 @@ export default class MsbIm {
* @param {*} params
*/
async sendMsg(params) {
const index = this.sessionData.findIndex(i => i.id === this.curSessionId)
const index = this.sessionData.findIndex((i) => i.id === this.curSessionId);
let curSession = this.sessionData[index];
// 临时消息体
let par = {
...params,
traceId: CreateUUID(),
traceType: 20,
}
traceType: 3,
};
let msgCtx = {
...params.content,
...par,
fromId: params.fromId,
createTimeStamp : (new Date()).getTime(),
sendStatus : 'loading'
}
createTimeStamp: new Date().getTime(),
sendStatus: 'loading',
};
// 点发送,立即把消息加入消息列表,标记为发送中状态
curSession.messageList.push(msgCtx);
// 超过时间未返回视为发送失败
this.timerStatus(msgCtx);
const { error, result } = await ToAsyncAwait(this[send](par));
console.log('发送消息', par, result);
console.log('[im] 发送消息--start', par);
const { error, result } = await ToAsyncAwait(this[send](par));
console.log('[im] 发送消息--end', result, error);
// 接到通知,标记消息是否发送成功
for (let i = curSession.messageList.length; i--; ) {
const item = curSession.messageList[i];
@ -352,12 +379,17 @@ export default class MsbIm {
*/
async resend(params) {
params.sendStatus = 'loading';
this.timerStatus(params)
const { error, result } = await ToAsyncAwait(this[send]({
this.timerStatus(params);
console.log('[im] 重新发送消息--start', params);
const { error, result } = await ToAsyncAwait(
this[send]({
traceId: params.traceId,
traceType: params.traceType,
content : params.content
}));
content: params.content,
})
);
console.log('[im] 重新发送消息--end', result, error);
params.createTimeStamp = result.createTimeStamp;
if (error) {
params.sendStatus = 'fail';
@ -367,7 +399,6 @@ export default class MsbIm {
return Promise.resolve(result);
}
timerStatus(msg) {
setTimeout(() => {
if (msg.sendStatus === 'loading') {
msg.sendStatus = 'fail';
@ -380,28 +411,30 @@ export default class MsbIm {
* @param {*} params
*/
async createSession(params) {
const { result, error } = await ToAsyncAwait(this[send]({
const par = {
traceId: CreateUUID(),
traceType : 21,
...params
}));
traceType: 9,
...params,
};
console.log('[im] 主动创建会话--start', par);
const { result, error } = await ToAsyncAwait(this[send](par));
console.log('[im] 主动创建会话--end', result, error);
if (error) {
return Promise.reject(error);
}
const { content } = result;
let historyData = this.sessionData;
let curSession = historyData.find(i => i.id === content.id);
let curSession = historyData.find((i) => i.id === content.id);
if (!curSession) {
curSession = {
...content,
unreadCount: 0,
messageList : []
}
messageList: [],
};
const newData = [...historyData, curSession];
this.setSessionData(newData);
}
return Promise.resolve(result);
}
}
export default MsbIm;

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-05-20 11:00:07
* @LastEditors: ch
* @LastEditTime: 2022-06-09 10:00:15
* @LastEditTime: 2022-06-09 11:32:37
* @Description: file content
*/

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2021-07-26 23:22:16
* @LastEditors: ch
* @LastEditTime: 2022-06-02 16:11:56
* @LastEditTime: 2022-06-09 11:43:04
* @Description: file content
*/
import Vue from 'vue';

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-26 14:32:03
* @LastEditors: ch
* @LastEditTime: 2022-06-02 17:33:13
* @LastEditTime: 2022-06-09 11:41:50
* @Description: file content
-->
<template>
@ -138,7 +138,8 @@ export default {
async createSessionMain(){
const {error, result} = await ToAsyncAwait(Im.createSession({
content : {
storeId : 1
// storeId : 1,
sessionType : 3
}
}));

Loading…
Cancel
Save