Files
ZhHealth/pages/im/private/index.vue
2022-01-25 13:35:14 +08:00

488 lines
18 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="chat-content">
<scroll-view class="chat-scrool" :scroll-y="true" :scroll-into-view="scrollIntoID"
:scroll-with-animation="false">
<!-- 聊天窗口 -->
<view class="chat-item" v-for="(item,index) in messages" :key="index">
<view class="chat-item-article" :class="item.messageDirection == 1 ? 'right' : 'left'">
<view class="chat-msg">
<!-- 文字消息 -->
<view class="chat-msg-text">{{ item.content.content }}</view>
<!-- 语音消息 -->
<view class="chat-msg-audio" @click="onPlayMsg()">
<image v-if="item.messageDirection == 0" src="@/static/icon/audio_ green.png" mode="widthFix"></image>
10"
<image v-if="item.messageDirection == 1" src="@/static/icon/audio_white.png" mode="widthFix"></image>
</view>
<!-- 预留一些图片语音表情包等位置 -->
</view>
<view class="chat-status" :class="{'hide': item.sentStatus == 50}"
v-if="item.messageDirection == 1">{{ item.sentStatus == 50 ? '已读': '未读'}}</view>
<view class="chat-avatar">
<u-avatar v-if="item.messageDirection == 2" shape="square" bg-color="#ffffff" :src="userInfo.portraitUrl" @click="showFriend(targetId)"></u-avatar>
<u-avatar v-else @click="showMine" shape="square" bg-color="#ffffff" :src="$store.getters.sender.portraitUrl" />
</view>
</view>
<view class="chat-item-time" :id="'chatId_'+index">
<text>{{ item.sentTime|timeCustomCN }}</text>
</view>
</view>
</scroll-view>
<view class="chat-footer">
<view class="msg-type" @click="msgType">
<image src="@/static/icon/key-icon.png" v-if="importTabs === 0" mode="widthFix"></image>
<image src="@/static/icon/msg-icon.png" v-if="importTabs === 1" mode="widthFix"></image>
</view>
<block v-if="importTabs === 0">
<button type="default" class="chat-mp3" hover-class="chat-hover" @touchstart="startAudio" @touchend="chendAudio">按住 说话</button>
</block>
<block v-if="importTabs === 1">
<input class="chat-input" type="text" v-model="inputTxt" confirm-type="发送" @confirm="send" cursor-spacing="10" />
</block>
<button class="chat-push" :disabled="disabled" size="mini" @click="send">发送</button>
</view>
<!-- 录音中提示 -->
<view class="audio-transcribe" v-if="showAudioTranscribe">
<image src="@/static/icon/record-icon.png" mode="widthFix"></image>
<view class="text">录音中 {{transcribeTime}} s</view>
</view>
</view>
</template>
<script>
import * as RongIMLib from '@rongcloud/imlib-uni'
import im from '@/utils/im/index.js'
import permision from "@/js_sdk/wa-permission/permission.js"
var transcribe
var recorderManager = uni.getRecorderManager()
export default {
data() {
return {
targetId: '',
scrollIntoID: 'chatID_0',
inputTxt: '',
messages: [],
conversationType: 1,
totalCount: 0,
userInfo: {
name: '',
userId: '',
portraitUrl: ''
},
importTabs: 0,
showAudioTranscribe:false,
transcribeTime: 60,
audioSrc: '',
audioContextPaused: true
}
},
onLoad(e) {
this.targetId = e.targetId
this.conversationType = e.conversationType // 会话类型
// 消息总数量
RongIMLib.getMessageCount(this.conversationType, this.targetId, ({
code,
count
}) => {
if (code == 0) {
this.totalCount = count
}
})
this.userInfo = this.$store.getters.userInfo(this.targetId)
uni.setNavigationBarTitle({
title: this.$store.getters.userInfo(this.targetId).name
})
RongIMLib.clearMessagesUnreadStatus(this.conversationType, this.targetId, new Date().getTime())
im.setNotifyBadge()
RongIMLib.sendReadReceiptMessage(this.conversationType, this.targetId, new Date().getTime())
this.getMessageList()
// 监听消息回执
RongIMLib.addReadReceiptReceivedListener((result) => {
const res = result.data.message
if (res.targetId == this.targetId) {
this.getMessageList()
}
})
// 监听录音结束
recorderManager.onStop(res => {
if(res.tempFilePath) this.audioSrc = res.tempFilePath
console.log('------------------获取到了录音的临时路径---------------')
console.log(res.tempFilePath)
})
},
onUnload() {
RongIMLib.clearReadReceiptReceivedListener()
},
computed: {
disabled() {
return this.inputTxt.length == 0
},
friend() {
return function(targetId) {
return this.$store.getters.userInfo(targetId)
}
}
},
onNavigationBarButtonTap(e) {
if (e.index == 0) {
uni.navigateTo({
url: '/pages/im/private/setting?targetId=' + this.targetId +
'&conversationType=' + this.conversationType,
events: {
messageClear: () => {
this.getMessageList()
console.log('聊天消息被清空');
}
}
})
}
},
watch: {
'$store.getters.newMessage': function(msg) {
if (msg.targetId == this.targetId) {
RongIMLib.clearMessagesUnreadStatus(msg.conversationType, msg.targetId, msg.sentTime)
RongIMLib.sendReadReceiptMessage(msg.conversationType, msg.targetId, msg.sentTime)
this.getMessageList()
im.setNotifyBadge()
}
}
},
methods: {
// 播放语音消息
onPlayMsg(){
let innerAudioContext = uni.createInnerAudioContext()
innerAudioContext.src = this.audioSrc
if(this.audioContextPaused){
innerAudioContext.play()
this.audioContextPaused = false
return
}
innerAudioContext.stop()
innerAudioContext.onStop(resStop => {
this.audioContextPaused = true
})
},
// 检查安卓录制权限
async getAndroidPermission(){
return await permision.requestAndroidPermission('android.permission.RECORD_AUDIO')
},
// 切换聊天信息
msgType(){
this.importTabs = this.importTabs === 1 ? 0: 1
},
// 录制语音消息
startAudio(e){
this.getAndroidPermission().then(code => {
switch (code){
case 1:
this.showAudioTranscribe = true
recorderManager.start()
transcribe = setInterval(() => {
this.transcribeTime -= 1
if(this.transcribeTime === 0){
this.chendAudio()
}
},1000)
break;
case 0:
uni.showToast({
title: '暂无麦克风权限,请前往应用设置开启麦克风',
icon : 'none'
})
break;
case -1:
uni.showToast({
title: '应用权限错误',
icon : 'none'
})
break;
}
})
},
// 结束录音
chendAudio(e){
if(!this.showAudioTranscribe) return
recorderManager.stop()
clearInterval(transcribe)
this.transcribeTime = 60
this.showAudioTranscribe = false
},
getMessageList() {
// 获取消息列表
const objectNames = [
'RC:TxtMsg',
'RC:VcMsg',
'RC:HQVCMsg',
'RC:ImgMsg',
'RC:GIFMsg',
'RC:ImgTextMsg',
'RC:FileMsg',
'RC:LBSMsg',
'RC:SightMsg',
'RC:ReferenceMsg',
'RC:CombineMsg'
]
const timeStamp = new Date().getTime()
const count = 20 // 获取的消息数量
const isForward = true // 是否向前获取
RongIMLib.getHistoryMessagesByTimestamp(this.conversationType, this.targetId, objectNames, timeStamp,
count,
isForward,
({
code,
messages
}) => {
if (code === 0) {
this.messages = messages.reverse()
this.scrollBottom()
}
}
)
},
send() {
im.sendMsg(this.conversationType, this.targetId, this.inputTxt, () => {
this.getMessageList()
this.inputTxt = ''
})
},
showFriend(targetId) {
uni.navigateTo({
url: '/pages/im/friends/info?targetId=' + targetId
})
},
showMine() {
uni.navigateTo({
url: '/pages/im/friends/mine'
})
},
scrollBottom() {
this.$nextTick(function() {
setTimeout(() => {
let len = this.messages.length
if (len) {
if (this.scrollIntoID == "chatId_" + (len - 1)) {
this.scrollIntoID = "chatId_" + (len - 2)
this.scrollBottom()
} else if (this.scrollIntoID == "chatId_" + (len - 2)) {
this.scrollIntoID = "chatId_" + (len - 1)
} else {
this.scrollIntoID = "chatId_" + (len - 1)
}
} else {
this.scrollIntoID = "chatId_0";
}
}, 50)
})
}
}
}
</script>
<style lang="scss" scoped>
.chat-content {
height: 100vh;
background: $window-color;
.audio-transcribe{
background: rgba($color: #000000, $alpha: .6);
position: fixed;
height: 200rpx;
width: 300rpx;
border-radius: $radius;
color: white;
z-index: 99;
top: 50%;
left: 50%;
margin-top: -200rpx;
margin-left: -150rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
image{
width: 88rpx;
height: 88rpx;
}
.text{
font-size: $title-size-m;
}
}
.chat-scrool {
height: calc(100vh - 140rpx);
box-sizing: border-box;
padding-bottom: $padding;
.chat-item {
.chat-item-time {
text-align: center;
padding: $padding/2 $padding;
text {
background: rgba($color: #000000, $alpha: .2);
color: white;
font-size: $title-size-sm - 4;
line-height: 40rpx;
padding: 0 15rpx;
display: inline-block;
border-radius: $radius-lg;
}
}
.chat-item-article {
position: relative;
padding: 10rpx ($padding + 110) 0;
overflow: hidden;
min-height: 40px;
.chat-msg {
overflow: hidden;
.chat-msg-text {
display: inline-block;
padding: ($padding - 10) $padding;
color: $text-color;
box-sizing: border-box;
font-size: $title-size-lg;
}
.chat-msg-audio{
@extend .chat-msg-text;
width: 50%;
image{
width: 38rpx;
height: 38rpx;
margin: 0;
vertical-align: middle;
}
}
}
.chat-status {
color: $text-gray;
font-size: $title-size-sm;
text-align: right;
&.hide {
color: $text-gray-m;
}
}
.chat-avatar {
position: absolute;
top: 0;
background: white;
border-radius: $radius-m;
}
&.left {
.chat-avatar {
left: $margin;
}
.chat-msg {
.chat-msg-text {
background-color: white;
border-radius: 0 $radius*2 $radius*2 $radius*2;
}
}
}
&.right {
.chat-avatar {
right: $margin;
}
.chat-msg {
text-align: right;
.chat-msg-text {
border-radius: $radius*2 0 $radius*2 $radius*2;
background: $main-color;
color: white;
}
}
}
}
}
}
.chat-footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 140rpx;
padding: 20rpx ($padding + 150rpx) 40rpx ($padding + 94rpx);
background: white;
box-sizing: border-box;
z-index: 99;
.msg-type{
position: absolute;
top: 20rpx;
left: $padding;
line-height: 80rpx;
image{
width: 64rpx;
height: 64rpx;
vertical-align: middle;
margin-bottom: 10rpx;
}
}
.chat-input {
background: $window-color;
height: 80rpx;
border-radius: $radius-lg;
font-size: $title-size-m;
padding: 0 $padding;
box-sizing: border-box;
}
.chat-mp3{
background: $window-color;
line-height: 80rpx;
text-align: center;
border-radius: $radius-lg;
font-weight: bold;
color: #333;
font-size: $title-size-m;
&::after{
display: none;
}
}
.chat-hover{
opacity: .5;
}
.chat-push[size='mini'] {
position: absolute;
right: $margin;
top: 20rpx;
height: 80rpx;
line-height: 80rpx;
padding: 0;
margin: 0;
width: 120rpx;
background: $main-color;
color: white;
border-radius: $radius-lg;
font-size: $title-size-m;
font-weight: bold;
&[disabled] {
background: rgba($color: $main-color, $alpha: .5);
}
&::after {
display: none;
}
}
}
}
</style>