ui库和web端产品库合并版本(还需修复细节)
This commit is contained in:
238
ui/packages/basic/AiAudio.vue
Normal file
238
ui/packages/basic/AiAudio.vue
Normal file
@@ -0,0 +1,238 @@
|
||||
<template>
|
||||
<section class="ai-audio">
|
||||
<div class="controller" :class="skinClassName">
|
||||
<el-row :gutter="10" type="flex">
|
||||
<el-col>
|
||||
<i class="play-icon" :class="playIcon" @click="play"></i>
|
||||
</el-col>
|
||||
<el-col class="play-progress">
|
||||
<el-slider
|
||||
:format-tooltip="getDateFormat"
|
||||
v-model="currentTime"
|
||||
:max="totalDuration"
|
||||
@change="audio.currentTime = currentTime">
|
||||
</el-slider>
|
||||
<span class="total" v-if="skin === 'flat'">{{ getDateFormat(currentTime) }}</span>
|
||||
<span class="total" v-else>{{ [getDateFormat(currentTime), getDateFormat(totalDuration)].join('/') }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<audio
|
||||
ref="audio"
|
||||
style="display: none;"
|
||||
:src="src"
|
||||
preload="metadata"
|
||||
@pause="playState = false"
|
||||
@playing="playing"
|
||||
@loadedmetadata="loadedmetadata"
|
||||
@timeupdate="timeupdate"
|
||||
></audio>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'dayjs'
|
||||
|
||||
export default {
|
||||
name: 'AiAudio',
|
||||
props: {
|
||||
/**
|
||||
* 播放资源url
|
||||
*/
|
||||
src: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
/**
|
||||
* 同时只允许一个播放
|
||||
*/
|
||||
singlePlay: {type: Boolean, default: false},
|
||||
/**
|
||||
* 播放器风格
|
||||
* default 旧版样式,flat 新版样式
|
||||
* @values default,flat
|
||||
*/
|
||||
skin: {
|
||||
type: String,
|
||||
default: 'default'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
audio: null,
|
||||
playState: false,
|
||||
currentTime: 0,
|
||||
totalTime: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
playIcon() {
|
||||
if (this.skin === 'flat') {
|
||||
return this.playState ? 'iconfont iconMediaPlayer_Stop' : 'iconfont iconMediaPlayer_Play'
|
||||
}
|
||||
|
||||
return this.playState ? 'el-icon-video-pause' : 'el-icon-video-play'
|
||||
},
|
||||
|
||||
totalDuration() {
|
||||
return Math.round(this.totalTime)
|
||||
},
|
||||
|
||||
skinClassName() {
|
||||
return this.skin === 'default' ? '' : this.skin
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.audio = this.$refs.audio
|
||||
},
|
||||
|
||||
methods: {
|
||||
play() {
|
||||
if (this.audio) {
|
||||
if (this.audio.paused) {
|
||||
if (this.singlePlay) this.stopAllAudio()
|
||||
this.audio.play()
|
||||
} else {
|
||||
this.audio.pause()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
stopAllAudio() {
|
||||
let audios = document.getElementsByTagName('audio')
|
||||
for (let i = 0; i < audios.length; i++) {
|
||||
if (audios[i]) audios[i].pause()
|
||||
}
|
||||
},
|
||||
|
||||
playing() {
|
||||
this.playState = true
|
||||
},
|
||||
|
||||
loadedmetadata() {
|
||||
this.totalTime = this.$refs.audio.duration || 0
|
||||
},
|
||||
|
||||
getDateFormat(val) {
|
||||
const time = moment.duration(val, 'seconds')
|
||||
return [
|
||||
this.prefixNum(time.minutes(), 2),
|
||||
this.prefixNum(time.seconds(), 2),
|
||||
].join(':')
|
||||
},
|
||||
|
||||
prefixNum(val, num) {
|
||||
return (Array(num).join('0') + val).slice(-num)
|
||||
},
|
||||
|
||||
timeupdate() {
|
||||
this.currentTime = parseInt(this.audio.currentTime)
|
||||
}
|
||||
},
|
||||
|
||||
destroyed() {
|
||||
this.audio.pause()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.ai-audio {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
|
||||
.controller {
|
||||
width: 205px;
|
||||
height: 40px;
|
||||
padding: 0 5px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
border-radius: 99px;
|
||||
|
||||
.el-col {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.play-icon {
|
||||
color: #4c84ff;
|
||||
cursor: pointer;
|
||||
line-height: 40px;
|
||||
font-size: 32px;
|
||||
transition: color 0.3s;
|
||||
|
||||
&:hover {
|
||||
color: #b3d8ff;
|
||||
}
|
||||
}
|
||||
|
||||
.play-progress {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
|
||||
.el-slider {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.total {
|
||||
margin-left: 15px;
|
||||
font-size: 12px;
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.flat {
|
||||
height: 32px;
|
||||
background: rgba(239, 246, 255, 1);
|
||||
border: 1px solid rgba(132, 181, 255, 1);
|
||||
border-radius: 5px;
|
||||
box-shadow: none;
|
||||
|
||||
.play-icon {
|
||||
position: relative;
|
||||
padding-left: 3px;
|
||||
color: #4c84ff;
|
||||
cursor: pointer;
|
||||
line-height: 32px;
|
||||
font-size: 20px;
|
||||
transition: color 0.3s;
|
||||
|
||||
&:hover {
|
||||
color: #b3d8ff;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep.el-slider__button {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: #1365DD;
|
||||
}
|
||||
|
||||
::v-deep.el-slider__bar {
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
::v-deep.el-slider__button-wrapper {
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
::v-deep.el-slider__runway {
|
||||
height: 2px;
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.play-progress {
|
||||
display: flex;
|
||||
|
||||
.el-slider {
|
||||
width: 84px;
|
||||
}
|
||||
|
||||
.total {
|
||||
margin-left: 8px;
|
||||
font-size: 12px;
|
||||
line-height: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user