Skip to content
This repository was archived by the owner on May 11, 2021. It is now read-only.

Commit 73265a6

Browse files
committed
完成 - player 添加 / 删除喜欢的歌曲逻辑,完成用户中心
1 parent 87c8e43 commit 73265a6

File tree

10 files changed

+293
-7
lines changed

10 files changed

+293
-7
lines changed

src/common/js/cache.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import localStorage from 'store/dist/store.modern'
1313

1414
const SEARCH_KEY = '__search__'
1515
const HAS_PLAYED_KEY = '__has_played__'
16+
const FAVORITE_SONGS_KEY = '__favorite_songs__'
1617

1718
const SEARCH_MAX_LENGTH = 15
1819
const HAS_PLAYED_MAX_LENGTH = 200
@@ -126,3 +127,35 @@ export function savePlayedSongs (query) {
126127
export function loadPlayedSongs () {
127128
return localStorage.get(HAS_PLAYED_KEY) || []
128129
}
130+
131+
/**
132+
* Save my favorite songs to localStorage
133+
*/
134+
135+
export function saveFavoriteSongs (song) {
136+
let favorite = localStorage.get(FAVORITE_SONGS_KEY) || []
137+
138+
insertItem(favorite, song, item => {
139+
return item.id === song.id
140+
})
141+
142+
localStorage.set(FAVORITE_SONGS_KEY, favorite)
143+
144+
return favorite
145+
}
146+
147+
export function deleteFavoriteSong (song) {
148+
let favorite = localStorage.get(FAVORITE_SONGS_KEY)
149+
150+
deleteItem(favorite, item => {
151+
return item.id === song.id
152+
})
153+
154+
localStorage.set(FAVORITE_SONGS_KEY, favorite)
155+
156+
return favorite
157+
}
158+
159+
export function loadFavoriteSongs () {
160+
return localStorage.get(FAVORITE_SONGS_KEY) || []
161+
}

src/components/app-header/app-header.vue

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,20 @@
22
<div class="app-header">
33
<div class="icon"></div>
44
<div class="text">Sonar Music</div>
5+
<div class="user-center" @click="showUserCenter">
6+
<i class="icon-mine"></i>
7+
</div>
58
</div>
69
</template>
710

811
<script>
9-
export default {}
12+
export default {
13+
methods: {
14+
showUserCenter () {
15+
this.$router.push({ path: '/user' })
16+
}
17+
}
18+
}
1019
</script>
1120

1221
<style lang="scss" scoped>
@@ -33,6 +42,17 @@ export default {}
3342
line-height: 44px;
3443
font-size: $font-size-large;
3544
}
45+
.user-center {
46+
position: absolute;
47+
top: 0;
48+
right: 0;
49+
.icon-mine {
50+
display: inline-block;
51+
padding: 12px;
52+
font-size: 20px;
53+
color: $color-theme;
54+
}
55+
}
3656
}
3757
3858
</style>

