diff --git a/App.vue b/App.vue index 919920c..70a01bc 100644 --- a/App.vue +++ b/App.vue @@ -3,10 +3,21 @@ //import checkupdate from "@/uni_modules/uni-upgrade-center-app/utils/check-update.js" //引进检查版本 // import callCheckVersion from '@/uni_modules/uni-upgrade-center-app/utils/call-check-version'; + + import { myCache } from '@/utils/utils.js'; + //#ifdef APP-PLUS const jpushModule = uni.requireNativePlugin('JG-JPush'); //#endif + export default { + data() { + return { + userid:"", + userName:"", + userheadimg:"", + } + }, onLaunch() { // 判断版本更新 需要真机进行测试 //checkupdate(); @@ -29,7 +40,6 @@ // }) // } - // // jpushModule.addTagAliasListener(result => { // let code = result.code // let sequence = result.sequence @@ -68,7 +78,449 @@ // console.log("自定义消息", result) // }) //#endif + + var user = myCache('user'); + this.userid = user.userid? user.userid:''; + this.userName=user.nickName?user.nickName:""; + this.userheadimg=user.avatar?user.avatar:require("@/static/image/girl.png"); + + // 接收信息 + if(uni.getStorageSync("token")&&this.userid){ + this.startHeartbeat(); + } + }, + methods: { + // 定时心跳包 + startHeartbeat() { + console.log("startHeartbeat"); + var that=this; + this.heartbeatInterval = setInterval(() => { + if(this.isConnected){ + // 如果已经连接ws + uni.sendSocketMessage({ + data: JSON.stringify({ + 'cmd': 1,//心跳 + 'data': { + 'accessToken':uni.getStorageSync("token") + }, + }), // 发送心跳包数据, + success(re) { + console.log(re); + console.log('消息发送成功!') + }, + fail(err) { + console.log(err); + console.log('消息发送失败!'); + that.reconnect(); + } + }); + } + else{ + // 重新连接 + that.reconnect(); + } + }, this.heartbeatTimeout); // 20秒执行一次 + }, + // 开始重连 + reconnect () { + if (!this.isConnected) { + clearTimeout(this.heartbeatInterval); + this.heartbeatInterval = setTimeout(() => { + console.log('开始重连...'); + this.socketinit(); + },this.heartbeatTimeout); + } + }, + // ws接收消息 + socketinit(){ + var that = this; + uni.connectSocket({ + url: "wss://www.sanduolantoyoga.com/yoga-imserver/", + header: { + // 'content-type': 'application/json', + Authorization: uni.getStorageSync("token"), + }, + success: (res) => { + console.log(res, 'socket连接成功success'); + }, + fail: (res) => { + console.log(res, 'socket连接失败') + }, + complete: (res) => { + console.log(res,'socket连接成功complete'); + } + }); + + uni.onSocketOpen(resopen => { + console.log('WebSocket连接已打开!'); + this.isConnected = true; + this.$forceUpdate(); + uni.sendSocketMessage({ + data: JSON.stringify({ + "cmd": 0,//心跳 + "data": { + "accessToken":uni.getStorageSync("token"), + }, + }), // 发送心跳包数据 // 发送的消息内容 + success(re) { + console.log(re); + console.log('消息发送成功!') + }, + fail(err) { + console.log(err); + console.log('消息发送失败!') + } + }); + + // 定时发送心跳包 + this.startHeartbeat(); + + }); + + // 连接关闭后重新连接 + uni.onSocketClose(res => { + console.log('WebSocket连接已关闭!',res); + this.isConnected = false; + this.$forceUpdate(); + // 重新连接socket + this.reconnect(); + }); + // 连接失败后重新连接 + uni.onSocketError(err => { + console.error('WebSocket连接打开失败,请检查:', err); + this.isConnected = false; + this.$forceUpdate(); + // 重新连接socket + this.reconnect(); + }); + + // 接收信息 + uni.onSocketMessage(res => { + console.log('收到WebSocket服务器消息:'); + if(res.data){ + var rs=JSON.parse(res.data); + console.log("onSocketMessage",rs); + if(rs.cmd==3){ + // 私聊 + if(rs.data){ + var data=rs.data; + if(data.recvId&&(data.recvId).toString()==(this.userid).toString()){ + // 是这个用户的接收的私聊信息 + // 加入聊天记录 + // 消息类型 0:文字 1:图片 2:文件 3:语音 4:视频 10, "撤回" 11, "已读 "12, "消息已读回执 " 30,"加载中标记" + if(data.type==0||data.type==1||data.type==2||data.type==3||data.type==4||data.type==5||data.type==6){ + if(data.type==0){ + data.content=decodeURIComponent(data.content); + } + var id="privatechat-" + data.recvId +"-" + data.sendId; + var index=this.ifadd(id); + var chatinfo=null; + var grouplist=myCache("chatlist-"+this.userid)?myCache("chatlist-"+this.userid):[]; + if(index>-1){ + grouplist[index].sl=(grouplist[index].sl?grouplist[index].sl+1:1); + grouplist[index].content=data.content; + grouplist[index].datetime=data.sendTime; + grouplist[index].type=data.type; + grouplist[index].minId=data.id; + grouplist[index].ifload=1; + that.$forceUpdate(); + chatinfo= JSON.parse(JSON.stringify(grouplist[index])); + } + else{ + // 未保存缓存 + // 接收到socket后更新聊天列表记录 + chatinfo={ + id: id, + content: data.content, + minId: data.id, + sl:1, + datetime: data.sendTime, + type: data.type, + name: "", + userid: data.recvId, + fromuser: data.sendId, + img: "", + sort:"privatechat", + ifload:0 + }; + grouplist.push(chatinfo); + this.$forceUpdate(); + } + myCache("chatlist-"+this.userid,grouplist); + this.getPrivateInfo(chatinfo); + } + else{ + // 10, "撤回" 11, "已读 " 12, "消息已读回执 " 30,"加载中标记" + } + } + } + } + else if(rs.cmd==4){ + // 群聊 + if(rs.data){ + var data=rs.data; + if(data.atUserIds&&data.atUserIds.includes(this.userid)){ + // 是这个用户的接收的群聊信息 + // 加入聊天记录 + // 消息类型 0:文字 1:图片 2:文件 3:语音 4:视频 10, "撤回" 11, "已读 "12, "消息已读回执 " 30,"加载中标记" + if(data.type==0||data.type==1||data.type==2||data.type==3||data.type==4||data.type==5||data.type==6){ + + if(data.type==0){ + data.content=decodeURIComponent(data.content); + } + + var id="groupchat-" + data.groupId; + var index=this.ifadd(id); + var chatinfo=null; + var grouplist=myCache("chatlist-"+this.userid)?myCache("chatlist-"+this.userid):[]; + if(index>-1){ + grouplist[index].sl=(grouplist[index].sl?grouplist[index].sl+1:1); + grouplist[index].content=data.content; + grouplist[index].datetime=data.sendTime; + grouplist[index].fromuser=data.sendId; + grouplist[index].type=data.type; + grouplist[index].minId=data.id; + grouplist[index].ifload=1; + that.$forceUpdate(); + chatinfo= JSON.parse(JSON.stringify(grouplist[index])); + } + else{ + // 未保存缓存 + // 接收到socket后更新聊天列表记录 + chatinfo={ + id: id, + groupId: data.groupId, + content: data.content, + minId: data.id, + sl:1, + datetime: data.sendTime, + type: data.type, + name: "", + userid: this.userid, + fromuser: data.sendId, + img: "", + sendId: data.sendId, + sendNickName: data.sendNickName, + sort:"groupchat", + ifload:0 + }; + grouplist.push(chatinfo); + } + myCache("chatlist-"+this.userid,grouplist); + this.getGroupInfo(chatinfo); + } + else{ + // 10, "撤回" 11, "已读 " 12, "消息已读回执 " 30,"加载中标记" + + } + } + } + } + } + }); + + }, + // 消息是否存在列表中 + ifadd(id){ + var ret=-1; + var grouplist=myCache("chatlist-"+this.userid)?myCache("chatlist-"+this.userid):[]; + grouplist.forEach((cell,ii)=>{ + if(cell.id==id){ + ret=ii; + } + }); + return ret; + }, + // 获取私聊信息 + async getPrivateInfo(info) { + if(info.ifload==0){ + info[info.fromuser]=(info.fromuser!=this.userid? await this.getFriend(info.fromuser):{}); + this.updateChatList(info); + } + else{ + this.updateChatList(info); + } + }, + // 获取群信息 + async getGroupInfo(info) { + if(info.ifload==0){ + const {data: res} = await uni.$http.get('/api/group/find/'+info.groupId); + if(res.data){ + var data = res.data; + info.name=data.name; + info.img=data.headImage||'/static/image/qltx.png'; + info.notice=data.notice; + info.remarkNickName=data.remarkNickName; + info.showNickName=data.showNickName; + info.showGroupName=data.showGroupName; + info.remarkGroupName=data.remarkGroupName; + info.customerService=data.customerService; + info.instructor=data.instructor; + info.ownerId=data.ownerId; + info.productId=data.productId; + info.productName=data.productName; + info[data.ownerId]=(data.ownerId!= this.userid? await this.getFriend(data.ownerId):{}); + info[data.customerService]=(data.customerService!= this.userid? await this.getFriend(data.customerService):{}); + info[data.instructor]=(data.instructor!= this.userid? await this.getFriend(data.instructor):{}); + this.updateChatGroupList(info); + } + } + else{ + this.updateChatGroupList(info); + } + }, + async getFriend(id){ + var name="匿名",img=require("@/static/image/girl.png"); + const {data: res} = await uni.$http.get("/api/friend/find/"+id); + if(res.data){ + name=res.data.nickName?res.data.nickName:"匿名"; + img=res.data.headImage?res.data.headImage:require("@/static/image/girl.png"); + } + return { + name:name, + img:img + }; + }, + async updateChatGroupList(info){ + var idx=this.ifadd(info.id); + if(idx<0){ + // 新增一条 + this.grouplist.push(info); + this.$forceUpdate(); + } + else{ + this.grouplist[idx].content=info.content; + this.grouplist[idx].datetime=info.datetime; + this.grouplist[idx].fromuser=info.fromuser; + this.grouplist[idx].type=info.type; + this.$forceUpdate(); + } + // 重新排序 保存缓存 + this.reorder(); + myCache("chatlist-"+ this.userid,this.grouplist); + + // 聊天框消息缓存 + // 获取发送人的信息 + var name=info[info.sendId]?info[info.sendId].name:"匿名",img=info[info.sendId]?info[info.sendId].img:require("@/static/image/girl.png"); + var msgchat=myCache(info.id); + if(!msgchat){ + // 第一条聊天记录保存缓存 + let firstmsg = [{ + "fromname": name, // 发送人 + "fromuser": info.fromuser, // 发送人 + "headimg": img, // 发送人 + "toname": userName, // 接收人 + "touser": this.userid, // 接收人姓名 + "content": info.content, + "time": info.type==3?(info.time?info.time:5):0, + "ifaudio":info.type==3? true:false, + "fromtime": info.datetime, + "type": info.type==0?'txt':(info.type==1?'image':info.type==3?'audio':(info.type==4?'video':'product')), + "id": info.minId, + "minId": info.minId, + "sendId": info.sendId, + "send": info.type==6?await this.getProduct(info.content):(info.type==5?await this.getOrder(info.content):null) + }]; + myCache(info.id,firstmsg); + } + else{ + // 是否已经加入到聊天记录中 + if(this.ifchatadd(info.id,info.minId)){ + // 聊天框信息 保存缓存 + let firstmsg = { + "fromname": name, // 发送人 + "fromuser": info.fromuser, // 发送人 + "headimg": img, // 发送人 + "toname": this.userName, // 接收人 + "touser": this.userid, // 接收人姓名 + "content": info.content, + "time": info.type==3?(info.time?info.time:5):0, + "ifaudio":info.type==3? true:false, + "fromtime": info.datetime, + "type": info.type==0?'txt':(info.type==1?'image':info.type==3?'audio':(info.type==4?'video':'product')), + "id": info.minId, + "minId": info.minId, + "sendId": info.sendId, + "send": info.type==6?await this.getProduct(info.content):(info.type==5?await this.getOrder(info.content):null) + }; + msgchat.push(firstmsg); + myCache(info.id,msgchat); + } + + } + }, + async updateChatList(info){ + // 此消息是否已经存在列表中 + var idx=this.ifadd(info.id); + if(idx<0){ + this.grouplist.push(info); + this.$forceUpdate(); + } + else{ + this.grouplist[idx].content=info.content; + this.grouplist[idx].datetime=info.datetime; + this.grouplist[idx].fromuser=info.fromuser; + this.grouplist[idx].type=info.type; + this.$forceUpdate(); + } + // 重新排序 保存缓存 + this.reorder(); + myCache("chatlist-"+this.userid,this.grouplist); + + // 聊天框消息缓存 + // 获取发送人的信息 + var name=info[info.fromuser]?info[info.fromuser].name:"匿名",img=info[info.fromuser]?info[info.fromuser].img:require("@/static/image/girl.png"); + var msgchat=myCache(info.id); + if(!msgchat){ + // 第一条聊天记录保存缓存 + let firstmsg = [{ + "fromname": name, // 发送人 + "fromuser": info.fromuser, // 发送人 + "headimg": img, // 发送人 + "toname": this.userName, // 接收人 + "touser": this.userid, // 接收人姓名 + "content": info.content, + "time": info.type==3?(info.time?info.time:5):0, + "ifaudio":info.type==3? true:false, + "fromtime": info.datetime, + "type": info.type==0?'txt':(info.type==1?'image':info.type==3?'audio':(info.type==4?'video':'product')), + "id": info.minId, + "minId": info.minId, + "recvId": info.recvId, + "sendId": info.sendId, + "send": info.type==6?await this.getProduct(info.content):(info.type==5?await this.getOrder(info.content):null) + }]; + myCache(info.id,firstmsg); + } + else{ + if(this.ifchatadd(info.id,info.minId)){ + // 聊天框信息 保存缓存 + let firstmsg = { + "fromname": name, // 发送人 + "fromuser": info.fromuser, // 发送人 + "headimg": img, // 发送人 + "toname": this.userName, // 接收人 + "touser": this.userid, // 接收人姓名 + "content": info.content, + "time": info.type==3?(info.time?info.time:5):0, + "ifaudio":info.type==3? true:false, + "fromtime": info.datetime, + "type": info.type==0?'txt':(info.type==1?'image':info.type==3?'audio':(info.type==4?'video':'product')), + "id": info.minId, + "minId": info.minId, + "recvId": info.recvId, + "sendId": info.sendId, + "send": info.type==6?await this.getProduct(info.content):(info.type==5?await this.getOrder(info.content):null) + }; + msgchat.push(firstmsg); + myCache(info.id,msgchat); + } + } + + }, + }, + } diff --git a/main.js b/main.js index abe66e8..a0da7d1 100644 --- a/main.js +++ b/main.js @@ -86,6 +86,10 @@ $http.afterRequest = function (response) { } Vue.config.productionTip = false; +Vue.prototype.isConnected = false; // ws是否已经连接; +Vue.prototype.heartbeatInterval = null; // 心跳; +Vue.prototype.heartbeatTimeout =20000; // ws20秒执行一次 + App.mpType = "app"; // 引入全局uView diff --git a/manifest.json b/manifest.json index c1782a1..8157569 100644 --- a/manifest.json +++ b/manifest.json @@ -2,8 +2,8 @@ "name" : "瑜伽汇", "appid" : "__UNI__B6E0086", "description" : "瑜伽汇", - "versionName" : "1.0.16", - "versionCode" : 1016, + "versionName" : "1.0.17", + "versionCode" : 1017, "transformPx" : false, "app-plus" : { "flexible" : true, diff --git a/pages/cart/cart.vue b/pages/cart/cart.vue index fc0525e..71a555b 100644 --- a/pages/cart/cart.vue +++ b/pages/cart/cart.vue @@ -143,7 +143,7 @@ + + diff --git a/pages/chat/groupchat.vue b/pages/chat/groupchat.vue index d1f6572..d0b587f 100644 --- a/pages/chat/groupchat.vue +++ b/pages/chat/groupchat.vue @@ -90,29 +90,36 @@ {{item.fromname}} - 已读 - {{item.readedCount?(2-item.readedCount):2}}未读 + + 已读{{item.read?item.read.length:0}} + 未读{{item.read?3-item.read.length:3}} + + {{item.content}} - 已读 - {{item.readedCount?(2-item.readedCount):2}}未读 + + 已读{{item.read?item.read.length:0}} + 未读{{item.read?3-item.read.length:3}} + - 已读 - {{item.readedCount?(2-item.readedCount):2}}未读 + + 已读{{item.read?item.read.length:0}} + 未读{{item.read?3-item.read.length:3}} + - 已读 - {{item.readedCount?(2-item.readedCount):2}}未读 - 已读 - {{item.readedCount?(2-item.readedCount):2}}未读 + + 已读{{item.read?item.read.length:0}} + 未读{{item.read?3-item.read.length:3}} + {{item.time}}″ @@ -122,8 +129,10 @@ - 已读 - {{item.readedCount?(2-item.readedCount):2}}未读 + + 已读{{item.read?item.read.length:0}} + 未读{{item.read?3-item.read.length:3}} + 订单咨询 @@ -199,23 +208,23 @@ - + - - {{info.teachername||"教练"}} + + {{info.instructorname||"教练"}} - - {{info.friendname||"客服"}} + + {{info.customername||"客服"}} - - {{info.showNickName||"咨询用户"}} + + {{info.ownername||"咨询用户"}} @@ -241,6 +250,31 @@ + + + + + + + 已读({{readinfo.read.length}}) + 未读({{readinfo.noread.length}}) + + + + {{value.name}} + {{value.time}} + + + + + {{value.name}} + + + + + + + @@ -314,10 +348,9 @@ oldTime: new Date(), inputh: '90', ifaudio:false, // 是否音频 - socketTask: null, // WebSocket实例 - isConnected: false, // WebSocket连接状态 - heartbeatInterval: null, // 心跳包20秒连接一次 - heartbeatTimeout: 20000, // 心跳间隔时间,例如每20秒发送一次 + // isConnected: false, // WebSocket连接状态 + // heartbeatInterval: null, // 心跳包20秒连接一次 + // heartbeatTimeout: 20000, // 心跳间隔时间,例如每20秒发送一次 // 是否需要发送 商品,课程,订单 ifsend: false, sendinfo:{ @@ -332,6 +365,11 @@ // isCourse: 0, // quantity:1, // spData:{"颜色":"绿","尺寸":"80"} + }, + ifread:true, + readinfo:{ + read:[], + noread:[] } } }, @@ -341,10 +379,11 @@ this.userName=user.nickName?user.nickName:""; this.userid=user.userid?user.userid:""; this.userheadimg=user.avatar?user.avatar:require("@/static/image/girl.png"); + if(options.data){ // 会话信息 this.info=JSON.parse(decodeURIComponent(options.data)); - console.log("chat",this.info) + console.log("groupchat",this.info) // 会话标题 var title = this.info.chatName; uni.setNavigationBarTitle({ @@ -361,37 +400,30 @@ this.sendinfo=null; this.$forceUpdate(); } + } + }, onShow() { + // 先获取聊天记录缓存 this.getchatstore(); // 获取客服 和 教练 头像和名称 this.getrwinfo(); + var that=this; // 跳转到最后一条数据 与前面的:id进行对照 setTimeout(() => { - console.log("onShow") - this.screendo(this.unshiftmsg.length - 1); - }, 100); + that.screendo(that.unshiftmsg.length - 1); + if(!that.isConnected){ + // 重新连接socket + that.reconnect(); + } + }, 500); + + this.getGroupInfo(this.info.groupId); - // 如果心跳包在发送,先停止,再启动 - if(this.heartbeatInterval){ - clearInterval(this.heartbeatInterval); // 停止心跳包发送 - } - }, - onBackPress(options) { - if (options.from === 'backbutton') { - // 来自顶部菜单的返回按钮 - // 在这里处理你的逻辑 - console.log('返回按钮被点击'); - // this.closeWebSocket(); - // uni.onSocketClose(function (res) { - // console.log('WebSocket 已关闭!'); - // }); - return false; - } }, //点击导航栏 buttons 时触发 添加任务 onNavigationBarButtonTap: async function(e) { @@ -399,42 +431,214 @@ if (index === 0) { this.$refs.popup.open("right"); } - }, - beforeDestroy() { - console.log('界面关闭socket,beforeDestroy'); - // 在组件销毁前,确保关闭 WebSocket 连接 - // this.closeWebSocket(); - // clearInterval(this.heartbeatInterval); // 停止心跳包发送 }, methods: { + // 定时心跳包 + startHeartbeat() { + console.log("startHeartbeat") + var that=this; + this.heartbeatInterval = setInterval(() => { + if(this.isConnected){ + uni.sendSocketMessage({ + data: JSON.stringify({ + 'cmd': 1,//心跳 + 'data': { + 'accessToken':uni.getStorageSync("token") + }, + }), // 发送心跳包数据, + success(re) { + console.log(re); + console.log('消息发送成功!') + }, + fail(err) { + console.log(err); + console.log('消息发送失败!'); + that.reconnect(); + } + }); + } + }, this.heartbeatTimeout); + }, + // 开始重连 + reconnect () { + if (!this.isConnected) { + clearTimeout(this.heartbeatInterval); + this.heartbeatInterval = setTimeout(() => { + console.log('开始重连...'); + this.socketinit(); + },this.heartbeatTimeout); + } + }, + // ws接收消息 + socketinit(){ + var that = this; + if (!this.isConnected) { + uni.connectSocket({ + url: "wss://www.sanduolantoyoga.com/yoga-imserver/", + header: { + // 'content-type': 'application/json', + Authorization: uni.getStorageSync("token"), + }, + success: (res) => { + console.log(res, 'socket连接成功success'); + // 获取当前聊天中的minId 拉取离线信息 + that.getReadedId(); + }, + fail: (res) => { + console.log(res, 'socket连接失败') + }, + complete: (res) => { + console.log(res,'socket连接成功complete'); + } + }); + uni.onSocketOpen(res => { + console.log('WebSocket连接已打开!'); + that.isConnected = true; + // 发送登录心跳包 + uni.sendSocketMessage({ + data: JSON.stringify({ + "cmd": 0,//心跳 + "data": { + "accessToken":uni.getStorageSync("token"), + }, + }), // 发送心跳包数据 // 发送的消息内容 + success(re) { + console.log(re); + console.log('消息发送成功!') + }, + fail(err) { + console.log(err); + console.log('消息发送失败!') + } + }); + // 发送心跳包 + this.startHeartbeat(); + }); + uni.onSocketClose(res => { + console.log('WebSocket连接已关闭!'); + this.isConnected = false; + this.$forceUpdate(); + // 重新连接socket + this.reconnect(); + }); + uni.onSocketError(err => { + console.error('WebSocket连接打开失败,请检查:', err); + this.isConnected = false; + this.$forceUpdate(); + // 重新连接socket + this.reconnect(); + }); + uni.onSocketMessage(res => { + console.log('收到WebSocket服务器消息:'); + if(res.data){ + let data=JSON.parse(res.data); + console.log("onSocketMessage",data); + if(data.cmd==4){ + // 群聊 + if(data.data){ + data=data.data; + // 是此群聊发送来的消息 + if(data.groupId==this.info.groupId){ + // 是否已经加入聊天记录 + if(this.ifadd(data.id)){ + // 加入聊天记录 + // 消息类型 0:文字 1:图片 2:文件 3:语音 4:视频 5 订单 6 商品 10, "撤回" 11, "已读 "12, "消息已读回执 " 30,"加载中标记" + if(data.type==0||data.type==1||data.type==2||data.type==3||data.type==4||data.type==5||data.type==6){ + this.getMsgSender(data); + // 已读操作 + this.readed(); + } + else{ + // 10, "撤回" 11, "已读 " 12, "消息已读回执 " 30,"加载中标记" + } + } + // 10, "撤回" 11, "已读 " 12, "消息已读回执 " 30,"加载中标记" + if(data.type==12){ + // 已读操作 + this.updateRead(data); + } + } + } + + } + } + }); + } + }, + + // 获取群信息 + async getGroupInfo(id) { + const {data: res} = await uni.$http.get('/api/group/find/'+id); + if(res.data){ + var data = res.data; + } + }, + // 获取客服和教练信息 async getrwinfo(){ // 客服 - const {data: res} = await uni.$http.get("/api/friend/find/"+this.info.friendId); - if(res.data){ - var data=res.data; - this.info.friendname=data.nickName?data.nickName:"客服"; - this.info.friendimg=data.headImage?data.headImage:require("@/static/image/kfr.png"); + if(this.userid==this.info.customerService){ + this.info.customername=this.userName; + this.info.customerimg=this.userheadimg; this.$forceUpdate(); } else{ - this.info.friendname="客服"; - this.info.friendimg=require("@/static/image/kfr.png"); - this.$forceUpdate(); + const {data: res} = await uni.$http.get("/api/friend/find/"+this.info.customerService); + if(res.data){ + var data=res.data; + this.info.customername=data.nickName?data.nickName:"客服"; + this.info.customerimg=data.headImage?data.headImage:require("@/static/image/kfr.png"); + this.$forceUpdate(); + } + else{ + this.info.customername="客服"; + this.info.customerimg=require("@/static/image/kfr.png"); + this.$forceUpdate(); + } } + // 教练 - const {data: res1} = await uni.$http.get("/api/friend/find/"+this.info.teacherId); - if(res1.data){ - var data=res1.data; - this.info.teachername=data.nickName?data.nickName:"教练"; - this.info.teacherimg=data.headImage?data.headImage:require("@/static/image/jltx.png"); + if(this.userid==this.info.instructor){ + this.info.instructorname=this.userName; + this.info.instructorimg=this.userheadimg; this.$forceUpdate(); } else{ - this.info.teachername="教练"; - this.info.teacherimg=require("@/static/image/jltx.png"); + const {data: res1} = await uni.$http.get("/api/friend/find/"+this.info.instructor); + if(res1.data){ + var data=res1.data; + this.info.instructorname=data.nickName?data.nickName:"教练"; + this.info.instructorimg=data.headImage?data.headImage:require("@/static/image/jltx.png"); + this.$forceUpdate(); + } + else{ + this.info.instructorname="教练"; + this.info.instructorimg=require("@/static/image/jltx.png"); + this.$forceUpdate(); + } + } + + // 咨询用户 + if(this.userid==this.info.ownerId){ + this.info.ownername=this.userName; + this.info.ownerimg=this.userheadimg; this.$forceUpdate(); } + else{ + const {data: res2} = await uni.$http.get("/api/friend/find/"+this.info.ownerId); + if(res2.data){ + var data=res2.data; + this.info.ownername=data.nickName?data.nickName:"咨询用户"; + this.info.ownerimg=data.headImage?data.headImage:require("@/static/image/jltx.png"); + this.$forceUpdate(); + } + else{ + this.info.ownername="咨询用户"; + this.info.ownerimg=require("@/static/image/jltx.png"); + this.$forceUpdate(); + } + } + }, gotoDetail(item){ var send=item.send; @@ -582,6 +786,8 @@ that.screendo(that.unshiftmsg.length-1); }, 100); } + // 已读操作 + this.readed(); } catch(err){ console.log(err); @@ -609,121 +815,6 @@ }); return ret; }, - // 定时心跳包 - startHeartbeat() { - console.log("startHeartbeat") - this.heartbeatInterval = setInterval(() => { - if (this.socketTask) { - this.socketTask.send({ - data: JSON.stringify({ - 'cmd': 1,//心跳 - 'data': { - 'accessToken':uni.getStorageSync("token") - }, - }) // 发送心跳包数据 - }); - } - }, this.heartbeatTimeout); - }, - // 关闭WebSocket连接 - closeWebSocket() { - if (this.socket) { - uni.closeSocket(); - this.socket = null; - this.isConnected = false; - } - }, - // ws接收消息 - socketinit(){ - var that = this; - if (!this.isConnected) { - this.socketTask=uni.connectSocket({ - url: "wss://www.sanduolantoyoga.com/yoga-imserver/", - header: { - // 'content-type': 'application/json', - Authorization: uni.getStorageSync("token"), - }, - success: (res) => { - console.log(res, 'socket连接成功success'); - // 获取当前聊天中的minId 拉取离线信息 - that.getReadedId(); - }, - fail: (res) => { - console.log(res, 'socket连接失败') - }, - complete: (res) => { - console.log(res,'socket连接成功complete'); - } - }); - uni.onSocketOpen(res => { - console.log('WebSocket连接已打开!'); - that.isConnected = true; - // 发送登录心跳包 - uni.sendSocketMessage({ - data: JSON.stringify({ - "cmd": 0,//心跳 - "data": { - "accessToken":uni.getStorageSync("token"), - }, - }), // 发送心跳包数据 // 发送的消息内容 - success(re) { - console.log(re); - console.log('消息发送成功!') - }, - fail(err) { - console.log(err); - console.log('消息发送失败!') - } - }); - // 发送心跳包 - this.startHeartbeat(); - }); - uni.onSocketMessage(res => { - console.log('收到WebSocket服务器消息:'); - if(res.data){ - let data=JSON.parse(res.data); - console.log(data); - if(data.cmd==4){ - // 群聊 - if(data.data){ - data=data.data; - - // 是此群聊发送来的消息 - if(data.groupId==this.info.groupId){ - if(this.ifadd(data.id)){ - // 加入聊天记录 - // 消息类型 0:文字 1:图片 2:文件 3:语音 4:视频 5 订单 6 商品 10, "撤回" 11, "已读 "12, "消息已读回执 " 30,"加载中标记" - if(data.type==0||data.type==1||data.type==2||data.type==3||data.type==4||data.type==5||data.type==6){ - this.getMsgSender(data); - // 已读操作 - this.readed(); - } - else{ - // 10, "撤回" 11, "已读 " 12, "消息已读回执 " 30,"加载中标记" - } - } - // 10, "撤回" 11, "已读 " 12, "消息已读回执 " 30,"加载中标记" - if(data.type==12){ - // 已读操作 - this.updateRead(data); - } - } - } - - } - } - }); - uni.onSocketClose(res => { - console.log('WebSocket连接已关闭!'); - that.isConnected = false; - clearInterval(that.heartbeatInterval); // 停止心跳包发送 - }); - uni.onSocketError(err => { - console.error('WebSocket连接打开失败,请检查:', err); - clearInterval(that.heartbeatInterval); // 停止心跳包发送 - }); - } - }, // 获取发送信息人信息 async getMsgSender(data){ var nickName="匿名"; @@ -740,7 +831,6 @@ } }, async msgMerge(data,nickName,headImage){ - if(data.type==0){ data.content=decodeURIComponent(data.content); } @@ -925,11 +1015,6 @@ this.unshiftmsg.unshift(mdata); } }); - // // 跳转到加载数据的第一条 与前面的:id进行对照 - // setTimeout(() => { - // that.screendo(gotonum -1); - // }, 100); - // 跳转到最后一条数据 与前面的:id进行对照 setTimeout(() => { that.screendo(that.unshiftmsg.length-1); }, 100); @@ -957,11 +1042,10 @@ sort:"groupchat" }; this.updateChatList(chatlastinfo); - - // 已读操作 - this.readed(); } // } + // 已读操作 + this.readed(); }, screendo(scrindex){ @@ -1320,6 +1404,9 @@ friendId: this.info.friendId, // 客服userid teacherId: this.info.teacherId?this.info.teacherId:this.info.instructor, // 教练userid fromuser: this.info.friendId, + customerService: this.info.customerService, + instructor: this.info.instructor, + ownerId: this.info.ownerId, img: this.info.chatAvatar, sort:"groupchat", send:this.sendinfo @@ -1353,7 +1440,10 @@ chatlist.forEach((cell,i)=>{ if(cell.id==this.info.chatId){ ifexist++; - chatlist[i]=chatlastinfo; + chatlist[i].content=chatlastinfo.content; + chatlist[i].datetime=chatlastinfo.datetime; + chatlist[i].fromuser=chatlastinfo.fromuser; + chatlist[i].type=chatlastinfo.type; } }); if(ifexist==0){ @@ -1371,12 +1461,25 @@ }, // 更新是否已读 updateRead(item){ - console.log(this.info) + console.log("updateRead") this.unshiftmsg.forEach((cell,index)=>{ if(cell.id==item.id){ this.unshiftmsg[index].readedCount=item.readedCount; - if(item.readedCount>=2){ - this.unshiftmsg[index].ifread=true; + var read={ + readedId:item.readedId, + readTime:new Date() + } + if(this.unshiftmsg[index].read){ + let tmp = this.unshiftmsg[index].read.some(val => { + return val.readedId == item.readedId; + }); + if(!tmp){ + this.unshiftmsg[index].read.push(read); + } + } + else{ + this.unshiftmsg[index].read=[]; + this.unshiftmsg[index].read.push(read); } this.$forceUpdate(); } @@ -1400,6 +1503,147 @@ this.unshiftmsg[index]["headimg"]= require("@/static/image/girl.png"); this.$forceUpdate(); }, + + // 打开未读 + openNoRead(item){ + this.ifread=false; + this.$forceUpdate(); + this.readinfo.read=[]; + this.readinfo.noread=[]; + // 已读人员列表 + if(item.read&&item.read.length>0){ + item.read.forEach(cell=>{ + if(cell.readedId==this.info.customerService){ + this.readinfo.read.push({ + id:cell.readedId, + name:this.info.customername, + time:this.changeTime(cell.readTime) + }) + } + else if(cell.readedId==this.info.instructor){ + this.readinfo.read.push({ + id:cell.readedId, + name:this.info.instructorname, + time:this.changeTime(cell.readTime) + }) + } + else if(cell.readedId==this.info.ownerId){ + this.readinfo.read.push({ + id:cell.readedId, + name:this.info.ownername, + time:this.changeTime(cell.readTime) + }) + } + }); + + } + // 未读人员列表 + var that=this; + let tmp = this.readinfo.read.some(val => { + return val.id == that.info.customerService; + }); + if(!tmp){ + this.readinfo.noread.push({ + id:this.info.customerService, + name:this.info.customername + }) + } + tmp = this.readinfo.read.some(val => { + return val.id == that.info.instructor; + }); + if(!tmp){ + this.readinfo.noread.push({ + id:this.info.instructor, + name:this.info.instructorname + }) + } + + tmp = this.readinfo.read.some(val => { + return val.id == that.info.ownerId; + }); + if(!tmp){ + this.readinfo.noread.push({ + id:this.info.ownerId, + name:this.info.ownername + }) + } + this.$refs.popupRead.open("right"); + }, + // 打开已读 + openRead(item){ + this.ifread=true; + this.$forceUpdate(); + this.readinfo.read=[]; + this.readinfo.noread=[]; + // 已读人员列表 + if(item.read&&item.read.length>0){ + item.read.forEach(cell=>{ + if(cell.readedId==this.info.customerService){ + this.readinfo.read.push({ + id:cell.readedId, + name:this.info.customername, + time:this.changeTime(cell.readTime) + }) + } + else if(cell.readedId==this.info.instructor){ + this.readinfo.read.push({ + id:cell.readedId, + name:this.info.instructorname, + time:this.changeTime(cell.readTime) + }) + } + else if(cell.readedId==this.info.ownerId){ + this.readinfo.read.push({ + id:cell.readedId, + name:this.info.ownername, + time:this.changeTime(cell.readTime) + }) + } + }); + + } + // 未读人员列表 + var that=this; + let tmp = this.readinfo.read.some(val => { + return val.id == that.info.customerService; + }); + if(!tmp){ + this.readinfo.noread.push({ + id:this.info.customerService, + name:this.info.customername + }) + } + tmp = this.readinfo.read.some(val => { + return val.id == that.info.instructor; + }); + if(!tmp){ + this.readinfo.noread.push({ + id:this.info.instructor, + name:this.info.instructorname + }) + } + + tmp = this.readinfo.read.some(val => { + return val.id == that.info.ownerId; + }); + if(!tmp){ + this.readinfo.noread.push({ + id:this.info.ownerId, + name:this.info.ownername + }) + } + this.$refs.popupRead.open("right"); + }, + qhrd(type){ + if(type==1){ + this.ifread=true; + this.$forceUpdate(); + } + else{ + this.ifread=false; + this.$forceUpdate(); + } + }, } } @@ -1723,6 +1967,12 @@ .msg-right { flex-direction: row-reverse; + .rcon{ + display: flex; + flex-direction: column; + justify-content: flex-end; + align-items: flex-end; + } .read{ font-size: 24rpx; color: #888; @@ -2066,6 +2316,51 @@ box-sizing: border-box; padding: 0rpx 20rpx; } + .qhbtn{ + width: 100%; + display: flex; + flex-direction: row; + .btn{ + width: 120rpx; + height: 60rpx; + border-radius: 20rpx; + background-color: #eee; + color: #000; + font-size: 26rpx; + display: flex; + align-items: center; + justify-content: center; + margin-right: 16rpx; + margin-top: 16rpx; + } + .cur{ + background-color: #00a89b; + color: #fff; + } + } + .readlist{ + display: flex; + flex-wrap: wrap; + padding: 20rpx 0 0 10rpx ; + } + .readcell{ + display: flex; + justify-content: space-between; + width: 100%; + padding: 16rpx 0; + border-bottom: 1rpx solid #eee; + .readtime{ + font-size: 24rpx; + color: #888; + } + .readname{ + font-size: 26rpx; + color: #33383c; + display: flex; + flex: 1; + } + } + .chatlist{ display: flex; flex-wrap: wrap; diff --git a/pages/chat/groupchat0.vue b/pages/chat/groupchat0.vue index 6919b6a..20ec245 100644 --- a/pages/chat/groupchat0.vue +++ b/pages/chat/groupchat0.vue @@ -212,11 +212,6 @@ return false; } }, - beforeDestroy() { - console.log('界面关闭socket,beforeDestroy'); - // 在组件销毁前,确保关闭 WebSocket 连接 - this.closeWebSocket(); - }, methods: { gotoInfo(item){ var data=encodeURIComponent(JSON.stringify(item)); diff --git a/pages/chat/groupchat3.vue b/pages/chat/groupchat3.vue new file mode 100644 index 0000000..a2c99cb --- /dev/null +++ b/pages/chat/groupchat3.vue @@ -0,0 +1,2189 @@ + + + + + diff --git a/pages/index/index.vue b/pages/index/index.vue index 8e50656..6657819 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -85,7 +85,7 @@ + + diff --git a/pages/product/cdetail.vue b/pages/product/cdetail.vue index 60ec3d5..fb7e17f 100644 --- a/pages/product/cdetail.vue +++ b/pages/product/cdetail.vue @@ -748,6 +748,7 @@ reason: data.reason, customerService: data.customerService, instructor: data.instructor, + ownerId: data.ownerId, productId: data.productId, productName: data.productName, sendinfo:{ diff --git a/pages/user/user.vue b/pages/user/user.vue index f6fda12..ec6af5d 100644 --- a/pages/user/user.vue +++ b/pages/user/user.vue @@ -177,7 +177,7 @@