105 lines
2.8 KiB
Vue
105 lines
2.8 KiB
Vue
<template>
|
||
<view class="voice-message" @click="playVoice">
|
||
<image
|
||
:src="isPlaying ? audioIcon : recordIcon"
|
||
:class="['audio-icon', { 'flipped': isSender }]"
|
||
mode="aspectFit"
|
||
/>
|
||
<text class="duration">{{ durationText }}</text>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
props: {
|
||
source: {
|
||
type: Object,
|
||
required: true
|
||
},
|
||
isSender: {
|
||
type: Boolean,
|
||
default: false
|
||
}
|
||
},
|
||
computed: {
|
||
durationText() {
|
||
const d = this.source && this.source.soundElem && this.source.soundElem.duration;
|
||
return d ? `${d}''` : '';
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
innerAudioContext: null,
|
||
isPlaying: false,
|
||
audioIcon: '/static/images/chating_footer_audio.png',
|
||
recordIcon: '/static/images/chating_footer_recording.png'
|
||
};
|
||
},
|
||
methods: {
|
||
getFixedSourceUrl(url) {
|
||
// 如果 url 以 http://49.232.154.205/api/object/ 开头,则替换为带端口的
|
||
// 或者 url 以 http://47.117.71.33/api/object/ 开头,也替换为http://49.232.154.205:10006/api/object/
|
||
if (typeof url === 'string' && url.startsWith('http://49.232.154.205/api/object/')) {
|
||
return url.replace('http://49.232.154.205/api/object/', 'http://49.232.154.205:10006/api/object/');
|
||
}
|
||
else if (typeof url === 'string' && url.startsWith('http://47.117.71.33/api/object/')) {
|
||
return url.replace('http://47.117.71.33/api/object/', 'http://49.232.154.205:10006/api/object/');
|
||
}
|
||
return url;
|
||
},
|
||
playVoice() {
|
||
if (this.innerAudioContext) {
|
||
this.innerAudioContext.stop();
|
||
this.innerAudioContext.destroy();
|
||
this.innerAudioContext = null;
|
||
}
|
||
this.innerAudioContext = uni.createInnerAudioContext();
|
||
const rawUrl = this.source && this.source.soundElem && this.source.soundElem.sourceUrl || '';
|
||
this.innerAudioContext.src = this.getFixedSourceUrl(rawUrl);
|
||
this.isPlaying = true;
|
||
this.innerAudioContext.play();
|
||
this.innerAudioContext.onEnded(() => {
|
||
this.innerAudioContext.destroy();
|
||
this.innerAudioContext = null;
|
||
this.isPlaying = false;
|
||
});
|
||
this.innerAudioContext.onStop(() => {
|
||
this.isPlaying = false;
|
||
});
|
||
this.innerAudioContext.onError(() => {
|
||
this.isPlaying = false;
|
||
});
|
||
}
|
||
},
|
||
beforeDestroy() {
|
||
if (this.innerAudioContext) {
|
||
this.innerAudioContext.destroy();
|
||
this.innerAudioContext = null;
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
.voice-message {
|
||
display: flex;
|
||
align-items: center;
|
||
cursor: pointer;
|
||
background: #f5f6fa;
|
||
border-radius: 18px;
|
||
padding: 8px 16px;
|
||
margin: 4px 0;
|
||
}
|
||
.audio-icon {
|
||
width: 28px;
|
||
height: 28px;
|
||
}
|
||
.flipped {
|
||
transform: rotate(180deg);
|
||
}
|
||
.duration {
|
||
margin-left: 8px;
|
||
color: #666;
|
||
font-size: 15px;
|
||
}
|
||
</style> |