优化下载功能的添加、删除、暂停任务时的流畅度

pull/733/head
lyswhut 2021-10-31 21:50:57 +08:00
parent f0f92952d6
commit e382f0dba0
6 changed files with 358 additions and 199 deletions

View File

@ -1,6 +1,7 @@
### 优化 ### 优化
- 优化我的列表、下载列表等列表的滚动流畅度 - 优化我的列表、下载列表等列表的滚动流畅度
- 优化下载功能的添加、删除、暂停任务时的流畅度,现在进行这些操作应该不会再觉得卡顿了
### 修复 ### 修复

View File

@ -148,7 +148,7 @@ export default {
}, },
downloadList: { downloadList: {
handler(n) { handler(n) {
this.saveDownloadList(n) this.saveDownloadList(window.downloadListFull)
}, },
deep: true, deep: true,
}, },
@ -373,12 +373,17 @@ export default {
}, },
initDownloadList(downloadList) { initDownloadList(downloadList) {
if (downloadList) { if (downloadList) {
downloadList.forEach(item => { downloadList = downloadList.filter(item => item && item.key && item.musicInfo)
for (const item of downloadList) {
if (item.name == null) {
item.name = `${item.musicInfo.name} - ${item.musicInfo.singer}`
item.songmid = item.musicInfo.songmid
}
if (item.status == this.downloadStatus.RUN || item.status == this.downloadStatus.WAITING) { if (item.status == this.downloadStatus.RUN || item.status == this.downloadStatus.WAITING) {
item.status = this.downloadStatus.PAUSE item.status = this.downloadStatus.PAUSE
item.statusText = '暂停下载' item.statusText = '暂停下载'
} }
}) }
this.updateDownloadList(downloadList) this.updateDownloadList(downloadList)
} }
}, },

View File

