<template>
<view class="chat">
<scroll-view
:style="{ height: `${windowHeight - inputHeight}rpx` }"
id="scrollview"
scroll-y="true"
:scroll-top="scrollTop"
class="scroll-view"
>
<!-- 聊天主体 -->
<view id="msglistview" class="chat-body">
<!-- 聊天记录 -->
<view v-for="(item, index) in msgList" :key="index">
<!-- 自己发的消息 -->
<view class="item self" v-if="item.sendId === nickName">
<!-- 文字内容 -->
<view
class="content right"
@click="toAnotherWeixinPro(item.message)"
>
{{ item.message }}
</view>
<!-- 头像 -->
<image class="avatar" :src="item.imgUrl"> </image>
</view>
<!-- 机器人发的消息 -->
<view class="item Ai" v-else>
<!-- 头像 -->
<image class="avatar" :src="item.imgUrl"> </image>
<!-- 文字内容 -->
<view class="sendContent">
<view class="sendName">{{ item.sendId }}</view>
<view class="content" @click="toAnotherWeixinPro(item.message)">
{{ item.message }}
</view>
</view>
</view>
<view v-if="item.types === 'SYS'" class="time">{{item.sendTime}}</view>
</view>
</view>
</scroll-view>
<!-- 底部消息发送栏 -->
<!-- 用来占位,防止聊天消息被发送框遮挡 -->
<view class="chat-bottom" :style="{ height: `${inputHeight}rpx` }">
<view class="send-msg" :style="{ bottom: `${keyboardHeight - 60}rpx` }">
<view class="uni-textarea">
<textarea
v-model="chatMsg"
maxlength="300"
confirm-type="send"
@confirm="handleSend"
placeholder="在此输入聊天内容"
:show-confirm-bar="false"
:adjust-position="false"
@linechange="sendHeight"
@focus="focus"
@blur="blur"
auto-height
></textarea>
</view>
<button @click="handleSend" class="send-btn">发送</button>
</view>
</view>
</view>
</template>
<script>
import store from "@/store"
import { userInfo } from "os";
import chat from '@/utils/chat.js'
export default {
data() {
return {
//键盘高度
keyboardHeight: 0,
//底部消息发送高度
bottomHeight: 0,
//滚动距离
scrollTop: 0,
userId: "",
//发送的消息
chatMsg: "",
msgList: [],
socketTask: null,
// 确保websocket是打开状态,初始未打开
is_open_socket: false,
message_itext: "",
imageValue:[]
};
},
updated() {
//页面更新时调用聊天消息定位到最底部
this.scrollToBottom();
},
computed: {
windowHeight() {
return this.rpxTopx(uni.getSystemInfoSync().windowHeight);
},
// 键盘弹起来的高度+发送框高度
inputHeight() {
return this.bottomHeight + this.keyboardHeight;
},
avatar() {
return this.$store.state.user.avatar;
},
nickName() {
return this.$store.state.user.name;
},
},
onLoad() {
uni.onKeyboardHeightChange((res) => {
//这里正常来讲代码直接写
//this.keyboardHeight=this.rpxTopx(res.height)就行了
//但是之前界面ui设计聊天框的高度有点高,为了不让键盘和聊天输入框之间距离差太大所以我改动了一下。
this.keyboardHeight = this.rpxTopx(res.height);
if (this.keyboardHeight < 0) this.keyboardHeight = 0;
});
},
onUnload() {
// uni.offKeyboardHeightChange()
},
// 关闭websocket,必须在实例销毁之前关闭,否则会是underfined错误
beforeDestroy() {
this.closeSocket();
},
mounted() {
// 进入这个页面的时候创建websocket连接,整个页面随时使用
//this.connectSocketInit();
this.socketTask = chat.get()
console.log(this.socketTask,'11111111111111111')
if(this.socketTask){
this.socketTask.onMessage((res) => {
console.log("收到服务器内容333333:" + res.data);
this.msgList.push(JSON.parse(res.data));
});
}
chat.history('获取历史记录')
},
methods: {
toAnotherWeixinPro(path) {
if (path.startsWith("#小程序://")) {
uni.navigateToMiniProgram({
//appId: 'wxc9cf7c95499ee604',
shortLink: path,
extraData: {},
success(res) {
// 打开成功
},
});
}
},
// 创建websocket连接方法
connectSocketInit() {
// 创建一个this.socketTask对象,发送、接收、关闭socket都由这个对象操作
this.socketTask = uni.connectSocket({
// 【非常重要】必须确保你的服务器是成功的
url:
"wss://2728d180b7.yicp.fun/chat/" +
encodeURI(this.$store.state.user.name), // 此处地址最好不要天127.0.0.1,不然手机调试的时候忘记改就会出错
success(data) {
console.log("websocket连接成功");
},
});
// 消息的发送和接收必须在正常连接打开中,才能发送或接收,否则会失败
this.socketTask.onOpen((res) => {
console.log("WebSocket连接正常打开中...");
this.socketTask.send({
data: "获取历史记录",
async success() {
// 同步接收
console.log("消息发送成功");
},
});
this.is_open_socket = true;
});
// 注:只有连接正常打开中 ,才能正常收到消息
this.socketTask.onMessage((res) => {
console.log("收到服务器内容:" + res.data);
this.msgList.push(JSON.parse(res.data));
});
// 这里仅是事件监听,如果socket关闭了会执行
this.socketTask.onClose(() => {
console.log("已经被关闭了");
this.is_open_socket = false;
});
},
// 关闭websocket,离开这个页面的时候执行关闭
closeSocket() {
this.socketTask.close({
success(res) {
this.is_open_socket = false;
console.log("关闭成功", res);
},
fail(err) {
console.log("关闭失败", err);
},
});
},
goback() {
uni.switchTab({
url: "/pages/tutorship/tutorship",
});
},
focus() {
this.scrollToBottom();
},
blur() {
this.scrollToBottom();
},
// px转换成rpx
rpxTopx(px) {
let deviceWidth = uni.getSystemInfoSync().windowWidth;
let rpx = (750 / deviceWidth) * Number(px);
return Math.floor(rpx);
},
// 监视聊天发送栏高度
sendHeight() {
setTimeout(() => {
let query = uni.createSelectorQuery();
query.select(".send-msg").boundingClientRect();
query.exec((res) => {
this.bottomHeight = this.rpxTopx(res[0].height);
});
}, 10);
},
// 滚动至聊天底部
scrollToBottom(e) {
setTimeout(() => {
let query = uni.createSelectorQuery().in(this);
query.select("#scrollview").boundingClientRect();
query.select("#msglistview").boundingClientRect();
query.exec((res) => {
if (res[1].height > res[0].height) {
this.scrollTop = this.rpxTopx(res[1].height - res[0].height);
}
});
}, 15);
},
// 发送消息
handleSend() {
//如果消息不为空
if (!this.chatMsg || !/^\s+$/.test(this.chatMsg)) {
chat.sendMsg(this.chatMsg)
this.chatMsg = "";
this.scrollToBottom();
} else {
this.$modal.showToast("不能发送空白消息");
}
},
// 获取上传状态
select(e){
console.log('选择文件:',e)
},
// 获取上传进度
progress(e){
console.log('上传进度:',e)
},
// 上传成功
success(e){
console.log('上传成功')
},
// 上传失败
fail(e){
console.log('上传失败:',e)
}
},
};
</script>
<style lang="scss" scoped>
$chatContentbgc: #c2dcff;
$sendBtnbgc: #4f7df5;
view,
button,
text,
input,
textarea {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* 聊天消息 */
.chat {
.topTabbar {
width: 100%;
height: 90rpx;
line-height: 90rpx;
display: flex;
margin-top: 80rpx;
justify-content: space-between;
.icon {
margin-left: 20rpx;
}
.text {
margin: auto;
font-size: 16px;
font-weight: 700;
}
.button {
width: 10%;
margin: auto 20rpx auto 0rpx;
}
}
.scroll-view {
::-webkit-scrollbar {
display: none;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
color: transparent;
}
// background-color: orange;
background-color: #f6f6f6;
.chat-body {
display: flex;
flex-direction: column;
padding-top: 23rpx;
// background-color:skyblue;
.time{
text-align: center;
font-size: 26rpx;
}
.self {
justify-content: flex-end;
}
.item {
display: flex;
padding: 23rpx 30rpx;
// background-color: greenyellow;
.right {
background-color: $chatContentbgc;
}
.left {
background-color: #ffffff;
}
// 聊天消息的三角形
.right::after {
position: absolute;
display: inline-block;
content: "";
width: 0;
height: 0;
left: 100%;
top: 10px;
border: 12rpx solid transparent;
border-left: 12rpx solid $chatContentbgc;
}
.left::after {
position: absolute;
display: inline-block;
content: "";
width: 0;
height: 0;
top: 10px;
right: 100%;
border: 12rpx solid transparent;
border-right: 12rpx solid #ffffff;
}
.content {
position: relative;
max-width: 486rpx;
border-radius: 8rpx;
word-wrap: break-word;
padding: 24rpx 24rpx;
margin: 0 24rpx;
border-radius: 5px;
font-size: 32rpx;
font-family: PingFang SC;
font-weight: 500;
color: #333333;
line-height: 42rpx;
}
.avatar {
display: flex;
justify-content: center;
width: 78rpx;
height: 78rpx;
background: $sendBtnbgc;
border-radius: 50rpx;
overflow: hidden;
image {
align-self: center;
}
}
.sendContent {
.sendName{
margin-left: 20rpx;
font-size: 26rpx;
margin-bottom: 10rpx;
}
.content {
background-color: #ffffff;
}
.content::after {
position: absolute;
display: inline-block;
content: "";
width: 0;
height: 0;
top: 10px;
right: 100%;
border: 12rpx solid transparent;
border-right: 12rpx solid #ffffff;
}
}
}
}
}
/* 底部聊天发送栏 */
.chat-bottom {
width: 100%;
height: 100rpx;
background: #f4f5f7;
transition: all 0.1s ease;
.send-msg {
display: flex;
align-items: flex-end;
padding: 16rpx 30rpx;
width: 100%;
min-height: 177rpx;
position: fixed;
bottom: 0;
background: #fff;
transition: all 0.1s ease;
}
.uni-textarea {
padding-bottom: 70rpx;
textarea {
width: 537rpx;
min-height: 75rpx;
max-height: 500rpx;
background: #f1f1f1;
border-radius: 2rpx;
font-size: 32rpx;
font-family: PingFang SC;
color: #333333;
line-height: 74rpx;
padding: 5rpx 8rpx;
text-indent: 30rpx;
}
}
.send-btn {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 76rpx;
margin-left: 25rpx;
width: 120rpx;
height: 75rpx;
background: #ed5a65;
border-radius: 2rpx;
font-size: 28rpx;
font-family: PingFang SC;
font-weight: 500;
color: #ffffff;
line-height: 28rpx;
}
}
}
</style>
08-10
06-11
03-01
6536