更改发送消息模式为promise

This commit is contained in:
2022-02-28 13:45:17 +08:00
parent bf94cca533
commit 39b8f158c0
9 changed files with 647 additions and 466 deletions

View File

@@ -1,79 +1,87 @@
<template>
<view class="emoji--lay" v-show="show">
<scroll-view class="scroll" :scroll-y="true">
<view class="emoji-flex">
<view class="item" v-for="(item, index) in emojiArr" :key="index" @click="$emit('onEmoji', item)">{{item.emoji}}</view>
</view>
</scroll-view>
<view class="tool">
<!-- <view class="item" @click="$emit('delete')">删除</view> -->
<view class="item sent" @click="$emit('sent')">发送</view>
</view>
</view>
</template>
<script>
import emoji from '@/static/im/emoji'
export default{
props:{
show: {
type: Boolean,
default: () => {
return false
}
}
},
data(){
return {
emojiArr: emoji
}
}
}
</script>
<style lang="scss" scoped>
.emoji--lay{
height: 600rpx;
position: relative;
.scroll{
height: 600rpx;
.emoji-flex{
padding: 15rpx 15rpx 120rpx;
display: flex;
flex-wrap: wrap;
.item{
margin: 10rpx 15rpx;
font-size: 52rpx;
width: calc(12.5% - 30rpx);
box-sizing: border-box;
}
}
}
.tool{
position: absolute;
bottom: 0;
left: 0;
right: 0;
background-image: linear-gradient(to top, #FFF, rgba(255, 255, 255, .0));
display: flex;
justify-content: flex-end;
padding: 20rpx 30rpx 30rpx;
.item{
line-height: 70rpx;
border-radius: 35rpx;
width: 140rpx;
text-align: center;
font-size: 28rpx;
margin-left: 20rpx;
background: white;
border: solid 1rpx #f5f5f5;
box-sizing: border-box;
&.sent{
border-color: #34CE98;
background: #34CE98;
color: white;
}
}
}
}
<template>
<view class="emoji--lay" v-show="show">
<scroll-view class="scroll" :scroll-y="true">
<view class="emoji-flex">
<view class="item" v-for="(item, index) in emojiArr" :key="index" @click="$emit('onEmoji', item)">
{{item.emoji}}
</view>
</view>
</scroll-view>
<view class="tool">
<!-- <view class="item" @click="$emit('delete')">删除</view> -->
<view class="item sent" @click="$emit('sent')">发送</view>
</view>
</view>
</template>
<script>
import emoji from '@/static/im/emoji'
export default {
props: {
show: {
type: Boolean,
default: () => {
return false
}
}
},
data() {
return {
emojiArr: emoji
}
}
}
</script>
<style lang="scss" scoped>
.emoji--lay {
height: 600rpx;
position: relative;
.scroll {
height: 600rpx;
.emoji-flex {
padding: 15rpx 15rpx 120rpx;
display: flex;
flex-wrap: wrap;
.item {
margin: 10rpx 15rpx;
font-size: 52rpx;
width: calc(12.5% - 30rpx);
box-sizing: border-box;
}
}
}
.tool {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background-image: linear-gradient(to top, #FFF, rgba(255, 255, 255, .0));
display: flex;
justify-content: flex-end;
padding: 20rpx 30rpx 30rpx;
.item {
line-height: 70rpx;
border-radius: 35rpx;
width: 140rpx;
text-align: center;
font-size: 28rpx;
margin-left: 20rpx;
background: white;
border: solid 1rpx #f5f5f5;
box-sizing: border-box;
&.sent {
border-color: #34CE98;
background: #34CE98;
color: white;
}
}
}
}
</style>

View File

@@ -25,6 +25,8 @@
<text class="text">文件</text>
</view>
<tki-file-manager ref="filemanager" @result="resultPath"></tki-file-manager>
<u-action-sheet :actions="callActions" cancelText="取消" @close="callShow = false" @select="singleCall"
:show="callShow">
</u-action-sheet>
@@ -34,11 +36,15 @@
<script>
import im from '@/utils/im/index.js'
import imBase from '../../mixins/imBase.js'
import tkiFileManager from "@/components/tki-file-manager/tki-file-manager.vue"
export default {
mixins: [
imBase
],
components: [
tkiFileManager
],
data() {
return {
callActions: [{
@@ -68,6 +74,11 @@
}
},
methods: {
resultPath(path) {
im.sentFile(this.conversationType, this.targetId, path).then(res => {
console.log('发送文件', res);
})
},
singleCall(e) {
uni.navigateTo({
url: '/pages/im/private/call?targetId=' + this.targetId + '&mediaType=' + e.type +
@@ -81,10 +92,15 @@
count: 9,
sourceType: ['album'],
success: res => {
im.sentImage(this.conversationType, this.targetId, res.tempFilePaths[0],
this.sender, (res) => {
this.success()
})
let funs = []
res.tempFilePaths.map((item, index) => {
funs[index] = im.sentImage(this.conversationType, this
.targetId, item)
})
Promise.all(funs).then(res => {
this.success()
})
}
})
break;
@@ -92,8 +108,8 @@
uni.chooseImage({
sourceType: ['camera'],
success: res => {
im.sentImage(this.conversationType, this.targetId, res.tempFilePaths[0],
this.sender, (res) => {
im.sentImage(this.conversationType, this.targetId, res.tempFilePaths[0])
.then((res) => {
this.success()
})
}
@@ -116,10 +132,12 @@
})
break;
case 'file':
uni.showToast({
icon: 'none',
title: '功能正在开发中'
})
this.$refs.filemanager._openFile()
// uni.showToast({
// icon: 'none',
// title: '功能正在开发中'
// })
break;
}
},

View File

@@ -1,17 +1,7 @@
<template>
<view class="sent--text">
<input
class="input"
type="text"
:auto-blur="true"
:focus="focusState"
v-model="inputTxt"
confirm-type="send"
cursor-spacing="10"
@focus="focus"
@blur="blur"
@confirm="sent"
/>
<input class="input" type="text" :auto-blur="true" :focus="focusState" v-model="inputTxt" confirm-type="send"
cursor-spacing="10" @focus="focus" @blur="blur" @confirm="sent" />
</view>
</template>
@@ -55,33 +45,33 @@
focusState: false,
inputTxt: ''
}
},
created(){
uni.$on('emojiValue', res => {
this.inputTxt = res.value
})
},
},
created() {
uni.$on('emojiValue', res => {
this.inputTxt = res.value
})
},
methods: {
sent() {
sent() {
if (!this.disabled) {
im.sentText(this.conversationType, this.targetId, this.inputTxt, this.sender, () => {
im.sentText(this.conversationType, this.targetId, this.inputTxt).then(() => {
RongIMLib.clearTextMessageDraft(this.conversationType, this.targetId)
this.$emit('success')
this.inputTxt = ''
})
}
},
focus() {
focus() {
this.$emit('focus')
},
blur(e) {
blur(e) {
uni.hideKeyboard()
this.$emit('blur', e.detail)
}
},
destroyed() {
uni.$off('emojiValue')
},
destroyed() {
uni.$off('emojiValue')
}
}
</script>
@@ -91,6 +81,7 @@
display: flex;
flex-direction: row;
justify-content: space-between;
.input {
background: #F3F6FB;
height: 70rpx;

View File

@@ -1,21 +1,22 @@
<template>
<view class="send--voice">
<view class="voice" hover-class="chat-hover" @touchstart="startRecord" @touchend="stopRecord" @touchmove="touchmove">
<view class="voice" hover-class="chat-hover" @touchstart="startRecord" @touchend="stopRecord"
@touchmove="touchmove">
<text class="button">按住 说话</text>
</view>
<!-- 录音层 -->
<view class="lay" v-if="showRecordTip">
<view class="lay-header">
<view class="modal">
<image class="icon" src="@/static/icon/record-icon.png" mode="widthFix"></image>
<text class="text">录音中 {{recordTime}} s</text>
</view>
</view>
<view class="lay-toast">上滑取消</view>
<view class="lay-footer">
<image class="lay-footer-icon videoFlicker" src="@/static/icon/audio_green.png" mode="widthFix"></image>
<view class="lay-footer-text">松开发送</view>
</view>
</view>
<!-- 录音层 -->
<view class="lay" v-if="showRecordTip">
<view class="lay-header">
<view class="modal">
<image class="icon" src="@/static/icon/record-icon.png" mode="widthFix"></image>
<text class="text">录音中 {{recordTime}} s</text>
</view>
</view>
<view class="lay-toast">上滑取消</view>
<view class="lay-footer">
<image class="lay-footer-icon videoFlicker" src="@/static/icon/audio_green.png" mode="widthFix"></image>
<view class="lay-footer-text">松开发送</view>
</view>
</view>
</view>
</template>
@@ -23,8 +24,8 @@
<script>
import im from '@/utils/im/index.js'
import permision from '@/utils/permission.js'
import imBase from '../../mixins/imBase.js'
import imBase from '../../mixins/imBase.js'
export default {
mixins: [
imBase
@@ -41,15 +42,15 @@
},
data() {
return {
showRecordTip: false,
showRecordTip: false,
recordTime: 60,
interval: 0,
maxRecordTime: 60,
recorderManager: null,
mp3AudioSrc: null,
isMoveCancel: false,
isBetaPlay: false, // 暂时无用
startOffsetTop: 0
recorderManager: null,
mp3AudioSrc: null,
isMoveCancel: false,
isBetaPlay: false, // 暂时无用
startOffsetTop: 0
}
},
computed: {
@@ -57,20 +58,20 @@
return this.$store.getters.sender
}
},
created() {
created() {
this.recorderManager = uni.getRecorderManager()
},
methods: {
methods: {
// 检查安卓录制权限
async getAndroidPermission() {
return await permision.requestAndroidPermission('android.permission.RECORD_AUDIO')
},
// 录制语音消息
startRecord(e) {
startRecord(e) {
this.getAndroidPermission().then(code => {
switch (code) {
case 1:
this.startOffsetTop = e.target.offsetTop
case 1:
this.startOffsetTop = e.target.offsetTop
this.showRecordTip = true
this.recorderManager.start()
this.interval = setInterval(() => {
@@ -96,103 +97,103 @@
})
},
// 结束录音
stopRecord(e) {
if (!this.showRecordTip) return
// 延迟500毫秒结束录音
setTimeout(()=> {
this.recorderManager.stop()
clearInterval(this.interval)
// 监听录音结束
this.recorderManager.onStop(res => {
if(this.isMoveCancel) {
this.isMoveCancel = false
return
}
if((this.maxRecordTime - this.recordTime) <= 0){
uni.showToast({
title: '说话时间太短',
icon : 'none',
})
this.showRecordTip = false
return
}
this.mp3AudioSrc = res.tempFilePath
this.showRecordTip = false
this.senVoice()
})
},500)
},
// 发送语音消息
senVoice(){
if(this.mp3AudioSrc === null) {
uni.showToast({
title: '发送失败, 暂无音频信息',
icon : 'none'
})
return
}
im.sentVoice(this.conversationType, this.targetId, this.mp3AudioSrc, (this.maxRecordTime -
this.recordTime), this.sender, () => {
this.recordTime = this.maxRecordTime
this.mp3AudioSrc = null
setTimeout(() => {
this.$emit('success')
this.toastAudiMp3()
}, 500)
})
},
// 移动按钮
touchmove(e){
if(this.startOffsetTop - e.changedTouches[0].pageY > 100){
if(this.showRecordTip){
this.isMoveCancel = true
this.showRecordTip = false
this.recorderManager.stop()
clearInterval(this.interval)
this.recordTime = this.maxRecordTime
this.mp3AudioSrc = null
return
}
}
},
// 试听语音
startPlay() {
let betaAudio = uni.createInnerAudioContext()
betaAudio.src = this.mp3AudioSrc;
// 在播放中
if(this.isBetaPlay){
betaAudio.stop()
betaAudio.onStop(() => {
this.isBetaPlay = false;
betaAudio.destroy()
})
return
}
// 监听音频播放中
betaAudio.play()
betaAudio.onPlay(() => {
this.isBetaPlay = true;
})
// 监听音频结束
betaAudio.onEnded(() => {
this.isBetaPlay = false;
betaAudio.destroy()
})
},
// 播放提示音乐
toastAudiMp3(){
let toastAudio = uni.createInnerAudioContext()
toastAudio.src = require('@/static/im/toast/sentVoice.mp3')
toastAudio.autoplay = true
toastAudio.volume = .1
toastAudio.onEnded(() => {
toastAudio.destroy()
})
stopRecord(e) {
if (!this.showRecordTip) return
// 延迟500毫秒结束录音
setTimeout(() => {
this.recorderManager.stop()
clearInterval(this.interval)
// 监听录音结束
this.recorderManager.onStop(res => {
if (this.isMoveCancel) {
this.isMoveCancel = false
return
}
if ((this.maxRecordTime - this.recordTime) <= 0) {
uni.showToast({
title: '说话时间太短',
icon: 'none',
})
this.showRecordTip = false
return
}
this.mp3AudioSrc = res.tempFilePath
this.showRecordTip = false
this.senVoice()
})
}, 500)
},
// 发送语音消息
senVoice() {
if (this.mp3AudioSrc === null) {
uni.showToast({
title: '发送失败, 暂无音频信息',
icon: 'none'
})
return
}
im.sentVoice(this.conversationType, this.targetId, this.mp3AudioSrc, (this.maxRecordTime -
this.recordTime)).then(() => {
this.recordTime = this.maxRecordTime
this.mp3AudioSrc = null
setTimeout(() => {
this.$emit('success')
this.toastAudiMp3()
}, 500)
})
},
// 移动按钮
touchmove(e) {
if (this.startOffsetTop - e.changedTouches[0].pageY > 100) {
if (this.showRecordTip) {
this.isMoveCancel = true
this.showRecordTip = false
this.recorderManager.stop()
clearInterval(this.interval)
this.recordTime = this.maxRecordTime
this.mp3AudioSrc = null
return
}
}
},
// 试听语音
startPlay() {
let betaAudio = uni.createInnerAudioContext()
betaAudio.src = this.mp3AudioSrc;
// 在播放中
if (this.isBetaPlay) {
betaAudio.stop()
betaAudio.onStop(() => {
this.isBetaPlay = false;
betaAudio.destroy()
})
return
}
// 监听音频播放中
betaAudio.play()
betaAudio.onPlay(() => {
this.isBetaPlay = true;
})
// 监听音频结束
betaAudio.onEnded(() => {
this.isBetaPlay = false;
betaAudio.destroy()
})
},
// 播放提示音乐
toastAudiMp3() {
let toastAudio = uni.createInnerAudioContext()
toastAudio.src = require('@/static/im/toast/sentVoice.mp3')
toastAudio.autoplay = true
toastAudio.volume = .1
toastAudio.onEnded(() => {
toastAudio.destroy()
})
}
}
}
</script>
</script>
<style>
@keyframes playFlicker {
0% {
@@ -225,77 +226,86 @@
width: 400rpx;
border-radius: 10rpx;
margin-right: 15rpx;
padding: 0 20rpx;
font-weight: bold;
padding: 0 20rpx;
font-weight: bold;
.button {
font-size: 30rpx;
color: #333;
}
}
.lay{
position: absolute;
left: 0;
top: 0;
z-index: 9;
background: rgba($color: #000000, $alpha: .5);
height: 100vh;
width: 100vw;
box-sizing: border-box;
.lay-header{
height: calc(100vh - 140px);
display: flex;
justify-content: center;
align-items: center;
.modal {
display: flex;
background: rgba(0, 0, 0, .6);
position: fixed;
height: 200rpx;
width: 300rpx;
border-radius: 10rpx;
z-index: 99;
flex-direction: column;
align-items: center;
justify-content: center;
.icon {
width: 88rpx;
height: 88rpx;
}
.text {
font-size: 28rpx;
color: #FFFFFF;
}
}
}
.lay-toast{
text-align: center;
color: rgba($color: #fff, $alpha: .8);
font-size: 28rpx;
}
.lay-footer{
background-color: white;
height: 100px;
border-radius: 50% 50% 0 0;
position: absolute;
bottom: 0;
left: 0;
right: 0;
text-align: center;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
.lay-footer-icon{
width: 58rpx;
height: 58rpx;
}
.lay-footer-text{
line-height: 40rpx;
color: gray;
font-size: 28rpx;
}
}
}
.lay {
position: absolute;
left: 0;
top: 0;
z-index: 9;
background: rgba($color: #000000, $alpha: .5);
height: 100vh;
width: 100vw;
box-sizing: border-box;
.lay-header {
height: calc(100vh - 140px);
display: flex;
justify-content: center;
align-items: center;
.modal {
display: flex;
background: rgba(0, 0, 0, .6);
position: fixed;
height: 200rpx;
width: 300rpx;
border-radius: 10rpx;
z-index: 99;
flex-direction: column;
align-items: center;
justify-content: center;
.icon {
width: 88rpx;
height: 88rpx;
}
.text {
font-size: 28rpx;
color: #FFFFFF;
}
}
}
.lay-toast {
text-align: center;
color: rgba($color: #fff, $alpha: .8);
font-size: 28rpx;
}
.lay-footer {
background-color: white;
height: 100px;
border-radius: 50% 50% 0 0;
position: absolute;
bottom: 0;
left: 0;
right: 0;
text-align: center;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
.lay-footer-icon {
width: 58rpx;
height: 58rpx;
}
.lay-footer-text {
line-height: 40rpx;
color: gray;
font-size: 28rpx;
}
}
}
}
</style>

View File

@@ -1,6 +1,7 @@
<template>
<view class="chat">
<sent-message-bar id="msgbar" :conversationType="conversationType" :targetId="targetId" @onSuccess="getNewMessage()" />
<sent-message-bar id="msgbar" :conversationType="conversationType" :targetId="targetId"
@onSuccess="getNewMessage()" />
<view class="shade" @click="hidePop" v-show="showPop">
<view class="pop" :style="popStyle" :class="{'show':showPop}">
@@ -31,13 +32,13 @@
import showMessageCell from '../components/showMessageCell'
import utils from '@/utils/index.js'
import onGroupDismiss from '../mixins/onGroupDismiss.js'
import imBase from '../mixins/imBase.js'
import imBase from '../mixins/imBase.js'
import messageActions from '../mixins/messageActions.js'
export default {
mixins: [
imBase,
onGroupDismiss,
onGroupDismiss,
messageActions
],
components: {
@@ -52,8 +53,8 @@
messages: [],
groupInfo: {
name: ''
},
placeHeight: uni.getSystemInfoSync().windowHeight,
},
placeHeight: uni.getSystemInfoSync().windowHeight,
bottomHeihgt: 56
}
},
@@ -71,21 +72,21 @@
onShow() {
this.initGroupInfo()
},
onLoad(e) {
const query = uni.createSelectorQuery().in(this);
this.$nextTick(function() {
query.select('#msgbar').boundingClientRect(bottom => {
this.bottomHeihgt = bottom.height
}).exec();
})
// 监听键盘高度变化
uni.onKeyboardHeightChange(keyboard => {
query.select('#scroll').boundingClientRect(scroll => {
const placeHeight = this.windowHeight - scroll.height - keyboard.height - this
.bottomHeihgt
this.placeHeight = placeHeight > 0 ? placeHeight : 0
}).exec();
})
onLoad(e) {
const query = uni.createSelectorQuery().in(this);
this.$nextTick(function() {
query.select('#msgbar').boundingClientRect(bottom => {
this.bottomHeihgt = bottom.height
}).exec();
})
// 监听键盘高度变化
uni.onKeyboardHeightChange(keyboard => {
query.select('#scroll').boundingClientRect(scroll => {
const placeHeight = this.windowHeight - scroll.height - keyboard.height - this
.bottomHeihgt
this.placeHeight = placeHeight > 0 ? placeHeight : 0
}).exec();
})
this.targetId = e.targetId
// 获取历史消息列表
this.getMessageList()
@@ -116,7 +117,7 @@
})
// 清理聊天记录
uni.$once('cleanGroupMessage', this.getMessageList)
uni.$on('onRecallMessage_' + this.targetId, (message) => {
uni.$on('onRecallMessage_' + this.targetId, (message) => {
this.messages = this.messages.map(item => {
if (message.messageId == item.messageId) {
return message
@@ -175,12 +176,9 @@
20,
true,
(messages) => {
console.log('获取消息列表', messages);
const msgs = messages.filter(item => item.receivedStatus == 0)
console.log('未读消息', msgs);
if (msgs.length) {
RongIMLib.sendReadReceiptResponse(3, this.targetId, msgs, (res) => {
console.error('发送群聊已读回执成功', res);
msgs.map(item => {
RongIMLib.setMessageReceivedStatus(item.messageId, 1)
})
@@ -245,7 +243,7 @@
height: 100%;
z-index: 999;
.pop {
.pop {
border-radius: 10rpx;
position: fixed;
z-index: 101;