src/components/app-player/app-player.vue

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
<i class="icon-next" @click="nextSong"></i>
9999
</div>
100100
<div class="icon icon-right">
101-
<i class="icon icon-not-like"></i>
101+
<i :class="['icon', hasFavorite]" @click="toggleFavorite"></i>
102102
</div>
103103
</div>
104104
</div>
@@ -174,7 +174,8 @@ export default {
174174
currentLyric: null,
175175
currentLineNum: 0,
176176
currentShow: 'cd',
177-
playingLyric: ''
177+
playingLyric: '',
178+
hasFavoriteSong: false
178179
}
179180
},
180181
@@ -214,6 +215,16 @@ export default {
214215
this.setFullScreen(true)
215216
},
216217
218+
toggleFavorite () {
219+
this.hasFavoriteSong = !this.hasFavoriteSong
220+
221+
if (this.hasFavoriteSong) {
222+
this.saveMyFavoriteSong(this.currentSong)
223+
} else {
224+
this.deleteMyFavoriteSong(this.currentSong)
225+
}
226+
},
227+
217228
showPlaylist () {
218229
this.$refs.playlist.showPlaylist()
219230
},
@@ -449,7 +460,9 @@ export default {
449460
}),
450461
451462
...mapActions([
452-
'savePlayedHistory'
463+
'savePlayedHistory',
464+
'saveMyFavoriteSong',
465+
'deleteMyFavoriteSong'
453466
])
454467
},
455468
@@ -488,6 +501,10 @@ export default {
488501
},
489502
490503
computed: {
504+
hasFavorite () {
505+
return this.hasFavoriteSong ? 'icon-like' : 'icon-not-like'
506+
},
507+
491508
rotateCD () {
492509
return this.playing ? 'play' : 'play pause'
493510
},
@@ -724,6 +741,9 @@ export default {
724741
.icon-right {
725742
text-align: left;
726743
}
744+
.icon-like {
745+
color: $color-sub-theme;
746+
}
727747
i {
728748
font-size: 30px;
729749
}
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
<template>
2+
<transition name="slide">
3+
<div class="user-center">
4+
5+
<div class="switch-wrapper">
6+
<BaseSwitches
7+
:switchOptions="switchOptions"
8+
:currentSwitchIndex="switchIndex"
9+
@selectSwitch="toggleSwitchIndex"
10+
/>
11+
</div>
12+
13+
<div class="back-btn" @click.stop="prevPage">
14+
<i class="icon-back"></i>
15+
</div>
16+
17+
<div class="random-play-btn" @click.stop="addAllSongsToList">
18+
<i class="icon-play"></i>
19+
<span class="btn-text">随机播放全部</span>
20+
</div>
21+
22+
<div class="list-wrapper">
23+
<BaseScroll class="scroll-wrapper" v-if="switchIndex === 0">
24+
<div class="favorite-list-wrapper">
25+
<BaseSongsList
26+
:songsData="myFavoriteSongs"
27+
@select="addSongToList"
28+
/>
29+
</div>
30+
</BaseScroll>
31+
32+
<BaseScroll class="scroll-wrapper" v-if="switchIndex === 1">
33+
<div class="has-played-wrapper">
34+
<BaseSongsList
35+
:songsData="playedHistory"
36+
@select="addSongToList"
37+
/>
38+
</div>
39+
</BaseScroll>
40+
</div>
41+
42+
<div class="no-result-wrapper" v-if="showNoResult">
43+
<BaseNoResult title="这里空空如也 ..."/>
44+
</div>
45+
46+
</div>
47+
</transition>
48+
</template>
49+
50+
<script>
51+
import BaseSwitches from 'base/base-switches/base-switches'
52+
import BaseScroll from 'base/base-scroll'
53+
import BaseSongsList from 'base/base-songs-list/base-songs-list'
54+
import BaseNoResult from 'base/base-no-result/base-no-result'
55+
import { mapGetters, mapActions } from 'vuex'
56+
import Song from 'common/js/normalize-song'
57+
58+
export default {
59+
data () {
60+
return {
61+
switchOptions: [{ name: '我喜欢的' }, { name: '最近播放' }],
62+
switchIndex: 0
63+
}
64+
},
65+
66+
methods: {
67+
addAllSongsToList () {
68+
if (this.switchIndex === 0) {
69+
70+
} else {
71+
const list = this.playedHistory.map(song => {
72+
return new Song(song)
73+
})
74+
75+
this.randomPlay({ list })
76+
}
77+
},
78+
79+
addSongToList (song, index) {
80+
// song 是从 localStorage 读取而来,没有 Song 原型上的方法 getLyric
81+
this.insertSong(new Song(song))
82+
},
83+
84+
prevPage () {
85+
this.$router.back()
86+
},
87+
88+
toggleSwitchIndex (index) {
89+
this.switchIndex = index
90+
},
91+
92+
...mapActions([
93+
'insertSong',
94+
'randomPlay'
95+
])
96+
},
97+
98+
computed: {
99+
showNoResult () {
100+
return (this.switchIndex === 0 && !this.myFavoriteSongs.length) || (this.switchIndex === 1 && !this.playedHistory.length)
101+
},
102+
103+
...mapGetters([
104+
'playedHistory',
105+
'myFavoriteSongs'
106+
])
107+
},
108+
109+
components: {
110+
BaseSwitches,
111+
BaseScroll,
112+
BaseSongsList,
113+
BaseNoResult
114+
}
115+
}
116+
</script>
117+
118+
<style lang="scss" scoped>
119+
@import '~scss/variables';
120+
121+
.user-center {
122+
position: fixed;
123+
top: 0;
124+
bottom: 0;
125+
width: 100%;
126+
z-index: 100;
127+
background-color: $color-background;
128+
font-size: 0;
129+
&.slide-enter, &.slide-leave-to {
130+
transform: translateX(100%);
131+
}
132+
&.slide-enter-active, &.slide-leave-active {
133+
transition: all .1s
134+
}
135+
.switch-wrapper {
136+
margin: 10px 0 30px;
137+
}
138+
.back-btn {
139+
position: absolute;
140+
top: 0;
141+
left: 6px;
142+
z-index: 50;
143+
.icon-back {
144+
display: inline-block;
145+
padding: 10px;
146+
font-size: $font-size-large-x;
147+
color: $color-theme;
148+
}
149+
}
150+
.random-play-btn {
151+
margin: 0 auto;
152+
padding: 7px 0;
153+
width: 135px;
154+
box-sizing: border-box;
155+
border: 1px solid $color-text-l;
156+
border-radius: 100px;
157+
text-align: center;
158+
color: $color-text-l;
159+
.icon-play {
160+
display: inline-block;
161+
vertical-align: middle;
162+
margin-right: 6px;
163+
font-size: $font-size-medium-x;
164+
}
165+
.btn-text {
166+
display: inline-block;
167+
vertical-align: middle;
168+
font-size: $font-size-small;
169+
}
170+
}
171+
.list-wrapper {
172+
position: absolute;
173+
top: 110px;
174+
bottom: 0;
175+
width: 100%;
176+
.scroll-wrapper {
177+
height: 100%;
178+
overflow: hidden;
179+
}
180+
}
181+
.no-result-wrapper {
182+
position: absolute;
183+
top: 50%;
184+
transform: translateY(-50%);
185+
width: 100%;
186+
}
187+
188+
}
189+
</style>

src/router/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import ArtistItem from 'components/parts-artist-item/parts-artist-item'
77
import Ranking from 'components/the-ranking/ranking'
88
import RankingItem from 'components/parts-ranking-item/parts-ranking-item'
99
import Search from 'components/the-search/search'
10+
import UserCenter from 'components/the-user-center/the-user-center'
1011

1112
Vue.use(Router)
1213

@@ -55,6 +56,10 @@ export default new Router({
5556
component: ArtistItem
5657
}
5758
]
59+
},
60+
{
61+
path: '/user',
62+
component: UserCenter
5863
}
5964
]
6065
})