@ -64,14 +64,14 @@ div(:class="$style.player")
//- transition(enter-active-class="animated lightSpeedIn" //- transition(enter-active-class="animated lightSpeedIn"
transition(enter-active-class="animated lightSpeedIn" transition(enter-active-class="animated lightSpeedIn"
leave-active-class="animated slideOutDown") leave-active-class="animated slideOutDown")
core-player-detail(v-if="isShowPlayerDetail" :visible.sync="isShowPlayerDetail" :musicInfo="listId == 'download' ? targetSong.musicInfo : targetSong" core-player-detail(v-if="isShowPlayerDetail" :visible.sync="isShowPlayerDetail" :musicInfo="currentMusicInfo"
:lyric="lyric" :list="list" :listId="listId" :lyric="lyric" :list="list" :listId="listId"
:playInfo="{ nowPlayTimeStr, maxPlayTimeStr, progress, nowPlayTime, status }" :playInfo="{ nowPlayTimeStr, maxPlayTimeStr, progress, nowPlayTime, status }"
:isPlay="isPlay" @action="handlePlayDetailAction" :isPlay="isPlay" @action="handlePlayDetailAction"
:nextTogglePlayName="nextTogglePlayName" :nextTogglePlayName="nextTogglePlayName"
@toggle-next-play-mode="toggleNextPlayMode" @add-music-to="addMusicTo") @toggle-next-play-mode="toggleNextPlayMode" @add-music-to="addMusicTo")
material-list-add-modal(:show="isShowAddMusicTo" :musicInfo="listId == 'download' ? targetSong.musicInfo : targetSong" @close="isShowAddMusicTo = false") material-list-add-modal(:show="isShowAddMusicTo" :musicInfo="currentMusicInfo" @close="isShowAddMusicTo = false")
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' style="display: none;") svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' style="display: none;")
defs defs
g(:id="$style.iconPic") g(:id="$style.iconPic")
@ -121,6 +121,7 @@ export default {
singer: '', singer: '',
album: '', album: '',
}, },
currentMusicInfo: {},
pregessWidth: 0, pregessWidth: 0,
lyric: { lyric: {
lines: [], lines: [],
@ -395,7 +396,7 @@ export default {
// console.log(this.retryNum) // console.log(this.retryNum)
if (!this.restorePlayTime) this.restorePlayTime = audio.currentTime // if (!this.restorePlayTime) this.restorePlayTime = audio.currentTime //
this.retryNum++ this.retryNum++
this.setUrl(this.targetSong, true) this.setUrl(this.currentMusicInfo, true)
this.status = this.statusText = this.$t('core.player.refresh_url') this.status = this.statusText = this.$t('core.player.refresh_url')
return return
} }
@ -485,7 +486,7 @@ export default {
this.clearDelayNextTimeout() this.clearDelayNextTimeout()
this.updateMediaSessionInfo() this.updateMediaSessionInfo()
const targetSong = this.targetSong let targetSong = this.targetSong
if (this.setting.player.togglePlayMethod == 'random' && !this.playMusicInfo.isTempPlay) this.setPlayedList(this.playMusicInfo) if (this.setting.player.togglePlayMethod == 'random' && !this.playMusicInfo.isTempPlay) this.setPlayedList(this.playMusicInfo)
this.retryNum = 0 this.retryNum = 0
@ -497,16 +498,18 @@ export default {
if (!await checkPath(filePath) || !targetSong.isComplate || /\.ape$/.test(filePath)) { if (!await checkPath(filePath) || !targetSong.isComplate || /\.ape$/.test(filePath)) {
return this.list.length == 1 ? null : this.playNext() return this.list.length == 1 ? null : this.playNext()
} }
this.musicInfo.songmid = targetSong.musicInfo.songmid this.currentMusicInfo = targetSong = window.downloadListFullMap.get(targetSong.key).musicInfo
this.musicInfo.singer = targetSong.musicInfo.singer this.musicInfo.songmid = targetSong.songmid
this.musicInfo.name = targetSong.musicInfo.name this.musicInfo.singer = targetSong.singer
this.musicInfo.name = targetSong.name
this.musicInfo.album = targetSong.albumName this.musicInfo.album = targetSong.albumName
audio.src = filePath audio.src = filePath
// console.log(filePath) // console.log(filePath)
this.setImg(targetSong.musicInfo) this.setImg(targetSong)
this.setLrc(targetSong.musicInfo) this.setLrc(targetSong)
} else { } else {
// if (!this.assertApiSupport(targetSong.source)) return this.playNext() // if (!this.assertApiSupport(targetSong.source)) return this.playNext()
this.currentMusicInfo = targetSong
this.musicInfo.songmid = targetSong.songmid this.musicInfo.songmid = targetSong.songmid
this.musicInfo.singer = targetSong.singer this.musicInfo.singer = targetSong.singer
this.musicInfo.name = targetSong.name this.musicInfo.name = targetSong.name
@ -771,7 +774,7 @@ export default {
}) })
}, },
showPlayerDetail() { showPlayerDetail() {
if (!this.targetSong) return if (!this.currentMusicInfo) return
this.isShowPlayerDetail = true this.isShowPlayerDetail = true
}, },
handleTransitionEnd(e) { handleTransitionEnd(e) {
@ -939,11 +942,11 @@ export default {
}, },
updateMediaSessionInfo() { updateMediaSessionInfo() {
const mediaMetadata = { const mediaMetadata = {
title: this.targetSong.name, title: this.currentMusicInfo.name,
artist: this.targetSong.singer, artist: this.currentMusicInfo.singer,
album: this.targetSong.albumName, album: this.currentMusicInfo.albumName,
} }
if (this.targetSong.img) mediaMetadata.artwork = [{ src: this.targetSong.img }] if (this.currentMusicInfo.img) mediaMetadata.artwork = [{ src: this.currentMusicInfo.img }]
navigator.mediaSession.metadata = new window.MediaMetadata(mediaMetadata) navigator.mediaSession.metadata = new window.MediaMetadata(mediaMetadata)
}, },
registerMediaSessionHandler() { registerMediaSessionHandler() {

View File

@ -16,6 +16,8 @@ import {
import { NAMES, rendererInvoke } from '@common/ipc' import { NAMES, rendererInvoke } from '@common/ipc'
window.downloadList = [] window.downloadList = []
window.downloadListFull = []
window.downloadListFullMap = new Map()
// state // state
const state = { const state = {
list: window.downloadList, list: window.downloadList,
@ -32,7 +34,6 @@ const state = {
const dls = {} const dls = {}
const tryNum = {} const tryNum = {}
let isRuningActionTask = false
// getters // getters
@ -72,7 +73,7 @@ const getExt = type => {
} }
} }
const checkList = (list, musicInfo, type, ext) => list.some(s => s.musicInfo.songmid === musicInfo.songmid && (s.type === type || s.ext === ext)) const checkList = (list, musicInfo, type, ext) => list.some(s => s.songmid === musicInfo.songmid && (s.type === type || s.ext === ext))
const getStartTask = (list, downloadStatus, maxDownloadNum) => { const getStartTask = (list, downloadStatus, maxDownloadNum) => {
let downloadCount = 0 let downloadCount = 0
@ -81,82 +82,6 @@ const getStartTask = (list, downloadStatus, maxDownloadNum) => {
return downloadCount < maxDownloadNum ? waitList.shift() || null : false return downloadCount < maxDownloadNum ? waitList.shift() || null : false
} }
const awaitRequestAnimationFrame = () => new Promise(resolve => window.requestAnimationFrame(() => resolve()))
const addTasks = async(store, list, type) => {
if (list.length == 0) return
let num = 3
while (num-- > 0) {
let item = list.shift()
if (!item) return
store.dispatch('createDownload', {
musicInfo: item,
type: getMusicType(item, type),
})
}
await awaitRequestAnimationFrame()
await addTasks(store, list, type)
}
const removeTasks = async(store, list) => {
let num = 20
while (num-- > 0) {
let item = list.pop()
if (!item) return
let index = store.state.list.indexOf(item)
if (index < 0) continue
store.dispatch('removeTask', item)
}
await awaitRequestAnimationFrame()
await removeTasks(store, list)
}
const startTasks = async(store, list) => {
let num = 5
while (num-- > 0) {
let item = list.shift()
if (!item) return
if (item.isComplate || item.status == state.downloadStatus.RUN || item.status == state.downloadStatus.WAITING) continue
let index = store.state.list.indexOf(item)
if (index < 0) continue
store.dispatch('startTask', item)
}
await awaitRequestAnimationFrame()
await startTasks(store, list)
}
const pauseTasks = async(store, list, runs = []) => {
let num = 6
let index
let stateList = store.state.list
while (num-- > 0) {
let item = list.shift()
if (item) {
if (item.isComplate) continue
switch (item.status) {
case state.downloadStatus.RUN:
runs.push(item)
continue
case state.downloadStatus.WAITING:
index = stateList.indexOf(item)
if (index < 0) return
store.dispatch('pauseTask', item)
continue
default:
continue
}
} else {
for (const item of runs) {
index = stateList.indexOf(item)
if (index < 0) return
await store.dispatch('pauseTask', item)
}
return
}
}
await awaitRequestAnimationFrame()
await pauseTasks(store, list, runs)
}
const handleGetMusicUrl = function(musicInfo, type, retryedSource = [], originMusic) { const handleGetMusicUrl = function(musicInfo, type, retryedSource = [], originMusic) {
// console.log(musicInfo.source) // console.log(musicInfo.source)
if (!originMusic) originMusic = musicInfo if (!originMusic) originMusic = musicInfo
@ -183,6 +108,7 @@ const handleGetMusicUrl = function(musicInfo, type, retryedSource = [], originMu
} }
const getMusicUrl = async function(downloadInfo, isUseOtherSource, isRefresh) { const getMusicUrl = async function(downloadInfo, isUseOtherSource, isRefresh) {
downloadInfo = window.downloadListFullMap.get(downloadInfo.key)
const cachedUrl = await getMusicUrlFormStorage(downloadInfo.musicInfo, downloadInfo.type) const cachedUrl = await getMusicUrlFormStorage(downloadInfo.musicInfo, downloadInfo.type)
if (!downloadInfo.musicInfo._types[downloadInfo.type]) { if (!downloadInfo.musicInfo._types[downloadInfo.type]) {
// 兼容旧版酷我源搜索列表过滤128k音质的bug // 兼容旧版酷我源搜索列表过滤128k音质的bug
@ -288,6 +214,7 @@ const fixKgLyric = lrc => /\[00:\d\d:\d\d.\d+\]/.test(lrc) ? lrc.replace(/(?:\[0
*/ */
const saveMeta = function(downloadInfo, filePath, isUseOtherSource, isEmbedPic, isEmbedLyric) { const saveMeta = function(downloadInfo, filePath, isUseOtherSource, isEmbedPic, isEmbedLyric) {
if (downloadInfo.type === 'ape') return if (downloadInfo.type === 'ape') return
downloadInfo = window.downloadListFullMap.get(downloadInfo.key)
const tasks = [ const tasks = [
isEmbedPic isEmbedPic
? downloadInfo.musicInfo.img ? downloadInfo.musicInfo.img
@ -323,6 +250,7 @@ const saveMeta = function(downloadInfo, filePath, isUseOtherSource, isEmbedPic,
* @param {*} filePath * @param {*} filePath
*/ */
const downloadLyric = function(downloadInfo, isUseOtherSource, filePath, lrcFormat) { const downloadLyric = function(downloadInfo, isUseOtherSource, filePath, lrcFormat) {
downloadInfo = window.downloadListFullMap.get(downloadInfo.key)
getLyric.call(this, downloadInfo.musicInfo, isUseOtherSource).then(lrcs => { getLyric.call(this, downloadInfo.musicInfo, isUseOtherSource).then(lrcs => {
if (lrcs?.lyric) { if (lrcs?.lyric) {
lrcs.lyric = fixKgLyric(lrcs.lyric) lrcs.lyric = fixKgLyric(lrcs.lyric)
@ -358,7 +286,7 @@ const refreshUrl = function(commit, downloadInfo, isUseOtherSource) {
*/ */
const deleteFile = path => new Promise((resolve, reject) => { const deleteFile = path => new Promise((resolve, reject) => {
fs.access(path, fs.constants.F_OK, err => { fs.access(path, fs.constants.F_OK, err => {
if (err) return reject(err) if (err) return err.code == 'ENOENT' ? resolve() : reject(err)
fs.unlink(path, err => { fs.unlink(path, err => {
if (err) return reject(err) if (err) return reject(err)
resolve() resolve()
@ -366,54 +294,91 @@ const deleteFile = path => new Promise((resolve, reject) => {
}) })
}) })
const createDownloadInfo = ({ musicInfo, type, list, fileName, savePath }) => {
type = getMusicType(musicInfo, type)
let ext = getExt(type)
const key = `${musicInfo.songmid}${ext}`
if (checkList(list, musicInfo, type, ext)) return null
const downloadInfo = {
isComplate: false,
status: state.downloadStatus.WAITING,
statusText: '待下载',
url: null,
songmid: musicInfo.songmid,
fileName: filterFileName(`${fileName
.replace('歌名', musicInfo.name)
.replace('歌手', musicInfo.singer)}.${ext}`),
progress: {
downloaded: 0,
total: 0,
progress: 0,
},
type,
ext,
name: `${musicInfo.name} - ${musicInfo.singer}`,
key,
}
downloadInfo.filePath = path.join(savePath, downloadInfo.fileName)
// commit('addTask', downloadInfo)
// 删除同路径下的同名文件
deleteFile(downloadInfo.filePath)
// .catch(err => {
// if (err.code !== 'ENOENT') return commit('setStatusText', { downloadInfo, text: '文件删除失败' })
// })
if (dls[downloadInfo.key]) {
const dl = dls[downloadInfo.key]
delete dls[downloadInfo.key]
dl.stop()
}
return downloadInfo
}
// let waitingUpdateTasks = {}
// const delayUpdateProgress = throttle(function(commit) {
// commit('setProgressDelay')
// }, 1000)
// actions // actions
const actions = { const actions = {
async createDownload({ state, rootState, commit, dispatch }, { musicInfo, type }) { async createDownload({ state, rootState, commit, dispatch }, { musicInfo, type }) {
let ext = getExt(type) const downloadInfo = createDownloadInfo({
if (checkList(state.list, musicInfo, type, ext)) return
const downloadInfo = {
isComplate: false,
status: state.downloadStatus.WAITING,
statusText: '待下载',
url: null,
// songmid: musicInfo.songmid,
fileName: filterFileName(`${rootState.setting.download.fileName
.replace('歌名', musicInfo.name)
.replace('歌手', musicInfo.singer)}.${ext}`),
progress: {
downloaded: 0,
total: 0,
progress: 0,
},
type,
ext,
musicInfo, musicInfo,
key: `${musicInfo.songmid}${ext}`, type,
} fileName: rootState.setting.download.fileName,
downloadInfo.filePath = path.join(rootState.setting.download.savePath, downloadInfo.fileName) savePath: rootState.setting.download.savePath,
commit('addTask', downloadInfo) list: state.list,
try { // 删除同路径下的同名文件 })
await deleteFile(downloadInfo.filePath) if (!downloadInfo) return
} catch (err) { commit('addTask', { downloadInfo, musicInfo, addMusicLocationType: rootState.setting.list.addMusicLocationType })
if (err.code !== 'ENOENT') return commit('setStatusText', { downloadInfo, text: '文件删除失败' }) let result = getStartTask(state.list, state.downloadStatus, rootState.setting.download.maxDownloadNum)
} while (result) {
if (dls[downloadInfo.key]) { dispatch('startTask', result)
dls[downloadInfo.key].stop().finally(() => { result = getStartTask(state.list, state.downloadStatus, rootState.setting.download.maxDownloadNum)
delete dls[downloadInfo.key]
dispatch('startTask', downloadInfo)
})
} else {
// console.log(downloadInfo)
dispatch('startTask', downloadInfo)
} }
}, },
createDownloadMultiple(store, { list, type }) { createDownloadMultiple({ state, rootState, commit, dispatch }, { list, type }) {
if (!list.length || isRuningActionTask) return if (!list.length) return
isRuningActionTask = true const downloadList = []
return addTasks(store, [...list], type).finally(() => { for (const musicInfo of list) {
isRuningActionTask = false const downloadInfo = createDownloadInfo({
}) musicInfo,
type,
fileName: rootState.setting.download.fileName,
savePath: rootState.setting.download.savePath,
list: state.list,
})
if (downloadInfo) downloadList.push({ downloadInfo, musicInfo })
}
commit('addTasks', { list: downloadList, addMusicLocationType: rootState.setting.list.addMusicLocationType })
let result = getStartTask(state.list, state.downloadStatus, rootState.setting.download.maxDownloadNum)
while (result) {
dispatch('startTask', result)
result = getStartTask(state.list, state.downloadStatus, rootState.setting.download.maxDownloadNum)
}
}, },
async handleStartTask({ commit, dispatch, rootState }, downloadInfo) { async handleStartTask({ commit, dispatch, rootState }, downloadInfo) {
// 开始任务 // 开始任务
@ -423,7 +388,7 @@ const actions = {
await checkPath(rootState.setting.download.savePath) await checkPath(rootState.setting.download.savePath)
} catch (error) { } catch (error) {
commit('onError', { downloadInfo, errorMsg: error.message }) commit('onError', { downloadInfo, errorMsg: error.message })
commit('setStatusText', '检查下载目录出错: ' + error.message) commit('setStatusText', { downloadInfo, text: '检查下载目录出错: ' + error.message })
await dispatch('startTask') await dispatch('startTask')
return return
} }
@ -447,9 +412,9 @@ const actions = {
console.log('on complate') console.log('on complate')
}, },
onError(err) { onError(err) {
// console.log(err) console.log(err)
if (err.code == 'EPERM') { if (err.code == 'EPERM') {
commit('onError', { downloadInfo, errorMsg: '歌曲下载目录没有写入权限,请尝试更改歌曲保存路径' }) commit('onError', { downloadInfo, errorMsg: '歌曲保存位置被占用或没有写入权限,请尝试更改歌曲保存目录或重启软件或重启电脑,错误详情:' + err.message })
return return
} }
// console.log(tryNum[downloadInfo.key]) // console.log(tryNum[downloadInfo.key])
@ -538,28 +503,38 @@ const actions = {
await dispatch('startTask') await dispatch('startTask')
} }
}, },
removeTasks(store, list) { removeTasks({ rootState, commit, dispatch }, list) {
let { rootState, state } = store for (const item of list) {
if (isRuningActionTask) return if (dls[item.key]) {
isRuningActionTask = true if (item.status == state.downloadStatus.RUN) {
return removeTasks(store, [...list]).finally(() => { dls[item.key].stop().finally(() => {
let result = getStartTask(state.list, state.downloadStatus, rootState.setting.download.maxDownloadNum) delete dls[item.key]
while (result) { })
store.dispatch('startTask', result) } else {
result = getStartTask(state.list, state.downloadStatus, rootState.setting.download.maxDownloadNum) delete dls[item.key]
}
} }
isRuningActionTask = false if (item.status != state.downloadStatus.COMPLETED) {
}) deleteFile(item.filePath).catch(_ => _)
}
}
commit('removeTasks', list)
let result = getStartTask(state.list, state.downloadStatus, rootState.setting.download.maxDownloadNum)
while (result) {
dispatch('startTask', result)
result = getStartTask(state.list, state.downloadStatus, rootState.setting.download.maxDownloadNum)
}
}, },
async startTask({ state, rootState, commit, dispatch }, downloadInfo) { async startTask({ state, rootState, commit, dispatch }, downloadInfo) {
// 检查是否可以开始任务 // 检查是否可以开始任务
let result = getStartTask(state.list, state.downloadStatus, rootState.setting.download.maxDownloadNum)
if (downloadInfo && !downloadInfo.isComplate && downloadInfo.status != state.downloadStatus.RUN) { if (downloadInfo && !downloadInfo.isComplate && downloadInfo.status != state.downloadStatus.RUN) {
const result = getStartTask(state.list, state.downloadStatus, rootState.setting.download.maxDownloadNum)
if (result === false) { if (result === false) {
commit('setStatus', { downloadInfo, status: state.downloadStatus.WAITING }) commit('setStatus', { downloadInfo, status: state.downloadStatus.WAITING })
return return
} }
} else { } else {
const result = getStartTask(state.list, state.downloadStatus, rootState.setting.download.maxDownloadNum)
if (!result) return if (!result) return
downloadInfo = result downloadInfo = result
} }
@ -582,52 +557,152 @@ const actions = {
await dispatch('handleStartTask', downloadInfo) await dispatch('handleStartTask', downloadInfo)
} }
}, },
startTasks(store, list) { startTasks({ commit, rootState, dispatch }, list) {
if (isRuningActionTask) return list = list.filter(item => !(item.isComplate || item.status == state.downloadStatus.RUN || item.status == state.downloadStatus.WAITING))
isRuningActionTask = true commit('setStatus', { list, status: state.downloadStatus.WAITING })
return startTasks(store, list.filter(item => !(item.isComplate || item.status == state.downloadStatus.RUN || item.status == state.downloadStatus.WAITING))).finally(() => { let result = getStartTask(state.list, state.downloadStatus, rootState.setting.download.maxDownloadNum)
isRuningActionTask = false while (result) {
}) dispatch('startTask', result)
result = getStartTask(state.list, state.downloadStatus, rootState.setting.download.maxDownloadNum)
}
}, },
async pauseTask(store, item) { async pauseTask({ commit }, item) {
if (item.isComplate) return if (item.isComplate) return
let dl = dls[item.key] let dl = dls[item.key]
if (dl) { if (dl) dl.stop()
try { commit('setStatus', { downloadInfo: item, status: state.downloadStatus.PAUSE })
await dl.stop()
} catch (_) {}
}
store.commit('pauseTask', item)
}, },
pauseTasks(store, list) { pauseTasks({ commit, rootState, dispatch }, list) {
if (isRuningActionTask) return const waitingTasks = list.filter(item => item.status == state.downloadStatus.WAITING)
isRuningActionTask = true commit('setStatus', { list: waitingTasks, status: state.downloadStatus.PAUSE })
return pauseTasks(store, [...list]).finally(() => { const runningTasks = list.filter(item => item.status == state.downloadStatus.RUN)
isRuningActionTask = false for (const item of runningTasks) {
}) if (item.isComplate) return
let dl = dls[item.key]
if (dl) dl.stop()
}
commit('setStatus', { list: runningTasks, status: state.downloadStatus.PAUSE })
}, },
} }
// mitations // mitations
const mutations = { const mutations = {
addTask(state, downloadInfo) { addTask(state, { downloadInfo, musicInfo, addMusicLocationType }) {
state.list.unshift(downloadInfo) const downloadInfoFull = { ...downloadInfo, musicInfo }
window.downloadListFullMap.set(downloadInfo.key, downloadInfoFull)
switch (addMusicLocationType) {
case 'top':
window.downloadListFull.unshift(downloadInfoFull)
state.list.unshift(downloadInfo)
break
case 'bottom':
default:
window.downloadListFull.push(downloadInfoFull)
state.list.push(downloadInfo)
break
}
},
addTasks(state, { list, addMusicLocationType }) {
const downloadInfoList = []
const curDownloadListFull = []
for (const { downloadInfo, musicInfo } of list) {
downloadInfoList.push(downloadInfo)
curDownloadListFull.push({ ...downloadInfo, musicInfo })
}
let newList
let newListFull
const map = {}
const fullMap = {}
const ids = []
switch (addMusicLocationType) {
case 'top':
newList = [...downloadInfoList, ...state.list]
newListFull = [...curDownloadListFull, ...window.downloadListFull]
for (let i = newList.length - 1; i > -1; i--) {
const item = newList[i]
if (map[item.key]) continue
ids.unshift(item.key)
map[item.key] = item
fullMap[item.key] = newListFull[i]
}
break
case 'bottom':
default:
newList = [...state.list, ...downloadInfoList]
newListFull = [...window.downloadListFull, ...curDownloadListFull]
newList.forEach((item, index) => {
if (map[item.key]) return
ids.push(item.key)
map[item.key] = item
fullMap[item.key] = newListFull[index]
})
break
}
window.downloadListFullMap.clear()
window.downloadListFull = ids.map(id => {
const info = fullMap[id]
window.downloadListFullMap.set(info.key, info)
return info
})
state.list.splice(0, state.list.length, ...ids.map(id => map[id]))
}, },
removeTask({ list }, downloadInfo) { removeTask({ list }, downloadInfo) {
list.splice(list.indexOf(downloadInfo), 1) const index = list.findIndex(m => m.key == downloadInfo.key)
if (index < 0) return
window.downloadListFull.splice(index, 1)
window.downloadListFullMap.delete(downloadInfo.key)
list.splice(index, 1)
},
removeTasks(state, list) {
let map = {}
let ids = []
for (const item of state.list) {
ids.push(item.key)
map[item.key] = item
}
for (const { key } of list) {
if (map[key]) delete map[key]
}
let newList = []
let newListFull = []
for (const id of ids) {
if (map[id]) {
newList.push(map[id])
newListFull.push(window.downloadListFullMap.get(id))
}
}
window.downloadListFull = newListFull
window.downloadListFullMap.clear()
for (const item of newListFull) {
window.downloadListFullMap.set(item.key, item)
}
state.list.splice(0, state.list.length, ...newList)
}, },
pauseTask(state, downloadInfo) { pauseTask(state, downloadInfo) {
const index = state.list.findIndex(m => m.key == downloadInfo.key)
if (index < 0) return
const downloadInfoFull = window.downloadListFull[index]
downloadInfoFull.status = state.downloadStatus.PAUSE
downloadInfoFull.statusText = '暂停下载'
downloadInfo.status = state.downloadStatus.PAUSE downloadInfo.status = state.downloadStatus.PAUSE
downloadInfo.statusText = '暂停下载' downloadInfo.statusText = '暂停下载'
}, },
setStatusText(state, { downloadInfo, index, text }) { // 设置状态文本 setStatusText(state, { downloadInfo, index, text }) { // 设置状态文本
if (downloadInfo) { if (downloadInfo) {
const index = state.list.findIndex(m => m.key == downloadInfo.key)
if (index < 0) return
const downloadInfoFull = window.downloadListFull[index]
if (downloadInfoFull) downloadInfoFull.statusText = text
downloadInfo.statusText = text downloadInfo.statusText = text
} else { } else {
state.list[index].statusText = text state.list[index].statusText = text
const downloadInfoFull = window.downloadListFull[index]
if (downloadInfoFull) downloadInfoFull.statusText = text
} }
}, },
setStatus(state, { downloadInfo, index, status }) { // 设置状态及状态文本 setStatus(state, { downloadInfo, index, status, list }) { // 设置状态及状态文本
let text let text
switch (status) { switch (status) {
case state.downloadStatus.RUN: case state.downloadStatus.RUN:
@ -646,43 +721,107 @@ const mutations = {
text = '下载完成' text = '下载完成'
break break
} }
if (downloadInfo) { if (list) {
downloadInfo.statusText = text for (const downloadInfo of list) {
downloadInfo.status = status const index = state.list.findIndex(m => m.key == downloadInfo.key)
if (index < 0) return
const downloadInfoFull = window.downloadListFull[index]
downloadInfoFull.statusText = text
downloadInfoFull.status = status
downloadInfo.statusText = text
downloadInfo.status = status
}
} else { } else {
state.list[index].statusText = text if (downloadInfo) {
state.list[index].status = status const index = state.list.findIndex(m => m.key == downloadInfo.key)
if (index < 0) return
const downloadInfoFull = window.downloadListFull[index]
downloadInfoFull.statusText = text
downloadInfoFull.status = status
downloadInfo.statusText = text
downloadInfo.status = status
} else {
const downloadInfoFull = window.downloadListFull[index]
downloadInfoFull.statusText = text
downloadInfoFull.status = status
state.list[index].statusText = text
state.list[index].status = status
}
} }
}, },
onCompleted(state, downloadInfo) { onCompleted(state, downloadInfo) {
const index = state.list.findIndex(m => m.key == downloadInfo.key)
console.log(index)
if (index < 0) return
const downloadInfoFull = window.downloadListFull[index]
downloadInfoFull.isComplate = true
downloadInfoFull.status = state.downloadStatus.COMPLETED
downloadInfoFull.statusText = '下载完成'
downloadInfo.isComplate = true downloadInfo.isComplate = true
downloadInfo.status = state.downloadStatus.COMPLETED downloadInfo.status = state.downloadStatus.COMPLETED
downloadInfo.statusText = '下载完成' downloadInfo.statusText = '下载完成'
}, },
onError(state, { downloadInfo, errorMsg }) { onError(state, { downloadInfo, errorMsg }) {
const index = state.list.findIndex(m => m.key == downloadInfo.key)
if (index < 0) return
const downloadInfoFull = window.downloadListFull[index]
downloadInfoFull.status = state.downloadStatus.ERROR
downloadInfoFull.statusText = errorMsg || '任务出错'
downloadInfo.status = state.downloadStatus.ERROR downloadInfo.status = state.downloadStatus.ERROR
downloadInfo.statusText = errorMsg || '任务出错' downloadInfo.statusText = errorMsg || '任务出错'
}, },
onStart(state, downloadInfo) { onStart(state, downloadInfo) {
const index = state.list.findIndex(m => m.key == downloadInfo.key)
if (index < 0) return
const downloadInfoFull = window.downloadListFull[index]
downloadInfoFull.status = state.downloadStatus.RUN
downloadInfoFull.statusText = '正在下载'
downloadInfo.status = state.downloadStatus.RUN downloadInfo.status = state.downloadStatus.RUN
downloadInfo.statusText = '正在下载' downloadInfo.statusText = '正在下载'
}, },
onProgress(state, { downloadInfo, status }) { onProgress(state, { downloadInfo, status }) {
const index = state.list.findIndex(m => m.key == downloadInfo.key)
if (index < 0) return
const downloadInfoFull = window.downloadListFull[index]
downloadInfoFull.progress.progress = status.progress
downloadInfoFull.progress.downloaded = status.downloaded
downloadInfoFull.progress.total = status.total
downloadInfo.progress.progress = status.progress downloadInfo.progress.progress = status.progress
downloadInfo.progress.downloaded = status.downloaded downloadInfo.progress.downloaded = status.downloaded
downloadInfo.progress.total = status.total downloadInfo.progress.total = status.total
}, },
setTotal(state, { order, downloadInfo }) {
downloadInfo.order = order
},
updateDownloadList(state, list) { updateDownloadList(state, list) {
state.list = window.downloadList = list window.downloadListFullMap.clear()
const stateList = list.map(downloadInfoFull => {
window.downloadListFullMap.set(downloadInfoFull.key, downloadInfoFull)
const downloadInfo = { ...downloadInfoFull }
delete downloadInfo.musicInfo
return downloadInfo
})
window.downloadListFull = list
state.list = window.downloadList = stateList
}, },
updateUrl(state, { downloadInfo, url }) { updateUrl(state, { downloadInfo, url }) {
const index = state.list.findIndex(m => m.key == downloadInfo.key)
if (index < 0) return
const downloadInfoFull = window.downloadListFull[index]
downloadInfoFull.url = url
downloadInfo.url = url downloadInfo.url = url
}, },
updateFilePath(state, { downloadInfo, filePath }) { updateFilePath(state, { downloadInfo, filePath }) {
if (downloadInfo.filePath === filePath) return if (downloadInfo.filePath === filePath) return
const index = state.list.findIndex(m => m.key == downloadInfo.key)
if (index < 0) return
const downloadInfoFull = window.downloadListFull[index]
downloadInfoFull.filePath = filePath
downloadInfo.filePath = filePath downloadInfo.filePath = filePath
}, },
} }

View File

@ -155,15 +155,23 @@ const getters = {
let listPlayIndex = Math.min(state.playIndex, state.listInfo.list.length - 1) let listPlayIndex = Math.min(state.playIndex, state.listInfo.list.length - 1)
if (listId != '__temp__') { if (listId != '__temp__') {
const currentSongmid = state.playMusicInfo.musicInfo.songmid || state.playMusicInfo.musicInfo.musicInfo.songmid if (state.playMusicInfo.musicInfo.key) {
if (isPlayList) { const currentKey = state.playMusicInfo.musicInfo.key
playIndex = state.listInfo.list.findIndex(m => (m.songmid || m.musicInfo.songmid) == currentSongmid) if (isPlayList) {
if (!isTempPlay) listPlayIndex = playIndex playIndex = state.listInfo.list.findIndex(m => m.key == currentKey)
} else if (listId == 'download') { if (!isTempPlay) listPlayIndex = playIndex
playIndex = window.downloadList.findIndex(m => m.musicInfo.songmid == currentSongmid) } else if (listId == 'download') {
playIndex = window.downloadList.findIndex(m => m.key == currentKey)
}
} else { } else {
let list = window.allList[listId] const currentSongmid = state.playMusicInfo.musicInfo.songmid || state.playMusicInfo.musicInfo.musicInfo.songmid
if (list) playIndex = list.list.findIndex(m => m.songmid == currentSongmid) if (isPlayList) {
playIndex = state.listInfo.list.findIndex(m => m.songmid == currentSongmid)
if (!isTempPlay) listPlayIndex = playIndex
} else {
let list = window.allList[listId]
if (list) playIndex = list.list.findIndex(m => m.songmid == currentSongmid)
}
} }
} }
if (listPlayIndex >= 0) prevListPlayIndex = listPlayIndex if (listPlayIndex >= 0) prevListPlayIndex = listPlayIndex
@ -186,6 +194,8 @@ const getters = {
// isTempPlay, // isTempPlay,
// // musicInfo: state.playMusicInfo.musicInfo, // // musicInfo: state.playMusicInfo.musicInfo,
// }) // })
console.log(state.playMusicInfo)
return { return {
listId, listId,
playIndex, playIndex,

View File

@ -20,10 +20,10 @@ div(:class="$style.download")
div.list-item(@click="handleDoubleClick($event, index)" @contextmenu="handleListItemRigthClick($event, index)" div.list-item(@click="handleDoubleClick($event, index)" @contextmenu="handleListItemRigthClick($event, index)"
:class="[{[$style.active]: playListIndex == index }, { selected: selectedIndex == index }, { active: selectedData.includes(item) }]") :class="[{[$style.active]: playListIndex == index }, { selected: selectedIndex == index }, { active: selectedData.includes(item) }]")
div.list-item-cell.nobreak.center(style="width: 5%; padding-left: 3px; padding-right: 3px;" @click.stop) {{index + 1}} div.list-item-cell.nobreak.center(style="width: 5%; padding-left: 3px; padding-right: 3px;" @click.stop) {{index + 1}}
div.list-item-cell.auto div.list-item-cell.auto(:tips="item.name")
span.select {{item.musicInfo.name}} - {{item.musicInfo.singer}} span.select {{item.name}}
div.list-item-cell(style="width: 20%;") {{item.progress.progress}}% div.list-item-cell(style="width: 20%;") {{item.progress.progress}}%
div.list-item-cell(style="width: 22%;") {{item.statusText}} div.list-item-cell(style="width: 22%;" :tips="item.statusText") {{item.statusText}}
div.list-item-cell(style="width: 10%;") {{item.type && item.type.toUpperCase()}} div.list-item-cell(style="width: 10%;") {{item.type && item.type.toUpperCase()}}
div.list-item-cell(style="width: 13%; padding-left: 0; padding-right: 0;") div.list-item-cell(style="width: 13%; padding-left: 0; padding-right: 0;")
material-list-buttons(:index="index" :download-btn="false" :file-btn="item.status != downloadStatus.ERROR" remove-btn material-list-buttons(:index="index" :download-btn="false" :file-btn="item.status != downloadStatus.ERROR" remove-btn
@ -309,7 +309,7 @@ export default {
this.handleOpenFolder(item.filePath) this.handleOpenFolder(item.filePath)
break break
case 'search': case 'search':
this.handleSearch(item.musicInfo) this.handleSearch(window.downloadListFullMap.get(item.key).musicInfo)
break break
} }
}, },
@ -350,7 +350,8 @@ export default {
this.selectedData = [] this.selectedData = []
}, },
handleListItemRigthClick(event, index) { handleListItemRigthClick(event, index) {
this.listMenu.itemMenuControl.sourceDetail = !!musicSdk[this.showList[index].musicInfo.source].getMusicDetailPageUrl const downloadInfo = window.downloadListFullMap.get(this.showList[index].key)
this.listMenu.itemMenuControl.sourceDetail = !!musicSdk[downloadInfo.musicInfo.source].getMusicDetailPageUrl
let dom_container = event.target.closest('.' + this.$style.download) let dom_container = event.target.closest('.' + this.$style.download)
const getOffsetValue = (target, x = 0, y = 0) => { const getOffsetValue = (target, x = 0, y = 0) => {
if (target === dom_container) return { x, y } if (target === dom_container) return { x, y }
@ -442,7 +443,7 @@ export default {
break break
case 'search': case 'search':
item = this.showList[index] item = this.showList[index]
if (item) this.handleSearch(item.musicInfo) if (item) this.handleSearch(window.downloadListFullMap.get(item.key).musicInfo)
break break
case 'remove': case 'remove':
if (this.selectedData.length) { if (this.selectedData.length) {
@ -466,7 +467,7 @@ export default {
} }
break break
case 'sourceDetail': case 'sourceDetail':
item = this.showList[index].musicInfo item = window.downloadListFullMap.get(this.showList[index].key).musicInfo
url = musicSdk[item.source].getMusicDetailPageUrl(item) url = musicSdk[item.source].getMusicDetailPageUrl(item)
if (!url) return if (!url) return
openUrl(url) openUrl(url)