第一次写出这么完美的聊天页面(自我感觉良好),有点激动,也不知道在小程序或者在app有没有问题,反正解决了当期的问题
一是键盘遮挡输入框问题(这次没遇到,小程序篇遇到了小程序聊天)
二是加载历史数据的时候,会把当前浏览的数据顶下去(反转页面来解决的)
三是问题二搞出来,就是只有少量数据的时候,消息在底部而不是在顶部
废话不多说,直接上代码
<template>
<view class="hotel_chat">
<!-- :style="{height: (contentViewHeight-bottomHeight) + 'px'}"-->
<view class="chat_content" id="chat_content">
<!-- :style="{height: (contentViewHeight-bottomHeight) + 'px'}" :scroll-into-view="scrollToView"-->
<scroll-view class="scroll_view" :lower-threshold="50" :upper-threshold="50" :scroll-anchoring="true" :scroll-top="currentTop" id="scrollview" scroll-y="true" @scrolltolower="scrolltolower" @scroll="scrollList" @touchstart="onTouchStart">
<view class="chat_list" id="msglistview">
<view class="list_content" v-for="(item,index) in chatList" :key="item.id">
<view class="list_right" v-if="item.fromUid != fromUid" :id="'msg' + item.id">
<view class="list_avatar">
<image src="https://htres.78plat.com/miniv3/static/user_default.png"></image>
</view>
<div class="content_right">
<view class="list_context">
<view class="list_title">{{item.guestName}}</view>
<view class="time_text">{{handlerMsgTime(item.timestamp)}}</view>
</view>
<view class="right_bg" v-if="item.content&&item.chatType=='text'">
<text class="text_info">{{item.content}}</text>
</view>
<view class="audio_box right_bg" v-if="item.content&&item.chatType=='audio'" @click="playAudio(item,index)">
<!-- 语音 -->
<image v-if="index == currentIndex" src="/static/user_audio_gif.gif" mode=""></image>
<image v-else src="/static/user_audio_icon.png" mode=""></image>
<view class="audio_text">{{item.duration || 0}}s</view>
</view>
</div>
</view>
<!-- 右边 -->
<view class="list_left" v-else :id="'msg' + item.id">
<view class="list_avatar">
<image src="https://htres.78plat.com/miniv3/static/hotel_default.png"></image>
</view>
<div class="content_left">
<view class="list_context">
<view class="list_title">{{item.guestName}}</view>
<view class="time_text">{{handlerMsgTime(item.timestamp)}}</view>
</view>
<view class="left_bg" v-if="item.content&&item.chatType=='text'">
<text class="text_info">{{item.content}}</text>
</view>
<view class="audio_box left_bg" :style="{width: widthPercent(item.duration)+'%'}" v-if="item.content&&item.chatType=='audio'" @click="playAudio(item,index)">
<!-- 语音 -->
<view class="audio_text">{{item.duration || 0}}s</view>
<image v-if="index == currentIndex" src="/static/hotel_audio_gif.gif" mode=""></image>
<image v-else src="/static/hotel_audio_icon.png" mode=""></image>
</view>
</div>
</view>
<!-- 左边 -->
</view>
</view>
</scroll-view>
</view>
<!-- :style="{bottom: felxHeight + 'px'}"-->
<view class="chat_below" id="below" >
<!-- <view class="below_left" @click="Tcyy">常用语</view>-->
<view class="below_right">
<input :adjust-position="false" v-model="msgValue" :focus="focus" @focus="inputFocus" @blur="inputBlur" placeholder="请输入内容"/>
<view class="rg_btn" @click="sendClick">发送</view>
</view>
</view>
</view>
</template>
<script>
import socketIO from '@/common/utils/newSocket'
export default {
data() {
return {
chatList: [
],
newChatList: [
{
name: '小明',
content: '你好啊,小红同学你好啊你好啊你好啊你好啊你好啊你好啊你好啊你好啊',
time: '1742196395',
id: 1,
userId: '123456'
},
{
name: '小红',
content: '你好啊,小红同学',
time: '1742196398',
id: 2,
userId: '456789'
},
{
name: '小明',
content: '你好啊,小红同学你好啊你好啊你好啊你好啊你好啊',
time: '1742196395',
id: 3,
userId: '123456'
},
{
name: '小红',
content: '你好啊,小红同学',
time: '1742196398',
id: 4,
userId: '456789'
},
{
name: '小明',
content: '你好啊,小红同学',
time: '1742196395',
id: 5,
userId: '123456'
},
{
name: '小红',
content: '你好啊,小红同学',
time: '1742196398',
id: 6,
userId: '456789'
},
{
name: '小明',
content: '你好啊,小红同学',
time: '1742196395',
id: 7,
userId: '123456'
},
{
name: '小红',
content: '你好啊,小红同学',
time: '1742196398',
id: 8,
userId: '456789'
},
{
name: '小明',
content: '你好啊,小红同学',
time: '1742196395',
id: 9,
userId: '123456'
},
{
name: '小红',
content: '你好啊,小红同学',
time: '1742196398',
id: 10,
userId: '456789'
},
{
name: '小明',
content: '你好啊,小红同学',
time: '1742196395',
id: 11,
userId: '123456'
},
{
name: '小红',
content: '你好啊,小红同学',
time: '1742196398',
id: 12,
userId: '456789'
},
],
scrollToView: '',
scrollViewHeight: '',
contentViewHeight: '',
bottomHeight: '',
felxHeight: '',
msgValue: '',
focus: false,
socketCase: null,
shopId: '',
merchantId: '',
mobile: '',
guestName: '',
roomNo: '',
shopName: '',
userId: '',
userPhone: '',
userName: '',
chatUrl:'',
pageCount: 0,
pageNo: 1,
pageSize: 10,
fromUid: '',
toUid: '',
currentIndex:null,
audioContext: null, // 存储音频实例
currentTop: 0,
oldScrollTop: 0
};
},
onLoad(options) {
this.shopId= options.shopId || '320'
this.merchantId= options.merchantId || '110060146'
this.mobile= options.mobile || '18365211931'
this.guestName= options.guestName || '李在明'
this.roomNo= options.roomNo || '888'
this.shopName = options.shopName || '合肥市格林豪泰爱电竞'
this.userId = options.userId || '4685'
this.userPhone= options.userPhone || ''
this.userName= options.userName || ''
const res = uni.getSystemInfoSync(); //获取手机可使用窗口高度 api为获取系统信息同步接口
this.scrollViewHeight = res.windowHeight; //像素 因为给出的是像素高度px
this.contentViewHeight = res.windowHeight; //像素 因为给出的是像素高度px
//获取自定义头部和消息框高度
let that = this;
this.nextTick(()=>{ //获取头部的高度
let query = uni.createSelectorQuery()
// query.select('#nav').boundingClientRect()
query.select('#below').boundingClientRect()
query.exec((res) => {
console.log(res,"获取的res")
// that.navHeight = res[0].height;
that.bottomHeight = res[0].height
})
})
//获取当前可视区域高度
this.contentViewHeight = this.contentViewHeight-this.bottomHeight;
},
onHide() {
if(this.socketCase) {
this.socketCase.Close()
this.socketCase = null
}
},
onUnload() {
if(this.socketCase) {
this.socketCase.Close()
this.socketCase = null
}
},
onShow() {
this.pageNo = 1
this.chatList = []
this.getWebSocket()
},
mounted() {
let that = this;
//H5解决办法
// #ifdef H5
window.onresize = () => {
let that = this;
this.nowPhoneHeight = window.innerHeight; //h5
if(this.nowPhoneHeightnextTick(()=>{
that.scrollToView = 'msg' + that.chatList[that.chatList.length - 1].id;
})
},50)
}else{
//手机键盘被关闭了。
console.log("手机键盘被关闭了")
this.felxHeight = 0;
this.contentViewHeight = this.scrollViewHeight;
this.scrollToView = '';
setTimeout(()=>{
that.nextTick(()=>{
that.scrollToView = 'msg' + that.chatList[that.chatList.length - 1].id;
})
},50)
}
}
// #endif
//解决app端--(安卓)--点击软键盘上关闭按钮以后留白问题
// #ifdef APP
uni.onKeyboardHeightChange(res => { //监听第三方软键盘关闭的时候恢复原始状态
if(res.height == 0){
that.felxHeight = 0;
that.contentViewHeight = that.scrollViewHeight;
// this.scrollToView = '';
that.scrollToView = 'msg' + that.chatList[that.chatList.length - 1].id;
}
})
// #endif
},
methods: {
sendClick(e) {
let that = this;
console.log("发送信息")
// let centerOnj = {
// name: '小红',
// content: this.msgValue,
// time: new Date().getTime(),
// id: this.chatList.length + 1,
// userId: '456789'
// }
// this.chatList.push(centerOnj)
// return;
// 完成
console.log(e, this.msgValue, "=========");
if (this.msgValue.length <= 0) {
uni.showToast({
title: "不能发送空白信息",
icon: "none",
})
return
}
//时间间隔处理
let data = {
content: this.fixedEncodeURIComponent(this.msgValue),
messageType: 20,
userType: 6,
fromUid: this.fromUid,
toUid: this.toUid,
channel: this.channel,
mobile: this.mobile,
guestName: this.guestName,
roomNo: this.roomNo,
chatType: 'text',
duration: '',
userId: this.userId,
userName: this.userName,
};
// if (this.socketOpen) {
// console.log("发消息不行",JSON.stringify(data));
// uni.sendSocketMessage({
// data: JSON.stringify(data),
// success(res) {
// console.log(res, "发送成功==");
// },
// complete(other) {
// console.log(other, "消息毁掉==");
// }
// });
// }
// 发送给服务器消息
// this.socketObj.sendMsg(JSON.stringify(data));
this.socketCase.send(data);
let centerData = {
content: this.msgValue,
messageType: 20,
userType: 6,
fromUid: this.fromUid,
toUid: this.toUid,
channel: this.channel,
mobile: this.mobile,
guestName: this.guestName,
roomNo: this.roomNo,
time: this.formatCurrentTime(),
timestamp: new Date().getTime(),
chatType: 'text',
duration: '',
userId: this.userId,
userName: this.userName,
}
// this.unshiftmsg.push(centerData);
// 因为整个数据是反过来的,所以是加在数据最前面
this.chatList.push(centerData);
this.msgValue = ''
this.backTop()
},
getMessage(msgData) {
// console.log(msgData, "接收到的消息");
if(msgData.data) {
console.log(msgData.data)
console.log((msgData.data.person.mobile + msgData.data.roomNo) != (this.mobile + this.roomNo),"咋不对",msgData.data.person.mobile+msgData.data.roomNo,"roomNo",this.mobile + this.roomNo);
if((msgData.data.person.mobile + msgData.data.roomNo) != (this.mobile + this.roomNo) ) {
return
}
if (msgData.data.fromUid != this.fromUid&&msgData.data.fromUid == this.toUid) {
msgData.data.content = decodeURIComponent(msgData.data.content)
msgData.data.time = this.formatCurrentTime(msgData.data.timestamp)
this.chatList.push(msgData.data);
this.backTop()
}
}
},
// 连接准备接口
async getWebSocket() {
let that = this
let param = {
shopId: this.shopId,
merchantId: this.merchantId,
mobile: this.mobile,
guestName: this.guestName,
userId: this.userId,
userPhone: this.userPhone,
userName: this.userName,
roomNo: this.roomNo,
shopName: this.shopName,
serviceFor: 'mini',
userType: 6,
}
const res = await this.Http.indexService.getWebSocket(param)
console.log(res, "聊天");
if(res.retdata) {
let ret = res.retdata
that.fromUid = ret.fromUid // 发送方标识
that.toUid = ret.toUid // 接收方标识
that.userType = ret.userType // 发送方类型
that.channel = ret.channel // 消息通道标识
that.chatUrl = ret.chatWsPath || ''
that.socketCase = new socketIO({}, 16000, ret.chatWsPath)
that.socketCase.connectSocketInit()
this.getHistoryChat()
// 接收数据
uni.on("getPositonsOrder", (res) => {
console.log(res, "监听不到信息");
this.getMessage(res)
})
}
},
async readChat() {
let param = {
mobile: this.mobile,
roomNo: this.roomNo,
guestName: this.guestName,
channel: this.channel,
fromUid: this.toUid,
toUid: this.fromUid,
serviceFor: 'mini',
computer: ''
}
const res = await this.Http.indexService.readChat(param)
console.log(res, "置未读为已读");
if(res.retcode=='0') {
console.log("置空成功")
} else {
console.log("置空失败")
}
},
async getHistoryChat() {
let that = this
if (that.pageNo == 1) {
that.chatList = []
}
let param = {
shopId: this.shopId,
pageNo: this.pageNo,
pageSize: this.pageSize,
mobile: this.mobile,
roomNo: this.roomNo,
channel: this.channel,
fromUid: this.fromUid,
toUid: this.toUid,
userType: this.userType,
serviceFor: "mini"
}
const res = await this.Http.indexService.getHistoryChat(param)
console.log(res, "历史消息");
if(res.retdata) {
this.pageCount = res?.retdata?.pageCount || 0
let ret = res?.retdata?.data || []
ret = ret.reverse();
// that.unshiftmsg = [...ret, ...that.unshiftmsg]
// ret = ret.reverse();
that.chatList = [...ret,...that.chatList]
if (that.pageNo == 1) {
this.backTop()
// 跳转到最后一条数据 与前面的:id进行对照
// this.nextTick(function() {
// this.currentTop = 0
// this.scrollToView = 'msg' + (this.chatList.length - 1)
// })
}
this.readChat()
}
},
// 触摸开始:说明可能是手势滑动
onTouchStart() {
console.log("说明可能是手势滑动")
if(this.focus) {
this.focus = false
}
// this.isTouching = true;
},
scrolltolower(e) {
console.log(e,"滚动到顶部")
if (this.pageNo < this.pageCount) {
this.pageNo += 1
this.getHistoryChat()
}
},
scrollList(e) {
// console.log(e,"页面滚动了====")
this.oldScrollTop = e.detail.scrollTop
},
playAudio(item, index) {
let path = item.content;
// 如果已有音频在播放,先停止并销毁
if (this.audioContext) {
this.audioContext.stop();
this.audioContext.destroy();
this.audioContext = null;
}
// 重新创建音频实例
this.audioContext = uni.createInnerAudioContext();
this.audioContext.src = path;
this.audioContext.autoplay = true; // 自动播放
this.audioContext.obeyMuteSwitch = false;
// 监听播放开始
this.audioContext.onPlay(() => {
this.currentIndex = index;
console.log("开始播放:", path);
});
// 监听播放结束
this.audioContext.onEnded(() => {
this.stopAudio();
});
// 监听错误
this.audioContext.onError((err) => {
console.error("播放错误:", err);
this.stopAudio();
});
// **关键点:确保 play() 触发**
this.audioContext.play();
},
stopAudio() {
if (this.audioContext) {
this.audioContext.stop();
this.audioContext.destroy();
this.audioContext = null;
this.currentIndex = null;
console.log("音频已停止");
}
},
// 语音长度随语音秒数变化
widthPercent(value=0) {
// 语音小于10秒 都返回最小长度15%
if (value < 2) {
return 3
}
if (value > 30) {
return 45
}
return value / 60 * 100
},
//监听input获取焦点事件和失去焦点时间
inputFocus(e) { //触发焦点
this.scrollToView = ''
this.felxHeight = e.detail.height; //获取软键盘高度修改输入框定位
this.contentViewHeight = this.contentViewHeight - e.detail.height; //可视高度减去软键盘高度
this.backTop()
this.focus = true
},
inputBlur(e){ //失去焦点
this.scrollToView = ''
this.felxHeight = 0; //失去焦点恢复原位
this.contentViewHeight = this.scrollViewHeight;
this.backTop()
this.focus = false
},
fixedEncodeURIComponent(str) {
return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
return '%' + c.charCodeAt(0).toString(16).toUpperCase();
});
},
backTop() {
let that = this;
console.log("回到底部")
this.currentTop = this.oldScrollTop
setTimeout(()=>{
that.nextTick(function(){
this.currentTop = 0
that.scrollToView = 'msg' + that.chatList?.[that.chatList.length - 1]?.id;
})
},50)
// that.scrollToView = ''
// setTimeout(()=>{
// that.nextTick(function(){
// that.scrollToView = 'msg' + that.chatList?.[that.chatList.length - 1]?.id;
// })
// },50)
},
formatCurrentTime(time = '') {
const now = time ? new Date(time) :new Date();
return now.getTime();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
return `{year}-{month}-{day}{hours}:{minutes}:{seconds}`;
},
handlerMsgTime(timeValueData) {
// console.log(timeValueData)
// 如果是字符串,先转成数字
let timeValue = (new Date(timeValueData)).getTime();
var timeNew = new Date().getTime(); // 当前时间
// console.log('传入的时间', timeValue, timeNew)
var timeDiffer = parseFloat(timeNew) - parseFloat(timeValue); // 与当前时间误差
// console.log(timeDiffer,"timeDiffer", parseFloat(timeNew),"==",parseFloat(timeValue))
// console.log('时间差', timeDiffer)
var returnTime = "";
// if (timeDiffer <= 60000) {
// // 一分钟内
// returnTime = "刚刚";
// } else if (timeDiffer > 60000 && timeDiffer < 3600000) {
// // 1小时内
// returnTime = Math.floor(timeDiffer / 60000) + "分钟前";
// } else if (
// timeDiffer >= 3600000 &&
if (timeDiffer < 86400000 && this.isYestday(timeValue) == false) {
// 今日
returnTime = this.formatTime(timeValue).substr(11, 5);
} else if (timeDiffer > 3600000 && this.isYestday(timeValue) == true) {
// 昨天
returnTime = "昨天 " + this.formatTime(timeValue).substr(11, 5);
} else if (timeDiffer > 86400000 && timeDiffer <= 518400000) {
// 星期几
returnTime =
this.getWeeken(timeValue) +
" " +
this.formatTime(timeValue).substr(11, 5);
} else if (
timeDiffer > 86400000 &&
this.isYestday(timeValue) === false &&
this.isYear(timeValue) === true
) {
// 今年
returnTime = this.formatTime(timeValue).substr(5, 11);
} else if (
timeDiffer > 86400000 &&
this.isYestday(timeValue) === false &&
this.isYear(timeValue) === false
) {
// 不属于今年
returnTime = this.formatTime(timeValue).substr(0, 16);
}
// console.log(returnTime,"=====")
return returnTime;
},
isYear(timeValue) {
// 是否为今年
const dateyear = new Date(timeValue).getFullYear();
const toyear = new Date().getFullYear();
// console.log(dateyear, toyear)
if (dateyear == toyear) {
return true;
} else {
return false;
}
},
getWeeken(date) {
var weekArray = new Array(
"星期日",
"星期一",
"星期二",
"星期三",
"星期四",
"星期五",
"星期六"
);
var week = weekArray[new Date(date).getDay()];
return week;
},
formatTime(date) {
var t = this.getTimeArray(date);
return (
[t[0], t[1], t[2]].map(this.formatNumber).join("-") +
" " +
[t[3], t[4], t[5]].map(this.formatNumber).join(":")
);
},
getTimeArray(date) {
date = new Date(date);
var year = date.getFullYear();
var month = date.getMonth() + 1;
var day = date.getDate();
var hour = date.getHours();
var minute = date.getMinutes();
var second = date.getSeconds();
return [year, month, day, hour, minute, second].map(this.formatNumber);
},
// 转化日期 如2018-7-6 -->(2018-07-06)
formatNumber(n) {
n = n.toString();
return n[1] ? n : "0" + n;
},
isYestday(timeValue) {
// 是否为昨天
const date = new Date(timeValue);
const today = new Date();
if (
date.getFullYear() == today.getFullYear() &&
date.getMonth() == today.getMonth()
) {
if (today.getDate() - date.getDate() == 1) {
return true;
} else {
return false;
}
} else {
return false;
}
}
}
}
</script>
<style lang="scss" scoped>
.hotel_chat {
background: #F7F9FA;
height: 100vh;
display: flex;
flex-direction: column;
overflow: hidden;
.chat_content {
flex: 1;
overflow: hidden;
padding: 0 28rpx 0 28rpx;
box-sizing: border-box;
.scroll_view {
height: 100%;
//overflow: auto;
transform: rotate(180deg);
//direction: rtl;
.chat_list {
//height: 100%;
transform: rotate(180deg);
overflow: auto;
min-height: 100%;
.text_info {
word-break:break-all;
}
}
.list_content {
margin-bottom: 40rpx;
&:first-child {
margin-top: 40rpx;
}
.list_avatar {
flex-shrink: 0;
width: 68rpx;
height: 68rpx;
border-radius: 50%;
background: #FFFFFF;
//border: 2rpx solid #FFF;
image {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
.list_right {
display: flex;
.content_right {
margin-left: 16rpx;
.audio_box {
justify-content: flex-start;
.audio_text {
margin-left: 20rpx;
}
}
}
.list_title {
margin-right: 12rpx;
}
.right_bg {
max-width: 460rpx;
padding: 12rpx 20rpx;
box-sizing: border-box;
border-radius: 8rpx;
background: #FFF;
color: #333333;
font-family: "PingFang SC";
font-size: 28rpx;
font-weight: 400;
width: fit-content;
}
}
.list_left {
display: flex;
flex-direction: row-reverse;
.content_left {
margin-right: 16rpx;
display: flex;
flex-direction: column;
align-items: flex-end;
.audio_box {
justify-content: flex-end;
.audio_text {
margin-right: 20rpx;
}
}
}
.list_context {
flex-direction: row-reverse;
.list_title {
margin-left: 12rpx;
}
}
.left_bg {
padding: 12rpx 20rpx;
box-sizing: border-box;
border-radius: 8rpx;
background: #0060FF;
color: #ffffff;
text-align: right;
font-family: "PingFang SC";
font-size: 28rpx;
font-weight: 400;
max-width: 460rpx;
width: fit-content;
align-self: flex-end;
flex: 1;
}
}
.list_context {
display: flex;
align-items: center;
margin-bottom: 16rpx;
.list_title {
margin-right: 12rpx;
color: #555b62;
font-family: "PingFang SC";
font-size: 20rpx;
font-weight: 400;
}
.time_text {
color: #9ea5ad;
font-family: "PingFang SC";
font-size: 20rpx;
font-weight: 400;
line-height: 28rpx;
word-break:break-all;
}
}
.audio_box {
display: flex;
align-items: center;
font-family: "PingFang SC";
font-size: 28rpx;
font-weight: 400;
//background: #287EFF;
min-width: 128rpx;
padding: 18rpx 24rpx;
box-sizing: border-box;
border-radius: 8rpx;
image {
width: 28rpx;
height: 28rpx;
//margin-left: 22rpx;
}
}
}
}
}
.chat_below {
display: flex;
align-items: center;
width: 750rpx;
padding: 24rpx 28rpx;
box-sizing: border-box;
background: #FFFFFF;
.below_right {
display: flex;
align-items: center;
flex: 1;
//margin-left: 20rpx;
input {
height: 64rpx;
flex: 1;
border-radius: 94rpx;
background: #F7F9FA;
padding: 0 28rpx;
box-sizing: border-box;
color: #333333;
font-family: "PingFang SC";
font-size: 28rpx;
font-weight: 400;
}
.rg_btn {
margin-left: 20rpx;
width: 132rpx;
height: 64rpx;
border-radius: 94rpx;
background: #0060FF;
display: flex;
align-items: center;
justify-content: center;
color: #ffffff;
font-family: "PingFang SC";
font-size: 28rpx;
font-weight: 400;
}
}
}
}
</style>
// newSocket.js
class socketIO {
constructor(data, time, url) {
this.socketTask = null
this.is_open_socket = false //避免重复连接
this.url = url ? url : '' //连接地址
this.data = data ? data : null
this.connectNum = 1 // 重连次数
this.traderDetailIndex = 100 // traderDetailIndex ==2 重连
this.accountStateIndex = 100 // accountStateIndex ==1 重连
this.followFlake = false // followFlake == true 重连
//心跳检测
this.timeout = time ? time : 15000 //多少秒执行检测
this.heartbeatInterval = null //检测服务器端是否还活着
this.reconnectTimeOut = null //重连之后多久再次重连
}
// 进入这个页面的时候创建websocket连接【整个页面随时使用】
connectSocketInit(data) {
this.data = data
this.socketTask = uni.connectSocket({
url: this.url,
success: () => {
console.log("正准备建立websocket中...");
// 返回实例
return this.socketTask
},
});
this.socketTask.onOpen((res) => {
this.connectNum = 1
console.log("WebSocket连接正常!");
uni.emit('connectSuccess')
this.send(data)
clearInterval(this.reconnectTimeOut)
clearInterval(this.heartbeatInterval)
this.is_open_socket = true;
this.start();
// 注:只有连接正常打开中 ,才能正常收到消息
this.socketTask.onMessage((e) => {
// 字符串转json
let res = JSON.parse(e.data);
console.log(e,"获取到消息res---------->", res) // 这里 查看 推送过来的消息
if (res) {
uni.emit('getPositonsOrder', JSON.parse(res));
}
});
})
// 监听连接失败,这里代码我注释掉的原因是因为如果服务器关闭后,和下面的onclose方法一起发起重连操作,这样会导致重复连接
uni.onSocketError((res) => {
console.log('WebSocket连接打开失败,请检查!');
this.socketTask = null
this.is_open_socket = false;
clearInterval(this.heartbeatInterval)
clearInterval(this.reconnectTimeOut)
uni.off('getPositonsOrder')
uni.off('connectSuccess')
if (this.connectNum < 6) {
uni.showToast({
title: `WebSocket连接失败,正尝试第{this.connectNum}次连接`,
icon: "none"
})
this.reconnect();
this.connectNum += 1
} else {
uni.emit('connectError');
this.connectNum = 1
}
});
// 这里仅是事件监听【如果socket关闭了会执行】
this.socketTask.onClose(() => {
console.log("已经被关闭了-------")
clearInterval(this.heartbeatInterval)
clearInterval(this.reconnectTimeOut)
this.is_open_socket = false;
this.socketTask = null
uni.off('getPositonsOrder')
uni.off('connectSuccess')
if (this.connectNum < 6) {
this.reconnect();
} else {
uni.$emit('connectError');
this.connectNum = 1
}
})
}
// 主动关闭socket连接
Close() {
if (!this.is_open_socket) {
return
}
this.socketTask.close({
success() {
console.log("SocketTask 关闭成功");
// uni.showToast({
// title: 'SocketTask 关闭成功',
// icon: "none"
// });
}
});
}
//发送消息
send(data) {
// console.log("data---------->", data);
// 注:只有连接正常打开中 ,才能正常成功发送消息
if (this.socketTask) {
this.socketTask.send({
data: JSON.stringify(data),
async success() {
console.log("消息发送成功");
},
});
}
}
//开启心跳检测
start() {
this.heartbeatInterval = setInterval(() => {
this.send({
"traderid": 10260,
"type": "Ping"
});
}, this.timeout)
}
//重新连接
reconnect() {
//停止发送心跳
clearInterval(this.heartbeatInterval)
//如果不是人为关闭的话,进行重连
if (!this.is_open_socket && (this.traderDetailIndex == 2 || this.accountStateIndex == 0 || this
.followFlake)) {
this.reconnectTimeOut = setInterval(() => {
this.connectSocketInit(this.data);
}, 5000)
}
}
/**
* @description 将 scoket 数据进行过滤
* @param {array} array
* @param {string} type 区分 弹窗 openposition 分为跟随和我的
*/
arrayFilter(array, type = 'normal', signalId = 0) {
let arr1 = []
let arr2 = []
let obj = {
arr1: [],
arr2: []
}
arr1 = array.filter(v => v.flwsig == true)
arr2 = array.filter(v => v.flwsig == false)
if (type == 'normal') {
if (signalId) {
arr1 = array.filter(v => v.flwsig == true && v.sigtraderid == signalId)
return arr1
} else {
return arr1.concat(arr2)
}
} else {
if (signalId > 0) {
arr1 = array.filter(v => v.flwsig == true && v.sigtraderid == signalId)
obj.arr1 = arr1
} else {
obj.arr1 = arr1
}
obj.arr2 = arr2
return obj
}
}
}
module.exports = socketIO
Comments | NOTHING