Compare commits

...

6 Commits

Author SHA1 Message Date
lyswhut
c92517960e 发布0.2.0版本 2019-08-20 13:35:59 +08:00
lyswhut
3a615a4a87 新增百度音源 2019-08-20 13:18:11 +08:00
lyswhut
78d2541c14 新增网易云、酷狗排行榜音乐直接试听下载 2019-08-20 01:19:01 +08:00
lyswhut
b8d07b365b 修复更新弹窗历史版本描述多余的换行问题 2019-08-19 21:52:56 +08:00
lyswhut
2d5848db94 发布0.1.6版本 2019-08-19 19:10:06 +08:00
lyswhut
d4c88edb8b 修复列表多选音源限制Bug 2019-08-19 19:08:19 +08:00
29 changed files with 527 additions and 64 deletions

View File

@@ -6,6 +6,25 @@ Project versioning adheres to [Semantic Versioning](http://semver.org/).
Commit convention is based on [Conventional Commits](http://conventionalcommits.org).
Change log format is based on [Keep a Changelog](http://keepachangelog.com/).
## [0.2.0](https://github.com/lyswhut/lx-music-desktop/compare/v0.1.6...v0.2.0) - 2019-08-20
### 新增
- 新增**百度音乐**排行榜及其音乐直接试听与下载
- 新增网易云排行榜音乐直接试听与下载目前仅支持128k音质
- 新增酷狗排行榜音乐直接试听与下载目前仅支持128k音质
### 修复
- 修复更新弹窗历史版本描述多余的换行问题
- 修复歌曲无法播放的情况下歌词仍会播放的问题
## [0.1.6](https://github.com/lyswhut/lx-music-desktop/compare/v0.1.5...v0.1.6) - 2019-08-19
### 修复
- 修复列表多选音源限制Bug
## [0.1.5](https://github.com/lyswhut/lx-music-desktop/compare/v0.1.4...v0.1.5) - 2019-08-19
### 新增

View File

@@ -1,6 +1,6 @@
{
"name": "lx-music-desktop",
"version": "0.1.5",
"version": "0.2.0",
"description": "一个免费的音乐下载助手",
"main": "./dist/electron/main.js",
"scripts": {

View File

@@ -1,10 +1,10 @@
### 新增
- 新增搜索列表批量试听与下载功能
- 新增排行榜列表批量试听与下载功能
- 新增试听列表批量移除与下载功能
- 新增下载列表批量开始、暂停与移除功能
- 新增**百度音乐**排行榜及其音乐直接试听与下载
- 新增网易云排行榜音乐直接试听与下载目前仅支持128k音质
- 新增酷狗排行榜音乐直接试听与下载目前仅支持128k音质
### 优化
### 修复
- 优化歌曲切换机制
- 修复更新弹窗历史版本描述多余的换行问题
- 修复歌曲无法播放的情况下歌词仍会播放的问题

View File

@@ -7,11 +7,12 @@ const clearAssets = require('./utils/clearAssets')
const updateVersionFile = require('./utils/updateChangeLog')
// const copyFile = require('./utils/copyFile')
// const githubRelease = require('./utils/githubRelease')
const { parseArgv } = require('./utils')
// const { parseArgv } = require('./utils')
const run = async() => {
const params = parseArgv(process.argv.slice(2))
const bak = await updateVersionFile(params.ver)
// const params = parseArgv(process.argv.slice(2))
// const bak = await updateVersionFile(params.ver)
const bak = await updateVersionFile(process.argv.slice(2)[0])
try {
console.log(chalk.blue('Clearing assets...'))

View File

@@ -1,7 +1,15 @@
{
"version": "0.1.5",
"desc": "<h3>新增</h3>\n<ul>\n<li>新增搜索列表批量试听与下载功能</li>\n<li>新增排行榜列表批量试听与下载功能</li>\n<li>新增试听列表批量移除与下载功能</li>\n<li>新增下载列表批量开始、暂停与移除功能</li>\n</ul>\n<h3>优化</h3>\n<ul>\n<li>优化歌曲切换机制</li>\n</ul>\n",
"version": "0.2.0",
"desc": "<h3>新增</h3>\n<ul>\n<li>新增<strong>百度音乐</strong>排行榜及其音乐直接试听与下载</li>\n<li>新增网易云排行榜音乐直接试听与下载目前仅支持128k音质</li>\n<li>新增酷狗排行榜音乐直接试听与下载目前仅支持128k音质</li>\n</ul>\n<h3>修复</h3>\n<ul>\n<li>修复更新弹窗历史版本描述多余的换行问题</li>\n<li>修复歌曲无法播放的情况下歌词仍会播放的问题</li>\n</ul>\n",
"history": [
{
"version": "0.1.6",
"desc": "<h3>修复</h3>\n<ul>\n<li>修复列表多选音源限制Bug</li>\n</ul>\n"
},
{
"version": "0.1.5",
"desc": "<h3>新增</h3>\n<ul>\n<li>新增搜索列表批量试听与下载功能</li>\n<li>新增排行榜列表批量试听与下载功能</li>\n<li>新增试听列表批量移除与下载功能</li>\n<li>新增下载列表批量开始、暂停与移除功能</li>\n</ul>\n<h3>优化</h3>\n<ul>\n<li>优化歌曲切换机制</li>\n</ul>\n"
},
{
"version": "0.1.4",
"desc": "<h3>新增</h3>\n<ul>\n<li>新增音乐来源切换,可到设置页面-基本设置 look look !</li>\n<li>为搜索结果列表添加多选功能。<br>\nP.S暂时没想好多选后的操作按钮放哪…</li>\n</ul>\n<h3>优化</h3>\n<ul>\n<li>重构与改进checkbox组件使其支持不定选中状态</li>\n<li>完善上一个版本的http请求封装并切换部分请求到该方法上</li>\n<li>优化其他一些细节</li>\n</ul>\n"

View File

@@ -61,12 +61,14 @@ export default {
name: '^',
singer: '^',
},
targetSong: null,
pregessWidth: 0,
lyric: {
lrc: null,
text: '',
line: 0,
},
retryNum: 0,
}
},
computed: {
@@ -137,6 +139,7 @@ export default {
'fixPlayIndex',
'resetChangePlay',
]),
...mapMutations('list', ['updateMusicInfo']),
init() {
this.audio = document.createElement('audio')
this.audio.controls = false
@@ -161,10 +164,16 @@ export default {
this.handleNext()
})
this.audio.addEventListener('error', () => {
// console.log('code', this.audio.error.code)
if (!this.musicInfo.songmid) return
console.log('出错')
if (this.audio.error.code == 4 && this.retryNum < 5) {
// console.log(this.retryNum)
this.retryNum++
this.setUrl(this.list[this.playIndex], true)
return
}
this.stopPlay()
this.status = '加载出错'
this.sendProgressEvent(this.progress, 'error')
// let urls = this.player_info.targetSong.urls
@@ -182,10 +191,14 @@ export default {
// } else {
// this.handleNext()
// }
this.handleNext()
this.status = '音频加载出错2 两秒后切换下一首'
setTimeout(() => {
this.handleNext()
}, 2000)
})
this.audio.addEventListener('loadeddata', () => {
this.maxPlayTime = this.audio.duration
if (!this.targetSong.interval && this.listId != 'download') this.updateMusicInfo({ index: this.playIndex, data: { interval: formatPlayTime2(this.maxPlayTime) } })
this.status = '音乐加载中...'
})
// this.audio.addEventListener('loadstart', () => {
@@ -228,7 +241,8 @@ export default {
},
play() {
console.log('play', this.playIndex)
let targetSong = this.list[this.playIndex]
let targetSong = this.targetSong = this.list[this.playIndex]
this.retryNum = 0
if (this.listId == 'download') {
if (!checkPath(targetSong.filePath) || !targetSong.isComplate || /\.ape$/.test(targetSong.filePath)) {
@@ -321,16 +335,21 @@ export default {
this.musicInfo.img = null
},
getPlayType(highQuality, songInfo) {
switch (songInfo.source) {
case 'wy':
case 'kg':
return '128k'
}
let type = songInfo._types['192k'] ? '192k' : '128k'
if (highQuality && songInfo._types['320k']) type = '320k'
return type
},
setUrl(targetSong) {
setUrl(targetSong, isRefresh) {
let type = this.getPlayType(this.setting.player.highQuality, targetSong)
this.musicInfo.url = targetSong.typeUrl[type]
this.status = '歌曲链接获取中...'
let urlP = this.musicInfo.url
let urlP = this.musicInfo.url && !isRefresh
? Promise.resolve()
: this.getUrl({ musicInfo: targetSong, type }).then(() => {
this.musicInfo.url = targetSong.typeUrl[type]
@@ -366,7 +385,7 @@ export default {
lrcP
.then(() => {
this.lyric.lrc.setLyric(this.musicInfo.lrc)
if (this.isPlay) this.lyric.lrc.play(this.audio.currentTime * 1000)
if (this.isPlay && (this.musicInfo.url || this.listId == 'download')) this.lyric.lrc.play(this.audio.currentTime * 1000)
})
.catch(err => {
this.status = err.message

View File

@@ -1,5 +1,5 @@
<template lang="pug">
button(:class="[$style.btn, min ? $style.min : '']" @click="$emit('click', $event)")
button(:class="[$style.btn, min ? $style.min : '']" :disabled="disabled" @click="$emit('click', $event)")
slot
</template>
@@ -9,6 +9,10 @@ export default {
min: {
type: Boolean,
},
disabled: {
type: Boolean,
default: false,
},
},
}
</script>
@@ -27,6 +31,9 @@ export default {
outline: none;
transition: background-color 0.2s ease;
background-color: @color-btn-background;
&[disabled] {
opacity: .4;
}
&:hover {
background-color: @color-theme_2-hover;

View File

@@ -5,7 +5,7 @@ material-modal(:show="show" :bg-close="bgClose" @close="handleClose")
| {{ info.name }}
br
| {{ info.singer }}
material-btn(:class="$style.btn" :key="type.type" @click="handleClick(type.type)" v-for="type in info.types") {{getTypeName(type.type)}} {{ type.type.toUpperCase() }}{{ type.size && ` - ${type.size.toUpperCase()}` }}
material-btn(:class="$style.btn" :title="!checkSource(type.type) && '目前酷狗、网易云音源仅支持下载128k音质'" :disabled="!checkSource(type.type)" :key="type.type" @click="handleClick(type.type)" v-for="type in info.types") {{getTypeName(type.type)}} {{ type.type.toUpperCase() }}{{ type.size && ` - ${type.size.toUpperCase()}` }}
</template>
@@ -49,6 +49,16 @@ export default {
return '普通音质'
}
},
checkSource(type) {
switch (this.musicInfo.source) {
case 'wy':
case 'kg':
return type == '128k'
default:
return true
}
},
},
}
</script>

View File

@@ -37,18 +37,6 @@ export default {
handleClose() {
this.$emit('close')
},
getTypeName(type) {
switch (type) {
case 'flac':
case 'ape':
return '无损音质'
case '320k':
return '高品音质'
case '192k':
case '128k':
return '普通音质'
}
},
},
}
</script>

View File

@@ -127,7 +127,7 @@ export default {
h3 {
padding: 5px 0 3px;
}
padding-left: 15px;
padding: 0 15px;
+ .item {
padding-top: 15px;
}

View File

@@ -55,7 +55,7 @@ const checkList = (list, musicInfo, type) => list.some(s => s.musicInfo.songmid
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)
// console.log(downloadCount, waitList)
return downloadCount < maxDownloadNum && waitList.length > 0 && waitList.shift()
}
@@ -168,7 +168,9 @@ const actions = {
console.log(err)
_this.dispatch('download/startTask')
})
return
}
_this.dispatch('download/startTask')
},
// onStateChanged(state) {
// console.log(state)
@@ -189,22 +191,25 @@ const actions = {
commit('resumeTask', downloadInfo)
},
}
commit('setStatusText', { downloadInfo, text: '获取URL中...' })
let p = options.url ? Promise.resolve() : refreshUrl(downloadInfo).then(result => {
commit('updateUrl', { downloadInfo, url: result.url })
if (!result.url) return Promise.reject(new Error('获取URL失败'))
options.url = result.url
}).catch(err => {
commit('onError', downloadInfo)
commit('setStatusText', { downloadInfo, text: err.message })
return Promise.reject(err)
})
p.then(() => {
tryNum[downloadInfo.key] = 0
dls[downloadInfo.key] = download(options)
}).catch(err => {
// console.log(err.message)
commit('onError', downloadInfo)
commit('setStatusText', { downloadInfo, text: err.message })
this.dispatch('download/startTask')
})
},
startTaskMultiple({ state, rootState }, list) {
// startTaskMultiple({ state, rootState }, list) {
},
// },
removeTask({ commit, state }, index) {
let info = state.list[index]
if (state.list[index].status == state.downloadStatus.RUN) {

View File

@@ -39,6 +39,9 @@ const mutations = {
defaultListRemove(state, index) {
state.defaultList.list.splice(index, 1)
},
updateMusicInfo(state, { index, data }) {
Object.assign(state.defaultList.list[index], data)
},
defaultListRemoveMultiple(state, list) {
list.forEach(musicInfo => {
let index = state.defaultList.list.indexOf(musicInfo)

View File

@@ -35,7 +35,6 @@ const actions = {
if (picRequest && picRequest.cancelHttp) picRequest.cancelHttp()
picRequest = music[musicInfo.source].getPic(musicInfo)
return picRequest.promise.then(url => {
console.log(url)
commit('getPic', { musicInfo, url })
}).finally(() => {
picRequest = null

View File

@@ -13,9 +13,9 @@ export default {
if (source != null) state.setting.leaderboard.source = source
},
setNewVersion(state, val) {
val.history.forEach(ver => {
ver.desc = ver.desc.replace(/\n/g, '<br>')
})
// val.history.forEach(ver => {
// ver.desc = ver.desc.replace(/\n/g, '<br>')
// })
// val.desc = val.desc.replace(/\n/g, '<br>')
state.version.newVersion = val
},

View File

@@ -1,10 +1,16 @@
import kw_api_messoer from './kw/api-messoer'
import kw_api_temp from './kw/api-temp'
import tx_api_messoer from './tx/api-messoer'
import kg_api_messoer from './kg/api-messoer'
import wy_api_messoer from './wy/api-messoer'
import bd_api_messoer from './bd/api-messoer'
const apis = {
kw_api_messoer,
tx_api_messoer,
kg_api_messoer,
wy_api_messoer,
bd_api_messoer,
kw_api_temp,
}
@@ -22,6 +28,12 @@ export default source => {
switch (source) {
case 'tx':
return getAPI('tx')
case 'kg':
return getAPI('kg')
case 'wy':
return getAPI('wy')
case 'bd':
return getAPI('bd')
default:
return getAPI('kw')
}

View File

@@ -0,0 +1,37 @@
import { httpFatch } from '../../request'
import { requestMsg } from '../../message'
const api_messoer = {
getMusicUrl(songInfo, type) {
const requestObj = httpFatch(`https://v1.itooi.cn/baidu/url?id=${songInfo.songmid}&quality=${type.replace(/k$/, '')}&isRedirect=0`, {
method: 'get',
timeout: 5000,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body.code === 200 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail))
})
return requestObj
},
getPic(songInfo, size = '500') {
const requestObj = httpFatch(`https://v1.itooi.cn/baidu/pic?id=${songInfo.songmid}&imageSize=${size}&isRedirect=0`, {
method: 'get',
timeout: 5000,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body.code === 200 ? Promise.resolve(body.data) : Promise.reject(new Error(requestMsg.fail))
})
return requestObj
},
getLyric(songInfo) {
const requestObj = httpFatch(`https://v1.itooi.cn/baidu/lrc?id=${songInfo.songmid}&isRedirect=0`, {
method: 'get',
timeout: 5000,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body ? Promise.resolve(body) : Promise.reject(new Error(requestMsg.fail))
})
return requestObj
},
}
export default api_messoer

View File

@@ -0,0 +1,21 @@
import leaderboard from './leaderboard'
import api_source from '../api-source'
import musicInfo from './musicInfo'
const bd = {
leaderboard,
getMusicUrl(songInfo, type) {
return api_source('bd').getMusicUrl(songInfo, type)
},
getLyric(songInfo) {
return api_source('bd').getLyric(songInfo)
},
getPic(songInfo) {
return api_source('bd').getPic(songInfo)
},
getMusicInfo(songInfo) {
return musicInfo.getMusicInfo(songInfo.songmid)
},
}
export default bd

View File

@@ -0,0 +1,132 @@
import { httpFatch } from '../../request'
// import { formatPlayTime } from '../../index'
// import jshtmlencode from 'js-htmlencode'
export default {
limit: 20,
list: [
{
id: 'bdrgb',
name: '热歌榜',
bangid: '2',
},
{
id: 'bdxgb',
name: '新歌榜',
bangid: '1',
},
{
id: 'bdycb',
name: '原创榜',
bangid: '200',
},
{
id: 'bdhyjqb',
name: '华语榜',
bangid: '20',
},
{
id: 'bdomjqb',
name: '欧美榜',
bangid: '21',
},
{
id: 'bdwugqb',
name: '网络榜',
bangid: '25',
},
{
id: 'bdjdlgb',
name: '老歌榜',
bangid: '22',
},
{
id: 'bdysjqb',
name: '影视金曲榜',
bangid: '24',
},
{
id: 'bdqgdcb',
name: '情歌对唱榜',
bangid: '23',
},
{
id: 'bdygb',
name: '摇滚榜',
bangid: '11',
},
],
getUrl(id, p) {
return `http://musicmini.qianqian.com/2018/static/bangdan/bangdanList_${id}_${p}.html`
},
regExps: {
item: /data-song="({.+?})"/g,
info: /{total[\s:]+"(\d+)", size[\s:]+"(\d+)", page[\s:]+"(\d+)"}/,
},
requestObj: null,
getData(url) {
if (this.requestObj) this.requestObj.cancelHttp()
this.requestObj = httpFatch(url)
return this.requestObj.promise
},
filterData(rawList) {
// console.log(rawList)
return rawList.map(item => {
const types = []
const _types = {}
let size = null
types.push({ type: '128k', size })
_types['128k'] = {
size,
}
if (item.biaoshi) {
types.push({ type: '320k', size })
_types['320k'] = {
size,
}
types.push({ type: 'flac', size })
_types['flac'] = {
size,
}
}
// types.reverse()
return {
singer: item.song_artist.replace(',', '、'),
name: item.song_title,
albumName: item.album_title,
albumId: item.album_id,
source: 'bd',
interval: '',
songmid: item.song_id,
img: null,
lrc: null,
types,
_types,
typeUrl: {},
}
})
},
parseData(rawData) {
// return rawData.map(item => JSON.parse(item.replace(this.regExps.item, '$1').replace(/&quot;/g, '"').replace(/\\\//g, '/').replace(/(@s_1,w_)\d+(,h_)\d+/, '$1500$2500')))
return rawData.map(item => JSON.parse(item.replace(this.regExps.item, '$1').replace(/&quot;/g, '"').replace(/\\\//g, '/')))
},
getList(id, page) {
let type = this.list.find(s => s.id === id)
if (!type) return Promise.reject()
return this.getData(this.getUrl(type.bangid, page)).then(({ body }) => {
let result = body.match(this.regExps.item)
if (!result) return Promise.reject(new Error('匹配list失败'))
let info = body.match(this.regExps.info)
if (!info) return Promise.reject(new Error('匹配info失败'))
const list = this.filterData(this.parseData(result))
this.limit = parseInt(info[2])
return {
total: parseInt(info[1]),
list,
limit: this.limit,
page: parseInt(info[3]),
}
})
},
}

View File

@@ -0,0 +1,11 @@
import { httpFatch } from '../../request'
export default {
getMusicInfo(songmid) {
const requestObj = httpFatch(`https://musicapi.qianqian.com/v1/restserver/ting?method=baidu.ting.song.getSongLink&format=json&from=bmpc&version=1.0.0&version_d=11.1.6.0&songid=${songmid}&type=1&res=1&s_protocol=1&aac=2&project=tpass`)
requestObj.promise = requestObj.promise.then(({ body }) => {
return body.error_code == 22000 ? body.reqult.songinfo : Promise.reject(new Error('获取音乐信息失败'))
})
return requestObj
},
}

View File

@@ -2,6 +2,7 @@ import kw from './kw'
import kg from './kg'
import tx from './tx'
import wy from './wy'
import bd from './bd'
export default {
sources: [
{
@@ -20,9 +21,14 @@ export default {
name: '网易音乐',
id: 'wy',
},
{
name: '百度音乐',
id: 'bd',
},
],
kw,
kg,
tx,
wy,
bd,
}

View File

@@ -0,0 +1,37 @@
import { httpFatch } from '../../request'
import { requestMsg } from '../../message'
const api_messoer = {
getMusicUrl(songInfo, type) {
const requestObj = httpFatch(`https://v1.itooi.cn/kugou/url?id=${songInfo._types[type].hash}&quality=${type.replace(/k$/, '')}&isRedirect=0`, {
method: 'get',
timeout: 5000,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body.code === 200 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail))
})
return requestObj
},
getPic(songInfo) {
const requestObj = httpFatch(`https://v1.itooi.cn/kugou/pic?id=${songInfo.hash}&isRedirect=0`, {
method: 'get',
timeout: 5000,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body.code === 200 ? Promise.resolve(body.data) : Promise.reject(new Error(requestMsg.fail))
})
return requestObj
},
getLyric(songInfo) {
const requestObj = httpFatch(`https://v1.itooi.cn/kugou/lrc?id=${songInfo.hash}&isRedirect=0`, {
method: 'get',
timeout: 5000,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body ? Promise.resolve(body) : Promise.reject(new Error(requestMsg.fail))
})
return requestObj
},
}
export default api_messoer

View File

@@ -1,7 +1,18 @@
import leaderboard from './leaderboard'
import api_source from '../api-source'
const kg = {
leaderboard,
getMusicUrl(songInfo, type) {
return api_source('kg').getMusicUrl(songInfo, type)
},
getLyric(songInfo) {
return api_source('kg').getLyric(songInfo)
},
getPic(songInfo) {
return api_source('kg').getPic(songInfo)
},
}
export default kg

View File

@@ -1,5 +1,5 @@
import { httpGet, cancelHttp } from '../../request'
import { formatPlayTime } from '../../index'
import { formatPlayTime, sizeFormate } from '../../index'
export default {
list: [
@@ -89,18 +89,58 @@ export default {
})
},
filterData(rawList) {
return rawList.map(item => ({
singer: item.singername,
name: item.songname,
albumName: item.album_name,
albumId: item.album_id,
songmid: item.audio_id,
source: 'kg',
interval: formatPlayTime(item.duration / 1000),
img: null,
lrc: null,
typeUrl: {},
}))
// console.log(rawList)
return rawList.map(item => {
const types = []
const _types = {}
if (item.filesize !== 0) {
let size = sizeFormate(item.filesize)
types.push({ type: '128k', size, hash: item.hash })
_types['128k'] = {
size,
hash: item.hash,
}
}
if (item.filesize_320 !== 0) {
let size = sizeFormate(item.filesize_320)
types.push({ type: '320k', size, hash: item.hash_320 })
_types['320k'] = {
size,
hash: item.hash_320,
}
}
if (item.filesize_ape !== 0) {
let size = sizeFormate(item.filesize_ape)
types.push({ type: 'ape', size, hash: item.hash_ape })
_types.ape = {
size,
hash: item.hash_ape,
}
}
if (item.filesize_flac !== 0) {
let size = sizeFormate(item.filesize_flac)
types.push({ type: 'flac', size, hash: item.hash_flac })
_types.flac = {
size,
hash: item.hash_flac,
}
}
return {
singer: item.singername,
name: item.songname,
albumName: item.album_name,
albumId: item.album_id,
songmid: item.audio_id,
source: 'kg',
interval: formatPlayTime(item.duration / 1000),
img: null,
lrc: null,
hash: item.HASH,
types,
_types,
typeUrl: {},
}
})
},
getList(id, page) {
let type = this.list.find(s => s.id === id)

View File

@@ -3,8 +3,14 @@
* @param {*} info
* @param {*} type
*/
const types = ['flac', 'ape', '320k', '192k', '128k']
export const getMusicType = (info, type) => {
switch (window.globalObj.apiSource) {
case 'kg':
case 'wy':
return '128k'
}
const rangeType = types.slice(types.indexOf(type))
for (const type of rangeType) {
if (info._types[type]) return type

View File

@@ -0,0 +1,37 @@
import { httpFatch } from '../../request'
import { requestMsg } from '../../message'
const api_messoer = {
getMusicUrl(songInfo, type) {
const requestObj = httpFatch(`https://v1.itooi.cn/netease/url?id=${songInfo.songmid}&quality=${type.replace(/k$/, '')}&isRedirect=0`, {
method: 'get',
timeout: 5000,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body.code === 200 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail))
})
return requestObj
},
getPic(songInfo) {
const requestObj = httpFatch(`https://v1.itooi.cn/netease/pic?id=${songInfo.songmid}&isRedirect=0`, {
method: 'get',
timeout: 5000,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body.code === 200 ? Promise.resolve(body.data) : Promise.reject(new Error(requestMsg.fail))
})
return requestObj
},
getLyric(songInfo) {
const requestObj = httpFatch(`https://v1.itooi.cn/netease/lrc?id=${songInfo.songmid}&isRedirect=0`, {
method: 'get',
timeout: 5000,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body ? Promise.resolve(body) : Promise.reject(new Error(requestMsg.fail))
})
return requestObj
},
}
export default api_messoer

View File

@@ -1,7 +1,17 @@
import leaderboard from './leaderboard'
import api_source from '../api-source'
const wy = {
leaderboard,
getMusicUrl(songInfo, type) {
return api_source('wy').getMusicUrl(songInfo, type)
},
getLyric(songInfo) {
return api_source('wy').getLyric(songInfo)
},
getPic(songInfo) {
return api_source('wy').getPic(songInfo)
},
}
export default wy

View File

@@ -91,6 +91,42 @@ export default {
filterData(rawList) {
// console.log(rawList)
return rawList.map(item => {
const types = []
const _types = {}
let size
switch (item.privilege.maxbr) {
case 999000:
size = null
types.push({ type: 'flac', size })
_types['flac'] = {
size,
}
case 320000:
size = null
types.push({ type: '320k', size })
_types['320k'] = {
size,
}
case 192000:
case 190000:
size = null
types.push({ type: '192k', size })
_types['192k'] = {
size,
}
// case '160000':
default:
size = null
types.push({ type: '128k', size })
_types['128k'] = {
size,
}
break
}
types.reverse()
return {
singer: this.getSinger(item.artists),
name: item.name,
@@ -101,6 +137,8 @@ export default {
songmid: item.id,
img: item.album.picUrl,
lrc: null,
types,
_types,
typeUrl: {},
}
})

View File

@@ -30,16 +30,16 @@
td.break(style="width: 20%;") {{item.singer}}
td.break(style="width: 22%;") {{item.albumName}}
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="handleListBtnClick")
material-list-buttons(:index="index" :search-btn="true" :play-btn="item.source == 'kw' || !isAPITemp" :download-btn="item.source == 'kw' || !isAPITemp" :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-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)')
td(style="width: 10%;") {{item.interval}}
td(style="width: 10%;") {{item.interval || '--/--'}}
div(:class="$style.pagination")
material-pagination(:count="info.total" :limit="info.limit" :page="info.page" @btn-click="handleTogglePage")
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")
material-flow-btn(:show="isShowEditBtn && (source == 'kw' || !isAPITemp)" :remove-btn="false" @btn-click="handleFlowBtnClick")
</template>
<script>
@@ -123,7 +123,7 @@ export default {
this.clickIndex = index
return
}
(this.source == 'kw' || (!this.isAPITemp && this.source == 'tx')) ? this.testPlay(index) : this.handleSearch(index)
(this.source == 'kw' || !this.isAPITemp) ? this.testPlay(index) : this.handleSearch(index)
this.clickTime = 0
this.clickIndex = -1
},
@@ -170,7 +170,7 @@ export default {
this.$router.push({
path: 'search',
query: {
text: `${info.name} - ${info.singer}`,
text: `${info.name} ${info.singer}`,
},
})
},
@@ -194,6 +194,11 @@ export default {
this.isShowDownload = false
},
handleAddDownloadMultiple(type) {
switch (this.source) {
case 'kg':
case 'wy':
type = '128k'
}
this.createDownloadMultiple({ list: [...this.selectdData], type })
this.resetSelect()
this.isShowDownloadMultiple = false

View File

@@ -35,7 +35,7 @@
//- 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-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)
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")
@@ -173,7 +173,8 @@ export default {
this.selectdData = []
},
handleAddDownloadMultiple(type) {
this.createDownloadMultiple({ list: [...this.selectdData], type })
const list = this.setting.apiSource == 'temp' ? this.selectdData.filter(s => s.source == 'kw') : [...this.selectdData]
this.createDownloadMultiple({ list, type })
this.resetSelect()
this.isShowDownloadMultiple = false
},