573 lines
14 KiB
Vue
573 lines
14 KiB
Vue
<template>
|
|
<view class="chat">
|
|
<view class="bg" @click="onMore(false)">
|
|
<image
|
|
class="bgImg"
|
|
src="https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/HomeBackground.png"
|
|
mode="scaleToFill"
|
|
/>
|
|
</view>
|
|
<view class="Return" @click="onBack">
|
|
<image
|
|
class="ReturnImg"
|
|
src="https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/Return.png"
|
|
mode="scaleToFill"
|
|
/>
|
|
</view>
|
|
<view class="title" @click="onMore(false)">{{ nickname }}</view>
|
|
<!-- 聊天内容 -->
|
|
<view
|
|
class="content"
|
|
@click="onMore(false)"
|
|
:style="{
|
|
bottom:
|
|
MoreStatus || KeyboardHeight != 0 || Elementheight != 0
|
|
? MoreStatus
|
|
? 650 + Elementheight + 'rpx'
|
|
: KeyboardHeight != 0
|
|
? KeyboardHeight + Elementheight + 'rpx'
|
|
: Elementheight + 'rpx'
|
|
: Elementheight + 'rpx',
|
|
}"
|
|
>
|
|
<scroll-view
|
|
show-scrollbar="false"
|
|
scroll-y="true"
|
|
class="scroll"
|
|
refresher-enabled="true"
|
|
refresher-threshold="40"
|
|
@refresherrefresh="onRefresherRefresh"
|
|
lower-threshold="100"
|
|
@scrolltolower="onScrollToLower"
|
|
:refresher-triggered="triggered"
|
|
:scroll-into-view="ElementPositioning"
|
|
@scroll="onScroll"
|
|
>
|
|
<view
|
|
class="chat-card"
|
|
v-for="(item, index) in chatList"
|
|
:key="item.id"
|
|
:id="item.id"
|
|
>
|
|
<view class="chat-time"v-if="checkInterval(item.timestamp)">{{
|
|
TimeFormatting(item.timestamp)
|
|
}}</view>
|
|
<view class="chat-avatar">
|
|
<!-- <textmessage :messagetext="item.payload.text"></textmessage> -->
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
<!-- 输入框组 -->
|
|
<view
|
|
class="inputComponent"
|
|
id:inputComponent
|
|
:style="{
|
|
bottom:
|
|
MoreStatus || KeyboardHeight != 0
|
|
? MoreStatus
|
|
? '650rpx'
|
|
: KeyboardHeight != 0
|
|
? KeyboardHeight + 'rpx'
|
|
: '0'
|
|
: '0',
|
|
}"
|
|
>
|
|
<view class="textareacomponent">
|
|
<textarea
|
|
v-model="content"
|
|
@input="SendInput"
|
|
auto-height
|
|
class="input"
|
|
:maxlength="500"
|
|
cursor-spacing="20"
|
|
@focus="onFocus"
|
|
@blur="onBlur"
|
|
:adjust-position="false"
|
|
></textarea>
|
|
</view>
|
|
<view class="sendComponent">
|
|
<image
|
|
v-if="!ButtonStatus"
|
|
class="MoreImg"
|
|
src="https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/chat_add.png"
|
|
mode="scaleToFill"
|
|
@click="onMore(!MoreStatus)"
|
|
/>
|
|
<button v-if="ButtonStatus" class="send" @click="onSend">发送</button>
|
|
</view>
|
|
</view>
|
|
<!-- 更多消息类型弹窗 -->
|
|
<view
|
|
class="MoreComponent"
|
|
:style="{
|
|
bottom:
|
|
MoreStatus || KeyboardHeight != 0
|
|
? MoreStatus
|
|
? '0'
|
|
: KeyboardHeight != 0
|
|
? '0'
|
|
: KeyboardHeight + 'rpx'
|
|
: '-650rpx',
|
|
}"
|
|
>
|
|
<view class="Morecontent">
|
|
<view class="MoreList" v-for="(item, index) in popUpList" :key="index">
|
|
<view class="MoreItem" @click="onMoreItem(item.type)">
|
|
<image class="Moreicon" :src="item.icon" mode="scaleToFill" />
|
|
<text class="MoreName">{{ item.name }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<!-- 相关消息事件弹窗 -->
|
|
<view
|
|
class="popUpInvitation"
|
|
@click="onMoreItem(null)"
|
|
:style="{ top: MoreItemStatus == null ? '100vh' : '0' }"
|
|
>
|
|
<view
|
|
class="popUpInvitationContent"
|
|
@click.stop
|
|
:style="{ bottom: MoreItemStatus == null ? '-1000rpx' : '0' }"
|
|
>
|
|
<!-- 更多相关消息组件 -->
|
|
<InvitationComponents
|
|
v-if="MoreItemStatus == 'Invitation'"
|
|
></InvitationComponents>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import textmessage from "./messageComponent/textmessage";
|
|
import InvitationComponents from "./moreMessageComponents/InvitationComponents";
|
|
import { generateId } from "../../../components/ChatId.js";
|
|
import TimeFormatting from "../../../components/TimeFormatting.js";
|
|
import {
|
|
getConversationMessages,
|
|
sendMessage,
|
|
messageRead,
|
|
} from "../../../components/goEasyTool/tool.js";
|
|
import GoEasy from "goeasy";
|
|
export default {
|
|
data() {
|
|
return {
|
|
userId: "", // 对方用户id
|
|
nickname: "", // 对方用户昵称
|
|
triggered: false, // 下拉刷新状态
|
|
avatar: "", // 对方用户头像
|
|
chatList: [], // 聊天记录
|
|
userinfo: {}, // 自己用户信息
|
|
ButtonStatus: false, // 发送按钮状态
|
|
MoreStatus: false, // 更多消息类型弹窗状态
|
|
KeyboardHeight: 0, // 键盘高度
|
|
content: "", // 输入框内容
|
|
MoreItemStatus: null, // 更多消息类型弹窗点击属性
|
|
ioshide: 0, // 隐藏ios键盘
|
|
ElementPositioning: null, // 元素定位
|
|
scrollviewheight: 0, // 滚动视图高度
|
|
Elementheight: 0, // 元素高度
|
|
Scrolling: false, // 滚动状态
|
|
scrollTop: 0, // 滚动高度
|
|
judgescrollTop: false, // 判断滚动高度
|
|
onPage: false, // 是否在页面
|
|
timer: null, // 定时器
|
|
lastTimestamp: null, // 上一次刷新时间戳
|
|
popUpList: [
|
|
{
|
|
name: "邀请",
|
|
icon: "https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/chat_invite.png",
|
|
type: "Invitation",
|
|
},
|
|
], /// 更多消息类型弹窗列表
|
|
};
|
|
},
|
|
onShow() {
|
|
this.onPage = true;
|
|
},
|
|
onHide() {
|
|
this.onPage = false;
|
|
},
|
|
onLoad(options) {
|
|
uni.getStorage({
|
|
key: "userinfo",
|
|
success: (res) => {
|
|
this.userinfo = res;
|
|
},
|
|
});
|
|
this.userId = options.userId;
|
|
this.nickname = options.nickname;
|
|
this.avatar = options.avatar;
|
|
// 获取和对方用户的聊天记录
|
|
getConversationMessages(this.$goeasy, this.userId, null).then((res) => {
|
|
this.chatList = res.map((item) => {
|
|
item.id = generateId();
|
|
return item;
|
|
});
|
|
console.log("获取和对方用户的聊天记录", this.chatList);
|
|
setTimeout(() => {
|
|
this.ElementPositioning = this.chatList[this.chatList.length - 1].id;
|
|
}, 300);
|
|
const query = uni.createSelectorQuery().in(this);
|
|
query
|
|
.select(".inputComponent")
|
|
.boundingClientRect((res) => {
|
|
this.Elementheight = res.height * 2;
|
|
})
|
|
.exec();
|
|
});
|
|
//已读对方的消息
|
|
messageRead(this.$goeasy, this.userId).then((res) => {
|
|
console.log("已读对方的消息");
|
|
});
|
|
this.getIOSDeviceType();
|
|
var im = this.$goeasy.im;
|
|
im.on(GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, this.onPrivateMessageReceived); //监听接受消息
|
|
im.on(GoEasy.IM_EVENT.MESSAGE_READ, this.onMessageRead); //监听已读消息
|
|
|
|
this.getscrollviewheight();
|
|
},
|
|
methods: {
|
|
//时间显示
|
|
checkInterval(timestamp) {
|
|
if (!this.lastTimestamp) {
|
|
this.lastTimestamp = timestamp;
|
|
return true;
|
|
}
|
|
|
|
const timeDiff = timestamp - this.lastTimestamp;
|
|
if (timeDiff >= 300000) {
|
|
// 5 分钟=300000 毫秒
|
|
this.lastTimestamp = timestamp;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
//时间格式化
|
|
TimeFormatting: TimeFormatting,
|
|
//获取容器高度
|
|
getscrollviewheight() {
|
|
const queryheight = uni.createSelectorQuery().in(this);
|
|
queryheight
|
|
.select(".scroll")
|
|
.boundingClientRect((res) => {
|
|
this.scrollviewheight = res.height;
|
|
})
|
|
.exec();
|
|
},
|
|
//滚动事件
|
|
onScroll(event) {
|
|
if (!this.judgescrollTop) {
|
|
this.scrollTop = event.detail.scrollTop;
|
|
this.judgescrollTop = true;
|
|
} else if (this.scrollTop - event.detail.scrollTop > this.scrollviewheight) {
|
|
this.Scrolling = true;
|
|
} else if (this.scrollTop - event.detail.scrollTop < this.scrollviewheight) {
|
|
this.Scrolling = false;
|
|
}
|
|
},
|
|
//监听已读消息
|
|
onMessageRead(message) {
|
|
console.log("已读消息", message);
|
|
},
|
|
//监听接受消息
|
|
onPrivateMessageReceived(message) {
|
|
if (!this.Scrolling) {
|
|
this.ElementPositioning = message.id = generateId();
|
|
this.judgescrollTop = false;
|
|
} else {
|
|
message.id = generateId();
|
|
}
|
|
this.chatList.push(message);
|
|
if (this.onPage) {
|
|
messageRead(this.$goeasy, this.userId).then((res) => {
|
|
console.log("已读对方的消息");
|
|
});
|
|
}
|
|
},
|
|
//发送消息
|
|
onSend() {
|
|
if (this.content != "") {
|
|
sendMessage(
|
|
this.$goeasy,
|
|
this.userId,
|
|
this.content,
|
|
this.avatar,
|
|
this.nickname
|
|
).then((res) => {
|
|
console.log("发送成功", res);
|
|
this.ElementPositioning = res.id = generateId();
|
|
this.chatList.push(res);
|
|
this.judgescrollTop = false;
|
|
});
|
|
this.content = "";
|
|
this.ButtonStatus = false;
|
|
}
|
|
},
|
|
|
|
//ios兼容
|
|
getIOSDeviceType() {
|
|
const systemInfo = uni.getSystemInfoSync();
|
|
const model = systemInfo.model;
|
|
if (/iPhone X|iPhone11|iPhone12|iPhone13|iPhone14/i.test(model)) {
|
|
if (/iPhone X|iPhone XS|iPhone 11 Pro/i.test(model)) {
|
|
this.ioshide = 88;
|
|
} else if (/iPhone 12|iPhone 13|iPhone 14/i.test(model)) {
|
|
this.ioshide = 94;
|
|
}
|
|
}
|
|
},
|
|
|
|
//更多消息类型弹窗事件
|
|
onMore(Status) {
|
|
if (!this.Scrolling) {
|
|
this.ElementPositioning = null;
|
|
setTimeout(() => {
|
|
this.ElementPositioning = this.chatList[this.chatList.length - 1].id;
|
|
}, 100);
|
|
this.judgescrollTop = false;
|
|
}
|
|
this.getscrollviewheight();
|
|
this.MoreStatus = Status;
|
|
const query = uni.createSelectorQuery().in(this);
|
|
query
|
|
.select(".inputComponent")
|
|
.boundingClientRect((res) => {
|
|
this.Elementheight = res.height * 2;
|
|
})
|
|
.exec();
|
|
},
|
|
//更多消息类型弹窗点击事件
|
|
onMoreItem(type) {
|
|
this.MoreItemStatus = type;
|
|
},
|
|
// 获取键盘高度
|
|
onFocus(event) {
|
|
if (!this.Scrolling) {
|
|
this.ElementPositioning = null;
|
|
setTimeout(() => {
|
|
this.ElementPositioning = this.chatList[this.chatList.length - 1].id;
|
|
}, 100);
|
|
this.judgescrollTop = false;
|
|
}
|
|
this.getscrollviewheight();
|
|
this.KeyboardHeight = event.detail.height * 2 - this.ioshide;
|
|
const query = uni.createSelectorQuery().in(this);
|
|
query
|
|
.select(".inputComponent")
|
|
.boundingClientRect((res) => {
|
|
this.Elementheight = res.height * 2;
|
|
})
|
|
.exec();
|
|
},
|
|
//键盘消失
|
|
onBlur(event) {
|
|
this.KeyboardHeight = 0;
|
|
const query = uni.createSelectorQuery().in(this);
|
|
query
|
|
.select(".inputComponent")
|
|
.boundingClientRect((res) => {
|
|
this.Elementheight = res.height * 2;
|
|
})
|
|
.exec();
|
|
this.getscrollviewheight();
|
|
},
|
|
//按钮切换
|
|
SendInput(event) {
|
|
const query = uni.createSelectorQuery().in(this);
|
|
query
|
|
.select(".inputComponent")
|
|
.boundingClientRect((res) => {
|
|
this.Elementheight = res.height * 2;
|
|
})
|
|
.exec();
|
|
if (event.target.value != "") {
|
|
this.ButtonStatus = true;
|
|
} else {
|
|
this.ButtonStatus = false;
|
|
}
|
|
},
|
|
// 返回上一页
|
|
onBack() {
|
|
this.onPage = false;
|
|
wx.navigateBack({
|
|
delta: 1,
|
|
});
|
|
},
|
|
},
|
|
components: {
|
|
textmessage,
|
|
InvitationComponents,
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
.bg {
|
|
position: fixed;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
top: 0;
|
|
z-index: -1;
|
|
}
|
|
.bgImg {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
.Return {
|
|
position: fixed;
|
|
left: 35rpx;
|
|
top: 120rpx;
|
|
width: 46rpx;
|
|
height: 46rpx;
|
|
z-index: 1;
|
|
}
|
|
.title {
|
|
position: fixed;
|
|
top: 120rpx;
|
|
left: 325rpx;
|
|
font-size: 34rpx;
|
|
color: #100e0f;
|
|
font-weight: bold;
|
|
z-index: 1;
|
|
}
|
|
.ReturnImg {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
.content {
|
|
position: absolute;
|
|
top: 200rpx;
|
|
left: 0rpx;
|
|
right: 0rpx;
|
|
}
|
|
.scroll {
|
|
width: 96%;
|
|
height: 100%;
|
|
padding: 0% 2% 0% 2%;
|
|
}
|
|
.inputComponent {
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
height: auto;
|
|
background-color: #f0f0f0;
|
|
padding: 15rpx 15rpx 37.5rpx 15rpx;
|
|
display: flex;
|
|
align-items: flex-end;
|
|
transition: bottom 0.1s ease;
|
|
}
|
|
.chat-card {
|
|
width: 100%;
|
|
height: auto;
|
|
margin-bottom: 20rpx;
|
|
margin-top: 20rpx;
|
|
padding: 10rpx;
|
|
}
|
|
.chat-time {
|
|
width: 100%;
|
|
height: 50rpx;
|
|
text-align: center;
|
|
font-size: 24rpx;
|
|
color: #999999;
|
|
line-height: 50rpx;
|
|
margin-top: 20rpx;
|
|
margin-bottom: 20rpx;
|
|
background-color: #00000000;
|
|
}
|
|
.chat-avatar {
|
|
width: 100%;
|
|
height: auto;
|
|
}
|
|
.textareacomponent {
|
|
width: 570rpx;
|
|
height: auto;
|
|
}
|
|
.input {
|
|
width: 95%;
|
|
background-color: #ffffff;
|
|
min-height: 60rpx;
|
|
max-height: 200rpx;
|
|
border-radius: 10rpx;
|
|
padding: 10rpx;
|
|
overflow-wrap: break-word;
|
|
margin-left: 30rpx;
|
|
}
|
|
.sendComponent {
|
|
margin-left: 40rpx;
|
|
}
|
|
.send {
|
|
width: 100rpx;
|
|
height: 75rpx;
|
|
background-color: #539c00;
|
|
border-radius: 10rpx;
|
|
color: #ffffff;
|
|
font-size: 20rpx;
|
|
text-align: center;
|
|
line-height: 75rpx;
|
|
}
|
|
.MoreImg {
|
|
margin-left: 20rpx;
|
|
height: 80rpx;
|
|
width: 80rpx;
|
|
margin-bottom: -10rpx;
|
|
border-radius: 50rpx;
|
|
}
|
|
.MoreComponent {
|
|
position: fixed;
|
|
left: 0;
|
|
right: 0;
|
|
height: 650rpx;
|
|
transition: bottom 0.1s ease;
|
|
background-color: #ffffff;
|
|
}
|
|
.Morecontent {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
align-content: baseline;
|
|
flex-wrap: wrap;
|
|
}
|
|
.MoreList {
|
|
width: 150rpx;
|
|
height: 150rpx;
|
|
background-color: #f1f1f1;
|
|
border-radius: 20rpx;
|
|
margin: 18.75rpx;
|
|
}
|
|
.MoreItem {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
.Moreicon {
|
|
width: 80rpx;
|
|
height: 80rpx;
|
|
}
|
|
.popUpInvitation {
|
|
position: fixed;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
transition: top 0.1s ease;
|
|
}
|
|
.popUpInvitationContent {
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
height: 1000rpx;
|
|
transition: bottom 0.1s ease;
|
|
background-color: #ffffff;
|
|
border-top-left-radius: 40rpx;
|
|
border-top-right-radius: 40rpx;
|
|
}
|
|
</style>
|