src/store/actions.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import * as types from './mutation-types'
44
import { playMode } from 'common/js/config'
55
import { shuffle } from 'common/js/util'
6-
import { saveSearchItem, deleteSearchItem, deleteAllSearchItem, savePlayedSongs } from 'common/js/cache'
6+
import { saveSearchItem, deleteSearchItem, deleteAllSearchItem, savePlayedSongs, saveFavoriteSongs, deleteFavoriteSong } from 'common/js/cache'
77

88
function findIndex (list, song) {
99
return list.findIndex(item => {
@@ -150,3 +150,13 @@ export const deleteAllSongsFromList = function ({ commit }) {
150150
export const savePlayedHistory = function ({ commit }, song) {
151151
commit(types.SET_PLAYED_HISTORY, savePlayedSongs(song))
152152
}
153+
154+
// 保存我喜欢的歌曲
155+
156+
export const saveMyFavoriteSong = function ({ commit }, song) {
157+
commit(types.SET_MY_FAVORITE_SONGS, saveFavoriteSongs(song))
158+
}
159+
160+
export const deleteMyFavoriteSong = function ({ commit }, song) {
161+
commit(types.SET_MY_FAVORITE_SONGS, deleteFavoriteSong(song))
162+
}

src/store/getters.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,5 @@ export const selectedTopList = state => state.selectedTopList
2323
export const searchHistory = state => state.searchHistory
2424

2525
export const playedHistory = state => state.playedHistory
26+
27+
export const myFavoriteSongs = state => state.myFavoriteSongs

src/store/mutation-types.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,5 @@ export const SET_SELECTED_TOP_LIST = 'SET_SELECTED_TOP_LIST'
2020
export const SET_SEARCH_HISTORY = 'SET_SEARCH_HISTORY'
2121

2222
export const SET_PLAYED_HISTORY = 'SET_PLAYED_HISTORY'
23+
24+
export const SET_MY_FAVORITE_SONGS = 'SET_MY_FAVORITE_SONGS'

0 commit comments

Comments
 (0)