194 lines
3.9 KiB
Vue
194 lines
3.9 KiB
Vue
<template>
|
||
<div class="audio-message">
|
||
<div class="videodisc">
|
||
<div class="disc" :class="{ play: isPlay }" @click="toPlay">
|
||
<i v-if="loading" class="el-icon-loading" />
|
||
<i v-else-if="isPlay" class="el-icon-video-pause" />
|
||
<i v-else class="el-icon-video-play" />
|
||
<audio
|
||
ref="audio"
|
||
type="audio/mp3"
|
||
:src="src"
|
||
@timeupdate="timeupdate"
|
||
@ended="ended"
|
||
@canplay="canplay"
|
||
></audio>
|
||
</div>
|
||
</div>
|
||
<div class="detail">
|
||
<div class="text">
|
||
<i class="el-icon-service" />
|
||
<span>{{ getCurrDuration }} / {{ getTotalDuration }}</span>
|
||
</div>
|
||
<div class="process">
|
||
<el-progress :percentage="progress" :show-text="false" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
function formatSeconds(value) {
|
||
var theTime = parseInt(value) // 秒
|
||
var theTime1 = 0 // 分
|
||
var theTime2 = 0 // 小时
|
||
if (theTime > 60) {
|
||
theTime1 = parseInt(theTime / 60)
|
||
theTime = parseInt(theTime % 60)
|
||
if (theTime1 > 60) {
|
||
theTime2 = parseInt(theTime1 / 60)
|
||
theTime1 = parseInt(theTime1 % 60)
|
||
}
|
||
}
|
||
|
||
var result = '' + parseInt(theTime) //秒
|
||
if (10 > theTime > 0) {
|
||
result = '0' + parseInt(theTime) //秒
|
||
} else {
|
||
result = '' + parseInt(theTime) //秒
|
||
}
|
||
|
||
if (10 > theTime1 > 0) {
|
||
result = '0' + parseInt(theTime1) + ':' + result //分,不足两位数,首位补充0,
|
||
} else {
|
||
result = '' + parseInt(theTime1) + ':' + result //分
|
||
}
|
||
if (theTime2 > 0) {
|
||
result = '' + parseInt(theTime2) + ':' + result //时
|
||
}
|
||
return result
|
||
}
|
||
|
||
export default {
|
||
name: 'AudioMessage',
|
||
props: {
|
||
src: {
|
||
type: String,
|
||
default: '',
|
||
},
|
||
},
|
||
data() {
|
||
return {
|
||
loading: true,
|
||
isPlay: false,
|
||
duration: 0,
|
||
currentTime: 0,
|
||
progress: 0,
|
||
}
|
||
},
|
||
computed: {
|
||
getTotalDuration() {
|
||
return formatSeconds(this.duration)
|
||
},
|
||
getCurrDuration() {
|
||
return formatSeconds(this.currentTime)
|
||
},
|
||
},
|
||
methods: {
|
||
toPlay() {
|
||
if (this.loading) {
|
||
return
|
||
}
|
||
|
||
let audio = this.$refs.audio
|
||
if (this.isPlay) {
|
||
audio.pause()
|
||
} else {
|
||
audio.play()
|
||
}
|
||
this.isPlay = !this.isPlay
|
||
},
|
||
|
||
// 当目前的播放位置已更改时
|
||
timeupdate() {
|
||
let audio = this.$refs.audio
|
||
this.currentTime = audio.currentTime
|
||
this.progress = (audio.currentTime / audio.duration) * 100
|
||
},
|
||
|
||
// 当浏览器可以播放音频/视频时
|
||
canplay() {
|
||
this.duration = this.$refs.audio.duration
|
||
this.loading = false
|
||
},
|
||
|
||
// 当目前的播放列表已结束时
|
||
ended() {
|
||
this.isPlay = false
|
||
},
|
||
},
|
||
}
|
||
</script>
|
||
<style scoped lang="less">
|
||
.audio-message {
|
||
width: 200px;
|
||
height: 60px;
|
||
border-radius: 5px;
|
||
background: #ffffff;
|
||
display: flex;
|
||
align-items: center;
|
||
border: 1px solid #03a9f4;
|
||
overflow: hidden;
|
||
|
||
> div {
|
||
height: 100%;
|
||
}
|
||
|
||
.videodisc {
|
||
flex-basis: 60px;
|
||
flex-shrink: 0;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
.disc {
|
||
width: 42px;
|
||
height: 42px;
|
||
background: #e9e5e5;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: white;
|
||
cursor: pointer;
|
||
transition: ease 0.5;
|
||
|
||
&.play {
|
||
background: #ff5722;
|
||
box-shadow: 0 0 4px 0px #f76a3e;
|
||
}
|
||
|
||
i {
|
||
font-size: 24px;
|
||
}
|
||
|
||
&:active i {
|
||
transform: scale(1.1);
|
||
}
|
||
}
|
||
}
|
||
|
||
.detail {
|
||
flex: 1 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
padding-top: 10px;
|
||
|
||
.text {
|
||
width: 90%;
|
||
font-size: 12px;
|
||
i {
|
||
margin-right: 5px;
|
||
}
|
||
}
|
||
|
||
.process {
|
||
padding-top: 10px;
|
||
height: 20px;
|
||
width: 90%;
|
||
}
|
||
}
|
||
}
|
||
</style>
|