![](https://img-blog.csdnimg.cn/f5d6ca65249e4afc95c6b2d0c7800410.png)
1. chat.wxml
<!--pages/contact/contact.wxml-->
<view wx:if="{{loading}}" style="position:absolute; top:45%;left:50%;transform: translate(-50%, -50%);">
<image src="/image/flow.gif" style="width: 100px; height: 100px;"></image>
</view>
<view>
<view style="display: flex; align-items: center;">
<image src="/image/back.png" style="width: 60rpx; height:60rpx; margin-top: 30rpx; margin-left: 10rpx; margin-bottom: 30rpx" bindtap="toBackClick"></image>
<view style="color: white; margin-top: 2rpx;margin-left: 30rpx; font-size: 35rpx; font-weight: 550;">
{{name}}
</view>
</view>
<view style="color: white; text-align: center; margin-bottom: 10rpx">{{time}}</view>
<scroll-view scroll-y scroll-into-view='{{toView}}' style='height: {{scrollHeight}};'>
<!-- <view class='scrollMsg'> -->
<block wx:key="index" wx:for='{{msgList}}' wx:for-index="index">
<!-- 单个消息1 客服发出(左) -->
<view wx:if='{{item.speaker=="server"}}' id='msg-{{index}}' style='display: flex; padding: 2vw 11vw 2vw 2vw;'>
<view style='width: 11vw; height: 11vw;'>
<image style='width: 11vw; height: 11vw; border-radius: 50%;' src='{{avatar_left}}'></image>
</view>
<view style='width: 4vw; height: 11vw; margin-left: 0.5vw; display: flex; align-items: center; z-index: 9;'>
<image style='width: 4vw;' mode='widthFix'></image>
</view>
<view class='leftMsg' style="color:white">{{item.content}}</view>
</view>
<!-- 单个消息2 用户发出(右) -->
<view wx:else id='msg-{{index}}' style='display: flex; justify-content: flex-end; padding: 2vw 2vw 2vw 11vw;'>
<view class='rightMsg' style="color: white">{{item.content}}</view>
<view style='width: 4vw; height: 11vw; margin-right: 0.5vw; display: flex; align-items: center; z-index: 9;'>
<image style='width: 4vw;' mode='widthFix'></image>
</view>
<view style='width: 11vw; height: 11vw;'>
<image style='width: 11vw; height: 11vw; border-radius: 50%;' src='{{avatar_right}}'></image>
</view>
</view>
</block>
<!-- </view> -->
<!-- 占位 -->
<view style='width: 100%; height: 18vw;'></view>
</scroll-view>
<view class='inputRoom' style='bottom: {{inputBottom}}'>
<image style='width: 7vw; margin-left: 3.2vw;' src='../../image/chat-photo.png' mode='widthFix'></image>
<input bindconfirm='sendClick' adjust-position='{{false}}' value='{{inputVal}}' confirm-type='send' style="color: white"></input>
</view>
</view>
2. chat.js
const domain_ws = require('../../utils/domain.js').domain_ws
const domain = require('../../utils/domain.js').domain
var SocketTask = ''
const app = getApp();
var inputVal = '';
var msgList = [];
var windowWidth = wx.getSystemInfoSync().windowWidth;
var windowHeight = wx.getSystemInfoSync().windowHeight;
var keyHeight = 0;
/**
* 初始化数据
*/
function initData(that) {
inputVal = '';
msgList = []
that.setData({
msgList,
inputVal
})
}
Page({
/**
* 页面的初始数据
*/
data: {
scrollHeight: '100vh',
inputBottom: 0,
avatar_left: '',
avatar_right: '',
name: '',
msg: '',
interval: '',
time: '',
loading: true
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
initData(this);
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function() {
var n = 1
var that = this
wx.request({
header: {
'alexmisko-user': wx.getStorageSync('token')
},
url: domain + '/message/user',
data:{
senderId: wx.getStorageSync('userinfo').userId,
receiverId: this.options.userId,
page: 1,
num: 5
},
success(res){
console.log(res)
res.data.data.records.forEach(function(e){
if(n == 1){
that.setData({
time: e.createTime
})
n --;
}
if(e.senderId == wx.getStorageSync('userinfo').userId){
msgList.unshift({
speaker: 'customer',
contentType: 'text',
content: e.message
})
}else{
msgList.unshift({
speaker: 'server',
contentType: 'text',
content: e.message
})
}
that.setData({
msgList,
loading: false
});
})
}
})
console.log(wx.getStorageSync('token'))
this.setData({
avatar_right: wx.getStorageSync('userinfo').avatar,
avatar_left: this.options.avatar,
name: this.options.name
})
SocketTask = wx.connectSocket({
url: domain_ws + '/ws/' + wx.getStorageSync('token'),
success(res){
console.log(res)
}
})
SocketTask.onOpen((res) =>{
console.log('连接打开成功')
this.setData({
interval: setInterval(this.heartbeat, 5000)
})
})
SocketTask.onClose((res) =>{
console.log('连接关闭成功')
})
SocketTask.onError((res) =>{
console.log('连接报错')
})
SocketTask.onMessage((res) =>{
console.log(res)
msgList.push({
speaker: 'server',
contentType: 'text',
content: JSON.parse(res.data).message
})
this.setData({
msgList
})
})
},
heartbeat(){
console.log("发送心跳")
SocketTask.send({
data: JSON.stringify(new this.MsgContent("keepalive", null, null)),
})
},
/**
* 发送点击监听
*/
sendClick: function(e) {
var that = this
var msgContent = new this.MsgContent("word", this.options.userId, e.detail.value)
SocketTask.send({
data: JSON.stringify(msgContent),
success(res){
console.log(res)
msgList.push({
speaker: 'customer',
contentType: 'text',
content: e.detail.value
})
inputVal = '';
that.setData({
msgList,
inputVal
});
}
})
},
/**
* 退回上一页
*/
toBackClick: function() {
wx.navigateBack({})
},
input(e){
this.setData({
msg: e.detail.value
})
},
MsgContent: function(type, receiverId, message){
this.type = type,
this.receiverId = receiverId,
this.message = message
},
onUnload(){
console.log("退出")
// SocketTask.close({
// })
clearInterval(this.data.interval)
}
})
3. chat.wxss
/* pages/contact/contact.wxss */
page {
background-color: black;
}
.inputRoom {
width: 100vw;
height: 16vw;
background-color: black;
position: fixed;
bottom: -10px;
display: flex;
align-items: center;
z-index: 20;
}
input {
width: 76vw;
height: 9.33vw;
background-color: #262626;
border-radius: 40rpx;
margin-left: 2vw;
padding: 0 3vw;
font-size: 28rpx;
color: #444;
}
.leftMsg {
font-size: 35rpx;
color: #444;
line-height: 7vw;
padding: 2vw 2.5vw;
background-image: linear-gradient(to right, #da22ff, #9733ee);
margin-left: -1.6vw;
border-radius: 10rpx;
z-index: 10;
}
.rightMsg {
font-size: 35rpx;
color: #444;
line-height: 7vw;
padding: 2vw 2.5vw;
background-image: linear-gradient(to left, #ec008c, #fc6767);
margin-right: -1.6vw;
border-radius: 10rpx;
z-index: 10;
}