| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400 |
- import type Message from '@/mode/Message'
- import type Receipt from '@/mode/Receipt'
- import type Webrtc from '@/mode/Webrtc'
- import SendCode from '@/utils/SendCode'
- import ChatUtils from '@/utils/ChatUtils'
- import vimConfig from '@/config/VimConfig'
- import Auth from '@/api/Auth'
- import ChatType from '@/utils/ChatType'
- import MessageType from '@/utils/MessageType'
- import {useUserStore} from '@/store/userStore'
- import {useChatStore} from '@/store/chatStore'
- import {useFriendStore} from '@/store/friendStore'
- import {useGroupStore} from '@/store/groupStore'
- import MessageUtils from '@/utils/MessageUtils'
- import VimPlugin from "@/plugins/VimPlugin";
- import WebrtcCtr from "@/imcall/WebrtcCtr";
- import dbApi from '@/api/DBactApi';
- import { encryptLong2,decryptLong2} from '@/store/cryptoAES';
- import el from 'date-fns/locale/el'
- const ready = `{"code":${SendCode.READY}}`
- const ping = `{"code":${SendCode.PING}}`
- class WsRequest {
- lockReconnect: boolean
- url: string | undefined
- //是否主动关闭
- closeByUser: boolean
- //心跳检测 多少秒执行检测
- timeout: number
- //重连超时时间
- timeoutError: number
- heartTask: number | null
- reconnectTimeoutTask: number | null
- socket: UniApp.SocketTask | null
- uuid: string
- private static instance: WsRequest
- private constructor() {
- this.lockReconnect = false //避免重复连接
- this.url = ''
- //是否主动关闭
- this.closeByUser = false
- //心跳检测 多少秒执行检测
- this.timeout = 3000
- //超过多少秒没反应就重连
- this.timeoutError = 5000
- this.heartTask = null
- this.reconnectTimeoutTask = null
- this.socket = null
- this.uuid = `${new Date().getTime()}`;
- }
- static getInstance() {
- if (!this.instance) {
- this.instance = new WsRequest()
- }
- return this.instance
- }
- public init(): void {
- this.closeByUser = false
- this.url = `${vimConfig.wsProtocol}://${vimConfig.host}:${vimConfig.wsPort}?token=${Auth.getToken()}&client=${vimConfig.client}&uuid=${this.uuid}`
- //console.log(this.url)
- this.socket = uni.connectSocket({
- url: this.url, //接口地址。
- fail: (err) => {
- console.log(err, '连接错误')
- }
- })
- this.socket.onOpen( () => {
- //告知服务器准备就绪
- console.log('告知服务器准备就绪');
- this.send(ready)
- // 开启检测
- this.reset()
- })
- // 如果希望websocket连接一直保持,在close或者error上绑定重新连接方法。
- this.socket.onClose(() => {
- if (!this.closeByUser) {
- this.reconnect()
- }
- })
- this.socket.onError (() => {
- this.reconnect()
- })
- this.socket.onMessage((res) => {
- const data = res.data
- //防止每次心跳都要进行 JSON.parse 优化性能
- if (data === ping) {
- this.reset()
- return
- }
- const sendInfo = JSON.parse(data)
- console.log('onMessage',sendInfo)
- // 真正的消息类型
- if (sendInfo.code === SendCode.MESSAGE) {
- this.onmessage(sendInfo.message)
- } else if (sendInfo.code === SendCode.OTHER_LOGIN && this.uuid !== sendInfo.message.uuid) {
- MessageUtils.error('账号已经在别处登录')
- Auth.logout()
- }else if (sendInfo.code === SendCode.NEW_FRIEND) {
- useFriendStore().loadValidateList()
- useFriendStore().loadData()
- } else if (sendInfo.code === SendCode.GROUP_VALIDATE) {
- useGroupStore().loadWaitCheckList()
- }
- else if (sendInfo.code === SendCode.READ){
- useChatStore().setLastReadTime(sendInfo.message)
- }
- else if (sendInfo.code === SendCode.WEBRTC_xinling){
- WebrtcCtr.messageListener(sendInfo.message);
- //this.callback(undefined);
- }
- else if (sendInfo.code === SendCode.WEBRTC_CALL){
- console.log('WEBRTC_CALL',sendInfo)
- if(uni.getSystemInfoSync().platform == "ios"){
- //ios不拉起
- //VimPlugin.messageListener(sendInfo)
- //WebrtcCtr.messageListener(sendInfo.message);//新的通话方式
- }
- else{
- WebrtcCtr.messageListener(sendInfo.message);//新的通话方式
- //VimPlugin.messageListener(sendInfo)
- }
- }
- else{
- WebrtcCtr.messageListener(sendInfo.message);//新的通话方式
- //VimPlugin.messageListener(sendInfo)
- }
- //接受任何消息都说明当前连接是正常的
- this.reset()
- })
- }
- /**
- * 发送状态
- * @param value
- */
- send(value: string): void {
- this.socket?.send({
- data:value
- })
- }
- /**
- * 打开socket,监听服务器实时消息和拉取未读消息
- * 收到消息
- * @param message 消息
- */
- onmessage = (message: Message): void => {
- const user = useUserStore().getUser()
- //群聊里面,自己发的消息不再显示
- if (user?.id === message.fromId) {
- message.mine = true
- }
- //友聊换chatId,chatId 不一样
- if (ChatType.FRIEND === message.type && user?.id !== message.fromId) {
- message.chatId = message.fromId
- }
- //console.log("onmessage",message);
- if (message.messageType === MessageType.back) {
- useChatStore().backMessage(message)//消息撤回
- //dbApi.deletemsg(message);
- dbApi.deleteLocalmsg(message);
- } else {
- if(message.mine){
- useChatStore().delLocalMessageList(message);
- dbApi.deleteMyLocalmsg(message);
- }
- //dbApi.insertmsg(message);
- dbApi.insertLocalmsg(message);
- useChatStore().pushMessage(message)//收到消息
- }
- if(!message.mine){
- this.callback(message)
- }
- }
- /**
- * 文件类消息预发送
- * @param message 消息
- */
- sendfileMessage(message: Message): void {
- var content='';
- if(message.messageType===MessageType.voice){
- content=encryptLong2('【音频】');
- message.content=content;
- }
- else if(message.messageType===MessageType.video){
- content=encryptLong2('【视频】');
- message.content=content;
- }
- else if(message.messageType===MessageType.image){
- content=encryptLong2('【图片】');
- message.content=content;
- }
- else if(message.messageType===MessageType.file){
- content=encryptLong2('【文件】');
- message.content=content;
- }
- dbApi.insertLocalmsg(message);
- useChatStore().pushMessage(message);//消息插入队列
- this.callback(message);
- }
-
- sendfileMsgFalse(message: Message): void {
- useChatStore().delLocalMessageList(message);
- dbApi.deleteMyLocalmsg(message);
- this.callback(message);
- }
- /**
- * 发送真正的聊天消息
- * @param message 消息
- */
- sendMessage(message: Message): void {
- //数据加密后发送
- //console.log('sendMessage1',message)
- var content='';
- if(message.messageType===MessageType.text){
- content=encryptLong2(message.content);
- message.content=content;
- }
- else if(message.messageType===MessageType.voice){
- content=encryptLong2('【音频】');
- message.content=content;
- }
- else if(message.messageType===MessageType.video){
- content=encryptLong2('【视频】');
- message.content=content;
- }
- else if(message.messageType===MessageType.image){
- content=encryptLong2('【图片】');
- message.content=content;
- }
- else if(message.messageType===MessageType.file){
- content=encryptLong2('【文件】');
- message.content=content;
- }
- console.log('sendMessage2',message)
-
- if(message.localtime){
- const sendInfo = {
- code: SendCode.MESSAGE,
- message: message
- }
- this.send(JSON.stringify(sendInfo));
- }
- else{
- var currentTime = new Date().getTime();
- message.localtime=currentTime;
- message.timestamp=currentTime;
-
- const sendInfo = {
- code: SendCode.MESSAGE,
- message: message
- }
- this.send(JSON.stringify(sendInfo));
- message.mine=true;
- message.id=JSON.stringify(currentTime);
- console.log('sendMessage3',message)
- dbApi.insertLocalmsg(message);
- useChatStore().pushMessage(message);//消息插入队列
- this.callback(message);
- }
- }
- /**
- * 发送webrtc通讯结果
- * @param receipt 消息读取回执
- */
- sendWEBRTCresult(message: any): void {
- var currentTime = new Date().getTime();
- message.localtime=currentTime;
- message.timestamp=currentTime;
-
- const sendInfo = {
- code: SendCode.MESSAGE,
- message: message
- }
- this.send(JSON.stringify(sendInfo));
- message.mine=true;
- message.id=JSON.stringify(currentTime);
- console.log('sendMessage3',message)
- dbApi.insertLocalmsg(message);
- useChatStore().pushMessage(message);//消息插入队列
- this.callback(message);
- }
-
- /**
- * 发送webrtc信令
- * @param receipt 消息读取回执
- */
- sendWEBRTC(webrtc: Webrtc): void {
- const sendInfo = {
- code: SendCode.WEBRTC_xinling,
- message: webrtc
- }
- this.send(JSON.stringify(sendInfo))
- }
- /**
- * 发送已读取消息
- * @param receipt 消息读取回执
- */
- sendRead(receipt: Receipt): void {
- const sendInfo = {
- code: SendCode.READ,
- message: receipt
- }
- this.send(JSON.stringify(sendInfo))
- }
- /**
- * reset和start方法主要用来控制心跳的定时。
- */
- reset(): void {
- // 清除定时器重新发送一个心跳信息
- if (this.heartTask) {
- clearTimeout(this.heartTask)
- }
- if (this.reconnectTimeoutTask) {
- clearTimeout(this.reconnectTimeoutTask)
- }
- this.lockReconnect = false
- this.heartTask = setTimeout(() => {
- //这里发送一个心跳,后端收到后,返回一个心跳消息,
- //onmessage拿到返回的心跳就说明连接正常
- this.send(ping)
- }, this.timeout)
- //onmessage拿到消息就会清理 reconnectTimeoutTask,如果没有清理,就会执行重连
- this.reconnectTimeoutTask = setTimeout(() => {
- this.reconnect()
- }, this.timeoutError)
- }
- /**
- * 立即验证连接有效性
- * 重置心跳检测和重连检测
- * 立刻发送一个心跳信息
- * 如果没有收到消息,就会执行重连
- */
- checkStatus(): void {
- // 清除定时器重新发送一个心跳信息
- if (this.heartTask) {
- clearTimeout(this.heartTask)
- }
- if (this.reconnectTimeoutTask) {
- clearTimeout(this.reconnectTimeoutTask)
- }
- this.lockReconnect = false
- this.send(ping)
- //onmessage拿到消息就会清理 reconnectTimeoutTask,如果没有清理,就会执行重连
- this.reconnectTimeoutTask = setTimeout(() => {
- this.reconnect()
- }, this.timeoutError - this.timeout)
- }
- /**
- * 收到消息的回调函数
- */
- callback = (message: Message) => {
- }
- // 重连
- reconnect(): void {
- // 防止多个方法调用,多处重连
- if (this.lockReconnect) {
- return
- }
- this.lockReconnect = true
- //没连接上会一直重连,设置延迟避免请求过多
- this.reconnectTimeoutTask = setTimeout(() => {
- // 重新连接
- this.init()
- this.lockReconnect = false
- }, this.timeoutError)
- }
- // 手动关闭
- close(closeByUser:boolean): void {
- this.lockReconnect = false
- //主动关闭
- if (this.heartTask) {
- clearTimeout(this.heartTask)
- }
- if (this.reconnectTimeoutTask) {
- clearTimeout(this.reconnectTimeoutTask)
- }
- this.closeByUser = closeByUser
- if (this.socket) {
- this.socket.close({ code: 1000, reason: '用户主动关闭' })
- }
- }
- }
- export default WsRequest
|