8 changed files with 390 additions and 16 deletions
@ -0,0 +1,304 @@
@@ -0,0 +1,304 @@
|
||||
<template> |
||||
<div class="MusicCollect"> |
||||
<BaseHeader> |
||||
<template v-slot:center> |
||||
<span class="f16">音乐收藏</span> |
||||
</template> |
||||
</BaseHeader> |
||||
<div class="content"> |
||||
<div class="list"> |
||||
<div class="item" v-for="(item,index) in list" @click="togglePlay(item,list)"> |
||||
<div class="music"> |
||||
<div class="cover-wrapper"> |
||||
<img v-lazy="$imgPreview(item.cover)" alt="" class="cover"> |
||||
<img v-if="!item.is_play" src="@/assets/img/icon/play-white.png" alt="" class="play"> |
||||
<img v-if="item.is_play" src="@/assets/img/icon/pause-white.png" alt="" class="play"> |
||||
</div> |
||||
<div class="desc"> |
||||
<span class="name">{{ item.name }}</span> |
||||
<div class="author">{{ item.author }}</div> |
||||
<div class="desc-bottom"> |
||||
<div class="duration">{{ $duration(item.duration) }}</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="option"> |
||||
<img src="@/assets/img/icon/menu2-white.png" alt="" @click.stop="$nav('/home/music')"> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<no-more class="mb7r"/> |
||||
</div> |
||||
<div class="float-play-music" v-if="currentItem"> |
||||
<div class="process" :style="{width : process + 'px'}"></div> |
||||
<div class="music-wrapper"> |
||||
<div class="music"> |
||||
<div class="cover-wrapper"> |
||||
<img v-lazy="$imgPreview(currentItem.cover)" alt="" class="cover"> |
||||
<img v-if="!currentItem.is_play" src="@/assets/img/icon/play-white.png" alt="" class="play"> |
||||
<img v-if="currentItem.is_play" src="@/assets/img/icon/pause-white.png" alt="" class="play"> |
||||
</div> |
||||
<div class="desc"> |
||||
<span class="name">{{ currentItem.name }}</span> |
||||
<div class="desc-bottom"> |
||||
<div class="duration">{{ $duration(currentItem.duration) }}</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="option"> |
||||
<b-button type="primary" size="small">使用</b-button> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import {mapState} from "vuex"; |
||||
|
||||
export default { |
||||
name: "MusicCollect", |
||||
components: {}, |
||||
props: {}, |
||||
data() { |
||||
return { |
||||
list: [], |
||||
audio: new Audio(), |
||||
currentItem: null, |
||||
step: null, |
||||
process: 0, |
||||
} |
||||
}, |
||||
computed: { |
||||
...mapState(['bodyWidth']) |
||||
}, |
||||
created() { |
||||
this.getData() |
||||
}, |
||||
mounted() { |
||||
this.audio.addEventListener('loadedmetadata', e => { |
||||
this.currentItem.duration = this.audio.duration |
||||
this.step = this.bodyWidth / Math.floor(this.audio.duration) |
||||
}) |
||||
this.audio.addEventListener('timeupdate', e => { |
||||
this.process = Math.ceil(e.target.currentTime) * this.step |
||||
}) |
||||
}, |
||||
methods: { |
||||
async getData() { |
||||
let res = await this.$api.videos.collect() |
||||
if (res.code === this.SUCCESS) { |
||||
this.list = res.data.music.list |
||||
} |
||||
}, |
||||
togglePlay(item, list) { |
||||
list.map(v => { |
||||
if (v.name !== item.name) { |
||||
v.is_play = false |
||||
} |
||||
}) |
||||
item.is_play = !item.is_play |
||||
if (item.is_play) { |
||||
if (this.currentItem) { |
||||
if (this.currentItem.name !== item.name) { |
||||
this.audio.pause() |
||||
this.audio.src = item.mp3 |
||||
this.audio.currentTime = 0 |
||||
} |
||||
} else { |
||||
this.audio.pause() |
||||
this.audio.src = item.mp3 |
||||
this.audio.currentTime = 0 |
||||
} |
||||
this.audio.play(); |
||||
this.audio.addEventListener('ended', () => item.is_play = false) |
||||
} else { |
||||
this.stopPlay() |
||||
} |
||||
this.currentItem = item |
||||
}, |
||||
stopPlay() { |
||||
this.audio.pause() |
||||
// this.audio.currentTime = 0 |
||||
this.audio.removeEventListener('ended', null) |
||||
} |
||||
}, |
||||
unmounted() { |
||||
this.stopPlay() |
||||
}, |
||||
} |
||||
</script> |
||||
|
||||
<style scoped lang="less"> |
||||
@import "@/assets/scss/index"; |
||||
|
||||
.MusicCollect { |
||||
position: fixed; |
||||
left: 0; |
||||
right: 0; |
||||
bottom: 0; |
||||
top: 0; |
||||
overflow: auto; |
||||
color: white; |
||||
font-size: 1.4rem; |
||||
|
||||
.content { |
||||
padding-top: 6rem; |
||||
|
||||
.list { |
||||
.item { |
||||
padding: 2rem 1.5rem; |
||||
padding-bottom: 0; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
|
||||
.music { |
||||
display: flex; |
||||
|
||||
.cover-wrapper { |
||||
margin-right: 1rem; |
||||
position: relative; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
|
||||
.play { |
||||
width: 3rem; |
||||
height: 3rem; |
||||
position: absolute; |
||||
} |
||||
|
||||
.cover { |
||||
border-radius: .2rem; |
||||
@width: 6rem; |
||||
width: @width; |
||||
height: @width; |
||||
} |
||||
} |
||||
|
||||
.desc { |
||||
display: flex; |
||||
flex-direction: column; |
||||
justify-content: space-between; |
||||
|
||||
.name { |
||||
white-space: nowrap; |
||||
text-overflow: ellipsis; |
||||
overflow: hidden; |
||||
max-width: 40vw; |
||||
} |
||||
|
||||
.author, .desc-bottom { |
||||
font-size: 1.2rem; |
||||
color: @second-text-color; |
||||
} |
||||
|
||||
.desc-bottom { |
||||
display: flex; |
||||
|
||||
.duration { |
||||
margin-right: 1.4rem; |
||||
position: relative; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.option { |
||||
img { |
||||
width: 2rem; |
||||
height: 2rem; |
||||
margin-left: 2rem; |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
||||
} |
||||
|
||||
.float-play-music { |
||||
position: fixed; |
||||
bottom: 0; |
||||
width: 100vw; |
||||
background: @main-bg; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
|
||||
.process { |
||||
position: absolute; |
||||
top: 0; |
||||
z-index: 2; |
||||
height: 1px; |
||||
width: 50vw; |
||||
background: yellow; |
||||
} |
||||
|
||||
.music-wrapper { |
||||
width: 100vw; |
||||
border-top: 1px solid #414141; |
||||
padding: 1rem 1.5rem; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
|
||||
.music { |
||||
display: flex; |
||||
|
||||
.cover-wrapper { |
||||
margin-right: 1rem; |
||||
position: relative; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
|
||||
.play { |
||||
width: 3rem; |
||||
height: 3rem; |
||||
position: absolute; |
||||
} |
||||
|
||||
.cover { |
||||
border-radius: .2rem; |
||||
@width: 5rem; |
||||
width: @width; |
||||
height: @width; |
||||
} |
||||
} |
||||
|
||||
.desc { |
||||
display: flex; |
||||
flex-direction: column; |
||||
justify-content: space-between; |
||||
|
||||
.name { |
||||
white-space: nowrap; |
||||
text-overflow: ellipsis; |
||||
overflow: hidden; |
||||
max-width: 40vw; |
||||
} |
||||
|
||||
.author, .desc-bottom { |
||||
font-size: 1.2rem; |
||||
color: @second-text-color; |
||||
} |
||||
|
||||
.desc-bottom { |
||||
display: flex; |
||||
|
||||
.duration { |
||||
margin-right: 1.4rem; |
||||
position: relative; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.option { |
||||
.button { |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
<template> |
||||
<div class="VideoCollect"> |
||||
<BaseHeader> |
||||
<template v-slot:center> |
||||
<span class="f16">申报学校信息</span> |
||||
</template> |
||||
</BaseHeader> |
||||
<div class="content"> |
||||
|
||||
</div> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
export default { |
||||
name: "VideoCollect", |
||||
components: {}, |
||||
props: { |
||||
modelValue: false |
||||
}, |
||||
data() { |
||||
return {} |
||||
}, |
||||
computed: {}, |
||||
created() { |
||||
}, |
||||
methods: {} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped lang="less"> |
||||
@import "../../../assets/scss/index"; |
||||
|
||||
.VideoCollect { |
||||
position: fixed; |
||||
left: 0; |
||||
right: 0; |
||||
bottom: 0; |
||||
top: 0; |
||||
overflow: auto; |
||||
color: white; |
||||
font-size: 1.4rem; |
||||
|
||||
.content { |
||||
padding-top: 6rem; |
||||
} |
||||
} |
||||
</style> |
Loading…
Reference in new issue