From 203ee223be866c4c8d4b5301144477ff8a90a8fc Mon Sep 17 00:00:00 2001 From: Zachary Date: Sat, 20 Feb 2021 00:09:31 +0800 Subject: [PATCH] feat: add songer detail page. --- src/api/songer.js | 15 + src/assets/css/base.css | 1 + src/assets/css/fakeqqmusic.css | 434 ++++++++------ src/common/apiHelper.js | 179 ++++++ src/common/utils.js | 143 +---- src/views/musicLibrary/AlbumDetail.vue | 16 + src/views/musicLibrary/Ranking.vue | 40 ++ src/views/musicLibrary/SongerDetail.vue | 718 ++++++++++++++++-------- 8 files changed, 997 insertions(+), 549 deletions(-) create mode 100644 src/common/apiHelper.js diff --git a/src/api/songer.js b/src/api/songer.js index f4e28cf..94b12a2 100644 --- a/src/api/songer.js +++ b/src/api/songer.js @@ -60,3 +60,18 @@ export const getSongers = (initial, type, area, page) => { }; return requset.get("/artist/list", { params: params }); }; + +export const getSongerTop50 = id => requset.get(`/artist/top/song?id=${id}`); + +export const getSongerAllSong = id => requset.get(`/artist/songs?id=${id}`); + +export const getSongerDesc = id => requset.get(`/artist/desc?id=${id}`); + +export const getSongerDetail = id => requset.get(`/artist/detail?id=${id}`); + +export const getSimiSongers = id => requset.get(`/simi/artist?id=${id}`); + +export const getSongerAlbums = params => + requset.get(`/artist/album`, { params: params }); + +export const getSongerMvs = id => requset.get(`/artist/mv?id=${id}`); diff --git a/src/assets/css/base.css b/src/assets/css/base.css index 497408c..ce17d70 100644 --- a/src/assets/css/base.css +++ b/src/assets/css/base.css @@ -2,6 +2,7 @@ body, html { padding: 0; margin: 0; + line-height: 1.5; } a, diff --git a/src/assets/css/fakeqqmusic.css b/src/assets/css/fakeqqmusic.css index 66567ee..40ce7ca 100644 --- a/src/assets/css/fakeqqmusic.css +++ b/src/assets/css/fakeqqmusic.css @@ -1,3 +1,170 @@ +.mod_btn { + border: 1px solid #c9c9c9; + color: #000; +} +.mod_btn_green { + border: 1px solid #31c27c; + background-color: #31c27c; + color: #fff; +} +.mod_btn, +.mod_btn_green { + border-radius: 2px; + font-size: 14px; + margin-right: 6px; + padding: 0 23px; + height: 38px; + line-height: 38px; + display: inline-block; + white-space: nowrap; + box-sizing: border-box; + overflow: hidden; +} +.mod_btn_green__icon_play { + width: 13px; + height: 16px; + background-position: -80px -220px; + vertical-align: -3px; +} +.mod_btn__icon_like { + width: 16px; + height: 16px; + background-position: -60px 0; + vertical-align: -4px; +} +.mod_btn__icon_comment { + width: 16px; + height: 16px; + background-position: -140px -120px; + vertical-align: -3px; +} +.mod_btn__icon_menu { + width: 16px; + height: 16px; + background-position: -20px -80px; +} +.mod_btn__icon_more { + width: 16px; + height: 16px; + background-position: -40px -80px; + vertical-align: -2px; +} +.mod_btn__icon_add { + width: 16px; + height: 16px; + background-position: -20px 0; +} +.mod_btn__icon_down { + width: 16px; + height: 16px; + background-position: -40px -220px; +} +.mod_btn__icon_batch { + width: 16px; + height: 16px; + background-position: -120px 0; +} +.mod_btn__icon_add, +.mod_btn__icon_batch, +.mod_btn__icon_comment, +.mod_btn__icon_copy, +.mod_btn__icon_delete, +.mod_btn__icon_down, +.mod_btn__icon_edit, +.mod_btn__icon_input, +.mod_btn__icon_less, +.mod_btn__icon_like, +.mod_btn__icon_manage, +.mod_btn__icon_menu, +.mod_btn__icon_more, +.mod_btn__icon_new, +.mod_btn__icon_no, +.mod_btn__icon_play, +.mod_btn__icon_qr, +.mod_btn__icon_recovery, +.mod_btn__icon_upload, +.mod_btn__icon_yes, +.mod_btn_green__icon_add, +.mod_btn_green__icon_clear, +.mod_btn_green__icon_delete, +.mod_btn_green__icon_down, +.mod_btn_green__icon_like, +.mod_btn_green__icon_more, +.mod_btn_green__icon_play, +.mod_btn_green__icon_radio { + display: inline-block; + margin-right: 6px; + background-image: url(../img/icon_sprite.png); + background-repeat: no-repeat; +} + +.list_menu__item { + display: inline-block; + margin-right: 10px; + vertical-align: top; +} +.list_menu__icon_add, +.list_menu__icon_delete, +.list_menu__icon_down, +.list_menu__icon_down_vip, +.list_menu__icon_edit, +.list_menu__icon_pause, +.list_menu__icon_play, +.list_menu__icon_share { + display: block; + width: 36px; + height: 36px; + background-image: url(../img/icon_list_menu.png); +} +.list_menu__icon_play { + background-position: 0 0; +} +.list_menu__icon_pause { + background-position: 0 -200px; +} +.list_menu__icon_share { + background-position: 0 -40px; +} +.list_menu__icon_add { + background-position: 0 -80px; +} +.list_menu__icon_down { + background-position: 0 -120px; +} +.list_menu__icon_down_vip { + background-position: 0 -280px; +} +.list_menu__icon_edit { + background-position: 0 -240px; +} +.list_menu__icon_delete { + background-position: 0 -160px; +} +.list_menu__item:hover .list_menu__icon_play { + background-position: -40px 0; +} +.list_menu__item:hover .list_menu__icon_pause { + background-position: -40px -200px; +} +.list_menu__item:hover .list_menu__icon_share { + background-position: -40px -40px; +} +.list_menu__item:hover .list_menu__icon_add { + background-position: -40px -80px; +} +.list_menu__item:hover .list_menu__icon_down { + background-position: -40px -120px; +} +.list_menu__item:hover .list_menu__icon_down_vip { + background-position: -40px -280px; +} +.list_menu__item:hover .list_menu__icon_edit { + background-position: -40px -240px; +} +.list_menu__item:hover .list_menu__icon_delete { + background-position: -40px -160px; +} + /* ************** * 歌手列表 css */ .singer_list_txt { @@ -116,6 +283,13 @@ font-size: 24px; font-weight: 400; line-height: 58px; + font-family: 微软雅黑; +} +.part__more { + position: absolute; + top: 20px; + right: 0; + font-size: 14px; } /* ***************** @@ -330,29 +504,6 @@ .mod_songlist { margin-bottom: 60px; } -.mod_btn { - border: 1px solid #c9c9c9; - color: #000; -} -.mod_btn_green { - border: 1px solid #31c27c; - background-color: #31c27c; - color: #fff; -} -.mod_btn, -.mod_btn_green { - border-radius: 2px; - font-size: 14px; - margin-right: 6px; - padding: 0 23px; - height: 38px; - line-height: 38px; - display: inline-block; - white-space: nowrap; - box-sizing: border-box; - overflow: hidden; - text-align: left; -} .mod_songlist_toolbar .mod_btn { min-width: 122px; text-align: center; @@ -363,12 +514,6 @@ background-color: rgba(0, 0, 0, 0.01); color: #999; } -.songlist__header { - height: 50px; - line-height: 50px; - background-color: rgba(0, 0, 0, 0.01); - color: #999; -} .songlist__edit { display: none; } @@ -383,10 +528,6 @@ position: relative; white-space: normal; } -.songlist__header_name, -.songlist__songname { - width: 72%; -} .songlist__header_time, .songlist__time { position: absolute; @@ -394,41 +535,30 @@ right: 38px; width: 50px; } -.songlist__list { - overflow: hidden; - clear: both; -} .songlist__header, .songlist__item { padding-left: 122px; } -.songlist__item { - height: 80px; - clear: both; - font-size: 0; - overflow: hidden; -} .songlist__header, .songlist__item { position: relative; padding-left: 122px; padding-right: 95px; } +.songlist__list { + overflow: hidden; + clear: both; +} +.songlist__item { + clear: both; + font-size: 0; + overflow: hidden; +} .songlist__item--even { background-color: rgba(0, 0, 0, 0.01); } -.songlist__album, -.songlist__artist, -.songlist__number, -.songlist__other, -.songlist__rank, -.songlist__songname, -.songlist__time { - line-height: 80px; - height: 80px; -} .songlist__number { position: absolute; top: 0; @@ -447,17 +577,6 @@ white-space: nowrap; font-size: 14px; } -.songlist__number { - width: 50px; - top: 2px; - left: 0; - text-align: left; - font-size: 24px; - color: #333; -} -.songlist__number--top { - color: #ff4222; -} .songlist__rank { position: absolute; top: 0; @@ -579,69 +698,6 @@ font-size: 0; height: 36px; } -.list_menu__item { - display: inline-block; - margin-right: 10px; - vertical-align: top; -} -.list_menu__icon_play { - background-position: 0 0; -} -.list_menu__icon_add { - background-position: 0 -80px; -} -.list_menu__icon_down_vip { - background-position: 0 -280px; -} -.list_menu__icon_share { - background-position: 0 -40px; -} -.list_menu__icon_add, -.list_menu__icon_delete, -.list_menu__icon_down, -.list_menu__icon_down_vip, -.list_menu__icon_edit, -.list_menu__icon_pause, -.list_menu__icon_play, -.list_menu__icon_share { - display: block; - width: 36px; - height: 36px; - background-image: url(../img/icon_list_menu.png); -} -.mod_btn__icon_add, -.mod_btn__icon_batch, -.mod_btn__icon_comment, -.mod_btn__icon_copy, -.mod_btn__icon_delete, -.mod_btn__icon_down, -.mod_btn__icon_edit, -.mod_btn__icon_input, -.mod_btn__icon_less, -.mod_btn__icon_like, -.mod_btn__icon_manage, -.mod_btn__icon_menu, -.mod_btn__icon_more, -.mod_btn__icon_new, -.mod_btn__icon_no, -.mod_btn__icon_play, -.mod_btn__icon_qr, -.mod_btn__icon_recovery, -.mod_btn__icon_upload, -.mod_btn__icon_yes, -.mod_btn_green__icon_add, -.mod_btn_green__icon_clear, -.mod_btn_green__icon_delete, -.mod_btn_green__icon_down, -.mod_btn_green__icon_like, -.mod_btn_green__icon_more, -.mod_btn_green__icon_play, -.mod_btn_green__icon_radio { - display: inline-block; - margin-right: 6px; - background-image: url(../img/icon_sprite.png); - background-repeat: no-repeat; -} .popup__icon_close, .popup__icon_close.sprite, .popup__icon_tips, @@ -828,51 +884,6 @@ img .playlist__pic { padding: 0 18px; font-family: 微软雅黑; } -.mod_btn_green { - border: 1px solid #31c27c; - background-color: #31c27c; - color: #fff; -} -.mod_btn { - border: 1px solid #c9c9c9; - color: #000; -} -.mod_btn, -.mod_btn_green { - border-radius: 2px; - font-size: 14px; - margin-right: 6px; - padding: 0 23px; - height: 38px; - line-height: 38px; - display: inline-block; - white-space: nowrap; - box-sizing: border-box; - overflow: hidden; -} -.mod_btn_green__icon_play { - width: 13px; - height: 16px; - background-position: -80px -220px; - vertical-align: -3px; -} -.mod_btn__icon_like { - width: 16px; - height: 16px; - background-position: -60px 0; - vertical-align: -4px; -} -.mod_btn__icon_comment { - width: 16px; - height: 16px; - background-position: -140px -120px; - vertical-align: -3px; -} -.mod_btn__icon_menu { - width: 16px; - height: 16px; - background-position: -20px -80px; -} .detail_layout { padding-right: 343px; @@ -1019,3 +1030,82 @@ img .playlist__pic { color: #fff; font-weight: 400; } + +/* + * + * + * + * + * + * + * + * songer page */ +.data__desc { + font-size: 14px; + height: 50px; + line-height: 50px; + margin-bottom: 4px; +} +.data__desc_txt { + float: left; + max-width: 80%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + margin-right: 2px; +} +.mod_data_statistic { + height: 23px; + line-height: 23px; + overflow: hidden; + font-size: 0; +} +.data_statistic__number { + font-size: 25px; + font-weight: 400; + margin-left: 10px; +} + +.icon_part_arrow { + display: inline-block; + width: 7px; + height: 12px; + background-position: -120px -40px; + margin-left: 6px; + vertical-align: -1px; +} +.songlist__song_txt, +.songlist__time { + color: #999; +} +.songlist__song_txt { + margin-left: 10px; +} +.singer_list__cover { + margin-left: auto; + margin-right: auto; +} +.singer_list__cover, +.singer_list__pic { + display: block; + width: 140px; + height: 140px; + border-radius: 126px; +} +.singer_list__cover, +.singer_list__pic { + display: block; + width: 140px; + height: 140px; + border-radius: 126px; +} +.singer_list__title { + font-size: 16px; + font-weight: 400; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + zoom: 1; + *width: 100%; + margin: 20px 30px 4px; +} diff --git a/src/common/apiHelper.js b/src/common/apiHelper.js new file mode 100644 index 0000000..4bf586a --- /dev/null +++ b/src/common/apiHelper.js @@ -0,0 +1,179 @@ +export function createSong(song) { + const { + id, + name, + img, + artists, + duration, + albumId, + albumName, + mvId, + ...rest + } = song; + + return { + id, + name, + img, + artists, + duration, + albumName, + url: genSongPlayUrl(song.id), + artistsText: genArtistisText(artists), + durationSecond: duration / 1000, + durationText: formatTime(duration / 1000), + albumId, + mvId, + ...rest + }; +} + +export function createAlbum(album) { + const { id, name, img, artists, publishTime, ...rest } = album; + + return { + id, + name, + img, + artists, + publishTime: formatDate(publishTime, "yyyy-MM-dd"), + ...rest + }; +} + +export function createMv(mv) { + const { id, name, img, duration, publishTime, playCount, ...rest } = mv; + + return { + id, + name, + img, + duration, + publishTime, + durationSecond: duration / 1000, + durationText: formatTime(duration / 1000), + playCount: processCount(playCount), + ...rest + }; +} + +export function createSonger(songer) { + return { + id: songer.artist.id, + name: songer.artist.name, + img: songer.artist.cover, + desc: songer.artist.briefDesc, + musicSize: songer.artist.musicSize, + albumSize: songer.artist.albumSize, + mvSize: songer.artist.mvSize + }; +} + +export function createSimiSonger(songer) { + return { + id: songer.id, + name: songer.name, + img: songer.picUrl + }; +} + +export function createUser(user) {} + +export function prcessSuggest(rest) { + let results = []; + if (rest.songs) { + for (let song of rest.songs) { + results.push({ + value: song.name + "-" + genArtistisText(song.artists), + id: song.id, + type: "歌曲", + typeId: 0 + }); + } + } + if (rest.artists) { + for (let artist of rest.artists) { + results.push({ + value: artist.name, + id: artist.id, + type: "歌手", + typeId: 1 + }); + } + } + if (rest.albums) { + for (let album of rest.albums) { + results.push({ + value: album.name + "-" + album.artist.name, + id: album.id, + type: "专辑", + typeId: 2 + }); + } + } + return results; +} + +export function genSongPlayUrl(id) { + return `https://music.163.com/song/media/outer/url?id=${id}.mp3`; +} + +export function genArtistisText(artists) { + return (artists || []).map(({ name }) => name).join("/"); +} + +export function pad(num, n = 2) { + let len = num.toString().length; + while (len < n) { + num = "0" + num; + len++; + } + return num; +} + +export function formatTime(interval) { + interval = interval | 0; + const minute = pad((interval / 60) | 0); + const second = pad(interval % 60); + return `${minute}:${second}`; +} + +export function formatDate(date, fmt = "yyyy-MM-dd hh:mm:ss") { + date = date instanceof Date ? date : new Date(date); + if (/(y+)/.test(fmt)) { + fmt = fmt.replace( + RegExp.$1, + (date.getFullYear() + "").substr(4 - RegExp.$1.length) + ); + } + let o = { + "M+": date.getMonth() + 1, + "d+": date.getDate(), + "h+": date.getHours(), + "m+": date.getMinutes(), + "s+": date.getSeconds() + }; + for (let k in o) { + if (new RegExp(`(${k})`).test(fmt)) { + let str = o[k] + ""; + fmt = fmt.replace( + RegExp.$1, + RegExp.$1.length === 1 ? str : padLeftZero(str) + ); + } + } + return fmt; +} + +function padLeftZero(str) { + return ("00" + str).substr(str.length); +} + +export function processCount(count) { + if (count > 10000000) { + return (count / 10000000).toFixed(2) + "亿"; + } else if (count > 1000) { + return (count / 1000).toFixed(2) + "万"; + } + return count; +} diff --git a/src/common/utils.js b/src/common/utils.js index 986452c..aad3055 100644 --- a/src/common/utils.js +++ b/src/common/utils.js @@ -1,147 +1,6 @@ export * from "./storeHelper"; - -export function processCount(count) { - if (count > 10000000) { - return (count / 10000000).toFixed(2) + "亿"; - } else if (count > 1000) { - return (count / 1000).toFixed(2) + "万"; - } - return count; -} +export * from "./apiHelper"; export function isDef(v) { return v !== undefined && v !== null; } - -export function createSong(song) { - const { - id, - name, - img, - artists, - duration, - albumId, - albumName, - mvId, - ...rest - } = song; - - return { - id, - name, - img, - artists, - duration, - albumName, - url: genSongPlayUrl(song.id), - artistsText: genArtistisText(artists), - durationSecond: duration / 1000, - durationText: formatTime(duration / 1000), - albumId, - mvId, - ...rest - }; -} - -export function createAlbum(album) { - const { id, name, img, artists, publishTime, ...rest } = album; - - return { - id, - name, - img, - artists, - publishTime: formatDate(publishTime, "yyyy-MM-dd"), - ...rest - }; -} - -export function genSongPlayUrl(id) { - return `https://music.163.com/song/media/outer/url?id=${id}.mp3`; -} - -export function genArtistisText(artists) { - return (artists || []).map(({ name }) => name).join("/"); -} - -export function pad(num, n = 2) { - let len = num.toString().length; - while (len < n) { - num = "0" + num; - len++; - } - return num; -} - -export function formatTime(interval) { - interval = interval | 0; - const minute = pad((interval / 60) | 0); - const second = pad(interval % 60); - return `${minute}:${second}`; -} - -export function prcessSuggest(rest) { - let results = []; - if (rest.songs) { - for (let song of rest.songs) { - results.push({ - value: song.name + "-" + genArtistisText(song.artists), - id: song.id, - type: "歌曲", - typeId: 0 - }); - } - } - if (rest.artists) { - for (let artist of rest.artists) { - results.push({ - value: artist.name, - id: artist.id, - type: "歌手", - typeId: 1 - }); - } - } - if (rest.albums) { - for (let album of rest.albums) { - results.push({ - value: album.name + "-" + album.artist.name, - id: album.id, - type: "专辑", - typeId: 2 - }); - } - } - return results; -} - -export function formatDate(date, fmt = "yyyy-MM-dd hh:mm:ss") { - date = date instanceof Date ? date : new Date(date); - if (/(y+)/.test(fmt)) { - fmt = fmt.replace( - RegExp.$1, - (date.getFullYear() + "").substr(4 - RegExp.$1.length) - ); - } - let o = { - "M+": date.getMonth() + 1, - "d+": date.getDate(), - "h+": date.getHours(), - "m+": date.getMinutes(), - "s+": date.getSeconds() - }; - for (let k in o) { - if (new RegExp(`(${k})`).test(fmt)) { - let str = o[k] + ""; - fmt = fmt.replace( - RegExp.$1, - RegExp.$1.length === 1 ? str : padLeftZero(str) - ); - } - } - return fmt; -} - -function padLeftZero(str) { - return ("00" + str).substr(str.length); -} diff --git a/src/views/musicLibrary/AlbumDetail.vue b/src/views/musicLibrary/AlbumDetail.vue index 69d1563..283d88d 100644 --- a/src/views/musicLibrary/AlbumDetail.vue +++ b/src/views/musicLibrary/AlbumDetail.vue @@ -421,6 +421,22 @@ ul { padding-left: 46px; padding-right: 95px; } +.songlist__songname { + line-height: 50px; + height: 50px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.songlist__album, +.songlist__artist, +.songlist__header_album, +.songlist__header_author { + float: left; + padding-left: 15px; + width: 25.5%; + box-sizing: border-box; +} .songlist__album, .songlist__artist, diff --git a/src/views/musicLibrary/Ranking.vue b/src/views/musicLibrary/Ranking.vue index 019b6e4..6e5634d 100644 --- a/src/views/musicLibrary/Ranking.vue +++ b/src/views/musicLibrary/Ranking.vue @@ -380,4 +380,44 @@ th { font-family: poppin, Tahoma, Arial, 微软雅黑, sans-serif; font-family: Tahoma, Arial, 微软雅黑, sans-serif/9; } + +/*overwrite*/ +.mod_btn, +.mod_btn_green { + border-radius: 2px; + font-size: 14px; + margin-right: 6px; + padding: 0 23px; + height: 38px; + line-height: 38px; + display: inline-block; + white-space: nowrap; + box-sizing: border-box; + overflow: hidden; + text-align: left; +} +.songlist__item { + height: 80px; +} +.songlist__album, +.songlist__artist, +.songlist__number, +.songlist__other, +.songlist__rank, +.songlist__songname, +.songlist__time { + line-height: 80px; + height: 80px; +} +.songlist__number { + width: 50px; + top: 2px; + left: 0; + text-align: left; + font-size: 24px; + color: #333; +} +.songlist__number--top { + color: #ff4222; +} diff --git a/src/views/musicLibrary/SongerDetail.vue b/src/views/musicLibrary/SongerDetail.vue index b2f08fe..ecbbaf1 100644 --- a/src/views/musicLibrary/SongerDetail.vue +++ b/src/views/musicLibrary/SongerDetail.vue @@ -1,312 +1,560 @@ -- GitLab