Files
im-uniapp/pages/conversation/chating/components/MessageItem/VoiceMessageRender.vue
2025-07-04 22:34:07 +08:00

97 lines
2.3 KiB
Vue

<template>
<view class="voice-message" @click="playVoice">
<image
:src="isPlaying ? audioIcon : recordIcon"
class="audio-icon flipped"
mode="aspectFit"
/>
<text class="duration">{{ durationText }}</text>
</view>
</template>
<script>
export default {
props: {
source: {
type: Object,
required: true
}
},
computed: {
durationText() {
const d = 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://47.117.71.33/api/object/ 开头,则替换为带端口的
if (typeof url === 'string' && url.startsWith('http://47.117.71.33/api/object/')) {
return url.replace('http://47.117.71.33/api/object/', 'http://47.117.71.33:15219/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.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>