排行榜界面添加播放、收藏整个排行榜功能

pull/486/head
lyswhut 2021-05-17 15:43:47 +08:00
parent 81643165c2
commit 0878c7398d
8 changed files with 190 additions and 31 deletions

View File

@ -1,3 +1,7 @@
### 新增
- 排行榜界面添加播放、收藏整个排行榜功能,可以右击排行榜名字后,在弹出的右键菜单中使用。注:收藏、播放存在分页的排行榜时需等待操作完成后才能切换排行榜,不然会导致操作中断。
### 修复
- 修复全局快捷键对桌面歌词无效的问题

View File

@ -84,6 +84,10 @@ export default {
type: String,
default: '列表加载中...',
},
hideListsMenu: {
type: Function,
default: () => {},
},
rowWidth: {
type: Object,
default() {
@ -349,6 +353,7 @@ export default {
this.listMenu.rightClickItemIndex = index
this.listMenu.menuLocation.x = dom_td.offsetLeft + event.offsetX
this.listMenu.menuLocation.y = dom_td.offsetParent.offsetTop + dom_td.offsetTop + event.offsetY - this.$refs.dom_scrollContent.scrollTop
this.hideListsMenu()
this.$nextTick(() => {
this.listMenu.isShowItemMenu = true
})

View File

@ -0,0 +1,4 @@
{
"play": "播放",
"collect": "收藏"
}

View File

@ -1,6 +1,7 @@
import music from '../../utils/music'
const sourceList = {}
const sources = []
const cache = new Map()
for (const source of music.sources) {
const leaderboard = music[source.id].leaderboard
if (!leaderboard || !leaderboard.getBoards) continue
@ -55,10 +56,39 @@ const actions = {
let tabId = rootState.setting.leaderboard.tabId
let [source, bangId] = tabId.split('__')
let key = `${source}${tabId}${page}`
if (state.list.length && state.key == key) return true
if (state.list.length && state.key == key) return Promise.resolve()
commit('clearList')
// return (
// cache.has(key)
// ? Promise.resolve(cache.get(key))
// : music[source].leaderboard.getList(bangId, page)
// ).then(result => commit('setList', { result, key }))
return music[source].leaderboard.getList(bangId, page).then(result => commit('setList', { result, key }))
},
getListAll({ state, rootState }, id) {
// console.log(source, id)
let [source, bangId] = id.split('__')
const loadData = (id, page) => {
let key = `${source}${id}${page}`
return cache.has(key)
? Promise.resolve(cache.get(key))
: music[source].leaderboard.getList(bangId, page).then(result => {
cache.set(key, result)
return result
})
}
return loadData(id, 1).then(result => {
if (result.total <= result.limit) return result.list
let maxPage = Math.ceil(result.total / result.limit)
const load = (loadPage = 2) => {
return loadPage == maxPage
? loadData(id, loadPage).then(result => result.list)
: loadData(id, loadPage).then(result1 => load(++loadPage).then(result2 => [...result1.list, ...result2]))
}
return load().then(result2 => [...result.list, ...result2])
})
},
}
// mitations
@ -72,6 +102,7 @@ const mutations = {
state.limit = result.limit
state.page = result.page
state.key = key
cache.set(key, result)
},
clearList(state) {
state.list = []

View File

@ -105,10 +105,10 @@ const actions = {
if (result.total <= result.limit) return filterList(result.list)
let maxPage = Math.ceil(result.total / result.limit)
const loadDetail = (loadPage = 1) => {
const loadDetail = (loadPage = 2) => {
return loadPage == maxPage
? loadData(id, ++loadPage).then(result => result.list)
: loadData(id, ++loadPage).then(result1 => loadDetail(loadPage).then(result2 => [...result1.list, ...result2]))
? loadData(id, loadPage).then(result => result.list)
: loadData(id, loadPage).then(result1 => loadDetail(++loadPage).then(result2 => [...result1.list, ...result2]))
}
return loadDetail().then(result2 => [...result.list, ...result2]).then(list => filterList(list))
})

View File

@ -5,31 +5,54 @@ import { formatPlayTime } from '../../index'
// const boardList = [{ id: 'mg__27553319', name: '咪咕尖叫新歌榜', bangid: '27553319' }, { id: 'mg__27186466', name: '咪咕尖叫热歌榜', bangid: '27186466' }, { id: 'mg__27553408', name: '咪咕尖叫原创榜', bangid: '27553408' }, { id: 'mg__23189800', name: '咪咕港台榜', bangid: '23189800' }, { id: 'mg__23189399', name: '咪咕内地榜', bangid: '23189399' }, { id: 'mg__19190036', name: '咪咕欧美榜', bangid: '19190036' }, { id: 'mg__23189813', name: '咪咕日韩榜', bangid: '23189813' }, { id: 'mg__23190126', name: '咪咕彩铃榜', bangid: '23190126' }, { id: 'mg__15140045', name: '咪咕KTV榜', bangid: '15140045' }, { id: 'mg__15140034', name: '咪咕网络榜', bangid: '15140034' }, { id: 'mg__23217754', name: 'MV榜', bangid: '23217754' }, { id: 'mg__23218151', name: '新专辑榜', bangid: '23218151' }, { id: 'mg__21958042', name: 'iTunes榜', bangid: '21958042' }, { id: 'mg__21975570', name: 'billboard榜', bangid: '21975570' }, { id: 'mg__22272815', name: '台湾Hito中文榜', bangid: '22272815' }, { id: 'mg__22272904', name: '中国TOP排行榜', bangid: '22272904' }, { id: 'mg__22272943', name: '韩国Melon榜', bangid: '22272943' }, { id: 'mg__22273437', name: '英国UK榜', bangid: '22273437' }]
const boardList = [
{ id: 'mg__jianjiao_newsong', bangid: 'jianjiao_newsong', name: '尖叫新歌榜' },
{ id: 'mg__jianjiao_hotsong', bangid: 'jianjiao_hotsong', name: '尖叫热歌榜' },
{ id: 'mg__jianjiao_original', bangid: 'jianjiao_original', name: '尖叫原创榜' },
{ id: 'mg__migumusic', bangid: 'migumusic', name: '音乐榜' },
{ id: 'mg__movies', bangid: 'movies', name: '影视榜' },
{ id: 'mg__mainland', bangid: 'mainland', name: '内地榜' },
{ id: 'mg__hktw', bangid: 'hktw', name: '港台榜' },
{ id: 'mg__eur_usa', bangid: 'eur_usa', name: '欧美榜' },
{ id: 'mg__jpn_kor', bangid: 'jpn_kor', name: '日韩榜' },
{ id: 'mg__coloring', bangid: 'coloring', name: '彩铃榜' },
{ id: 'mg__ktv', bangid: 'ktv', name: 'KTV榜' },
{ id: 'mg__network', bangid: 'network', name: '网络榜' },
{ id: 'mg__newalbum', bangid: 'newalbum', name: '新专辑榜' },
{ id: 'mg__mv', bangid: 'mv', name: 'MV榜' },
{ id: 'mg__itunes', bangid: 'itunes', name: '美国iTunes榜' },
{ id: 'mg__billboard', bangid: 'billboard', name: '美国billboard榜' },
{ id: 'mg__hito', bangid: 'hito', name: 'Hito中文榜' },
{ id: 'mg__mnet', bangid: 'mnet', name: '韩国Melon榜' },
{ id: 'mg__uk', bangid: 'uk', name: '英国UK榜' },
{ id: 'mg__27553319', name: '尖叫新歌榜', bangid: '27553319', webId: 'jianjiao_newsong' },
{ id: 'mg__27186466', name: '尖叫热歌榜', bangid: '27186466', webId: 'jianjiao_hotsong' },
{ id: 'mg__27553408', name: '尖叫原创榜', bangid: '27553408', webId: 'jianjiao_original' },
{ id: 'mg__migumusic', name: '音乐榜', bangid: 'migumusic', webId: 'migumusic' },
{ id: 'mg__movies', name: '影视榜', bangid: 'movies', webId: 'movies' },
{ id: 'mg__23189800', name: '港台榜', bangid: '23189800', webId: 'hktw' },
{ id: 'mg__23189399', name: '内地榜', bangid: '23189399', webId: 'mainland' },
{ id: 'mg__19190036', name: '欧美榜', bangid: '19190036', webId: 'eur_usa' },
{ id: 'mg__23189813', name: '日韩榜', bangid: '23189813', webId: 'jpn_kor' },
{ id: 'mg__23190126', name: '彩铃榜', bangid: '23190126', webId: 'coloring' },
{ id: 'mg__15140045', name: 'KTV榜', bangid: '15140045', webId: 'ktv' },
{ id: 'mg__15140034', name: '网络榜', bangid: '15140034', webId: 'network' },
{ id: 'mg__23217754', name: 'MV榜', bangid: '23217754', webId: 'mv' },
{ id: 'mg__23218151', name: '新专辑榜', bangid: '23218151', webId: 'newalbum' },
{ id: 'mg__21958042', name: '美国iTunes榜', bangid: '21958042', webId: 'itunes' },
{ id: 'mg__21975570', name: '美国billboard榜', bangid: '21975570', webId: 'billboard' },
{ id: 'mg__22272815', name: '台湾Hito中文榜', bangid: '22272815', webId: 'hito' },
{ id: 'mg__22272904', name: '中国TOP排行榜', bangid: '22272904' },
{ id: 'mg__22272943', name: '韩国Melon榜', bangid: '22272943', webId: 'mnet' },
{ id: 'mg__22273437', name: '英国UK榜', bangid: '22273437', webId: 'uk' },
]
// const boardList = [
// { id: 'mg__jianjiao_newsong', bangid: 'jianjiao_newsong', name: '尖叫新歌榜' },
// { id: 'mg__jianjiao_hotsong', bangid: 'jianjiao_hotsong', name: '尖叫热歌榜' },
// { id: 'mg__jianjiao_original', bangid: 'jianjiao_original', name: '尖叫原创榜' },
// { id: 'mg__migumusic', bangid: 'migumusic', name: '音乐榜' },
// { id: 'mg__movies', bangid: 'movies', name: '影视榜' },
// { id: 'mg__mainland', bangid: 'mainland', name: '内地榜' },
// { id: 'mg__hktw', bangid: 'hktw', name: '港台榜' },
// { id: 'mg__eur_usa', bangid: 'eur_usa', name: '欧美榜' },
// { id: 'mg__jpn_kor', bangid: 'jpn_kor', name: '日韩榜' },
// { id: 'mg__coloring', bangid: 'coloring', name: '彩铃榜' },
// { id: 'mg__ktv', bangid: 'ktv', name: 'KTV榜' },
// { id: 'mg__network', bangid: 'network', name: '网络榜' },
// { id: 'mg__newalbum', bangid: 'newalbum', name: '新专辑榜' },
// { id: 'mg__mv', bangid: 'mv', name: 'MV榜' },
// { id: 'mg__itunes', bangid: 'itunes', name: '美国iTunes榜' },
// { id: 'mg__billboard', bangid: 'billboard', name: '美国billboard榜' },
// { id: 'mg__hito', bangid: 'hito', name: 'Hito中文榜' },
// { id: 'mg__mnet', bangid: 'mnet', name: '韩国Melon榜' },
// { id: 'mg__uk', bangid: 'uk', name: '英国UK榜' },
// ]
export default {
limit: 10000,
getUrl(id, page) {
return `https://music.migu.cn/v3/music/top/${id}`
const targetBoard = boardList.find(board => board.bangid == id)
return `https://music.migu.cn/v3/music/top/${targetBoard.webId}`
// return `http://m.music.migu.cn/migu/remoting/cms_list_tag?nid=${id}&pageSize=${this.limit}&pageNo=${page - 1}`
},
successCode: '000000',
@ -93,8 +116,8 @@ export default {
list.push({
singer: this.getSinger(item.singers),
name: item.name,
albumName: item.album.albumName,
albumId: item.album.albumId,
albumName: item.album && item.album.albumName,
albumId: item.album && item.album.albumId,
songmid: item.copyrightId,
songId: item.id,
copyrightId: item.copyrightId,

View File

@ -11,14 +11,17 @@
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='70%' viewBox='0 0 24 24' space='preserve')
use(xlink:href='#icon-list-add')
ul.scroll(:class="$style.listsContent" ref="dom_lists_list")
li(:class="[$style.listsItem, item.id == tabId ? $style.active : null]" :tips="item.name" v-for="item in boardList" :key="item.id" @click="handleToggleList(item.id)")
li(:class="[$style.listsItem, item.id == tabId ? $style.active : null, { [$style.clicked]: boardListData.rightClickItemIndex == index }]"
:tips="item.name" v-for="(item, index) in boardList" :key="item.id" @click="handleToggleList(item.id)"
@contextmenu="handleListsItemRigthClick($event, index)")
span(:class="$style.listsLabel") {{item.name}}
div(:class="$style.list")
material-song-list(v-model="selectedData" :rowWidth="{r1: '5%', r2: 'auto', r3: '22%', r4: '22%', r5: '9%', r6: '15%'}" @action="handleSongListAction" :source="source" :page="page" :limit="info.limit" :total="info.total" :noItem="$t('material.song_list.loding_list')" :list="list")
material-song-list(v-model="selectedData" ref="songList" :hideListsMenu="hideListsMenu" :rowWidth="{r1: '5%', r2: 'auto', r3: '22%', r4: '22%', r5: '9%', r6: '15%'}" @action="handleSongListAction" :source="source" :page="page" :limit="info.limit" :total="info.total" :noItem="$t('material.song_list.loding_list')" :list="list")
material-download-modal(:show="isShowDownload" :musicInfo="musicInfo" @select="handleAddDownload" @close="isShowDownload = false")
material-download-multiple-modal(:show="isShowDownloadMultiple" :list="selectedData" @select="handleAddDownloadMultiple" @close="isShowDownloadMultiple = false")
material-list-add-modal(:show="isShowListAdd" :musicInfo="musicInfo" @close="isShowListAdd = false")
material-list-add-multiple-modal(:show="isShowListAddMultiple" :musicList="selectedData" @close="handleListAddModalClose")
material-menu(:menus="listsItemMenu" :location="boardListData.menuLocation" item-name="name" :isShow="boardListData.isShowItemMenu" @menu-click="handleListsItemMenuClick")
</template>
<script>
@ -38,6 +41,21 @@ export default {
isShowDownloadMultiple: false,
isShowListAdd: false,
isShowListAddMultiple: false,
boardListData: {
isShowItemMenu: false,
itemMenuControl: {
rename: true,
sync: false,
moveup: true,
movedown: true,
remove: true,
},
rightClickItemIndex: -1,
menuLocation: {
x: 0,
y: 0,
},
},
}
},
computed: {
@ -47,6 +65,20 @@ export default {
boardList() {
return this.source && this.boards[this.source] ? this.boards[this.source] : []
},
listsItemMenu() {
return [
{
name: this.$t('view.leaderboard.play'),
action: 'play',
disabled: false,
},
{
name: this.$t('view.leaderboard.collect'),
action: 'collect',
disabled: false,
},
]
},
},
watch: {
tabId(n, o) {
@ -74,9 +106,9 @@ export default {
},
methods: {
...mapMutations(['setLeaderboard']),
...mapActions('leaderboard', ['getBoardsList', 'getList']),
...mapActions('leaderboard', ['getBoardsList', 'getList', 'getListAll']),
...mapActions('download', ['createDownload', 'createDownloadMultiple']),
...mapMutations('list', ['listAdd', 'listAddMultiple']),
...mapMutations('list', ['listAdd', 'listAddMultiple', 'createUserList']),
...mapMutations('player', ['setList', 'setTempPlayList']),
handleListBtnClick(info) {
switch (info.action) {
@ -228,6 +260,55 @@ export default {
resetSelect() {
this.selectedData = []
},
handleListsItemRigthClick(event, index) {
// const board = this.boardList[index]
// this.boardListData.itemMenuControl.sync = !!source && !!musicSdk[source].songList
// this.boardListData.itemMenuControl.moveup = index > 0
// this.boardListData.itemMenuControl.movedown = index < this.userList.length - 1
this.boardListData.rightClickItemIndex = index
this.boardListData.menuLocation.x = event.currentTarget.offsetLeft + event.offsetX
this.boardListData.menuLocation.y = event.currentTarget.offsetTop + event.offsetY - this.$refs.dom_lists_list.scrollTop
// this.hideListsMenu()
this.$refs.songList.hideListMenu()
this.$nextTick(() => {
this.boardListData.isShowItemMenu = true
})
},
hideListsMenu() {
this.boardListData.isShowItemMenu = false
this.boardListData.rightClickItemIndex = -1
},
async handleListsItemMenuClick(action) {
let index = this.boardListData.rightClickItemIndex
this.hideListsMenu()
this.boardListData.isShowItemMenu = false
if (action) {
const board = this.boardList[index]
const list = await this.getListAll(board.id)
if (!list.length) return
switch (action && action.action) {
case 'play':
this.setList({
list: {
list,
id: null,
},
index: 0,
})
break
case 'collect':
this.createUserList({
name: board.name,
id: `board__${this.source}__${board.id}`,
list,
source: this.source,
sourceListId: `board__${board.id}`,
})
break
}
}
},
},
}
</script>

View File

@ -358,6 +358,9 @@ export default {
'sortList',
]),
...mapActions('songList', ['getListDetailAll']),
...mapActions('leaderboard', {
getBoardListAll: 'getListAll',
}),
...mapActions('download', ['createDownload', 'createDownloadMultiple']),
...mapMutations('player', {
setPlayList: 'setList',
@ -902,7 +905,15 @@ export default {
} else {
this.fetchingListStatus[id] = true
}
return this.getListDetailAll({ source, id: sourceListId }).finally(() => {
let promise
if (/board__/.test(sourceListId)) {
const id = sourceListId.replace(/board__/, '')
promise = this.getBoardListAll(id)
} else {
promise = this.getListDetailAll({ source, id: sourceListId })
}
return promise.finally(() => {
this.fetchingListStatus[id] = false
})
},