Skip to content

Commit

Permalink
feat: 全部歌单页面
Browse files Browse the repository at this point in the history
  • Loading branch information
sl1673495 committed Jul 25, 2019
1 parent 8f1cb23 commit f524c86
Show file tree
Hide file tree
Showing 29 changed files with 447 additions and 87 deletions.
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="stylesheet" type="text/css" href="//at.alicdn.com/t/font_777085_l3va2z9boyg.css">
<link rel="stylesheet" type="text/css" href="//at.alicdn.com/t/font_777085_pk0u28fv7cl.css">
<title>vue-netease-muisc</title>
</head>

Expand Down
3 changes: 3 additions & 0 deletions src/api/playlist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import {request} from '@/utils/axios'

export const getPlaylists = (params) => request.get('/top/playlist', { params })
11 changes: 7 additions & 4 deletions src/base/leave-hide.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,22 @@ export default {
default: false
},
reserveDoms: {
type: Array
type: Array,
default: () => []
}
},
methods: {
clickEvent(e) {
const triggerElement = e.target
// 触发点击事件的dom是否是playlist的子节点
const firstChildElm = this.$slots.default[0].elm
const defaultReserveDoms = Array.from(
document.querySelectorAll('.el-loading-mask, .el-loading-spinner')
)
const reserves = defaultReserveDoms.concat(firstChildElm)
if (!hasParent(
triggerElement,
this.reserveDoms
? this.reserveDoms.concat(firstChildElm)
: firstChildElm
reserves.concat(this.reserveDoms)
)) {
this.$emit('clickOutside')
}
Expand Down
105 changes: 105 additions & 0 deletions src/base/tabs.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<template>
<div
class="tab-wrap"
:class="{[align]: true}"
>
<div
v-for="(tab, index) in tabs"
:key="index"
class="tab-item"
:class="getActiveCls(tab, index)"
@click="onChangeTab(tab, index)"
>
<span class="title">
{{tab.title}}
</span>
</div>
</div>
</template>

<script type="text/ecmascript-6">
const ACTIVE_PROP = 'active'
const ACTIVE_CHANGE = 'tabChange'
export default {
created() {
this.ACTIVE_PROP = ACTIVE_PROP
},
props: {
[ACTIVE_PROP]: {
type: Number,
default: 0,
},
tabs: {
type: Array,
default: () => []
},
align: {
type: String,
default: 'left'
}
},
model: {
prop: ACTIVE_PROP,
event: ACTIVE_CHANGE
},
methods: {
onChangeTab(tab, index) {
if (this.isRouteMode) {
this.$router.push(tab.to)
} else {
this.$emit(ACTIVE_CHANGE, index)
}
},
getActiveCls(tab, index) {
const ACTIVE_CLS = 'active'
// 路由模式
if (this.isRouteMode) {
if (this.$route.path === tab.to) {
return ACTIVE_CLS
}
} else if (index === this[ACTIVE_PROP]) {
return ACTIVE_CLS
}
}
},
computed: {
isRouteMode() {
return this.tabs.length && !!this.tabs[0].to
}
}
}
</script>

<style lang="scss" scoped>
.tab-wrap {
// padding: 12px;
display: flex;
&.center {
justify-content: center;
}
.tab-item {
padding: 12px;
color: var(--tab-item-color);
cursor: pointer;
&.active {
color: var(--tab-item-active-color);
&:hover {
color: var(--tab-item-active-color);
}
}
&:hover {
color: var(--tab-item-hover-color);
}
.title {
font-size: $font-size-medium;
}
}
}
</style>
15 changes: 9 additions & 6 deletions src/components/mini-player.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
:value="isPlaylistPromptShow"
trigger="manual"
>
<p>已加入歌单</p>
<p>已更新歌单</p>
<Icon
slot="reference"
class="icon"
Expand All @@ -65,8 +65,8 @@
@click.native="togglePlaylistShow"
/>
</el-popover>

<volume @volumeChange="onVolumeChange" />
<!-- 音量 -->
<Volume @volumeChange="onVolumeChange" />
</div>
<div
v-if="hasCurrentSong"
Expand All @@ -84,14 +84,13 @@
@ended="end"
@timeupdate="updateTime"
></audio>

</div>
</template>

<script type="text/ecmascript-6">
import { mapState, mapMutations, mapGetters, mapActions } from "vuex"
import ProgressBar from "@/base/progress-bar"
import volume from '@/base/volume'
import Volume from '@/base/volume'
import { formatTime } from "@/utils/common"
export default {
Expand Down Expand Up @@ -155,9 +154,13 @@ export default {
},
watch: {
currentSong(newSong, oldSong) {
// 清空了歌曲
if (!newSong.id) {
this.audio.pause()
this.audio.currentTime = 0
return
}
// 单曲循环
if (oldSong) {
if (newSong.id === oldSong.id) {
this.currentTime = 0
Expand Down Expand Up @@ -203,7 +206,7 @@ export default {
...mapGetters(["prevSong", "nextSong"])
},
components: {
ProgressBar, volume
ProgressBar, Volume
}
}
</script>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
<template>
<div class="play-list-card">
<div
@click="onClickCard"
class="playlist-card"
>
<div class="img-wrap">
<img :src="img" />
<div class="desc-wrap">
<img :src="`${img}?param=300y300`" />
<div
v-if="desc"
class="desc-wrap"
>
<span class="desc">{{desc}}</span>
</div>
<Icon
Expand All @@ -16,12 +22,17 @@

<script>
export default {
props: ["img", "name", "desc"]
props: ["id", "img", "name", "desc"],
methods: {
onClickCard() {
this.$router.push(`/playlist/${this.id}`)
}
}
}
</script>

<style lang="scss" scoped>
.play-list-card {
.playlist-card {
position: relative;
width: calc(20% - 8px);
margin: 4px;
Expand All @@ -33,6 +44,7 @@ export default {
width: 100%;
padding-top: 100%;
margin-bottom: 8px;
border-radius: 4px;
overflow: hidden;
img {
Expand Down
77 changes: 66 additions & 11 deletions src/components/playlist.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,31 @@
v-show="isPlaylistShow"
class="playlist"
>
<Tabs
v-model="activeTab"
:tabs="tabs"
align="center"
/>
<div class="header">
<p class="total">总共{{playlist.length}}首</p>
<p class="total">总共{{dataSource.length}}首</p>
<div
class="remove"
v-if="dataSource.length"
@click="clear"
>
<Icon type="remove" />
<span class="text">清空</span>
</div>
</div>
<template>
<div
v-if="playlist.length"
v-if="dataSource.length"
class="song-table-wrap"
>
<SongTable
:songs="playlist"
:songs="dataSource"
:hideColumns="['index', 'albumName']"
:showPromptOnPlay="false"
/>
</div>
<div
Expand All @@ -35,32 +49,59 @@
</template>

<script type="text/ecmascript-6">
import { mapState, mapMutations } from 'vuex'
import { mapState, mapMutations, mapActions } from 'vuex'
import Tabs from '@/base/tabs'
import LeaveHide from '@/base/leave-hide'
import SongTable from './song-table'
export default {
mounted() {
// 点击需要保留播放器的dom
this.reserveDoms = [
this.$refs.playlist,
document.getElementById('mini-player'),
...document.querySelectorAll('.el-loading-mask')
]
},
data() {
this.tabs = [{
title: '播放列表',
}, {
title: '历史记录'
}]
this.LIST_TAB = 0
this.HISTORY_TAB = 1
return {
reserveDoms: null
activeTab: this.LIST_TAB,
reserveDoms: null,
}
},
methods: {
...mapMutations(['setPlaylistShow'])
clear() {
if (this.isPlaylist) {
this.setPlaylist({
data: [],
showPrompt: false
})
this.clearCurrentSong()
} else {
this.clearHistory()
}
},
...mapMutations(['setPlaylistShow', 'setPlaylist']),
...mapActions(['clearCurrentSong', 'clearHistory'])
},
computed: {
...mapState(['isPlaylistShow', 'playlist'])
dataSource() {
return this.isPlaylist ? this.playlist : this.playHistory
},
isPlaylist() {
return this.activeTab === this.LIST_TAB
},
...mapState(['isPlaylistShow', 'playlist', 'playHistory'])
},
components: {
SongTable,
LeaveHide
LeaveHide,
Tabs
}
}
</script>
Expand All @@ -82,13 +123,27 @@ export default {
@include el-table-theme(var(--playlist-bgcolor));
.header {
padding: 16px 0;
display: flex;
justify-content: space-between;
align-items: center;
height: 40px;
margin: 0 20px;
border-bottom: 1px solid var(--border);
.total {
font-size: $font-size-sm;
}
.remove {
@include flex-center;
cursor: pointer;
font-size: $font-size-sm;
.text {
display: inline-block;
margin-left: 4px;
}
}
}
.song-table-wrap {
Expand Down
4 changes: 2 additions & 2 deletions src/components/search.vue
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,11 @@ export default {
id, name, artists, duration
})
this.startSong(song)
this.setPlaylist([song])
this.setPlaylist({ data: [song] })
},
onClickPlaylist(item) {
const { id } = item
this.$router.push(`/song-list-detail/${id}`)
this.$router.push(`/playlist/${id}`)
this.searchPanelShow = false
},
...mapMutations(['setPlaylist']),
Expand Down
Loading

0 comments on commit f524c86

Please sign in to comment.