2025-07-18 13:06:06 +08:00
< 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 :
2025-07-25 16:39:52 +08:00
MoreStatus || KeyboardHeight != 0
2025-07-18 13:06:06 +08:00
? MoreStatus
? 650 + Elementheight + 'rpx'
: KeyboardHeight != 0
? KeyboardHeight + Elementheight + 'rpx'
2025-07-25 16:39:52 +08:00
: '10vh'
: '10vh' ,
2025-07-18 13:06:06 +08:00
} "
>
< scroll-view
show - scrollbar = "false"
scroll - y = "true"
class = "scroll"
2025-07-21 22:10:59 +08:00
upper - threshold = "100"
@ scrolltoupper = "onScrollToUpper"
2025-07-18 13:06:06 +08:00
: scroll - into - view = "ElementPositioning"
@ scroll = "onScroll"
>
< view
class = "chat-card"
v - for = "(item, index) in chatList"
: key = "item.id"
: id = "item.id"
>
2025-07-21 22:10:59 +08:00
< view class = "chat-time" v-if = "item.timestampStatus" > {{
2025-07-18 13:06:06 +08:00
TimeFormatting ( item . timestamp )
} } < / view >
< view class = "chat-avatar" >
2025-07-21 22:10:59 +08:00
<!-- 对方消息 -- >
< view class = "oppositeChatNews" v-if = "item.senderId == userId" >
< image class = "chat-avatarImg" :src = "avatar" mode = "scaleToFill" / >
< view class = "oppositesharpCorner" >
2025-07-25 16:39:52 +08:00
< view
class = "oppositeSharpCornercion"
v - if = "item.type == 'text' || item.type == 'audio'"
> < / view >
2025-07-21 22:10:59 +08:00
< / view >
2025-07-25 16:39:52 +08:00
< view
class = "oppositeChatNewsContent"
: style = " {
backgroundColor :
item . type == 'text' || item . type == 'audio' ? '#7bbd0093' : '#ffffff' ,
} "
>
2025-07-21 22:10:59 +08:00
<!-- 消息类型 -- >
2025-07-25 16:39:52 +08:00
<!-- 文字消息 -- >
2025-07-21 22:10:59 +08:00
< textmessage
v - if = "item.type == 'text'"
: messagetext = "item.payload.text"
> < / textmessage >
2025-07-25 16:39:52 +08:00
<!-- 自定义PK消息 -- >
2025-07-21 22:10:59 +08:00
< customPKMessage
v - if = "item.type == 'pk'"
: message = "item.payload"
> < / customPKMessage >
2025-07-25 16:39:52 +08:00
<!-- 图片消息 -- >
< imageMessage
v - if = "item.type == 'image'"
: message = "item.payload"
> < / imageMessage >
<!-- 视频消息 -- >
< videoMessage
v - if = "item.type == 'video'"
: message = "item.payload"
> < / videoMessage >
<!-- 语音消息 -- >
< voiceMessage
v - if = "item.type == 'audio'"
: message = "item.payload"
: senderId = "item.senderId"
: userId = "userinfo.id"
>
< / voiceMessage >
2025-07-21 22:10:59 +08:00
< / view >
< / view >
<!-- 自己消息 -- >
< view class = "myChatNews" v-if = "item.senderId == userinfo.id" >
< image
class = "chat-avatarImg"
: src = "userinfo.headerIcon"
mode = "scaleToFill"
/ >
< view class = "mysharpCorner" >
2025-07-25 16:39:52 +08:00
< view
class = "mySharpCornercion"
v - if = "item.type == 'text' || item.type == 'audio'"
> < / view >
2025-07-21 22:10:59 +08:00
< / view >
2025-07-25 16:39:52 +08:00
< view
class = "myChatNewsContent"
: style = " {
backgroundColor :
item . type == 'text' || item . type == 'audio' ? '#7bbd0093' : '#ffffff' ,
} "
>
2025-07-21 22:10:59 +08:00
<!-- 消息类型 -- >
2025-07-25 16:39:52 +08:00
<!-- 文字消息 -- >
2025-07-21 22:10:59 +08:00
< textmessage
v - if = "item.type == 'text'"
: messagetext = "item.payload.text"
> < / textmessage >
2025-07-25 16:39:52 +08:00
<!-- 自定义PK消息 -- >
2025-07-21 22:10:59 +08:00
< customPKMessage
v - if = "item.type == 'pk'"
: message = "item.payload"
> < / customPKMessage >
2025-07-25 16:39:52 +08:00
<!-- 图片消息 -- >
< imageMessage
v - if = "item.type == 'image'"
: message = "item.payload"
> < / imageMessage >
<!-- 视频消息 -- >
< videoMessage
v - if = "item.type == 'video'"
: message = "item.payload"
> < / videoMessage >
<!-- 语音消息 -- >
< voiceMessage
v - if = "item.type == 'audio'"
: message = "item.payload"
: senderId = "item.senderId"
: userId = "userinfo.id"
: playbackStatus = "playbackStatus"
@ notplayVoice = "notplayVoice"
>
< / voiceMessage >
2025-07-21 22:10:59 +08:00
< / view >
< / view >
2025-07-18 13:06:06 +08:00
< / view >
< / view >
< / scroll-view >
< / view >
<!-- 输入框组 -- >
< view
class = "inputComponent"
id : inputComponent
: style = " {
bottom :
2025-07-21 22:10:59 +08:00
MoreStatus || KeyboardHeight > 300
2025-07-18 13:06:06 +08:00
? MoreStatus
? '650rpx'
2025-07-21 22:10:59 +08:00
: KeyboardHeight > 300
2025-07-18 13:06:06 +08:00
? KeyboardHeight + 'rpx'
: '0'
: '0' ,
} "
>
2025-07-25 16:39:52 +08:00
< view class = "Voice" >
< view class = "MicrophoneImg" v-if = "!voiceStatus" @click="onVoice(!voiceStatus)" >
< image
class = "Microphonepng"
src = "https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/Microphone.png"
mode = "scaleToFill"
/ >
< / view >
< view class = "KeyboardImg" v-if = "voiceStatus" @click="onVoice(!voiceStatus)" >
< image
class = "Keyboardpng"
src = "https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/Keyboard.png"
mode = "scaleToFill"
/ >
< / view >
< / view >
< view class = "textareacomponent" v-if = "voiceStatus" >
< view
class = "VoiceInput"
@ touchstart = "voiceTouchstart"
@ touchend = "voiceTouchend"
@ touchmove = "voiceTouchmove"
@ touchcancel = "voiceTouchcancel"
> 按住 & nbsp ; 说话 < / v i e w
>
< / view >
< view class = "textareacomponent" v-if = "!voiceStatus" >
2025-07-18 13:06:06 +08:00
< textarea
v - model = "content"
@ input = "SendInput"
auto - height
class = "input"
: maxlength = "500"
cursor - spacing = "20"
@ focus = "onFocus"
2025-07-25 16:39:52 +08:00
: focus = "inputfocus"
2025-07-18 13:06:06 +08:00
@ 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 :
2025-07-21 22:10:59 +08:00
MoreStatus || KeyboardHeight > 300
2025-07-18 13:06:06 +08:00
? MoreStatus
? '0'
2025-07-21 22:10:59 +08:00
: KeyboardHeight > 300
2025-07-18 13:06:06 +08:00
? '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' }"
>
2025-07-21 22:10:59 +08:00
<!-- 自定义消息组件 -- >
2025-07-18 13:06:06 +08:00
< InvitationComponents
v - if = "MoreItemStatus == 'Invitation'"
2025-07-21 22:10:59 +08:00
: oppositeId = "userId"
: myId = "userinfo.id"
: avatar = "avatar"
: nickname = "nickname"
@ refreshMessage = "refreshMessage"
2025-07-18 13:06:06 +08:00
> < / InvitationComponents >
< / view >
< / view >
2025-07-25 16:39:52 +08:00
<!-- 语音组件 -- >
< view class = "popUpVoice" : style = "{ top: voicepopUpstart == false ? '100vh' : '0' }" >
< view
class = "popUpvoiceContent"
: style = "{ bottom: voicepopUpstart == false ? '-1000rpx' : '0' }"
>
< view class = "voiceCenter" >
< view class = "gifModule" >
< video
class = "video-player"
src = "https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/Recording.mp4"
: autoplay = "true"
: loop = "true"
: controls = "false"
> < / video >
< / view >
< view
class = "CancelModule"
: style = "{ backgroundColor: voiceCancelOrSend ? '#ebebeb' : '#000000a9' }"
>
取消
< / view >
< view
class = "btnModule"
: style = "{ backgroundColor: !voiceCancelOrSend ? '#ebebeb' : '#000000a9' }"
>
{ { voiceCancelOrSend ? "取消" : "松手发送" } }
< / view >
< / view >
< / view >
< / view >
2025-07-18 13:06:06 +08:00
< / view >
< / template >
< script >
import textmessage from "./messageComponent/textmessage" ;
2025-07-21 22:10:59 +08:00
import customPKMessage from "./messageComponent/customPKMessage" ;
2025-07-25 16:39:52 +08:00
import imageMessage from "./messageComponent/imageMessage" ;
import videoMessage from "./messageComponent/videoMessage" ;
import voiceMessage from "./messageComponent/voiceMessage" ;
2025-07-18 13:06:06 +08:00
import InvitationComponents from "./moreMessageComponents/InvitationComponents" ;
import { generateId } from "../../../components/ChatId.js" ;
import TimeFormatting from "../../../components/TimeFormatting.js" ;
2025-07-21 22:10:59 +08:00
import request from "../../../components/request.js" ;
2025-07-18 13:06:06 +08:00
import {
getConversationMessages ,
sendMessage ,
messageRead ,
2025-07-21 22:10:59 +08:00
sendCustomMessage ,
2025-07-25 16:39:52 +08:00
sendGroupMessage ,
2025-07-18 13:06:06 +08:00
} from "../../../components/goEasyTool/tool.js" ;
import GoEasy from "goeasy" ;
export default {
data ( ) {
return {
userId : "" , // 对方用户id
nickname : "" , // 对方用户昵称
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 , // 上一次刷新时间戳
2025-07-21 22:10:59 +08:00
LastTime : null , // 最后聊天记录的时间戳
MoreMessageList : [ ] ,
Record : null , // 定位记录
myitem : null , //直接发送自定义消息的我的选中主播
youritem : null , //直接发送自定义消息的对方选中主播
type : null , //直接发送自定义消息的消息类型
2025-07-25 16:39:52 +08:00
voiceStatus : false , // 语音状态
inputfocus : false , // 输入框焦点状态
voicepopUpstart : false , // 语音长按状态/false关闭/true开启
voiceCancelOrSend : false , // 语音取消/发送/false发送/true取消
recorderManager : uni . getRecorderManager ( ) ,
playbackStatus : true , // 语音播放状态
2025-07-18 13:06:06 +08:00
popUpList : [
2025-07-21 22:10:59 +08:00
{
2025-07-25 16:39:52 +08:00
name : "图片" ,
2025-07-21 22:10:59 +08:00
icon : "https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/Album.png" ,
type : "Album" ,
} ,
2025-08-05 22:05:56 +08:00
// {
// name: "视频",
// icon: "https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/Video.png",
// type: "Video",
// },
2025-07-18 13:06:06 +08:00
{
name : "邀请" ,
icon : "https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/chat_invite.png" ,
type : "Invitation" ,
} ,
] , /// 更多消息类型弹窗列表
} ;
} ,
onShow ( ) {
this . onPage = true ;
2025-07-21 22:10:59 +08:00
uni . onKeyboardHeightChange ( ( res ) => {
this . KeyboardHeight = res . height * 2 - this . ioshide ;
} ) ;
2025-07-18 13:06:06 +08:00
} ,
onHide ( ) {
this . onPage = false ;
} ,
2025-07-29 14:23:27 +08:00
onUnload ( ) {
this . onPage = false ;
} ,
2025-07-18 13:06:06 +08:00
onLoad ( options ) {
2025-07-25 16:39:52 +08:00
this . recorderManager . onStop ( ( res ) => {
console . log ( "录音结束" , res ) ;
if ( this . ioshide != 0 ) {
if ( res . fileSize < 20 * 1024 ) {
uni . showToast ( {
title : "您说话太短" ,
icon : "none" ,
duration : 2000 ,
} ) ;
} else {
if ( this . voiceCancelOrSend ) {
this . voiceCancelOrSend = false ;
} else {
this . sendVoice ( res )
this . voiceCancelOrSend = false ;
}
}
} else {
if ( res . fileSize < 2 * 1024 ) {
uni . showToast ( {
title : "您说话太短" ,
icon : "none" ,
duration : 2000 ,
} ) ;
} else {
if ( this . voiceCancelOrSend ) {
this . voiceCancelOrSend = false ;
} else {
this . sendVoice ( res )
this . voiceCancelOrSend = false ;
}
}
}
} ) ;
2025-07-18 13:06:06 +08:00
uni . getStorage ( {
key : "userinfo" ,
success : ( res ) => {
2025-07-21 22:10:59 +08:00
this . userinfo = res . data ;
2025-07-18 13:06:06 +08:00
} ,
} ) ;
this . userId = options . userId ;
this . nickname = options . nickname ;
this . avatar = options . avatar ;
2025-07-21 22:10:59 +08:00
this . type = options . type ;
try {
this . myitem = JSON . parse ( options . myitem ) ;
this . youritem = JSON . parse ( options . youritem ) ;
} catch ( e ) { }
if ( this . type == "pk" ) {
setTimeout ( ( ) => {
this . sendCustomMessage ( ) ;
} , 500 ) ;
}
2025-07-18 13:06:06 +08:00
// 获取和对方用户的聊天记录
getConversationMessages ( this . $goeasy , this . userId , null ) . then ( ( res ) => {
this . chatList = res . map ( ( item ) => {
item . id = generateId ( ) ;
2025-07-21 22:10:59 +08:00
item . timestampStatus = this . checkInterval ( item . timestamp ) ;
2025-07-18 13:06:06 +08:00
return item ;
} ) ;
setTimeout ( ( ) => {
2025-07-21 22:10:59 +08:00
if ( this . chatList . length > 0 ) {
this . ElementPositioning = this . chatList [ this . chatList . length - 1 ] . id ;
this . LastTime = this . chatList [ 0 ] . timestamp ;
} else {
uni . showToast ( {
title : "您和对方暂无聊天记录,快去聊天吧" ,
icon : "none" ,
duration : 2000 ,
} ) ;
}
2025-07-18 13:06:06 +08:00
} , 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 ( ) ;
2025-09-29 20:48:31 +08:00
this . checkRecordPermission ( ) ;
2025-07-18 13:06:06 +08:00
} ,
methods : {
2025-07-25 16:39:52 +08:00
//暂停所有播放
notplayVoice ( type ) {
this . playbackStatus = type ;
} ,
//发送录音
sendVoice ( res ) {
const im = this . $goeasy . im ;
var message = im . createAudioMessage ( {
file : res ,
to : {
type : GoEasy . IM _SCENE . PRIVATE ,
id : this . userId , //对方用户id
data : { avatar : this . avatar , nickname : this . nickname } ,
} ,
onProgress : function ( event ) {
console . log ( "file uploading:" , event ) ;
} , //获取上传进度
} ) ;
sendGroupMessage ( this . $goeasy , message ) . then ( ( ress ) => {
this . ElementPositioning = ress . id = generateId ( ) ;
ress . timestampStatus = this . checkInterval ( ress . timestamp ) ;
this . chatList . push ( ress ) ;
this . judgescrollTop = false ;
} ) ;
} ,
//长按语音
voiceTouchstart ( ) {
console . log ( "长按语音" ) ;
this . voicepopUpstart = true ;
this . recorderManager . start ( ) ;
this . notplayVoice ( false ) ;
} ,
//松开语音
voiceTouchend ( ) {
setTimeout ( ( ) => {
this . recorderManager . stop ( ) ;
} , 100 ) ;
console . log ( "松开语音" ) ;
this . voicepopUpstart = false ;
} ,
//移动语音
voiceTouchmove ( event ) {
const threshold = uni . getSystemInfoSync ( ) . windowHeight * 0.86 ;
try {
if ( event . touches [ 0 ] . clientY > threshold ) {
this . voiceCancelOrSend = false ;
} else {
this . voiceCancelOrSend = true ;
}
} catch ( e ) { }
} ,
//中断语音
voiceTouchcancel ( ) {
console . log ( "中断语音" ) ;
this . voicepopUpstart = false ;
this . voiceCancelOrSend = false ;
} ,
//语音切换
onVoice ( status ) {
if ( status ) {
this . inputfocus = false ;
this . MoreStatus = false ;
} else {
this . inputfocus = true ;
}
this . voiceStatus = status ;
} ,
//录音权限
checkRecordPermission ( ) {
// 检查当前录音权限状态
uni . getSetting ( {
success : ( res ) => {
const hasPermission = res . authSetting [ "scope.record" ] ;
if ( hasPermission === undefined ) {
this . requestPermission ( ) ;
} else if ( ! hasPermission ) {
this . voiceStatus = false ;
uni . showModal ( {
title : "权限提示" ,
content : "需要录音权限才能正常使用功能,请在设置中开启" ,
confirmText : "去开启" ,
success : ( modalRes ) => {
if ( modalRes . confirm ) {
uni . openSetting ( {
success : ( settingRes ) => {
if ( settingRes . authSetting [ "scope.record" ] === true ) {
this . checkRecordPermission ( ) ;
}
} ,
} ) ;
}
} ,
} ) ;
}
} ,
} ) ;
} ,
//请求录音权限
requestPermission ( ) {
uni . authorize ( {
scope : "scope.record" ,
fail : ( err ) => {
this . voiceStatus = false ;
uni . showToast ( {
title : "请授予麦克风权限,否则可能导致语音功能异常" ,
icon : "none" ,
} ) ;
} ,
} ) ;
} ,
2025-07-21 22:10:59 +08:00
//直接发送自定义消息
sendCustomMessage ( ) {
request ( {
url : "pk/createPkRecord" ,
method : "POST" ,
data : {
pkIdA : this . youritem . id ,
pkIdB : this . myitem . id ,
userIdA : this . userId ,
userIdB : this . userinfo . id ,
pkTime : this . youritem . pkTime ,
pkNumber : this . youritem . pkNumber ,
anchorIdA : this . youritem . anchorId ,
anchorIdB : this . myitem . anchorId ,
anchorIconA : this . youritem . anchorIcon ,
anchorIconB : this . myitem . anchorIcon ,
piIdA : this . youritem . id ,
piIdB : this . myitem . id ,
} ,
userInfo : true ,
} ) . then ( ( res ) => {
if ( res . code == 200 ) {
const customData = {
id : res . data . id ,
pkIdA : this . youritem . id ,
pkIdB : this . myitem . id ,
} ;
let order = {
customData : customData ,
link : "https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/pk.png" ,
text : "PK邀请消息" ,
} ;
sendCustomMessage (
this . $goeasy ,
this . type ,
this . userId ,
order ,
this . avatar ,
this . nickname
) . then ( ( res ) => {
this . ElementPositioning = res . id = generateId ( ) ;
res . timestampStatus = this . checkInterval ( res . timestamp ) ;
this . chatList . push ( res ) ;
uni . showToast ( {
title : "发送成功" ,
icon : "none" ,
} ) ;
} ) ;
} else {
uni . showToast ( {
title : res . msg ,
icon : "none" ,
} ) ;
}
} ) ;
} ,
2025-07-18 13:06:06 +08:00
//时间显示
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 ;
}
} ,
2025-07-21 22:10:59 +08:00
//获取更多聊天记录
onScrollToUpper ( ) {
this . lastTimestamp = null ;
getConversationMessages ( this . $goeasy , this . userId , this . LastTime ) . then ( ( res ) => {
this . Record = this . chatList [ 0 ] . id ;
this . MoreMessageList = res . map ( ( item ) => {
item . id = generateId ( ) ;
item . timestampStatus = this . checkInterval ( item . timestamp ) ;
return item ;
} ) ;
} ) ;
setTimeout ( ( ) => {
this . chatList = [ ... this . MoreMessageList , ... this . chatList ] ;
console . log ( "获取更多聊天记录" , this . chatList ) ;
this . LastTime = this . chatList [ 0 ] . timestamp ;
this . ElementPositioning = this . Record ;
} , 300 ) ;
} ,
2025-07-18 13:06:06 +08:00
//监听已读消息
onMessageRead ( message ) {
2025-07-21 22:10:59 +08:00
console . log ( "1已读消息" , message ) ;
2025-07-18 13:06:06 +08:00
} ,
//监听接受消息
onPrivateMessageReceived ( message ) {
if ( ! this . Scrolling ) {
this . ElementPositioning = message . id = generateId ( ) ;
2025-07-21 22:10:59 +08:00
message . timestampStatus = this . checkInterval ( message . timestamp ) ;
2025-07-18 13:06:06 +08:00
this . judgescrollTop = false ;
} else {
message . id = generateId ( ) ;
2025-07-21 22:10:59 +08:00
message . timestampStatus = this . checkInterval ( message . timestamp ) ;
2025-07-18 13:06:06 +08:00
}
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 ( ) ;
2025-07-21 22:10:59 +08:00
res . timestampStatus = this . checkInterval ( res . timestamp ) ;
2025-07-18 13:06:06 +08:00
this . chatList . push ( res ) ;
this . judgescrollTop = false ;
} ) ;
this . content = "" ;
this . ButtonStatus = false ;
}
} ,
2025-07-21 22:10:59 +08:00
//自定义消息发送返回处理
refreshMessage ( message ) {
this . MoreItemStatus = null ;
this . ElementPositioning = message . message . id = generateId ( ) ;
message . timestampStatus = this . checkInterval ( message . message . timestamp ) ;
this . chatList . push ( message . message ) ;
this . judgescrollTop = false ;
this . MoreStatus = false ;
} ,
2025-07-18 13:06:06 +08:00
//ios兼容
getIOSDeviceType ( ) {
const systemInfo = uni . getSystemInfoSync ( ) ;
const model = systemInfo . model ;
2025-09-29 20:48:31 +08:00
if ( /iPhone X|iPhone11|iPhone12|iPhone13|iPhone14|iPhone15|iPhone16|iPhone15 Pro|iPhone15 Pro Max|iPhone14 Pro|iPhone14 Pro Max|iPhone13 Pro|iPhone13 Pro Max|iPhone12 Pro|iPhone12 Pro Max|iPhone11 Pro|iPhone11 Pro Max|iPhone13 mini|iPhone12 mini|iPhoneXS|iPhoneXS Max/i . test ( model ) ) {
if ( /iPhone X|iPhone XS|iPhone 11 Pro|iPhone 11 Pro Max|iPhone 12 Pro|iPhone 12 Pro Max|iPhone 13 Pro|iPhone 13 Pro Max|iPhone 14 Pro|iPhone 14 Pro Max|iPhone 15 Pro|iPhone 15 Pro Max|iPhone 16/i . test ( model ) ) {
2025-07-18 13:06:06 +08:00
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 ( ) ;
2025-07-25 16:39:52 +08:00
if ( Status ) {
this . MoreStatus = Status ;
this . voiceStatus = false ;
} else {
this . MoreStatus = Status ;
}
2025-07-18 13:06:06 +08:00
const query = uni . createSelectorQuery ( ) . in ( this ) ;
query
. select ( ".inputComponent" )
. boundingClientRect ( ( res ) => {
this . Elementheight = res . height * 2 ;
} )
. exec ( ) ;
} ,
//更多消息类型弹窗点击事件
onMoreItem ( type ) {
2025-07-21 22:10:59 +08:00
if ( type == "Album" ) {
2025-07-25 16:39:52 +08:00
this . onSendMedia ( ) ; //发送图片
} else if ( type == "Video" ) {
this . onSendVideo ( ) ; //发送视频
2025-07-21 22:10:59 +08:00
} else {
this . MoreItemStatus = type ;
}
} ,
2025-07-25 16:39:52 +08:00
//发送视频
onSendVideo ( ) {
var im = this . $goeasy . im ;
uni . chooseVideo ( {
2025-07-21 22:10:59 +08:00
sourceType : [ "album" , "camera" ] ,
2025-07-25 16:39:52 +08:00
success : ( res ) => {
var message = im . createVideoMessage ( {
file : res , //H5获得的视频file对象, Uniapp和小程序调用chooseVideo, success时得到的res对象
to : {
type : GoEasy . IM _SCENE . PRIVATE ,
id : this . userId , //对方用户id
data : { avatar : this . avatar , nickname : this . nickname } ,
} ,
onProgress : function ( event ) {
console . log ( "file uploading:" , event ) ;
} , //获取上传进度
} ) ;
sendGroupMessage ( this . $goeasy , message ) . then ( ( res ) => {
this . ElementPositioning = res . id = generateId ( ) ;
res . timestampStatus = this . checkInterval ( res . timestamp ) ;
this . chatList . push ( res ) ;
this . judgescrollTop = false ;
} ) ;
2025-07-21 22:10:59 +08:00
} ,
} ) ;
} ,
2025-07-25 16:39:52 +08:00
//发送图片
onSendMedia ( ) {
var im = this . $goeasy . im ;
uni . chooseImage ( {
count : 9 , //默认9
sizeType : [ "original" , "compressed" ] , //可以指定是原图还是压缩图,默认二者都有
sourceType : [ "album" , "camera" ] , //从相册选择
success : ( res ) => {
const tempFiles = res . tempFiles ;
tempFiles . forEach ( ( item , index ) => {
var message = im . createImageMessage ( {
file : item ,
to : {
type : GoEasy . IM _SCENE . PRIVATE ,
id : this . userId ,
data : { avatar : this . avatar , nickname : this . nickname } ,
} ,
onProgress : function ( event ) {
console . log ( "上传进度" , event ) ;
} , //获取上传进度
} ) ;
sendGroupMessage ( this . $goeasy , message ) . then ( ( res ) => {
this . ElementPositioning = res . id = generateId ( ) ;
res . timestampStatus = this . checkInterval ( res . timestamp ) ;
this . chatList . push ( res ) ;
this . judgescrollTop = false ;
} ) ;
} ) ;
} ,
} ) ;
2025-07-18 13:06:06 +08:00
} ,
// 获取键盘高度
onFocus ( event ) {
if ( ! this . Scrolling ) {
this . ElementPositioning = null ;
setTimeout ( ( ) => {
this . ElementPositioning = this . chatList [ this . chatList . length - 1 ] . id ;
} , 100 ) ;
this . judgescrollTop = false ;
}
this . getscrollviewheight ( ) ;
const query = uni . createSelectorQuery ( ) . in ( this ) ;
query
. select ( ".inputComponent" )
. boundingClientRect ( ( res ) => {
this . Elementheight = res . height * 2 ;
} )
. exec ( ) ;
} ,
//键盘消失
onBlur ( event ) {
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 ,
2025-07-21 22:10:59 +08:00
customPKMessage ,
2025-07-25 16:39:52 +08:00
imageMessage ,
videoMessage ,
voiceMessage ,
2025-07-18 13:06:06 +08:00
} ,
} ;
< / 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 : 35 rpx ;
top : 120 rpx ;
width : 46 rpx ;
height : 46 rpx ;
2025-07-29 14:23:27 +08:00
z - index : 2 ;
2025-07-18 13:06:06 +08:00
}
. title {
position : fixed ;
top : 120 rpx ;
2025-07-29 14:23:27 +08:00
left : 0 ;
right : 0 ;
text - align : center ;
2025-07-18 13:06:06 +08:00
font - size : 34 rpx ;
color : # 100 e0f ;
font - weight : bold ;
z - index : 1 ;
}
. ReturnImg {
width : 100 % ;
height : 100 % ;
}
. content {
position : absolute ;
top : 200 rpx ;
left : 0 rpx ;
right : 0 rpx ;
}
. scroll {
width : 96 % ;
height : 100 % ;
padding : 0 % 2 % 0 % 2 % ;
}
2025-07-21 22:10:59 +08:00
. scroll : : - webkit - scrollbar {
width : 0 ;
height : 0 ;
color : transparent ;
display : none ;
}
2025-07-18 13:06:06 +08:00
. inputComponent {
position : absolute ;
left : 0 ;
right : 0 ;
height : auto ;
background - color : # f0f0f0 ;
padding : 15 rpx 15 rpx 37.5 rpx 15 rpx ;
display : flex ;
align - items : flex - end ;
2025-07-21 22:10:59 +08:00
transition : bottom 0.25 s ease ;
2025-07-18 13:06:06 +08:00
}
. chat - card {
width : 100 % ;
height : auto ;
2025-07-21 22:10:59 +08:00
margin - bottom : 10 rpx ;
margin - top : 10 rpx ;
2025-07-18 13:06:06 +08:00
padding : 10 rpx ;
2025-07-21 22:10:59 +08:00
/* background-color: #ffffff; */
2025-07-18 13:06:06 +08:00
}
. chat - time {
width : 100 % ;
height : 50 rpx ;
text - align : center ;
font - size : 24 rpx ;
color : # 999999 ;
line - height : 50 rpx ;
margin - top : 20 rpx ;
margin - bottom : 20 rpx ;
background - color : # 00000000 ;
}
. chat - avatar {
width : 100 % ;
height : auto ;
2025-07-21 22:10:59 +08:00
display : flex ;
align - items : flex - start ;
}
. oppositeChatNews {
width : 100 % ;
display : flex ;
align - items : flex - start ;
}
. oppositesharpCorner {
width : 20 rpx ;
height : 80 rpx ;
display : flex ;
flex - direction : row - reverse ;
align - items : center ;
}
. oppositeSharpCornercion {
width : 0 ;
height : 0 ;
border - top : 13 rpx solid transparent ;
border - right : 13 rpx solid # ffffff ;
border - bottom : 13 rpx solid transparent ;
}
. oppositeChatNewsContent {
width : auto ;
height : auto ;
background - color : # ffffff ;
border - radius : 10 rpx ;
max - width : 450 rpx ;
}
. myChatNews {
width : 100 % ;
display : flex ;
flex - direction : row - reverse ;
align - items : flex - start ;
margin - right : 15 rpx ;
}
. mysharpCorner {
width : 20 rpx ;
height : 80 rpx ;
display : flex ;
align - items : center ;
}
. mySharpCornercion {
width : 0 ;
height : 0 ;
border - top : 13 rpx solid transparent ;
border - left : 13 rpx solid # 7 bbd0093 ;
border - bottom : 13 rpx solid transparent ;
}
. myChatNewsContent {
width : auto ;
height : auto ;
border - radius : 20 rpx ;
max - width : 450 rpx ;
}
. chat - avatarImg {
width : 80 rpx ;
height : 80 rpx ;
border - radius : 10 rpx ;
2025-07-18 13:06:06 +08:00
}
2025-07-25 16:39:52 +08:00
. Voice {
width : 80 rpx ;
height : 80 rpx ;
border - radius : 50 rpx ;
margin - left : 10 rpx ;
display : flex ;
justify - content : center ;
align - items : center ;
}
. KeyboardImg {
width : 70 rpx ;
height : 70 rpx ;
border - radius : 50 rpx ;
display : flex ;
justify - content : center ;
align - items : center ;
}
. Keyboardpng {
width : 100 % ;
height : 100 % ;
border - radius : 50 rpx ;
}
. MicrophoneImg {
margin - top : 5 rpx ;
width : 53 rpx ;
height : 53 rpx ;
border : 4 rpx solid # 424242 ;
border - radius : 50 rpx ;
display : flex ;
justify - content : center ;
align - items : center ;
}
. Microphonepng {
width : 80 % ;
height : 80 % ;
border - radius : 50 rpx ;
}
2025-07-18 13:06:06 +08:00
. textareacomponent {
width : 570 rpx ;
height : auto ;
}
. input {
width : 95 % ;
background - color : # ffffff ;
min - height : 60 rpx ;
max - height : 200 rpx ;
border - radius : 10 rpx ;
padding : 10 rpx ;
overflow - wrap : break - word ;
margin - left : 30 rpx ;
}
2025-07-25 16:39:52 +08:00
. VoiceInput {
width : 95 % ;
background - color : # ffffff ;
height : 60 rpx ;
border - radius : 10 rpx ;
padding : 10 rpx ;
overflow - wrap : break - word ;
margin - left : 30 rpx ;
line - height : 60 rpx ;
text - align : center ;
color : # 000 ;
}
2025-07-18 13:06:06 +08:00
. sendComponent {
margin - left : 40 rpx ;
}
. send {
width : 100 rpx ;
height : 75 rpx ;
background - color : # 539 c00 ;
border - radius : 10 rpx ;
color : # ffffff ;
font - size : 20 rpx ;
text - align : center ;
line - height : 75 rpx ;
}
. MoreImg {
margin - left : 20 rpx ;
height : 80 rpx ;
width : 80 rpx ;
margin - bottom : - 10 rpx ;
border - radius : 50 rpx ;
}
. MoreComponent {
position : fixed ;
left : 0 ;
right : 0 ;
height : 650 rpx ;
2025-07-21 22:10:59 +08:00
transition : bottom 0.25 s ease ;
2025-07-18 13:06:06 +08:00
background - color : # ffffff ;
}
. Morecontent {
width : 100 % ;
height : 100 % ;
display : flex ;
align - content : baseline ;
flex - wrap : wrap ;
}
. MoreList {
width : 150 rpx ;
height : 150 rpx ;
background - color : # f1f1f1 ;
border - radius : 20 rpx ;
margin : 18.75 rpx ;
}
. MoreItem {
width : 100 % ;
height : 100 % ;
display : flex ;
flex - direction : column ;
justify - content : center ;
align - items : center ;
}
. Moreicon {
width : 80 rpx ;
height : 80 rpx ;
}
. popUpInvitation {
position : fixed ;
left : 0 ;
right : 0 ;
bottom : 0 ;
2025-07-21 22:10:59 +08:00
transition : top 0.25 s ease ;
z - index : 1000 ;
2025-07-18 13:06:06 +08:00
}
2025-07-25 16:39:52 +08:00
. popUpVoice {
position : fixed ;
left : 0 ;
right : 0 ;
bottom : 0 ;
z - index : 1000 ;
background - color : # 8 b8b8bd7 ;
}
2025-07-18 13:06:06 +08:00
. popUpInvitationContent {
position : absolute ;
left : 0 ;
right : 0 ;
height : 1000 rpx ;
2025-07-21 22:10:59 +08:00
transition : bottom 0.25 s ease ;
2025-07-18 13:06:06 +08:00
background - color : # ffffff ;
border - top - left - radius : 40 rpx ;
border - top - right - radius : 40 rpx ;
}
2025-07-25 16:39:52 +08:00
. popUpvoiceContent {
position : absolute ;
left : 0 ;
right : 0 ;
height : 1000 rpx ;
/* transition: bottom 0.1s ease; */
/* background-color: #ebebeb; */
}
. gifModule {
padding : 20 rpx ;
border - radius : 20 rpx ;
overflow : hidden ;
height : 120 rpx ;
background - color : # 232123 ;
}
. voiceCenter {
width : 100 % ;
height : 100 % ;
display : flex ;
flex - direction : column ;
justify - content : space - between ;
align - items : center ;
}
. video - player {
width : 300 rpx ;
height : 300 rpx ;
border - radius : 20 rpx ;
margin - top : - 94 rpx ;
}
. CancelModule {
width : 95 % ;
height : 100 rpx ;
text - align : center ;
line - height : 100 rpx ;
background - color : # 000000 a9 ;
font - size : 30 rpx ;
color : # 999999 ;
border - radius : 50 rpx ;
margin - top : 500 rpx ;
}
. btnModule {
width : 100 % ;
height : 200 rpx ;
background - color : # 000000 ;
color : # 999999 ;
font - size : 30 rpx ;
text - align : center ;
line - height : 200 rpx ;
border - top - left - radius : 50 % ;
border - top - right - radius : 50 % ;
}
2025-07-18 13:06:06 +08:00
< / style >