新增列表多选操作功能
parent
8817318a53
commit
601e1a67a1
|
@ -10,7 +10,7 @@ const { mergeCSSLoaderDev } = require('../utils')
|
||||||
|
|
||||||
module.exports = merge(baseConfig, {
|
module.exports = merge(baseConfig, {
|
||||||
mode: 'development',
|
mode: 'development',
|
||||||
devtool: '#cheap-module-eval-source-map',
|
devtool: 'eval-source-map',
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
|
@ -46,7 +46,7 @@ module.exports = merge(baseConfig, {
|
||||||
NODE_ENV: '"development"',
|
NODE_ENV: '"development"',
|
||||||
ELECTRON_DISABLE_SECURITY_WARNINGS: 'true',
|
ELECTRON_DISABLE_SECURITY_WARNINGS: 'true',
|
||||||
},
|
},
|
||||||
'__static': `"${path.join(__dirname, '../../src/static').replace(/\\/g, '\\\\')}"`,
|
__static: `"${path.join(__dirname, '../../src/static').replace(/\\/g, '\\\\')}"`,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
performance: {
|
performance: {
|
||||||
|
|
|
@ -9,7 +9,7 @@ const { mergeCSSLoaderDev } = require('../utils')
|
||||||
|
|
||||||
module.exports = merge(baseConfig, {
|
module.exports = merge(baseConfig, {
|
||||||
mode: 'development',
|
mode: 'development',
|
||||||
devtool: '#cheap-module-eval-source-map',
|
devtool: 'eval-source-map',
|
||||||
output: {
|
output: {
|
||||||
filename: '[name].js',
|
filename: '[name].js',
|
||||||
path: path.join(__dirname, '../../dist/web'),
|
path: path.join(__dirname, '../../dist/web'),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "lx-music-desktop",
|
"name": "lx-music-desktop",
|
||||||
"version": "0.1.0",
|
"version": "0.1.4",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
### 新增
|
||||||
|
|
||||||
|
- 新增搜索列表批量试听与下载功能
|
||||||
|
- 新增排行榜列表批量试听与下载功能
|
||||||
|
- 新增试听列表批量移除与下载功能
|
||||||
|
- 新增下载列表批量开始、暂停与移除功能
|
||||||
|
|
||||||
|
### 优化
|
||||||
|
|
||||||
|
- 优化歌曲切换机制
|
|
@ -16,7 +16,7 @@ const run = async() => {
|
||||||
try {
|
try {
|
||||||
console.log(chalk.blue('Clearing assets...'))
|
console.log(chalk.blue('Clearing assets...'))
|
||||||
await clearAssets()
|
await clearAssets()
|
||||||
console.log(chalk.green('Assets clear complated...'))
|
console.log(chalk.green('Assets clear completed...'))
|
||||||
|
|
||||||
// console.log(chalk.blue('Compileing assets...'))
|
// console.log(chalk.blue('Compileing assets...'))
|
||||||
// await compileAssets()
|
// await compileAssets()
|
||||||
|
|
|
@ -38,6 +38,7 @@ export default {
|
||||||
...mapGetters('list', ['defaultList']),
|
...mapGetters('list', ['defaultList']),
|
||||||
...mapGetters('download', {
|
...mapGetters('download', {
|
||||||
downloadList: 'list',
|
downloadList: 'list',
|
||||||
|
downloadStatus: 'downloadStatus',
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -119,6 +120,12 @@ export default {
|
||||||
initDownloadList() {
|
initDownloadList() {
|
||||||
let downloadList = this.electronStore.get('download.list')
|
let downloadList = this.electronStore.get('download.list')
|
||||||
if (downloadList) {
|
if (downloadList) {
|
||||||
|
downloadList.forEach(item => {
|
||||||
|
if (item.status == this.downloadStatus.RUN || item.status == this.downloadStatus.WAITING) {
|
||||||
|
item.status = this.downloadStatus.PAUSE
|
||||||
|
item.statusText = '暂停下载'
|
||||||
|
}
|
||||||
|
})
|
||||||
this.updateDownloadList(downloadList)
|
this.updateDownloadList(downloadList)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -252,36 +252,43 @@ export default {
|
||||||
},
|
},
|
||||||
handleNext() {
|
handleNext() {
|
||||||
// if (this.list.listName === null) return
|
// if (this.list.listName === null) return
|
||||||
const list = this.isAPITemp ? this.list.filter(s => s.source == 'kw') : this.list
|
let list
|
||||||
if (!list.length) return
|
if (this.listId == 'download') {
|
||||||
|
list = this.list.filter(s => !(!checkPath(s.filePath) || !s.isComplate || /\.ape$/.test(s.filePath)))
|
||||||
|
} else if (this.isAPITemp) {
|
||||||
|
list = this.list.filter(s => s.source == 'kw')
|
||||||
|
} else {
|
||||||
|
list = this.list
|
||||||
|
}
|
||||||
|
if (!list.length) return this.setPlayIndex(-1)
|
||||||
|
let playIndex = this.list === list ? this.playIndex : list.indexOf(this.list[this.playIndex])
|
||||||
|
|
||||||
let index
|
let index
|
||||||
switch (this.setting.player.togglePlayMethod) {
|
switch (this.setting.player.togglePlayMethod) {
|
||||||
case 'listLoop':
|
case 'listLoop':
|
||||||
index = this.hanldeListLoop()
|
index = this.hanldeListLoop(list, playIndex)
|
||||||
break
|
break
|
||||||
case 'random':
|
case 'random':
|
||||||
index = this.hanldeListRandom()
|
index = this.hanldeListRandom(list, playIndex)
|
||||||
break
|
break
|
||||||
case 'list':
|
case 'list':
|
||||||
index = this.hanldeListNext()
|
index = this.hanldeListNext(list, playIndex)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (index < 0) return
|
if (index < 0) return
|
||||||
|
if (this.list !== list) index = this.list.indexOf(list[index])
|
||||||
this.setPlayIndex(index)
|
this.setPlayIndex(index)
|
||||||
},
|
},
|
||||||
hanldeListLoop(index = this.playIndex) {
|
hanldeListLoop(list, index) {
|
||||||
index = index === this.list.length - 1 ? 0 : index + 1
|
return index === list.length - 1 ? 0 : index + 1
|
||||||
return this.isAPITemp && this.list[index].source != 'kw' ? this.hanldeListLoop(index) : index
|
|
||||||
},
|
},
|
||||||
hanldeListNext(index = this.playIndex) {
|
hanldeListNext(list, index) {
|
||||||
index = index === this.list.length - 1 ? -1 : index + 1
|
return index === list.length - 1 ? -1 : index + 1
|
||||||
return this.isAPITemp && this.list[index].source != 'kw' ? this.hanldeListNext(index) : index
|
|
||||||
},
|
},
|
||||||
hanldeListRandom(index = this.playIndex) {
|
hanldeListRandom(list, index) {
|
||||||
index = getRandom(0, this.list.length)
|
return getRandom(0, list.length)
|
||||||
return this.isAPITemp && this.list[index].source != 'kw' ? this.hanldeListRandom(index) : index
|
|
||||||
},
|
},
|
||||||
startPlay() {
|
startPlay() {
|
||||||
this.isPlay = true
|
this.isPlay = true
|
||||||
|
@ -333,6 +340,9 @@ export default {
|
||||||
this.audio.src = this.musicInfo.url
|
this.audio.src = this.musicInfo.url
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
this.status = err.message
|
this.status = err.message
|
||||||
|
setTimeout(() => {
|
||||||
|
this.handleNext()
|
||||||
|
}, 2000)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
setImg(targetSong) {
|
setImg(targetSong) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ div(:class="$style.checkbox")
|
||||||
div(v-else)
|
div(v-else)
|
||||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' width="100%" viewBox='0 32 448 448' space='preserve')
|
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' width="100%" viewBox='0 32 448 448' space='preserve')
|
||||||
use(xlink:href='#icon-check-true')
|
use(xlink:href='#icon-check-true')
|
||||||
span(v-if="label != null") {{label}}
|
span(v-if="label != null" v-html="label")
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
<template lang="pug">
|
||||||
|
material-modal(:show="show" :bg-close="bgClose" @close="handleClose")
|
||||||
|
main(:class="$style.main")
|
||||||
|
h2
|
||||||
|
| 已选择 {{list.length}} 首歌曲
|
||||||
|
br
|
||||||
|
| 请选择要优先下载的音质
|
||||||
|
material-btn(:class="$style.btn" @click="handleClick('128k')") 普通音质 - 128K
|
||||||
|
material-btn(:class="$style.btn" @click="handleClick('320k')") 高品音质 - 320K
|
||||||
|
material-btn(:class="$style.btn" @click="handleClick('ape')") 无损音质 - APE
|
||||||
|
material-btn(:class="$style.btn" @click="handleClick('flac')") 无损音质 - FLAC
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
bgClose: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
type: Array,
|
||||||
|
default() {
|
||||||
|
return []
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleClick(type) {
|
||||||
|
this.$emit('select', type)
|
||||||
|
},
|
||||||
|
handleClose() {
|
||||||
|
this.$emit('close')
|
||||||
|
},
|
||||||
|
getTypeName(type) {
|
||||||
|
switch (type) {
|
||||||
|
case 'flac':
|
||||||
|
case 'ape':
|
||||||
|
return '无损音质'
|
||||||
|
case '320k':
|
||||||
|
return '高品音质'
|
||||||
|
case '192k':
|
||||||
|
case '128k':
|
||||||
|
return '普通音质'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="less" module>
|
||||||
|
@import '../../assets/styles/layout.less';
|
||||||
|
|
||||||
|
.main {
|
||||||
|
padding: 15px;
|
||||||
|
max-width: 300px;
|
||||||
|
min-width: 200px;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
justify-content: center;
|
||||||
|
h2 {
|
||||||
|
font-size: 13px;
|
||||||
|
color: @color-theme_2-font;
|
||||||
|
line-height: 1.3;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
each(@themes, {
|
||||||
|
:global(#container.@{value}) {
|
||||||
|
.main {
|
||||||
|
h2 {
|
||||||
|
color: ~'@{color-@{value}-theme_2-font}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,122 @@
|
||||||
|
<template lang="pug">
|
||||||
|
transition(enter-active-class="animated-fast zoomIn" leave-active-class="animated zoomOut")
|
||||||
|
div(:class="$style.btns" v-show="show")
|
||||||
|
button(type="button" v-if="playBtn" title="播放" @click.stop="handleClick('play')")
|
||||||
|
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 287.386 287.386' space='preserve')
|
||||||
|
use(xlink:href='#icon-testPlay')
|
||||||
|
button(type="button" v-if="addBtn" title="添加" @click.stop="handleClick('add')")
|
||||||
|
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 42 42' space='preserve')
|
||||||
|
use(xlink:href='#icon-addTo')
|
||||||
|
button(type="button" v-if="downloadBtn" title="下载" @click.stop="handleClick('download')")
|
||||||
|
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 475.078 475.077' space='preserve')
|
||||||
|
use(xlink:href='#icon-download')
|
||||||
|
button(type="button" v-if="startBtn" title="开始" @click.stop="handleClick('start')")
|
||||||
|
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 170 170' space='preserve')
|
||||||
|
use(xlink:href='#icon-play')
|
||||||
|
button(type="button" v-if="pauseBtn" title="暂停" @click.stop="handleClick('pause')")
|
||||||
|
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 277.338 277.338' space='preserve')
|
||||||
|
use(xlink:href='#icon-pause')
|
||||||
|
button(type="button" v-if="removeBtn" title="移除" @click.stop="handleClick('remove')")
|
||||||
|
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 212.982 212.982' space='preserve')
|
||||||
|
use(xlink:href='#icon-delete')
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
removeBtn: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
startBtn: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
pauseBtn: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
downloadBtn: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
addBtn: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
playBtn: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleClick(action) {
|
||||||
|
this.$emit('btn-click', action)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="less" module>
|
||||||
|
@import '../../assets/styles/layout.less';
|
||||||
|
|
||||||
|
.btns {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 80px;
|
||||||
|
right: 30px;
|
||||||
|
background-color: @color-search-form-background;
|
||||||
|
border-radius: 5px;
|
||||||
|
// padding: 3px 5px;
|
||||||
|
box-shadow: 0 1px 5px 0 rgba(0,0,0,.2);
|
||||||
|
button {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
border-radius: 3px;
|
||||||
|
margin-right: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 4px 7px;
|
||||||
|
color: @color-btn;
|
||||||
|
outline: none;
|
||||||
|
transition: background-color 0.2s ease;
|
||||||
|
line-height: 0;
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
height: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: @color-theme_2-hover;
|
||||||
|
}
|
||||||
|
&:active {
|
||||||
|
background-color: @color-theme_2-active;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
each(@themes, {
|
||||||
|
:global(#container.@{value}) {
|
||||||
|
.btns {
|
||||||
|
background-color: ~'@{color-@{value}-search-form-background}';
|
||||||
|
button {
|
||||||
|
color: ~'@{color-@{value}-btn}';
|
||||||
|
&:hover {
|
||||||
|
background-color: ~'@{color-@{value}-theme_2-hover}';
|
||||||
|
}
|
||||||
|
&:active {
|
||||||
|
background-color: ~'@{color-@{value}-theme_2-active}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</style>
|
|
@ -9,6 +9,12 @@ div(:class="$style.btns")
|
||||||
button(type="button" title="添加" v-if="userInfo" @click.stop="handleClick('add')")
|
button(type="button" title="添加" v-if="userInfo" @click.stop="handleClick('add')")
|
||||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 42 42' space='preserve')
|
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 42 42' space='preserve')
|
||||||
use(xlink:href='#icon-addTo')
|
use(xlink:href='#icon-addTo')
|
||||||
|
button(type="button" v-if="startBtn" title="开始" @click.stop="handleClick('start')")
|
||||||
|
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 170 170' space='preserve')
|
||||||
|
use(xlink:href='#icon-play')
|
||||||
|
button(type="button" v-if="pauseBtn" title="暂停" @click.stop="handleClick('pause')")
|
||||||
|
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 277.338 277.338' space='preserve')
|
||||||
|
use(xlink:href='#icon-pause')
|
||||||
button(type="button" v-if="removeBtn" title="移除" @click.stop="handleClick('remove')")
|
button(type="button" v-if="removeBtn" title="移除" @click.stop="handleClick('remove')")
|
||||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 212.982 212.982' space='preserve')
|
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 212.982 212.982' space='preserve')
|
||||||
use(xlink:href='#icon-delete')
|
use(xlink:href='#icon-delete')
|
||||||
|
@ -27,6 +33,14 @@ export default {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
startBtn: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
pauseBtn: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
removeBtn: {
|
removeBtn: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
|
|
|
@ -2,18 +2,30 @@ import download from '../../utils/download'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import music from '../../utils/music'
|
import music from '../../utils/music'
|
||||||
|
import { getMusicType } from '../../utils/music/utils'
|
||||||
|
|
||||||
// state
|
// state
|
||||||
const state = {
|
const state = {
|
||||||
list: [],
|
list: [],
|
||||||
|
waitingList: [],
|
||||||
|
downloadStatus: {
|
||||||
|
RUN: 'run',
|
||||||
|
WAITING: 'waiting',
|
||||||
|
PAUSE: 'pause',
|
||||||
|
ERROR: 'error',
|
||||||
|
COMPLETED: 'completed',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const dls = {}
|
const dls = {}
|
||||||
|
const tryNum = {}
|
||||||
|
|
||||||
// getters
|
// getters
|
||||||
const getters = {
|
const getters = {
|
||||||
list: state => state.list || [],
|
list: state => state.list || [],
|
||||||
dls: () => dls || {},
|
dls: () => dls || {},
|
||||||
|
downloadStatus: state => state.downloadStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkPath = path => {
|
const checkPath = path => {
|
||||||
|
@ -40,19 +52,37 @@ const getExt = type => {
|
||||||
|
|
||||||
const checkList = (list, musicInfo, type) => list.some(s => s.musicInfo.songmid === musicInfo.songmid && s.type === type)
|
const checkList = (list, musicInfo, type) => list.some(s => s.musicInfo.songmid === musicInfo.songmid && s.type === type)
|
||||||
|
|
||||||
|
const getStartTask = (list, downloadStatus, maxDownloadNum) => {
|
||||||
|
let downloadCount = 0
|
||||||
|
const waitList = list.filter(item => item.status == downloadStatus.WAITING ? true : (item.status === downloadStatus.RUN && ++downloadCount && false))
|
||||||
|
console.log(downloadCount, waitList)
|
||||||
|
return downloadCount < maxDownloadNum && waitList.length > 0 && waitList.shift()
|
||||||
|
}
|
||||||
|
|
||||||
|
const addTask = (list, type, store) => {
|
||||||
|
window.requestAnimationFrame(() => {
|
||||||
|
let item = list.shift()
|
||||||
|
store.dispatch('download/createDownload', {
|
||||||
|
musicInfo: item,
|
||||||
|
type: getMusicType(item, type),
|
||||||
|
})
|
||||||
|
if (list.length) addTask(list, type, store)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const refreshUrl = downloadInfo => {
|
const refreshUrl = downloadInfo => {
|
||||||
return music[downloadInfo.musicInfo.source].getMusicUrl(downloadInfo.musicInfo, downloadInfo.type).promise
|
return music[downloadInfo.musicInfo.source].getMusicUrl(downloadInfo.musicInfo, downloadInfo.type).promise
|
||||||
}
|
}
|
||||||
|
|
||||||
// actions
|
// actions
|
||||||
const actions = {
|
const actions = {
|
||||||
createDownload({ state, rootState }, { musicInfo, type }) {
|
createDownload({ state, rootState, commit }, { musicInfo, type }) {
|
||||||
if (checkList(state.list, musicInfo, type)) return
|
if (checkList(state.list, musicInfo, type)) return
|
||||||
let ext = getExt(type)
|
let ext = getExt(type)
|
||||||
const downloadInfo = {
|
const downloadInfo = {
|
||||||
isComplate: false,
|
isComplate: false,
|
||||||
isDownloading: false,
|
status: state.downloadStatus.WAITING,
|
||||||
statusText: '任务初始化中',
|
statusText: '待下载',
|
||||||
url: null,
|
url: null,
|
||||||
fileName: `${rootState.setting.download.fileName
|
fileName: `${rootState.setting.download.fileName
|
||||||
.replace('歌名', musicInfo.name)
|
.replace('歌名', musicInfo.name)
|
||||||
|
@ -68,19 +98,33 @@ const actions = {
|
||||||
key: `${musicInfo.songmid}${ext}`,
|
key: `${musicInfo.songmid}${ext}`,
|
||||||
}
|
}
|
||||||
downloadInfo.filePath = path.join(rootState.setting.download.savePath, downloadInfo.fileName)
|
downloadInfo.filePath = path.join(rootState.setting.download.savePath, downloadInfo.fileName)
|
||||||
|
commit('addTask', downloadInfo)
|
||||||
if (dls[downloadInfo.key]) {
|
if (dls[downloadInfo.key]) {
|
||||||
dls[downloadInfo.key].stop().finally(() => {
|
dls[downloadInfo.key].stop().finally(() => {
|
||||||
this.dispatch('download/addTask', downloadInfo)
|
delete dls[downloadInfo.key]
|
||||||
|
this.dispatch('download/startTask', downloadInfo)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// console.log(downloadInfo)
|
// console.log(downloadInfo)
|
||||||
this.dispatch('download/addTask', downloadInfo)
|
this.dispatch('download/startTask', downloadInfo)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
addTask({ commit, rootState }, downloadInfo) {
|
createDownloadMultiple({ state, rootState }, { list, type }) {
|
||||||
commit('addTask', downloadInfo)
|
addTask([...list], type, this)
|
||||||
|
},
|
||||||
|
startTask({ commit, state, rootState }, downloadInfo) {
|
||||||
|
// 检查是否可以开始任务
|
||||||
|
if (downloadInfo && downloadInfo != state.downloadStatus.WAITING) commit('setStatus', { downloadInfo, status: state.downloadStatus.WAITING })
|
||||||
|
let result = getStartTask(state.list, state.downloadStatus, rootState.setting.download.maxDownloadNum)
|
||||||
|
if (!result) return downloadInfo && commit('setStatus', { downloadInfo, status: state.downloadStatus.WAITING })
|
||||||
|
if (!downloadInfo) downloadInfo = result
|
||||||
|
|
||||||
|
// 开始任务
|
||||||
|
commit('setStatusText', { downloadInfo, text: '任务初始化中' })
|
||||||
|
commit('onDownload', downloadInfo)
|
||||||
let msg = checkPath(rootState.setting.download.savePath)
|
let msg = checkPath(rootState.setting.download.savePath)
|
||||||
if (msg) return commit('setStatusText', '检查下载目录出错: ' + msg)
|
if (msg) return commit('setStatusText', '检查下载目录出错: ' + msg)
|
||||||
|
const _this = this
|
||||||
const options = {
|
const options = {
|
||||||
url: downloadInfo.url,
|
url: downloadInfo.url,
|
||||||
path: rootState.setting.download.savePath,
|
path: rootState.setting.download.savePath,
|
||||||
|
@ -89,16 +133,30 @@ const actions = {
|
||||||
override: true,
|
override: true,
|
||||||
onEnd() {
|
onEnd() {
|
||||||
commit('onEnd', downloadInfo)
|
commit('onEnd', downloadInfo)
|
||||||
|
_this.dispatch('download/startTask')
|
||||||
console.log('on complate')
|
console.log('on complate')
|
||||||
},
|
},
|
||||||
onError(err) {
|
onError(err) {
|
||||||
console.log(err)
|
console.log(err.message)
|
||||||
|
commit('onError', downloadInfo)
|
||||||
|
// console.log(tryNum[downloadInfo.key])
|
||||||
|
if (++tryNum[downloadInfo.key] > 5) return
|
||||||
|
let code
|
||||||
if (err.message.includes('Response status was')) {
|
if (err.message.includes('Response status was')) {
|
||||||
const code = err.message.replace(/Response status was (\d+)$/, '$1')
|
code = err.message.replace(/Response status was (\d+)$/, '$1')
|
||||||
|
} if (err.code === 'ETIMEDOUT') {
|
||||||
|
code = 'ETIMEDOUT'
|
||||||
|
} else {
|
||||||
|
console.log('Download failed, Attempting Retry')
|
||||||
|
dls[downloadInfo.key].resume()
|
||||||
|
commit('setStatusText', { downloadInfo, text: '正在重试' })
|
||||||
|
return
|
||||||
|
}
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case '401':
|
case '401':
|
||||||
case '403':
|
case '403':
|
||||||
case '410':
|
case '410':
|
||||||
|
case 'ETIMEDOUT':
|
||||||
commit('setStatusText', { downloadInfo, text: '链接失效,正在刷新链接' })
|
commit('setStatusText', { downloadInfo, text: '链接失效,正在刷新链接' })
|
||||||
refreshUrl(downloadInfo).then(result => {
|
refreshUrl(downloadInfo).then(result => {
|
||||||
commit('updateUrl', { downloadInfo, url: result.url })
|
commit('updateUrl', { downloadInfo, url: result.url })
|
||||||
|
@ -108,18 +166,13 @@ const actions = {
|
||||||
dls[downloadInfo.key].resume()
|
dls[downloadInfo.key].resume()
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
|
_this.dispatch('download/startTask')
|
||||||
})
|
})
|
||||||
return
|
|
||||||
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
commit('onError', downloadInfo)
|
|
||||||
},
|
|
||||||
onStateChanged(state) {
|
|
||||||
console.log(state)
|
|
||||||
},
|
},
|
||||||
|
// onStateChanged(state) {
|
||||||
|
// console.log(state)
|
||||||
|
// },
|
||||||
onDownload() {
|
onDownload() {
|
||||||
commit('onDownload', downloadInfo)
|
commit('onDownload', downloadInfo)
|
||||||
console.log('on download')
|
console.log('on download')
|
||||||
|
@ -130,6 +183,7 @@ const actions = {
|
||||||
},
|
},
|
||||||
onPause() {
|
onPause() {
|
||||||
commit('pauseTask', downloadInfo)
|
commit('pauseTask', downloadInfo)
|
||||||
|
_this.dispatch('download/startTask')
|
||||||
},
|
},
|
||||||
onResume() {
|
onResume() {
|
||||||
commit('resumeTask', downloadInfo)
|
commit('resumeTask', downloadInfo)
|
||||||
|
@ -138,80 +192,52 @@ const actions = {
|
||||||
let p = options.url ? Promise.resolve() : refreshUrl(downloadInfo).then(result => {
|
let p = options.url ? Promise.resolve() : refreshUrl(downloadInfo).then(result => {
|
||||||
commit('updateUrl', { downloadInfo, url: result.url })
|
commit('updateUrl', { downloadInfo, url: result.url })
|
||||||
options.url = result.url
|
options.url = result.url
|
||||||
|
}).catch(err => {
|
||||||
|
commit('onError', downloadInfo)
|
||||||
|
commit('setStatusText', { downloadInfo, text: err.message })
|
||||||
|
return Promise.reject(err)
|
||||||
})
|
})
|
||||||
p.then(() => {
|
p.then(() => {
|
||||||
|
tryNum[downloadInfo.key] = 0
|
||||||
dls[downloadInfo.key] = download(options)
|
dls[downloadInfo.key] = download(options)
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
startTaskMultiple({ state, rootState }, list) {
|
||||||
|
|
||||||
},
|
},
|
||||||
removeTask({ commit, state }, index) {
|
removeTask({ commit, state }, index) {
|
||||||
let info = state.list[index]
|
let info = state.list[index]
|
||||||
if (state.list[index].isDownloading) {
|
if (state.list[index].status == state.downloadStatus.RUN) {
|
||||||
|
if (dls[info.key]) {
|
||||||
dls[info.key].stop().finally(() => {
|
dls[info.key].stop().finally(() => {
|
||||||
delete dls[info.key]
|
delete dls[info.key]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
commit('removeTask', index)
|
commit('removeTask', index)
|
||||||
if (dls[info.key]) delete dls[info.key]
|
if (dls[info.key]) delete dls[info.key]
|
||||||
|
this.dispatch('download/startTask')
|
||||||
},
|
},
|
||||||
resumeTask({ commit, rootState }, downloadInfo) {
|
removeTaskMultiple({ commit, rootState, state }, list) {
|
||||||
let msg = checkPath(rootState.setting.download.savePath)
|
list.forEach(item => {
|
||||||
if (msg) return commit('setStatusText', '检查下载目录出错: ' + msg)
|
let index = state.list.indexOf(item)
|
||||||
const options = {
|
if (index < 0) return
|
||||||
url: downloadInfo.url,
|
// this.dispatch('download/removeTask', index)
|
||||||
path: rootState.setting.download.savePath,
|
if (state.list[index].status == state.downloadStatus.RUN) {
|
||||||
fileName: downloadInfo.fileName,
|
if (dls[item.key]) {
|
||||||
method: 'get',
|
dls[item.key].stop().finally(() => {
|
||||||
override: true,
|
delete dls[item.key]
|
||||||
onEnd() {
|
|
||||||
commit('onEnd', downloadInfo)
|
|
||||||
console.log('on complate')
|
|
||||||
},
|
|
||||||
onError(err) {
|
|
||||||
commit('onError', downloadInfo)
|
|
||||||
commit('setStatusText', { downloadInfo, text: '链接失效,正在刷新链接' })
|
|
||||||
refreshUrl(downloadInfo).then(result => {
|
|
||||||
commit('updateUrl', { downloadInfo, url: result.url })
|
|
||||||
commit('setStatusText', { downloadInfo, text: '链接刷新成功' })
|
|
||||||
dls[downloadInfo.key].url = dls[downloadInfo.key].requestURL = result.url
|
|
||||||
dls[downloadInfo.key].__initProtocol(result.url)
|
|
||||||
dls[downloadInfo.key].resume()
|
|
||||||
}).catch(err => {
|
|
||||||
console.log(err)
|
|
||||||
})
|
})
|
||||||
console.log(err)
|
|
||||||
},
|
|
||||||
onStateChanged(state) {
|
|
||||||
console.log(state)
|
|
||||||
},
|
|
||||||
onDownload() {
|
|
||||||
commit('onDownload', downloadInfo)
|
|
||||||
console.log('on download')
|
|
||||||
},
|
|
||||||
onProgress(status) {
|
|
||||||
commit('onProgress', { downloadInfo, status })
|
|
||||||
console.log(status)
|
|
||||||
},
|
|
||||||
onPause() {
|
|
||||||
commit('pauseTask', downloadInfo)
|
|
||||||
},
|
|
||||||
onResume() {
|
|
||||||
commit('resumeTask', downloadInfo)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
let p = options.url ? Promise.resolve() : refreshUrl(downloadInfo).then(result => {
|
|
||||||
commit('updateUrl', { downloadInfo, url: result.url })
|
|
||||||
options.url = result.url
|
|
||||||
})
|
|
||||||
|
|
||||||
if (fs.existsSync(downloadInfo.filePath)) {
|
|
||||||
options.resumeInfo = {
|
|
||||||
totalFileSize: downloadInfo.progress.total,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.then(() => {
|
commit('removeTask', index)
|
||||||
dls[downloadInfo.key] = download(options)
|
if (dls[item.key]) delete dls[item.key]
|
||||||
})
|
})
|
||||||
|
let result = getStartTask(state.list, state.downloadStatus, rootState.setting.download.maxDownloadNum)
|
||||||
|
while (result) {
|
||||||
|
this.dispatch('download/startTask', result)
|
||||||
|
result = getStartTask(state.list, state.downloadStatus, rootState.setting.download.maxDownloadNum)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,29 +250,57 @@ const mutations = {
|
||||||
state.list.splice(index, 1)
|
state.list.splice(index, 1)
|
||||||
},
|
},
|
||||||
pauseTask(state, downloadInfo) {
|
pauseTask(state, downloadInfo) {
|
||||||
downloadInfo.isDownloading = false
|
downloadInfo.status = state.downloadStatus.PAUSE
|
||||||
|
downloadInfo.statusText = '暂停下载'
|
||||||
},
|
},
|
||||||
resumeTask(state, downloadInfo) {
|
resumeTask(state, downloadInfo) {
|
||||||
downloadInfo.statusText = '恢复下载'
|
downloadInfo.statusText = '开始下载'
|
||||||
},
|
},
|
||||||
setStatusText(state, { downloadInfo, index, text }) {
|
setStatusText(state, { downloadInfo, index, text }) { // 设置状态文本
|
||||||
if (downloadInfo) {
|
if (downloadInfo) {
|
||||||
downloadInfo.statusText = text
|
downloadInfo.statusText = text
|
||||||
} else {
|
} else {
|
||||||
state.list[index].statusText = text
|
state.list[index].statusText = text
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setStatus(state, { downloadInfo, index, status }) { // 设置状态及状态文本
|
||||||
|
let text
|
||||||
|
switch (status) {
|
||||||
|
case state.downloadStatus.RUN:
|
||||||
|
text = '正在下载'
|
||||||
|
break
|
||||||
|
case state.downloadStatus.WAITING:
|
||||||
|
text = '等待下载'
|
||||||
|
break
|
||||||
|
case state.downloadStatus.PAUSE:
|
||||||
|
text = '暂停下载'
|
||||||
|
break
|
||||||
|
case state.downloadStatus.ERROR:
|
||||||
|
text = '任务出错'
|
||||||
|
break
|
||||||
|
case state.downloadStatus.COMPLETED:
|
||||||
|
text = '下载完成'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (downloadInfo) {
|
||||||
|
downloadInfo.statusText = text
|
||||||
|
downloadInfo.status = status
|
||||||
|
} else {
|
||||||
|
state.list[index].statusText = text
|
||||||
|
state.list[index].status = status
|
||||||
|
}
|
||||||
|
},
|
||||||
onEnd(state, downloadInfo) {
|
onEnd(state, downloadInfo) {
|
||||||
downloadInfo.isComplate = true
|
downloadInfo.isComplate = true
|
||||||
downloadInfo.isDownloading = false
|
downloadInfo.status = state.downloadStatus.COMPLETED
|
||||||
downloadInfo.statusText = '下载完成'
|
downloadInfo.statusText = '下载完成'
|
||||||
},
|
},
|
||||||
onError(state, downloadInfo) {
|
onError(state, downloadInfo) {
|
||||||
downloadInfo.isDownloading = false
|
downloadInfo.status = state.downloadStatus.ERROR
|
||||||
downloadInfo.statusText = '任务出错'
|
downloadInfo.statusText = '任务出错'
|
||||||
},
|
},
|
||||||
onDownload(state, downloadInfo) {
|
onDownload(state, downloadInfo) {
|
||||||
downloadInfo.isDownloading = true
|
downloadInfo.status = state.downloadStatus.RUN
|
||||||
downloadInfo.statusText = '正在下载'
|
downloadInfo.statusText = '正在下载'
|
||||||
},
|
},
|
||||||
onProgress(state, { downloadInfo, status }) {
|
onProgress(state, { downloadInfo, status }) {
|
||||||
|
|
|
@ -30,9 +30,22 @@ const mutations = {
|
||||||
if (state.defaultList.list.some(s => s.songmid === musicInfo.songmid)) return
|
if (state.defaultList.list.some(s => s.songmid === musicInfo.songmid)) return
|
||||||
state.defaultList.list.push(musicInfo)
|
state.defaultList.list.push(musicInfo)
|
||||||
},
|
},
|
||||||
|
defaultListAddMultiple(state, list) {
|
||||||
|
list.forEach(musicInfo => {
|
||||||
|
if (state.defaultList.list.some(s => s.songmid === musicInfo.songmid)) return
|
||||||
|
state.defaultList.list.push(musicInfo)
|
||||||
|
})
|
||||||
|
},
|
||||||
defaultListRemove(state, index) {
|
defaultListRemove(state, index) {
|
||||||
state.defaultList.list.splice(index, 1)
|
state.defaultList.list.splice(index, 1)
|
||||||
},
|
},
|
||||||
|
defaultListRemoveMultiple(state, list) {
|
||||||
|
list.forEach(musicInfo => {
|
||||||
|
let index = state.defaultList.list.indexOf(musicInfo)
|
||||||
|
if (index < 0) return
|
||||||
|
state.defaultList.list.splice(index, 1)
|
||||||
|
})
|
||||||
|
},
|
||||||
defaultListClear(state) {
|
defaultListClear(state) {
|
||||||
state.defaultList.list.length = 0
|
state.defaultList.list.length = 0
|
||||||
},
|
},
|
||||||
|
|
|
@ -45,9 +45,8 @@ export default ({
|
||||||
onEnd()
|
onEnd()
|
||||||
debugDownload && console.log('Download Completed')
|
debugDownload && console.log('Download Completed')
|
||||||
}).on('error', err => {
|
}).on('error', err => {
|
||||||
|
if (err.message === 'socket hang up') return
|
||||||
onError(err)
|
onError(err)
|
||||||
dl.resume()
|
|
||||||
console.log('Download failed, Attempting Retry')
|
|
||||||
debugDownload && console.error('Something happend', err)
|
debugDownload && console.error('Something happend', err)
|
||||||
}).on('stateChanged', state => {
|
}).on('stateChanged', state => {
|
||||||
onStateChanged(state)
|
onStateChanged(state)
|
||||||
|
|
|
@ -156,8 +156,12 @@ export const isChildren = (parent, children) => {
|
||||||
return children.parentNode ? children.parentNode === parent ? true : isChildren(parent, children.parentNode) : false
|
return children.parentNode ? children.parentNode === parent ? true : isChildren(parent, children.parentNode) : false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 升级设置
|
||||||
|
* @param {*} setting
|
||||||
|
*/
|
||||||
export const updateSetting = setting => {
|
export const updateSetting = setting => {
|
||||||
const defaultVersion = '1.0.2'
|
const defaultVersion = '1.0.3'
|
||||||
const defaultSetting = {
|
const defaultSetting = {
|
||||||
version: defaultVersion,
|
version: defaultVersion,
|
||||||
player: {
|
player: {
|
||||||
|
@ -170,6 +174,7 @@ export const updateSetting = setting => {
|
||||||
download: {
|
download: {
|
||||||
savePath: path.join(os.homedir(), 'Desktop'),
|
savePath: path.join(os.homedir(), 'Desktop'),
|
||||||
fileName: '歌名 - 歌手',
|
fileName: '歌名 - 歌手',
|
||||||
|
maxDownloadNum: 3,
|
||||||
},
|
},
|
||||||
leaderboard: {
|
leaderboard: {
|
||||||
source: 'kw',
|
source: 'kw',
|
||||||
|
@ -203,3 +208,4 @@ export const updateSetting = setting => {
|
||||||
export const openUrl = url => {
|
export const openUrl = url => {
|
||||||
shell.openExternal(url)
|
shell.openExternal(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
export const requestMsg = {
|
||||||
|
fail: '请求异常😮,可以多试几次,若还是不行就换一首吧。。。',
|
||||||
|
unachievable: '哦No😱...接口无法访问了!已帮你切换到临时接口,重试下看能不能播放吧~',
|
||||||
|
notConnectNetwork: '无法连接网络',
|
||||||
|
cancelRequest: '取消http请求',
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import { httpFatch } from '../../request'
|
import { httpFatch } from '../../request'
|
||||||
|
import { requestMsg } from '../../message'
|
||||||
|
|
||||||
const api_messoer = {
|
const api_messoer = {
|
||||||
getMusicUrl(songInfo, type) {
|
getMusicUrl(songInfo, type) {
|
||||||
|
@ -7,7 +8,7 @@ const api_messoer = {
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
})
|
})
|
||||||
requestObj.promise = requestObj.promise.then(({ body }) => {
|
requestObj.promise = requestObj.promise.then(({ body }) => {
|
||||||
return body.code === 200 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(body.msg))
|
return body.code === 200 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail))
|
||||||
})
|
})
|
||||||
return requestObj
|
return requestObj
|
||||||
},
|
},
|
||||||
|
@ -17,7 +18,7 @@ const api_messoer = {
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
})
|
})
|
||||||
requestObj.promise = requestObj.promise.then(({ body }) => {
|
requestObj.promise = requestObj.promise.then(({ body }) => {
|
||||||
return body.code === 200 ? Promise.resolve(body.data) : Promise.reject(new Error(body.msg))
|
return body.code === 200 ? Promise.resolve(body.data) : Promise.reject(new Error(requestMsg.fail))
|
||||||
})
|
})
|
||||||
return requestObj
|
return requestObj
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,11 +7,6 @@ const api_temp = {
|
||||||
})
|
})
|
||||||
requestObj.promise = requestObj.promise.then(({ body }) => {
|
requestObj.promise = requestObj.promise.then(({ body }) => {
|
||||||
return body.code === 0 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(body.msg))
|
return body.code === 0 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(body.msg))
|
||||||
}).catch(err => {
|
|
||||||
console.log(err)
|
|
||||||
if (err.message === 'socket hang up') return Promise.reject(new Error('接口挂了'))
|
|
||||||
if (err.code === 'ENOTFOUND') return Promise.reject(new Error('无法连接网络'))
|
|
||||||
return Promise.reject(err)
|
|
||||||
})
|
})
|
||||||
return requestObj
|
return requestObj
|
||||||
},
|
},
|
||||||
|
@ -21,10 +16,6 @@ const api_temp = {
|
||||||
})
|
})
|
||||||
requestObj.promise = requestObj.promise.then(({ body }) => {
|
requestObj.promise = requestObj.promise.then(({ body }) => {
|
||||||
return body.code === 0 ? Promise.resolve(body.data) : Promise.reject(new Error(body.msg))
|
return body.code === 0 ? Promise.resolve(body.data) : Promise.reject(new Error(body.msg))
|
||||||
}).catch(err => {
|
|
||||||
if (err.message === 'socket hang up') return Promise.reject(new Error('接口挂了'))
|
|
||||||
if (err.code === 'ENOTFOUND') return Promise.reject(new Error('无法连接网络'))
|
|
||||||
return Promise.reject(err)
|
|
||||||
})
|
})
|
||||||
return requestObj
|
return requestObj
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { httpFatch } from '../../request'
|
import { httpFatch } from '../../request'
|
||||||
|
import { requestMsg } from '../../message'
|
||||||
|
|
||||||
const api_messoer = {
|
const api_messoer = {
|
||||||
getMusicUrl(songInfo, type) {
|
getMusicUrl(songInfo, type) {
|
||||||
|
@ -7,7 +8,7 @@ const api_messoer = {
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
})
|
})
|
||||||
requestObj.promise = requestObj.promise.then(({ body }) => {
|
requestObj.promise = requestObj.promise.then(({ body }) => {
|
||||||
return body.code === 200 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(body.msg))
|
return body.code === 200 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail))
|
||||||
})
|
})
|
||||||
return requestObj
|
return requestObj
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
/**
|
||||||
|
* 获取音乐音质
|
||||||
|
* @param {*} info
|
||||||
|
* @param {*} type
|
||||||
|
*/
|
||||||
|
const types = ['flac', 'ape', '320k', '192k', '128k']
|
||||||
|
export const getMusicType = (info, type) => {
|
||||||
|
const rangeType = types.slice(types.indexOf(type))
|
||||||
|
for (const type of rangeType) {
|
||||||
|
if (info._types[type]) return type
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
import request from 'request'
|
import request from 'request'
|
||||||
// import progress from 'request-progress'
|
// import progress from 'request-progress'
|
||||||
import { debugRequest } from './env'
|
import { debugRequest } from './env'
|
||||||
|
import { requestMsg } from './message'
|
||||||
// import fs from 'fs'
|
// import fs from 'fs'
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
|
@ -9,7 +10,7 @@ const headers = {
|
||||||
|
|
||||||
const fatchData = (url, method, options, callback) => {
|
const fatchData = (url, method, options, callback) => {
|
||||||
// console.log(url, options)
|
// console.log(url, options)
|
||||||
// console.log('---start---', url)
|
console.log('---start---', url)
|
||||||
return request(url, {
|
return request(url, {
|
||||||
method,
|
method,
|
||||||
headers: Object.assign({}, headers, options.headers || {}),
|
headers: Object.assign({}, headers, options.headers || {}),
|
||||||
|
@ -60,7 +61,7 @@ const buildHttpPromose = (url, options) => {
|
||||||
console.log('cancel')
|
console.log('cancel')
|
||||||
if (!requestObj) return
|
if (!requestObj) return
|
||||||
cancelHttp(requestObj)
|
cancelHttp(requestObj)
|
||||||
cancelFn(new Error('取消http请求'))
|
cancelFn(new Error(requestMsg.cancelRequest))
|
||||||
requestObj = null
|
requestObj = null
|
||||||
cancelFn = null
|
cancelFn = null
|
||||||
},
|
},
|
||||||
|
@ -84,9 +85,9 @@ export const httpFatch = (url, options = { method: 'get' }) => {
|
||||||
}
|
}
|
||||||
if (err.message === 'socket hang up') {
|
if (err.message === 'socket hang up') {
|
||||||
window.globalObj.apiSource = 'temp'
|
window.globalObj.apiSource = 'temp'
|
||||||
return Promise.reject(new Error('哦No😱...接口无法访问了!已帮你切换到临时接口,重试下看能不能播放吧~'))
|
return Promise.reject(new Error(requestMsg.unachievable))
|
||||||
}
|
}
|
||||||
if (err.code === 'ENOTFOUND') return Promise.reject(new Error('无法连接网络'))
|
if (err.code === 'ENOTFOUND') return Promise.reject(new Error(requestMsg.notConnectNetwork))
|
||||||
return Promise.reject(err)
|
return Promise.reject(err)
|
||||||
})
|
})
|
||||||
return requestObj
|
return requestObj
|
||||||
|
|
|
@ -6,8 +6,11 @@ div(:class="$style.download")
|
||||||
table
|
table
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
th.nobreak(style="width: 30%;") 歌曲名
|
th.nobreak.center(style="width: 37px;")
|
||||||
th.nobreak(style="width: 25%;") 进度
|
material-checkbox(id="search_select_all" v-model="isSelectAll" @change="handleSelectAllData"
|
||||||
|
:indeterminate="isIndeterminate" :title="isSelectAll && !isIndeterminate ? '全不选' : '全选'")
|
||||||
|
th.nobreak(style="width: 28%;") 歌曲名
|
||||||
|
th.nobreak(style="width: 22%;") 进度
|
||||||
th.nobreak(style="width: 15%;") 状态
|
th.nobreak(style="width: 15%;") 状态
|
||||||
th.nobreak(style="width: 10%;") 品质
|
th.nobreak(style="width: 10%;") 品质
|
||||||
th.nobreak(style="width: 20%;") 操作
|
th.nobreak(style="width: 20%;") 操作
|
||||||
|
@ -15,12 +18,17 @@ div(:class="$style.download")
|
||||||
table
|
table
|
||||||
tbody
|
tbody
|
||||||
tr(v-for='(item, index) in list' :key='item.key' @click="handleDoubleClick(index)" :class="isPlayList && playIndex === index ? $style.active : ''")
|
tr(v-for='(item, index) in list' :key='item.key' @click="handleDoubleClick(index)" :class="isPlayList && playIndex === index ? $style.active : ''")
|
||||||
td.break(style="width: 30%;") {{item.musicInfo.name}} - {{item.musicInfo.singer}}
|
td.nobreak.center(style="width: 37px;" @click.stop)
|
||||||
td.break(style="width: 25%;") {{item.progress.progress}}%
|
material-checkbox(:id="index.toString()" v-model="selectdData" :value="item")
|
||||||
|
td.break(style="width: 28%;") {{item.musicInfo.name}} - {{item.musicInfo.singer}}
|
||||||
|
td.break(style="width: 22%;") {{item.progress.progress}}%
|
||||||
td.break(style="width: 15%;") {{item.statusText}}
|
td.break(style="width: 15%;") {{item.statusText}}
|
||||||
td.break(style="width: 10%;") {{item.type.toUpperCase()}}
|
td.break(style="width: 10%;") {{item.type.toUpperCase()}}
|
||||||
td(style="width: 20%; padding-left: 0; padding-right: 0;")
|
td(style="width: 20%; padding-left: 0; padding-right: 0;")
|
||||||
material-list-buttons(:index="index" :downloadBtn="false" @btn-click="handleBtnClick")
|
material-list-buttons(:index="index" :download-btn="false" :start-btn="!item.isComplate && item.status != downloadStatus.WAITING && (item.status != downloadStatus.RUN)"
|
||||||
|
:pause-btn="!item.isComplate && (item.status == downloadStatus.RUN || item.status == downloadStatus.WAITING)"
|
||||||
|
:play-btn="item.status == downloadStatus.COMPLETED" @btn-click="handleListBtnClick")
|
||||||
|
material-flow-btn(:show="isShowEditBtn" :play-btn="false" :download-btn="false" :add-btn="false" :start-btn="true" :pause-btn="true" @btn-click="handleFlowBtnClick")
|
||||||
div(:class="$style.noItem" v-else)
|
div(:class="$style.noItem" v-else)
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -34,26 +42,51 @@ export default {
|
||||||
return {
|
return {
|
||||||
clickTime: window.performance.now(),
|
clickTime: window.performance.now(),
|
||||||
clickIndex: -1,
|
clickIndex: -1,
|
||||||
|
selectdData: [],
|
||||||
|
isSelectAll: false,
|
||||||
|
isIndeterminate: false,
|
||||||
|
isShowEditBtn: false,
|
||||||
|
isShowDownloadMultiple: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters('download', ['list', 'dls']),
|
...mapGetters('download', ['list', 'dls', 'downloadStatus']),
|
||||||
...mapGetters('player', ['listId', 'playIndex']),
|
...mapGetters('player', ['listId', 'playIndex']),
|
||||||
isPlayList() {
|
isPlayList() {
|
||||||
return this.listId == 'download'
|
return this.listId == 'download'
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
watch: {
|
||||||
...mapActions('download', ['removeTask', 'resumeTask']),
|
selectdData(n) {
|
||||||
...mapMutations('player', ['setList']),
|
const len = n.length
|
||||||
pauseTask(index) {
|
if (len) {
|
||||||
let info = this.list[index]
|
this.isSelectAll = true
|
||||||
this.dls[info.key].pause()
|
this.isIndeterminate = len !== this.list.length
|
||||||
|
this.isShowEditBtn = true
|
||||||
|
} else {
|
||||||
|
this.isSelectAll = false
|
||||||
|
this.isShowEditBtn = false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
startTask(index) {
|
list() {
|
||||||
|
this.resetSelect()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions('download', ['removeTask', 'removeTaskMultiple', 'startTask']),
|
||||||
|
...mapMutations('player', ['setList']),
|
||||||
|
...mapMutations('download', ['pauseTask']),
|
||||||
|
handlePauseTask(index) {
|
||||||
let info = this.list[index]
|
let info = this.list[index]
|
||||||
let dl = this.dls[info.key]
|
let dl = this.dls[info.key]
|
||||||
dl ? dl.resume() : this.resumeTask(info)
|
dl ? dl.pause() : this.pauseTask(info)
|
||||||
|
console.log('pause')
|
||||||
|
},
|
||||||
|
handleStartTask(index) {
|
||||||
|
console.log('start')
|
||||||
|
let info = this.list[index]
|
||||||
|
let dl = this.dls[info.key]
|
||||||
|
dl ? dl.resume() : this.startTask(info)
|
||||||
},
|
},
|
||||||
handleDoubleClick(index) {
|
handleDoubleClick(index) {
|
||||||
if (
|
if (
|
||||||
|
@ -72,26 +105,71 @@ export default {
|
||||||
let info = this.list[index]
|
let info = this.list[index]
|
||||||
if (info.isComplate) {
|
if (info.isComplate) {
|
||||||
this.handlePlay(index)
|
this.handlePlay(index)
|
||||||
} else if (info.isDownloading) {
|
} else if (info.status === this.downloadStatus.RUN) {
|
||||||
this.pauseTask(index)
|
this.handlePauseTask(index)
|
||||||
} else {
|
} else {
|
||||||
this.startTask(index)
|
this.handleStartTask(index)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handlePlay(index) {
|
handlePlay(index) {
|
||||||
if (!checkPath(this.list[index].filePath)) return
|
if (!checkPath(this.list[index].filePath)) return
|
||||||
this.setList({ list: this.list, listId: 'download', index })
|
this.setList({ list: this.list, listId: 'download', index })
|
||||||
},
|
},
|
||||||
handleBtnClick(info) {
|
handleListBtnClick(info) {
|
||||||
switch (info.action) {
|
switch (info.action) {
|
||||||
case 'play':
|
case 'play':
|
||||||
this.handlePlay(info.index)
|
this.handlePlay(info.index)
|
||||||
break
|
break
|
||||||
|
case 'start':
|
||||||
|
this.handleStartTask(info.index)
|
||||||
|
break
|
||||||
|
case 'pause':
|
||||||
|
this.handlePauseTask(info.index)
|
||||||
|
break
|
||||||
case 'remove':
|
case 'remove':
|
||||||
this.removeTask(info.index)
|
this.removeTask(info.index)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
handleSelectAllData(isSelect) {
|
||||||
|
this.selectdData = isSelect ? [...this.list] : []
|
||||||
|
},
|
||||||
|
resetSelect() {
|
||||||
|
this.isSelectAll = false
|
||||||
|
this.selectdData = []
|
||||||
|
},
|
||||||
|
handleFlowBtnClick(action) {
|
||||||
|
switch (action) {
|
||||||
|
case 'start':
|
||||||
|
this.selectdData.forEach(item => {
|
||||||
|
if (item.isComplate || item.status == this.downloadStatus.RUN) return
|
||||||
|
let index = this.list.indexOf(item)
|
||||||
|
if (index < 0) return
|
||||||
|
this.handleStartTask(index)
|
||||||
|
})
|
||||||
|
break
|
||||||
|
case 'pause':
|
||||||
|
let runs = []
|
||||||
|
this.selectdData.forEach(item => {
|
||||||
|
if (item.isComplate || item.status == this.downloadStatus.PAUSE) return
|
||||||
|
if (item.status == this.downloadStatus.RUN) return runs.push(item)
|
||||||
|
let index = this.list.indexOf(item)
|
||||||
|
if (index < 0) return
|
||||||
|
this.handlePauseTask(index)
|
||||||
|
})
|
||||||
|
runs.forEach(item => {
|
||||||
|
if (item.isComplate || item.status == this.downloadStatus.PAUSE) return
|
||||||
|
let index = this.list.indexOf(item)
|
||||||
|
if (index < 0) return
|
||||||
|
this.handlePauseTask(index)
|
||||||
|
})
|
||||||
|
break
|
||||||
|
case 'remove':
|
||||||
|
this.removeTaskMultiple(this.selectdData)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
this.resetSelect()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -9,30 +9,37 @@
|
||||||
table
|
table
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
th.nobreak(style="width: 27%;") 歌曲名
|
th.nobreak.center(style="width: 37px;")
|
||||||
|
material-checkbox(id="search_select_all" v-model="isSelectAll" @change="handleSelectAllData"
|
||||||
|
:indeterminate="isIndeterminate" :title="isSelectAll && !isIndeterminate ? '全不选' : '全选'")
|
||||||
|
th.nobreak(style="width: 25%;") 歌曲名
|
||||||
th.nobreak(style="width: 20%;") 歌手
|
th.nobreak(style="width: 20%;") 歌手
|
||||||
th.nobreak(style="width: 25%;") 专辑
|
th.nobreak(style="width: 22%;") 专辑
|
||||||
th.nobreak(style="width: 18%;") 操作
|
th.nobreak(style="width: 18%;") 操作
|
||||||
th.nobreak(style="width: 10%;") 时长
|
th.nobreak(style="width: 10%;") 时长
|
||||||
div.scroll(:class="$style.tbody" ref="dom_scrollContent")
|
div.scroll(:class="$style.tbody" ref="dom_scrollContent")
|
||||||
table
|
table
|
||||||
tbody
|
tbody
|
||||||
tr(v-for='(item, index) in list' :key='item.songmid' @click="handleDoubleClick(index)")
|
tr(v-for='(item, index) in list' :key='item.songmid' @click="handleDoubleClick(index)")
|
||||||
td.break(style="width: 27%;")
|
td.nobreak.center(style="width: 37px;" @click.stop)
|
||||||
|
material-checkbox(:id="index.toString()" v-model="selectdData" :value="item")
|
||||||
|
td.break(style="width: 25%;")
|
||||||
| {{item.name}}
|
| {{item.name}}
|
||||||
//- span.badge.badge-info(v-if="item._types['320k']") 高品质
|
//- span.badge.badge-info(v-if="item._types['320k']") 高品质
|
||||||
//- span.badge.badge-success(v-if="item._types.ape || item._types.flac") 无损
|
//- span.badge.badge-success(v-if="item._types.ape || item._types.flac") 无损
|
||||||
td.break(style="width: 20%;") {{item.singer}}
|
td.break(style="width: 20%;") {{item.singer}}
|
||||||
td.break(style="width: 25%;") {{item.albumName}}
|
td.break(style="width: 22%;") {{item.albumName}}
|
||||||
td(style="width: 18%;")
|
td(style="width: 18%;")
|
||||||
material-list-buttons(:index="index" :search-btn="true" :play-btn="item.source == 'kw' || (!isAPITemp && item.source == 'tx')" :download-btn="item.source == 'kw' || (!isAPITemp && item.source == 'tx')" :remove-btn="false" @btn-click="handleBtnClick")
|
material-list-buttons(:index="index" :search-btn="true" :play-btn="item.source == 'kw' || (!isAPITemp && item.source == 'tx')" :download-btn="item.source == 'kw' || (!isAPITemp && item.source == 'tx')" :remove-btn="false" @btn-click="handleListBtnClick")
|
||||||
//- button.btn-info(type='button' v-if="item._types['128k'] || item._types['192k'] || item._types['320k'] || item._types.flac" @click.stop='openDownloadModal(index)') 下载
|
//- button.btn-info(type='button' v-if="item._types['128k'] || item._types['192k'] || item._types['320k'] || item._types.flac" @click.stop='openDownloadModal(index)') 下载
|
||||||
//- button.btn-secondary(type='button' v-if="item._types['128k'] || item._types['192k'] || item._types['320k']" @click.stop='testPlay(index)') 试听
|
//- button.btn-secondary(type='button' v-if="item._types['128k'] || item._types['192k'] || item._types['320k']" @click.stop='testPlay(index)') 试听
|
||||||
//- button.btn-success(type='button' v-if="(item._types['128k'] || item._types['192k'] || item._types['320k']) && userInfo" @click.stop='showListModal(index)') +
|
//- button.btn-success(type='button' v-if="(item._types['128k'] || item._types['192k'] || item._types['320k']) && userInfo" @click.stop='showListModal(index)') +
|
||||||
td(style="width: 10%;") {{item.interval}}
|
td(style="width: 10%;") {{item.interval}}
|
||||||
div(:class="$style.pagination")
|
div(:class="$style.pagination")
|
||||||
material-pagination(:count="info.total" :limit="info.limit" :page="info.page" @btn-click="handleTogglePage")
|
material-pagination(:count="info.total" :limit="info.limit" :page="info.page" @btn-click="handleTogglePage")
|
||||||
material-download-modal(:show="showDownload" :musicInfo="musicInfo" @select="handleAddDownload" @close="showDownload = false")
|
material-download-modal(:show="isShowDownload" :musicInfo="musicInfo" @select="handleAddDownload" @close="isShowDownload = false")
|
||||||
|
material-download-multiple-modal(:show="isShowDownloadMultiple" :list="selectdData" @select="handleAddDownloadMultiple" @close="isShowDownloadMultiple = false")
|
||||||
|
material-flow-btn(:show="isShowEditBtn" :remove-btn="false" @btn-click="handleFlowBtnClick")
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -48,8 +55,13 @@ export default {
|
||||||
page: 1,
|
page: 1,
|
||||||
clickTime: 0,
|
clickTime: 0,
|
||||||
clickIndex: -1,
|
clickIndex: -1,
|
||||||
showDownload: false,
|
isShowDownload: false,
|
||||||
musicInfo: null,
|
musicInfo: null,
|
||||||
|
selectdData: [],
|
||||||
|
isSelectAll: false,
|
||||||
|
isIndeterminate: false,
|
||||||
|
isShowEditBtn: false,
|
||||||
|
isShowDownloadMultiple: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -76,6 +88,20 @@ export default {
|
||||||
this.setLeaderboard({ source: n })
|
this.setLeaderboard({ source: n })
|
||||||
if (o) this.tabId = this.types[0] && this.types[0].id
|
if (o) this.tabId = this.types[0] && this.types[0].id
|
||||||
},
|
},
|
||||||
|
selectdData(n) {
|
||||||
|
const len = n.length
|
||||||
|
if (len) {
|
||||||
|
this.isSelectAll = true
|
||||||
|
this.isIndeterminate = len !== this.list.length
|
||||||
|
this.isShowEditBtn = true
|
||||||
|
} else {
|
||||||
|
this.isSelectAll = false
|
||||||
|
this.isShowEditBtn = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
list() {
|
||||||
|
this.resetSelect()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.source = this.setting.leaderboard.source
|
this.source = this.setting.leaderboard.source
|
||||||
|
@ -85,8 +111,8 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
...mapMutations(['setLeaderboard']),
|
...mapMutations(['setLeaderboard']),
|
||||||
...mapActions('leaderboard', ['getList']),
|
...mapActions('leaderboard', ['getList']),
|
||||||
...mapActions('download', ['createDownload']),
|
...mapActions('download', ['createDownload', 'createDownloadMultiple']),
|
||||||
...mapMutations('list', ['defaultListAdd']),
|
...mapMutations('list', ['defaultListAdd', 'defaultListAddMultiple']),
|
||||||
...mapMutations('player', ['setList']),
|
...mapMutations('player', ['setList']),
|
||||||
handleDoubleClick(index) {
|
handleDoubleClick(index) {
|
||||||
if (
|
if (
|
||||||
|
@ -101,12 +127,12 @@ export default {
|
||||||
this.clickTime = 0
|
this.clickTime = 0
|
||||||
this.clickIndex = -1
|
this.clickIndex = -1
|
||||||
},
|
},
|
||||||
handleBtnClick(info) {
|
handleListBtnClick(info) {
|
||||||
switch (info.action) {
|
switch (info.action) {
|
||||||
case 'download':
|
case 'download':
|
||||||
this.musicInfo = this.list[info.index]
|
this.musicInfo = this.list[info.index]
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.showDownload = true
|
this.isShowDownload = true
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case 'play':
|
case 'play':
|
||||||
|
@ -120,8 +146,14 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
testPlay(index) {
|
testPlay(index) {
|
||||||
let targetSong = this.list[index]
|
let targetSong
|
||||||
|
if (index == null) {
|
||||||
|
targetSong = this.selectdData[0]
|
||||||
|
this.defaultListAddMultiple(this.selectdData)
|
||||||
|
} else {
|
||||||
|
targetSong = this.list[index]
|
||||||
this.defaultListAdd(targetSong)
|
this.defaultListAdd(targetSong)
|
||||||
|
}
|
||||||
let targetIndex = this.defaultList.list.findIndex(
|
let targetIndex = this.defaultList.list.findIndex(
|
||||||
s => s.songmid === targetSong.songmid
|
s => s.songmid === targetSong.songmid
|
||||||
)
|
)
|
||||||
|
@ -150,9 +182,36 @@ export default {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
handleSelectAllData(isSelect) {
|
||||||
|
this.selectdData = isSelect ? [...this.list] : []
|
||||||
|
},
|
||||||
|
resetSelect() {
|
||||||
|
this.isSelectAll = false
|
||||||
|
this.selectdData = []
|
||||||
|
},
|
||||||
handleAddDownload(type) {
|
handleAddDownload(type) {
|
||||||
this.createDownload({ musicInfo: this.musicInfo, type })
|
this.createDownload({ musicInfo: this.musicInfo, type })
|
||||||
this.showDownload = false
|
this.isShowDownload = false
|
||||||
|
},
|
||||||
|
handleAddDownloadMultiple(type) {
|
||||||
|
this.createDownloadMultiple({ list: [...this.selectdData], type })
|
||||||
|
this.resetSelect()
|
||||||
|
this.isShowDownloadMultiple = false
|
||||||
|
},
|
||||||
|
handleFlowBtnClick(action) {
|
||||||
|
switch (action) {
|
||||||
|
case 'download':
|
||||||
|
this.isShowDownloadMultiple = true
|
||||||
|
break
|
||||||
|
case 'play':
|
||||||
|
this.testPlay()
|
||||||
|
this.resetSelect()
|
||||||
|
break
|
||||||
|
case 'add':
|
||||||
|
this.defaultListAddMultiple(this.selectdData)
|
||||||
|
this.resetSelect()
|
||||||
|
break
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,12 @@
|
||||||
table
|
table
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
|
th.nobreak.center(style="width: 37px;")
|
||||||
|
material-checkbox(id="search_select_all" v-model="isSelectAll" @change="handleSelectAllData"
|
||||||
|
:indeterminate="isIndeterminate" :title="isSelectAll && !isIndeterminate ? '全不选' : '全选'")
|
||||||
th.nobreak(style="width: 25%;") 歌曲名
|
th.nobreak(style="width: 25%;") 歌曲名
|
||||||
th.nobreak(style="width: 20%;") 歌手
|
th.nobreak(style="width: 20%;") 歌手
|
||||||
th.nobreak(style="width: 25%;" v-if="setting.list.isShowAlbumName") 专辑
|
th.nobreak(style="width: 20%;" v-if="setting.list.isShowAlbumName") 专辑
|
||||||
th.nobreak(style="width: 20%;") 操作
|
th.nobreak(style="width: 20%;") 操作
|
||||||
th.nobreak(style="width: 10%;") 时长
|
th.nobreak(style="width: 10%;") 时长
|
||||||
div.scroll(:class="$style.tbody")
|
div.scroll(:class="$style.tbody")
|
||||||
|
@ -16,6 +19,8 @@
|
||||||
tbody
|
tbody
|
||||||
tr(v-for='(item, index) in list' :key='item.songmid'
|
tr(v-for='(item, index) in list' :key='item.songmid'
|
||||||
@click="handleDoubleClick(index)" :class="[isPlayList && playIndex === index ? $style.active : '', isAPITemp && item.source != 'kw' ? $style.disabled : '']")
|
@click="handleDoubleClick(index)" :class="[isPlayList && playIndex === index ? $style.active : '', isAPITemp && item.source != 'kw' ? $style.disabled : '']")
|
||||||
|
td.nobreak.center(style="width: 37px;" @click.stop)
|
||||||
|
material-checkbox(:id="index.toString()" v-model="selectdData" :value="item")
|
||||||
td.break(style="width: 25%;") {{item.name}}
|
td.break(style="width: 25%;") {{item.name}}
|
||||||
//- span.badge.badge-light(v-if="item._types['128k']") 128K
|
//- span.badge.badge-light(v-if="item._types['128k']") 128K
|
||||||
//- span.badge.badge-light(v-if="item._types['192k']") 192K
|
//- span.badge.badge-light(v-if="item._types['192k']") 192K
|
||||||
|
@ -23,16 +28,18 @@
|
||||||
//- span.badge.badge-info(v-if="item._types.ape") APE
|
//- span.badge.badge-info(v-if="item._types.ape") APE
|
||||||
//- span.badge.badge-success(v-if="item._types.flac") FLAC
|
//- span.badge.badge-success(v-if="item._types.flac") FLAC
|
||||||
td.break(style="width: 20%;") {{item.singer}}
|
td.break(style="width: 20%;") {{item.singer}}
|
||||||
td.break(style="width: 25%;" v-if="setting.list.isShowAlbumName") {{item.albumName}}
|
td.break(style="width: 20%;" v-if="setting.list.isShowAlbumName") {{item.albumName}}
|
||||||
td(style="width: 20%; padding-left: 0; padding-right: 0;")
|
td(style="width: 20%; padding-left: 0; padding-right: 0;")
|
||||||
material-list-buttons(:index="index" @btn-click="handleBtnClick")
|
material-list-buttons(:index="index" @btn-click="handleListBtnClick")
|
||||||
//- button.btn-info(type='button' v-if="item._types['128k'] || item._types['192k'] || item._types['320k'] || item._types.flac" @click.stop='openDownloadModal(index)') 下载
|
//- button.btn-info(type='button' v-if="item._types['128k'] || item._types['192k'] || item._types['320k'] || item._types.flac" @click.stop='openDownloadModal(index)') 下载
|
||||||
//- button.btn-secondary(type='button' v-if="item._types['128k'] || item._types['192k'] || item._types['320k']" @click.stop='testPlay(index)') 试听
|
//- button.btn-secondary(type='button' v-if="item._types['128k'] || item._types['192k'] || item._types['320k']" @click.stop='testPlay(index)') 试听
|
||||||
//- button.btn-secondary(type='button' @click.stop='handleRemove(index)') 删除
|
//- button.btn-secondary(type='button' @click.stop='handleRemove(index)') 删除
|
||||||
//- button.btn-success(type='button' v-if="(item._types['128k'] || item._types['192k'] || item._types['320k']) && userInfo" @click.stop='showListModal(index)') +
|
//- button.btn-success(type='button' v-if="(item._types['128k'] || item._types['192k'] || item._types['320k']) && userInfo" @click.stop='showListModal(index)') +
|
||||||
td(style="width: 10%;") {{item.interval}}
|
td(style="width: 10%;") {{item.interval}}
|
||||||
div(:class="$style.noItem" v-else)
|
div(:class="$style.noItem" v-else)
|
||||||
material-download-modal(:show="showDownload" :musicInfo="musicInfo" @select="handleAddDownload" @close="showDownload = false")
|
material-download-modal(:show="isShowDownload" :musicInfo="musicInfo" @select="handleAddDownload" @close="isShowDownload = false")
|
||||||
|
material-download-multiple-modal(:show="isShowDownloadMultiple" :list="selectdData" @select="handleAddDownloadMultiple" @close="isShowDownloadMultiple = false")
|
||||||
|
material-flow-btn(:show="isShowEditBtn" :add-btn="false" :play-btn="false" @btn-click="handleFlowBtnClick")
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -43,8 +50,13 @@ export default {
|
||||||
return {
|
return {
|
||||||
clickTime: window.performance.now(),
|
clickTime: window.performance.now(),
|
||||||
clickIndex: -1,
|
clickIndex: -1,
|
||||||
showDownload: false,
|
isShowDownload: false,
|
||||||
musicInfo: null,
|
musicInfo: null,
|
||||||
|
selectdData: [],
|
||||||
|
isSelectAll: false,
|
||||||
|
isIndeterminate: false,
|
||||||
|
isShowEditBtn: false,
|
||||||
|
isShowDownloadMultiple: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -66,6 +78,22 @@ export default {
|
||||||
return this.setting.apiSource == 'temp'
|
return this.setting.apiSource == 'temp'
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
selectdData(n) {
|
||||||
|
const len = n.length
|
||||||
|
if (len) {
|
||||||
|
this.isSelectAll = true
|
||||||
|
this.isIndeterminate = len !== this.list.length
|
||||||
|
this.isShowEditBtn = true
|
||||||
|
} else {
|
||||||
|
this.isSelectAll = false
|
||||||
|
this.isShowEditBtn = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
list() {
|
||||||
|
this.resetSelect()
|
||||||
|
},
|
||||||
|
},
|
||||||
// beforeRouteUpdate(to, from, next) {
|
// beforeRouteUpdate(to, from, next) {
|
||||||
// // if (to.query.id === undefined) return
|
// // if (to.query.id === undefined) return
|
||||||
// // if (to.query.text === '') {
|
// // if (to.query.text === '') {
|
||||||
|
@ -92,9 +120,9 @@ export default {
|
||||||
// }
|
// }
|
||||||
// },
|
// },
|
||||||
methods: {
|
methods: {
|
||||||
...mapMutations('list', ['defaultListRemove']),
|
...mapMutations('list', ['defaultListRemove', 'defaultListRemoveMultiple']),
|
||||||
|
...mapActions('download', ['createDownload', 'createDownloadMultiple']),
|
||||||
...mapMutations('player', ['setList']),
|
...mapMutations('player', ['setList']),
|
||||||
...mapActions('download', ['createDownload']),
|
|
||||||
handleDoubleClick(index) {
|
handleDoubleClick(index) {
|
||||||
if (
|
if (
|
||||||
window.performance.now() - this.clickTime > 400 ||
|
window.performance.now() - this.clickTime > 400 ||
|
||||||
|
@ -115,12 +143,12 @@ export default {
|
||||||
handleRemove(index) {
|
handleRemove(index) {
|
||||||
this.defaultListRemove(index)
|
this.defaultListRemove(index)
|
||||||
},
|
},
|
||||||
handleBtnClick(info) {
|
handleListBtnClick(info) {
|
||||||
switch (info.action) {
|
switch (info.action) {
|
||||||
case 'download':
|
case 'download':
|
||||||
this.musicInfo = this.list[info.index]
|
this.musicInfo = this.list[info.index]
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.showDownload = true
|
this.isShowDownload = true
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case 'play':
|
case 'play':
|
||||||
|
@ -135,7 +163,30 @@ export default {
|
||||||
},
|
},
|
||||||
handleAddDownload(type) {
|
handleAddDownload(type) {
|
||||||
this.createDownload({ musicInfo: this.musicInfo, type })
|
this.createDownload({ musicInfo: this.musicInfo, type })
|
||||||
this.showDownload = false
|
this.isShowDownload = false
|
||||||
|
},
|
||||||
|
handleSelectAllData(isSelect) {
|
||||||
|
this.selectdData = isSelect ? [...this.list] : []
|
||||||
|
},
|
||||||
|
resetSelect() {
|
||||||
|
this.isSelectAll = false
|
||||||
|
this.selectdData = []
|
||||||
|
},
|
||||||
|
handleAddDownloadMultiple(type) {
|
||||||
|
this.createDownloadMultiple({ list: [...this.selectdData], type })
|
||||||
|
this.resetSelect()
|
||||||
|
this.isShowDownloadMultiple = false
|
||||||
|
},
|
||||||
|
handleFlowBtnClick(action) {
|
||||||
|
switch (action) {
|
||||||
|
case 'download':
|
||||||
|
this.isShowDownloadMultiple = true
|
||||||
|
break
|
||||||
|
case 'remove':
|
||||||
|
this.defaultListRemoveMultiple(this.selectdData)
|
||||||
|
this.resetSelect()
|
||||||
|
break
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,13 +27,15 @@
|
||||||
td.break(style="width: 20%;") {{item.singer}}
|
td.break(style="width: 20%;") {{item.singer}}
|
||||||
td.break(style="width: 25%;") {{item.albumName}}
|
td.break(style="width: 25%;") {{item.albumName}}
|
||||||
td(style="width: 15%;")
|
td(style="width: 15%;")
|
||||||
material-list-buttons(:index="index" :remove-btn="false" @btn-click="handleBtnClick")
|
material-list-buttons(:index="index" :remove-btn="false" @btn-click="handleListBtnClick")
|
||||||
td(style="width: 10%;") {{item.interval}}
|
td(style="width: 10%;") {{item.interval}}
|
||||||
div(:class="$style.pagination")
|
div(:class="$style.pagination")
|
||||||
material-pagination(:count="listInfo.total" :limit="limit" :page="page" @btn-click="handleTogglePage")
|
material-pagination(:count="listInfo.total" :limit="limit" :page="page" @btn-click="handleTogglePage")
|
||||||
div(v-else :class="$style.noitem")
|
div(v-else :class="$style.noitem")
|
||||||
p 搜我所想~~😉
|
p 搜我所想~~😉
|
||||||
material-download-modal(:show="showDownload" :musicInfo="musicInfo" @select="handleAddDownload" @close="showDownload = false")
|
material-download-modal(:show="isShowDownload" :musicInfo="musicInfo" @select="handleAddDownload" @close="isShowDownload = false")
|
||||||
|
material-download-multiple-modal(:show="isShowDownloadMultiple" :list="selectdData" @select="handleAddDownloadMultiple" @close="isShowDownloadMultiple = false")
|
||||||
|
material-flow-btn(:show="isShowEditBtn" :remove-btn="false" @btn-click="handleFlowBtnClick")
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -48,12 +50,13 @@ export default {
|
||||||
text: '',
|
text: '',
|
||||||
clickTime: 0,
|
clickTime: 0,
|
||||||
clickIndex: -1,
|
clickIndex: -1,
|
||||||
showDownload: false,
|
isShowDownload: false,
|
||||||
musicInfo: null,
|
musicInfo: null,
|
||||||
selectdData: [],
|
selectdData: [],
|
||||||
isSelectAll: false,
|
isSelectAll: false,
|
||||||
isIndeterminate: false,
|
isIndeterminate: false,
|
||||||
isShowEditBtn: false,
|
isShowEditBtn: false,
|
||||||
|
isShowDownloadMultiple: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeRouteUpdate(to, from, next) {
|
beforeRouteUpdate(to, from, next) {
|
||||||
|
@ -104,9 +107,9 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions('search', ['search']),
|
...mapActions('search', ['search']),
|
||||||
...mapActions('download', ['createDownload']),
|
...mapActions('download', ['createDownload', 'createDownloadMultiple']),
|
||||||
...mapMutations('search', ['clearList', 'setPage']),
|
...mapMutations('search', ['clearList', 'setPage']),
|
||||||
...mapMutations('list', ['defaultListAdd']),
|
...mapMutations('list', ['defaultListAdd', 'defaultListAddMultiple']),
|
||||||
...mapMutations('player', ['setList']),
|
...mapMutations('player', ['setList']),
|
||||||
handleSearch(text, page) {
|
handleSearch(text, page) {
|
||||||
this.search({ text, page, limit: this.limit }).then(data => {
|
this.search({ text, page, limit: this.limit }).then(data => {
|
||||||
|
@ -129,12 +132,12 @@ export default {
|
||||||
this.clickTime = 0
|
this.clickTime = 0
|
||||||
this.clickIndex = -1
|
this.clickIndex = -1
|
||||||
},
|
},
|
||||||
handleBtnClick(info) {
|
handleListBtnClick(info) {
|
||||||
switch (info.action) {
|
switch (info.action) {
|
||||||
case 'download':
|
case 'download':
|
||||||
this.musicInfo = this.list[info.index]
|
this.musicInfo = this.list[info.index]
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.showDownload = true
|
this.isShowDownload = true
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case 'play':
|
case 'play':
|
||||||
|
@ -145,8 +148,14 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
testPlay(index) {
|
testPlay(index) {
|
||||||
let targetSong = this.list[index]
|
let targetSong
|
||||||
|
if (index == null) {
|
||||||
|
targetSong = this.selectdData[0]
|
||||||
|
this.defaultListAddMultiple(this.selectdData)
|
||||||
|
} else {
|
||||||
|
targetSong = this.list[index]
|
||||||
this.defaultListAdd(targetSong)
|
this.defaultListAdd(targetSong)
|
||||||
|
}
|
||||||
let targetIndex = this.defaultList.list.findIndex(
|
let targetIndex = this.defaultList.list.findIndex(
|
||||||
s => s.songmid === targetSong.songmid
|
s => s.songmid === targetSong.songmid
|
||||||
)
|
)
|
||||||
|
@ -163,7 +172,12 @@ export default {
|
||||||
},
|
},
|
||||||
handleAddDownload(type) {
|
handleAddDownload(type) {
|
||||||
this.createDownload({ musicInfo: this.musicInfo, type })
|
this.createDownload({ musicInfo: this.musicInfo, type })
|
||||||
this.showDownload = false
|
this.isShowDownload = false
|
||||||
|
},
|
||||||
|
handleAddDownloadMultiple(type) {
|
||||||
|
this.createDownloadMultiple({ list: [...this.selectdData], type })
|
||||||
|
this.resetSelect()
|
||||||
|
this.isShowDownloadMultiple = false
|
||||||
},
|
},
|
||||||
handleSelectAllData(isSelect) {
|
handleSelectAllData(isSelect) {
|
||||||
this.selectdData = isSelect ? [...this.list] : []
|
this.selectdData = isSelect ? [...this.list] : []
|
||||||
|
@ -172,6 +186,21 @@ export default {
|
||||||
this.isSelectAll = false
|
this.isSelectAll = false
|
||||||
this.selectdData = []
|
this.selectdData = []
|
||||||
},
|
},
|
||||||
|
handleFlowBtnClick(action) {
|
||||||
|
switch (action) {
|
||||||
|
case 'download':
|
||||||
|
this.isShowDownloadMultiple = true
|
||||||
|
break
|
||||||
|
case 'play':
|
||||||
|
this.testPlay()
|
||||||
|
this.resetSelect()
|
||||||
|
break
|
||||||
|
case 'add':
|
||||||
|
this.defaultListAddMultiple(this.selectdData)
|
||||||
|
this.resetSelect()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -142,7 +142,7 @@ export default {
|
||||||
apiSources: [
|
apiSources: [
|
||||||
{
|
{
|
||||||
id: 'messoer',
|
id: 'messoer',
|
||||||
label: '由 messoer 提供的接口(推荐,软件的所有功能都可用)',
|
label: '由 messoer 提供的接口(推荐,软件的所有功能都可用)<br><span style="line-height: 1.5;"><strong>注意:</strong>本接口10秒内请求数超过100次会封10小时的IP</span>',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'temp',
|
id: 'temp',
|
||||||
|
|
Loading…
Reference in New Issue