微信小程序聊天
<!--pages/contact/contact.wxml-->
<view>
<scroll-view scroll-y scroll-into-view='{{toView}}' style='height: {{scrollHeight}};'>
<!-- <view class='scrollMsg'> -->
<block wx:key 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: 10rpx;' src='https://cdn.pixabay.com/photo/2020/02/10/12/47/girl-4836394__340.jpg'></image>
</view>
<view style='width: 4vw; height: 11vw; margin-left: 0.5vw; display: flex; align-items: center; z-index: 9;'>
<view class="triangle_border_left"></view>
</view>
<view class='leftMsg'>{{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'>{{item.content}}</view>
<view style='width: 4vw; height: 11vw; margin-right: 0.5vw; display: flex; align-items: center; z-index: 9;'>
<view class="triangle_border_right"></view>
</view>
<view style='width: 11vw; height: 11vw;'>
<image style='width: 11vw; height: 11vw; border-radius: 10rpx;' src='https://cdn.pixabay.com/photo/2021/09/24/10/00/chick-6652163__340.jpg'></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='https://img95.699pic.com/element/40030/6429.png_300.png' mode='widthFix'></image>
<input bindconfirm='sendClick' adjust-position='{{false}}' value='{{inputVal}}' confirm-type='send' bindfocus='focus' bindblur='blur'></input>
</view>
</view>
复制代码
2.小程序页面样式代码所在路径 /pages/contact/contact.wxss>
/* pages/contact/contact.wxss */
page {
background-color: #f1f1f1;
}
.inputRoom {
width: 100vw;
height: 16vw;
border-top: 1px solid #cdcdcd;
background-color: #f1f1f1;
position: fixed;
bottom: 0;
display: flex;
align-items: center;
z-index: 20;
}
input {
width: 76vw;
height: 9.33vw;
background-color: #fff;
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-color: #fff;
margin-left: -1.6vw;
border-radius: 10rpx;
z-index: 10;
}
.rightMsg {
font-size: 35rpx;
color: #444;
line-height: 7vw;
padding: 2vw 2.5vw;
background-color: #96EB6A;
margin-right: -1.6vw;
border-radius: 10rpx;
z-index: 10;
}
/*向左*/
.triangle_border_left {
width: 0;
height: 0;
border-width: 10px 30px 30px 0;
border-style: solid;
border-color: transparent #fff transparent transparent;
/*透明 黄 透明 透明 */
margin: 40px auto;
position: relative;
}
/*向右*/
.triangle_border_right {
width: 0;
height: 0;
border-width: 0px 30px 20px 13px;
border-style: solid;
border-color: transparent transparent transparent #96EB6A;
/*透明 透明 透明 黄*/
margin: 40px auto;
position: relative;
}
复制代码
3.小程序配置文件代码所在路径 /pages/contact/contact.json>
{
"navigationBarTitleText":"柯作客服",
"usingComponents": {
}
}
复制代码
4.小程序业务逻辑代码所在路径 /pages/contact/contact.js>
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 = [{
speaker: 'server',
contentType: 'text',
content: 'Hi,亲爱的小主,终于等到您啦!欢迎来到柯作店铺,很荣幸为您服务。'
},
{
speaker: 'customer',
contentType: 'text',
content: '你高兴的太早了'
}
]
that.setData({
msgList,
inputVal
})
}
Page({
/**
* 页面的初始数据
*/
data: {
scrollHeight: '100vh',
inputBottom: 0
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
//初始化websocket连接
this.chat();
//监听心跳的方法
this.webSocketXin();
//聊天方法
initData(this);
//监听消息
wx.onSocketMessage(res=>{
//追加到消息列表里
msgList.push(JSON.parse(res.data))
inputVal = '';
this.setData({
msgList,
inputVal
});
})
},
//页面卸载时间
onUnload(){
wx.closeSocket();
},
/**
* 获取聚焦
*/
focus: function(e) {
keyHeight = e.detail.height;
this.setData({
scrollHeight: (windowHeight - keyHeight) + 'px'
});
this.setData({
toView: 'msg-' + (msgList.length - 1),
inputBottom: keyHeight + 'px'
})
//计算msg高度
// calScrollHeight(this, keyHeight);
},
//失去聚焦(软键盘消失)
blur: function(e) {
this.setData({
scrollHeight: '100vh',
inputBottom: 0
})
this.setData({
toView: 'msg-' + (msgList.length - 1)
})
},
/**
* 发送点击监听
*/
sendClick: function(e) {
//客户发的信息
let customerMsg = {
uid: 10,
speaker: 'customer',
contentType: 'text',
content: e.detail.value
};
//关闭心跳包
this.webSocketXin(60000, false)
//发送给websocket
wx.sendSocketMessage({
data: JSON.stringify(customerMsg),
success:res=>{
//重启心跳包
this.webSocketXin(40000, true)
}
})
//追加到消息列表里
msgList.push(customerMsg)
inputVal = '';
this.setData({
msgList,
inputVal
});
},
/**
* 退回上一页
*/
toBackClick: function() {
wx.navigateBack({})
},
/**
* websocket
*/
chat(){
//进行连接php的socket
wx.connectSocket({
//wss 协议相当于你要有一个ssl证书,https
//ws 就相当于不实用证书 http
url: 'ws://study.lishuo.net',
success: function () {
console.log('websocket连接成功~')
},
fail: function () {
console.log('websocket连接失败~')
}
})
},
/**
* 监听websocket心跳连接的方法
*/
webSocketXin(time=60000,status=true){
var timing;
if(status == true){
timing = setInterval(function () {
console.log("当前心跳已重新连接");
//循环执行代码
wx.sendSocketMessage({
data: JSON.stringify({
type: 'active'
}),
fail(res) {
//关闭连接
wx.closeSocket();
//提示
wx.showToast({
title: '当前聊天已断开',
icon:'none'
})
clearInterval(timing);
console.log("当前心跳已关闭");
}
});
}, time) //循环时间,注意不要超过1分钟
} else {
//关闭定时器
clearInterval(timing);
console.log("当前心跳已关闭");
}
}
})
复制代码
2.服务端代码(PHP代码)
wechat_websocket.php>
<?php
//创建WebSocket Server对象,监听0.0.0.0:9502端口
$ws = new Swoole\WebSocket\Server('0.0.0.0', 9511);
//监听WebSocket连接打开事件
$ws->on('Open', function ($ws, $request) {
echo $request->fd . '我连接上了';
});
//监听WebSocket消息事件
$ws->on('Message', function ($ws, $frame) {
//把前台传过来的json字符串转成数组
$params = json_decode($frame->data, true);
//判断是否是心跳消息,如果是心跳消息
if (isset($params['type']) && isset($params['type'])=='active'){
echo '这是心跳监听消息';
}else{
//先判断当前用户有没有正在连接
if (isset($params['uid']) && !empty($params['uid'] == 666)) {
//去用户表查询当前用户 fd
$fd = 2;
} else {
$fd = 1;
}
//客服id
$ws->push($fd, json_encode($params, JSON_UNESCAPED_UNICODE));
}
});
//监听WebSocket连接关闭事件
$ws->on('Close', function ($ws, $fd) {
echo "client-{$fd} is closed\n";
});
$ws->start();