diff --git a/CHANGELOG.md b/CHANGELOG.md
index e6a8e92c31..5ae393fc61 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,20 @@ 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.1.4](https://github.com/lyswhut/lx-music-desktop/compare/v0.1.3...v0.1.4) - 2019-08-18
+
+### 新增
+
+- 新增音乐来源切换,可到设置页面-基本设置 look look !
+- 为搜索结果列表添加多选功能。
+P.S:暂时没想好多选后的操作按钮放哪...
+
+### 优化
+
+- 重构与改进checkbox组件,使其支持不定选中状态
+- 完善上一个版本的http请求封装并切换部分请求到该方法上
+- 优化其他一些细节
+
## [0.1.3](https://github.com/lyswhut/lx-music-desktop/compare/v0.1.2...v0.1.3) - 2019-08-17
### 新增
diff --git a/package.json b/package.json
index 2906035068..39edb0966b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "lx-music-desktop",
- "version": "0.1.3",
+ "version": "0.1.4",
"description": "一个免费的音乐下载助手",
"main": "./dist/electron/main.js",
"scripts": {
diff --git a/publish/changeLog.md b/publish/changeLog.md
index 31b0e97b87..3cb0c6ea07 100644
--- a/publish/changeLog.md
+++ b/publish/changeLog.md
@@ -1,3 +1,11 @@
+### 新增
+
+- 新增音乐来源切换,可到设置页面-基本设置 look look !
+- 为搜索结果列表添加多选功能。
+P.S:暂时没想好多选后的操作按钮放哪...
+
### 优化
-- 重构checkbox组件
+- 重构与改进checkbox组件,使其支持不定选中状态
+- 完善上一个版本的http请求封装并切换部分请求到该方法上
+- 优化其他一些细节
diff --git a/publish/version.json b/publish/version.json
index 7a8d641ef1..b45f25f36a 100644
--- a/publish/version.json
+++ b/publish/version.json
@@ -1,7 +1,11 @@
{
- "version": "0.1.3",
- "desc": "
新增
\n\n修复
\n\n- 修复安装包许可协议乱码问题
\n- messoer 提供的接口已挂,暂时切换到临时接口!
\n
\n移除
\n\n- 由于messoer接口无法使用,QQ音乐排行榜直接播放/下载功能暂时关闭
\n
\n",
+ "version": "0.1.4",
+ "desc": "新增
\n\n- 新增音乐来源切换,可到设置页面-基本设置 look look !
\n- 为搜索结果列表添加多选功能。
\nP.S:暂时没想好多选后的操作按钮放哪… \n
\n优化
\n\n- 重构与改进checkbox组件,使其支持不定选中状态
\n- 完善上一个版本的http请求封装并切换部分请求到该方法上
\n- 优化其他一些细节
\n
\n",
"history": [
+ {
+ "version": "0.1.3",
+ "desc": "新增
\n\n修复
\n\n- 修复安装包许可协议乱码问题
\n- messoer 提供的接口已挂,暂时切换到临时接口!
\n
\n移除
\n\n- 由于messoer接口无法使用,QQ音乐排行榜直接播放/下载功能暂时关闭
\n
\n"
+ },
{
"version": "0.1.2",
"desc": "修复
\n\n"
diff --git a/src/renderer/App.vue b/src/renderer/App.vue
index a0e28c3666..66d50448b5 100644
--- a/src/renderer/App.vue
+++ b/src/renderer/App.vue
@@ -28,6 +28,9 @@ export default {
data() {
return {
isProd: process.env.NODE_ENV === 'production',
+ globalObj: {
+ apiSource: 'messoer',
+ },
}
},
computed: {
@@ -59,12 +62,20 @@ export default {
},
deep: true,
},
+ 'globalObj.apiSource'(n) {
+ if (n != this.setting.apiSource) {
+ this.setSetting(Object.assign({}, this.setting, {
+ apiSource: n,
+ }))
+ }
+ },
},
methods: {
...mapActions(['getVersionInfo']),
...mapMutations(['setNewVersion', 'setVersionVisible']),
...mapMutations('list', ['initDefaultList']),
...mapMutations('download', ['updateDownloadList']),
+ ...mapMutations(['setSetting']),
init() {
if (this.isProd) {
body.addEventListener('mouseenter', this.dieableIgnoreMouseEvents)
@@ -80,6 +91,8 @@ export default {
})
this.initData()
+ this.globalObj.apiSource = this.setting.apiSource
+ window.globalObj = this.globalObj
},
enableIgnoreMouseEvents() {
win.setIgnoreMouseEvents(false)
diff --git a/src/renderer/components/core/Player.vue b/src/renderer/components/core/Player.vue
index 50d4c0372a..f085e9bcf8 100644
--- a/src/renderer/components/core/Player.vue
+++ b/src/renderer/components/core/Player.vue
@@ -90,6 +90,9 @@ export default {
// return 50
return this.nowPlayTime / this.maxPlayTime || 0
},
+ isAPITemp() {
+ return this.setting.apiSource == 'temp'
+ },
},
mounted() {
this.setProgessWidth()
@@ -249,7 +252,8 @@ export default {
},
handleNext() {
// if (this.list.listName === null) return
- if (!this.list.length) return
+ const list = this.isAPITemp ? this.list.filter(s => s.source == 'kw') : this.list
+ if (!list.length) return
let index
switch (this.setting.player.togglePlayMethod) {
case 'listLoop':
@@ -267,14 +271,17 @@ export default {
if (index < 0) return
this.setPlayIndex(index)
},
- hanldeListLoop() {
- return this.playIndex === this.list.length - 1 ? 0 : this.playIndex + 1
+ hanldeListLoop(index = this.playIndex) {
+ index = index === this.list.length - 1 ? 0 : index + 1
+ return this.isAPITemp && this.list[index].source != 'kw' ? this.hanldeListLoop(index) : index
},
- hanldeListNext() {
- return this.playIndex === this.list.length - 1 ? -1 : this.playIndex + 1
+ hanldeListNext(index = this.playIndex) {
+ index = index === this.list.length - 1 ? -1 : index + 1
+ return this.isAPITemp && this.list[index].source != 'kw' ? this.hanldeListNext(index) : index
},
- hanldeListRandom() {
- return getRandom(0, this.list.length)
+ hanldeListRandom(index = this.playIndex) {
+ index = getRandom(0, this.list.length)
+ return this.isAPITemp && this.list[index].source != 'kw' ? this.hanldeListRandom(index) : index
},
startPlay() {
this.isPlay = true
@@ -314,6 +321,7 @@ export default {
setUrl(targetSong) {
let type = this.getPlayType(this.setting.player.highQuality, targetSong)
this.musicInfo.url = targetSong.typeUrl[type]
+ this.status = '歌曲链接获取中...'
let urlP = this.musicInfo.url
? Promise.resolve()
@@ -323,6 +331,8 @@ export default {
urlP.then(() => {
this.audio.src = this.musicInfo.url
+ }).catch(err => {
+ this.status = err.message
})
},
setImg(targetSong) {
diff --git a/src/renderer/store/modules/player.js b/src/renderer/store/modules/player.js
index d9b04a8ed1..2ba6bd9736 100644
--- a/src/renderer/store/modules/player.js
+++ b/src/renderer/store/modules/player.js
@@ -8,7 +8,9 @@ const state = {
changePlay: false,
}
-let request
+let urlRequest
+let picRequest
+let lrcRequest
// getters
const getters = {
@@ -21,19 +23,32 @@ const getters = {
// actions
const actions = {
getUrl({ commit, state }, { musicInfo, type }) {
- if (request && request.cancelHttp) request.cancelHttp()
- request = music[musicInfo.source].getMusicUrl(musicInfo, type)
- return request.promise.then(result => {
+ if (urlRequest && urlRequest.cancelHttp) urlRequest.cancelHttp()
+ urlRequest = music[musicInfo.source].getMusicUrl(musicInfo, type)
+ return urlRequest.promise.then(result => {
commit('setUrl', { musicInfo, url: result.url, type })
}).finally(() => {
- request = null
+ urlRequest = null
})
},
getPic({ commit, state }, musicInfo) {
- return music[musicInfo.source].getPic(musicInfo).then(url => commit('getPic', { musicInfo, url }))
+ 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
+ })
},
getLrc({ commit, state }, musicInfo) {
- return music[musicInfo.source].getLyric(musicInfo).then(lrc => commit('setLrc', { musicInfo, lrc }))
+ if (lrcRequest && lrcRequest.cancelHttp) lrcRequest.cancelHttp()
+ lrcRequest = music[musicInfo.source].getLyric(musicInfo)
+ return lrcRequest.promise.then(lrc => {
+ commit('setLrc', { musicInfo, lrc })
+ }).finally(() => {
+ lrcRequest = null
+ })
},
}
diff --git a/src/renderer/utils/index.js b/src/renderer/utils/index.js
index f86d4c6be5..25699eb709 100644
--- a/src/renderer/utils/index.js
+++ b/src/renderer/utils/index.js
@@ -157,7 +157,7 @@ export const isChildren = (parent, children) => {
}
export const updateSetting = setting => {
- const defaultVersion = '1.0.1'
+ const defaultVersion = '1.0.2'
const defaultSetting = {
version: defaultVersion,
player: {
@@ -177,6 +177,7 @@ export const updateSetting = setting => {
},
themeId: 0,
sourceId: 'kw',
+ apiSource: 'messoer',
randomAnimate: true,
}
const overwriteSetting = {
diff --git a/src/renderer/utils/music/api-source.js b/src/renderer/utils/music/api-source.js
new file mode 100644
index 0000000000..4fa59fdc91
--- /dev/null
+++ b/src/renderer/utils/music/api-source.js
@@ -0,0 +1,28 @@
+import kw_api_messoer from './kw/api-messoer'
+import kw_api_temp from './kw/api-temp'
+import tx_api_messoer from './tx/api-messoer'
+
+const apis = {
+ kw_api_messoer,
+ tx_api_messoer,
+ kw_api_temp,
+}
+
+
+const getAPI = source => {
+ switch (window.globalObj.apiSource) {
+ case 'messoer':
+ return apis[`${source}_api_messoer`]
+ case 'temp':
+ return apis[`${source}_api_temp`]
+ }
+}
+
+export default source => {
+ switch (source) {
+ case 'tx':
+ return getAPI('tx')
+ default:
+ return getAPI('kw')
+ }
+}
diff --git a/src/renderer/utils/music/kw/api-messoer.js b/src/renderer/utils/music/kw/api-messoer.js
new file mode 100644
index 0000000000..9a4749e435
--- /dev/null
+++ b/src/renderer/utils/music/kw/api-messoer.js
@@ -0,0 +1,26 @@
+import { httpFatch } from '../../request'
+
+const api_messoer = {
+ getMusicUrl(songInfo, type) {
+ const requestObj = httpFatch(`https://v1.itooi.cn/kuwo/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(body.msg))
+ })
+ return requestObj
+ },
+ getPic(songInfo) {
+ const requestObj = httpFatch(`https://v1.itooi.cn/kuwo/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(body.msg))
+ })
+ return requestObj
+ },
+}
+
+export default api_messoer
diff --git a/src/renderer/utils/music/kw/api-temp.js b/src/renderer/utils/music/kw/api-temp.js
new file mode 100644
index 0000000000..d7091ae043
--- /dev/null
+++ b/src/renderer/utils/music/kw/api-temp.js
@@ -0,0 +1,33 @@
+import { httpFatch } from '../../request'
+
+const api_temp = {
+ getMusicUrl(songInfo, type) {
+ const requestObj = httpFatch(`https://www.stsky.cn/api/temp/getMusicUrl.php?id=${songInfo.songmid}&type=${type}`, {
+ method: 'get',
+ })
+ requestObj.promise = requestObj.promise.then(({ body }) => {
+ 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
+ },
+ getPic(songInfo) {
+ const requestObj = httpFatch(`https://www.stsky.cn/api/temp/getPic.php?size=320&songmid=${songInfo.songmid}`, {
+ method: 'get',
+ })
+ requestObj.promise = requestObj.promise.then(({ body }) => {
+ 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
+ },
+}
+
+export default api_temp
diff --git a/src/renderer/utils/music/kw/index.js b/src/renderer/utils/music/kw/index.js
index d7c2bf6a81..9176328d5d 100644
--- a/src/renderer/utils/music/kw/index.js
+++ b/src/renderer/utils/music/kw/index.js
@@ -4,6 +4,7 @@ import musicSearch from './musicSearch'
import { formatSinger } from './util'
import leaderboard from './leaderboard'
import lyric from './lyric'
+import api_source from '../api-source'
const kw = {
_musicInfoRequestObj: null,
@@ -52,36 +53,7 @@ const kw = {
},
getMusicUrl(songInfo, type) {
- let requestObj
- let cancelFn
- const p = new Promise((resolve, reject) => {
- cancelFn = reject
- // requestObj = httpGet(`https://v1.itooi.cn/kuwo/url?id=${songInfo.songmid}&quality=${type.replace(/k$/, '')}&isRedirect=0`, (err, resp, body) => {
- requestObj = httpGet(`https://www.stsky.cn/api/temp/getMusicUrl.php?id=${songInfo.songmid}&type=${type}`, (err, resp, body) => {
- requestObj = null
- cancelFn = null
- if (err) {
- if (err.message === 'socket hang up') return reject(new Error('接口挂了'))
- const { promise, cancelHttp } = this.getMusicUrl(songInfo, type)
- obj.cancelHttp = cancelHttp
- return promise
- }
- // body.code === 200 ? resolve({ type, url: body.data }) : reject(new Error(body.msg))
- body.code === 0 ? resolve({ type, url: body.data }) : reject(new Error(body.msg))
- })
- })
- const obj = {
- promise: p,
- cancelHttp() {
- console.log('cancel')
- if (!requestObj) return
- cancelHttp(requestObj)
- cancelFn(new Error('取消http请求'))
- requestObj = null
- cancelFn = null
- },
- }
- return obj
+ return api_source('kw').getMusicUrl(songInfo, type)
},
getMusicInfo(songInfo) {
@@ -119,24 +91,7 @@ const kw = {
},
getPic(songInfo) {
- if (this._musicPicRequestObj != null) {
- cancelHttp(this._musicPicRequestObj)
- this._musicPicPromiseCancelFn(new Error('取消http请求'))
- }
- return new Promise((resolve, reject) => {
- this._musicPicPromiseCancelFn = reject
- // this._musicPicRequestObj = httpGet(`https://v1.itooi.cn/kuwo/pic?id=${songInfo.songmid}&isRedirect=0`, (err, resp, body) => {
- this._musicPicRequestObj = httpGet(`https://www.stsky.cn/api/temp/getPic.php?size=320&songmid=${songInfo.songmid}`, (err, resp, body) => {
- this._musicPicRequestObj = null
- this._musicPicPromiseCancelFn = null
- if (err) {
- console.log(err)
- reject(err)
- }
- // body.code === 200 ? resolve(body.data) : reject(new Error(body.msg))
- body.code === 0 ? resolve(body.data) : reject(new Error(body.msg))
- })
- })
+ return api_source('kw').getPic(songInfo)
},
}
diff --git a/src/renderer/utils/music/kw/leaderboard.js b/src/renderer/utils/music/kw/leaderboard.js
index 2132dac6b6..2146eb6613 100644
--- a/src/renderer/utils/music/kw/leaderboard.js
+++ b/src/renderer/utils/music/kw/leaderboard.js
@@ -106,6 +106,7 @@ export default {
})
},
filterData(rawList, rawList2) {
+ // console.log(rawList.length, rawList2.length)
return rawList.map((item, inedx) => {
let formats = item.formats.split('|')
let types = []
@@ -148,7 +149,7 @@ export default {
albumId: item.albumid,
songmid: item.id,
source: 'kw',
- interval: formatPlayTime(rawList2[inedx].duration),
+ interval: rawList2[inedx] && formatPlayTime(rawList2[inedx].duration),
img: item.pic,
lrc: null,
types,
diff --git a/src/renderer/utils/music/kw/lyric.js b/src/renderer/utils/music/kw/lyric.js
index 8ba752c0bf..b24bbc86b2 100644
--- a/src/renderer/utils/music/kw/lyric.js
+++ b/src/renderer/utils/music/kw/lyric.js
@@ -1,8 +1,6 @@
-import { httpGet, cancelHttp } from '../../request'
+import { httpFatch } from '../../request'
export default {
- _musicLrcRequestObj: null,
- _musicLrcPromiseCancelFn: null,
formatTime(time) {
let m = parseInt(time / 60)
let s = (time % 60).toFixed(2)
@@ -12,23 +10,10 @@ export default {
return `[ti:${songinfo.songName}]\n[ar:${songinfo.artist}]\n[al:${songinfo.album}]\n[by:]\n[offset:0]\n${lrclist ? lrclist.map(l => `[${this.formatTime(l.time)}]${l.lineLyric}\n`).join('') : '暂无歌词'}`
},
getLyric(songId) {
- if (this._musicLrcRequestObj != null) {
- cancelHttp(this._musicLrcRequestObj)
- this._musicLrcPromiseCancelFn(new Error('取消http请求'))
- }
- return new Promise((resolve, reject) => {
- this._musicLrcPromiseCancelFn = reject
- // this._musicLrcRequestObj = httpGet(`https://v1.itooi.cn/kuwo/lrc?id=${songId}`, (err, resp, body) => {
- this._musicLrcRequestObj = httpGet(`http://m.kuwo.cn/newh5/singles/songinfoandlrc?musicId=${songId}`, (err, resp, body) => {
- this._musicLrcRequestObj = null
- this._musicLrcPromiseCancelFn = null
- if (err) {
- console.log(err)
- reject(err)
- }
- // resolve(body)
- resolve(this.transformLrc(body.data))
- })
+ const requestObj = httpFatch(`http://m.kuwo.cn/newh5/singles/songinfoandlrc?musicId=${songId}`)
+ requestObj.promise = requestObj.promise.then(({ body }) => {
+ return this.transformLrc(body.data)
})
+ return requestObj
},
}
diff --git a/src/renderer/utils/music/tx/api-messoer.js b/src/renderer/utils/music/tx/api-messoer.js
new file mode 100644
index 0000000000..0b00f62977
--- /dev/null
+++ b/src/renderer/utils/music/tx/api-messoer.js
@@ -0,0 +1,21 @@
+import { httpFatch } from '../../request'
+
+const api_messoer = {
+ getMusicUrl(songInfo, type) {
+ const requestObj = httpFatch(`https://v1.itooi.cn/tencent/url?id=${songInfo.strMediaMid}&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(body.msg))
+ })
+ return requestObj
+ },
+ getPic(songInfo) {
+ return {
+ promise: Promise.resolve(`https://y.gtimg.cn/music/photo_new/T002R500x500M000${songInfo.albumId}.jpg`),
+ }
+ },
+}
+
+export default api_messoer
diff --git a/src/renderer/utils/music/tx/index.js b/src/renderer/utils/music/tx/index.js
index 62667f9ea9..54959c8f16 100644
--- a/src/renderer/utils/music/tx/index.js
+++ b/src/renderer/utils/music/tx/index.js
@@ -1,46 +1,19 @@
-import { httpGet, cancelHttp } from '../../request'
import leaderboard from './leaderboard'
import lyric from './lyric'
+import api_source from '../api-source'
const tx = {
leaderboard,
getMusicUrl(songInfo, type) {
- let requestObj
- let cancelFn
- const p = new Promise((resolve, reject) => {
- cancelFn = reject
- requestObj = httpGet(`https://v1.itooi.cn/tencent/url?id=${songInfo.strMediaMid}&quality=${type.replace(/k$/, '')}&isRedirect=0`, (err, resp, body) => {
- requestObj = null
- cancelFn = null
- if (err) {
- console.log(err)
- const { promise, cancelHttp } = this.getMusicUrl(songInfo, type)
- obj.cancelHttp = cancelHttp
- return promise
- }
- body.code === 200 ? resolve({ type, url: body.data }) : reject(new Error(body.msg))
- })
- })
- const obj = {
- promise: p,
- cancelHttp() {
- console.log('cancel')
- if (!requestObj) return
- cancelHttp(requestObj)
- cancelFn(new Error('取消http请求'))
- requestObj = null
- cancelFn = null
- },
- }
- return obj
+ return api_source('tx').getMusicUrl(songInfo, type)
},
getLyric(songInfo) {
// let singer = songInfo.singer.indexOf('、') > -1 ? songInfo.singer.split('、')[0] : songInfo.singer
return lyric.getLyric(songInfo.songmid)
},
getPic(songInfo) {
- return Promise.resolve(`https://y.gtimg.cn/music/photo_new/T002R500x500M000${songInfo.albumId}.jpg`)
+ return api_source('tx').getPic(songInfo)
},
}
diff --git a/src/renderer/utils/music/tx/lyric.js b/src/renderer/utils/music/tx/lyric.js
index 9af8ba4be9..a94cb1e32b 100644
--- a/src/renderer/utils/music/tx/lyric.js
+++ b/src/renderer/utils/music/tx/lyric.js
@@ -1,32 +1,19 @@
-import { httpGet, cancelHttp } from '../../request'
+import { httpFatch } from '../../request'
import { b64DecodeUnicode } from '../../index'
export default {
- _musicLrcRequestObj: null,
- _musicLrcPromiseCancelFn: null,
regexps: {
matchLrc: /.+"lyric":"([\w=+/]*)".+/,
},
getLyric(songmid) {
- if (this._musicLrcRequestObj != null) {
- cancelHttp(this._musicLrcRequestObj)
- this._musicLrcPromiseCancelFn(new Error('取消http请求'))
- }
- return new Promise((resolve, reject) => {
- this._musicLrcPromiseCancelFn = reject
- this._musicLrcRequestObj = httpGet(`https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg?songmid=${songmid}&g_tk=2001461048&loginUin=0&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8&platform=yqq`, {
- headers: {
- Referer: 'https://y.qq.com/portal/player.html',
- },
- }, (err, resp, body) => {
- this._musicLrcRequestObj = null
- this._musicLrcPromiseCancelFn = null
- if (err) {
- console.log(err)
- reject(err)
- }
- resolve(b64DecodeUnicode(body.replace(this.regexps.matchLrc, '$1')))
- })
+ const requestObj = httpFatch(`https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg?songmid=${songmid}&g_tk=2001461048&loginUin=0&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8&platform=yqq`, {
+ headers: {
+ Referer: 'https://y.qq.com/portal/player.html',
+ },
})
+ requestObj.promise = requestObj.promise.then(({ body }) => {
+ return b64DecodeUnicode(body.replace(this.regexps.matchLrc, '$1'))
+ })
+ return requestObj
},
}
diff --git a/src/renderer/utils/request.js b/src/renderer/utils/request.js
index 782dbb1037..c22d29d625 100644
--- a/src/renderer/utils/request.js
+++ b/src/renderer/utils/request.js
@@ -3,17 +3,26 @@ import request from 'request'
import { debugRequest } from './env'
// import fs from 'fs'
+const headers = {
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
+}
+
const fatchData = (url, method, options, callback) => {
+ console.log(url, options)
// console.log('---start---', url)
return request(url, {
method,
- headers: options.headers,
+ headers: Object.assign({}, headers, options.headers || {}),
Origin: options.origin,
data: options.data,
- // timeout: 5000,
+ timeout: options.timeout || 10000,
json: options.format === undefined || options.format === 'json',
}, (err, resp, body) => {
- if (err) return callback(err, null)
+ if (err) {
+ if (err.message === 'socket hang up') window.globalObj.apiSource = 'temp'
+ return callback(err, null)
+ }
+
// console.log('---end---', url)
callback(null, resp, body)
})
@@ -24,7 +33,7 @@ const fatchData = (url, method, options, callback) => {
* @param {*} url
* @param {*} options
*/
-export const httpFatch = (url, options = { method: 'get' }) => {
+const buildHttpPromose = (url, options) => {
let requestObj
let cancelFn
const p = new Promise((resolve, reject) => {
@@ -37,12 +46,13 @@ export const httpFatch = (url, options = { method: 'get' }) => {
requestObj = null
cancelFn = null
if (err) {
- console.log(err)
- if (err.code === 'ETIMEDOUT') {
+ console.log(err.code)
+ if (err.code === 'ETIMEDOUT' || err.code == 'ESOCKETTIMEDOUT') {
const { promise, cancelHttp } = httpFatch(url, options)
obj.cancelHttp = cancelHttp
- return promise
+ promise.then()
}
+ return reject(err)
}
resolve(resp)
})
@@ -61,6 +71,27 @@ export const httpFatch = (url, options = { method: 'get' }) => {
return obj
}
+/**
+ * 请求超时自动重试
+ * @param {*} url
+ * @param {*} options
+ */
+export const httpFatch = (url, options = { method: 'get' }) => {
+ const requestObj = buildHttpPromose(url, options)
+ requestObj.promise = requestObj.promise.catch(err => {
+ if (err.code === 'ETIMEDOUT' || err.code == 'ESOCKETTIMEDOUT') {
+ const { promise, cancelHttp } = httpFatch(url, options)
+ requestObj.cancelHttp()
+ requestObj.cancelHttp = cancelHttp
+ return promise
+ }
+ if (err.message === 'socket hang up') return Promise.reject(new Error('哦No😱...接口挂了!已帮你切换到临时接口,重试下看能不能播放吧~'))
+ if (err.code === 'ENOTFOUND') return Promise.reject(new Error('无法连接网络'))
+ return Promise.reject(err)
+ })
+ return requestObj
+}
+
/**
* 取消请求
* @param {*} index
diff --git a/src/renderer/views/Leaderboard.vue b/src/renderer/views/Leaderboard.vue
index 2690df87b3..9130097835 100644
--- a/src/renderer/views/Leaderboard.vue
+++ b/src/renderer/views/Leaderboard.vue
@@ -25,7 +25,7 @@
td.break(style="width: 20%;") {{item.singer}}
td.break(style="width: 25%;") {{item.albumName}}
td(style="width: 18%;")
- material-list-buttons(:index="index" :search-btn="true" :play-btn="item.source == 'kw'" :download-btn="item.source == 'kw'" :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="handleBtnClick")
//- 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)') +
@@ -59,6 +59,9 @@ export default {
types() {
return this.source ? this.sourceInfo.sourceList[this.source] : []
},
+ isAPITemp() {
+ return this.setting.apiSource == 'temp'
+ },
},
watch: {
tabId(n, o) {
@@ -94,7 +97,7 @@ export default {
this.clickIndex = index
return
}
- (this.source == 'kw') ? this.testPlay(index) : this.handleSearch(index)
+ (this.source == 'kw' || (!this.isAPITemp && this.source == 'tx')) ? this.testPlay(index) : this.handleSearch(index)
this.clickTime = 0
this.clickIndex = -1
},
diff --git a/src/renderer/views/List.vue b/src/renderer/views/List.vue
index 9ddb3b79e5..b06c5785b9 100644
--- a/src/renderer/views/List.vue
+++ b/src/renderer/views/List.vue
@@ -14,7 +14,8 @@
div.scroll(:class="$style.tbody")
table
tbody
- tr(v-for='(item, index) in list' :key='item.songmid' @click="handleDoubleClick(index)" :class="isPlayList && playIndex === index ? $style.active : ''")
+ 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 : '']")
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['192k']") 192K
@@ -61,6 +62,9 @@ export default {
? this.defaultList.list
: this.userList.find(l => l._id == this.$route.query.id) || []
},
+ isAPITemp() {
+ return this.setting.apiSource == 'temp'
+ },
},
// beforeRouteUpdate(to, from, next) {
// // if (to.query.id === undefined) return
@@ -105,6 +109,7 @@ export default {
this.clickIndex = -1
},
testPlay(index) {
+ if (this.isAPITemp && this.list[index].source != 'kw') return
this.setList({ list: this.list, listId: 'test', index })
},
handleRemove(index) {
@@ -178,6 +183,10 @@ export default {
}
}
+.disabled {
+ opacity: .5;
+}
+
each(@themes, {
:global(#container.@{value}) {
.tbody {
diff --git a/src/renderer/views/Search.vue b/src/renderer/views/Search.vue
index bb960e3d00..4f6bc07bc1 100644
--- a/src/renderer/views/Search.vue
+++ b/src/renderer/views/Search.vue
@@ -7,7 +7,8 @@
thead
tr
th.nobreak.center(style="width: 37px;")
- material-checkbox(id="search_select_all" v-model="isSelectAll" @change="handleSelectAllData" :indeterminate="isIndeterminate")
+ 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: 25%;") 专辑
diff --git a/src/renderer/views/Setting.vue b/src/renderer/views/Setting.vue
index 5c51d6e509..6280c9fa46 100644
--- a/src/renderer/views/Setting.vue
+++ b/src/renderer/views/Setting.vue
@@ -15,11 +15,17 @@ div.scroll(:class="$style.setting")
div
material-checkbox(id="setting_animate" v-model="current_setting.randomAnimate" label="是否启用")
+ dd(title='选择音乐来源')
+ h3 音乐来源
+ div
+ material-checkbox(v-for="item in apiSources" :id="`setting_api_source_${item.id}`" @change="handleAPISourceChange(item.id)" :class="$style.gapTop"
+ need v-model="current_setting.apiSource" :value="item.id" :label="item.label" :key="item.id")
+
dt 播放设置
dd(title="都不选时播放完当前歌曲就停止播放")
h3 歌曲切换方式
div
- material-checkbox(:id="`setting_player_togglePlay_${item.value}`" :class="$style.gap" :value="item.value" :key="item.value"
+ material-checkbox(:id="`setting_player_togglePlay_${item.value}`" :class="$style.gapLeft" :value="item.value" :key="item.value"
v-model="current_setting.player.togglePlayMethod" v-for="item in togglePlayMethods" :label="item.name")
dd(title='启用时将优先播放320K品质的歌曲')
h3 优先播放高品质音乐
@@ -37,7 +43,7 @@ div.scroll(:class="$style.setting")
dd(title='下载歌曲时的命名方式')
h3 文件命名方式
div
- material-checkbox(:id="`setting_download_musicName_${item.value}`" :class="$style.gap" name="setting_download_musicName" :value="item.value" :key="item.value" need
+ material-checkbox(:id="`setting_download_musicName_${item.value}`" :class="$style.gapLeft" name="setting_download_musicName" :value="item.value" :key="item.value" need
v-model="current_setting.download.fileName" v-for="item in musicNames" :label="item.name")
dt 列表设置
dd(title='播放列表是否显示专辑栏')
@@ -48,15 +54,15 @@ div.scroll(:class="$style.setting")
dd
h3 部分数据
div
- material-btn(:class="[$style.btn, $style.gap]" min @click="handleImportPlayList") 导入列表
- material-btn(:class="[$style.btn, $style.gap]" min @click="handleExportPlayList") 导出列表
- material-btn(:class="[$style.btn, $style.gap]" min @click="handleImportSetting") 导入设置
- material-btn(:class="[$style.btn, $style.gap]" min @click="handleExportSetting") 导出设置
+ material-btn(:class="[$style.btn, $style.gapLeft]" min @click="handleImportPlayList") 导入列表
+ material-btn(:class="[$style.btn, $style.gapLeft]" min @click="handleExportPlayList") 导出列表
+ material-btn(:class="[$style.btn, $style.gapLeft]" min @click="handleImportSetting") 导入设置
+ material-btn(:class="[$style.btn, $style.gapLeft]" min @click="handleExportSetting") 导出设置
dd
h3 所有数据(设置与试听列表)
div
- material-btn(:class="[$style.btn, $style.gap]" min @click="handleImportAllData") 导入
- material-btn(:class="[$style.btn, $style.gap]" min @click="handleExportAllData") 导出
+ material-btn(:class="[$style.btn, $style.gapLeft]" min @click="handleImportAllData") 导入
+ material-btn(:class="[$style.btn, $style.gapLeft]" min @click="handleExportAllData") 导出
dt 关于洛雪音乐
dd
p.small
@@ -113,6 +119,7 @@ export default {
themeId: 0,
sourceId: 0,
randomAnimate: true,
+ apiSource: 'messoer',
},
togglePlayMethods: [
{
@@ -132,6 +139,16 @@ export default {
value: 'singleLoop',
},
],
+ apiSources: [
+ {
+ id: 'messoer',
+ label: '由 messoer 提供的接口(推荐,软件的所有功能都可用)',
+ },
+ {
+ id: 'temp',
+ label: '临时接口(软件的某些功能将不可用,建议在messoer不可用时再切换到本选项)',
+ },
+ ],
musicNames: [
{
name: '歌名 - 歌手',
@@ -310,6 +327,11 @@ export default {
handleOpenUrl(url) {
openUrl(url)
},
+ handleAPISourceChange(id) {
+ this.$nextTick(() => {
+ window.globalObj.apiSource = id
+ })
+ },
},
}
@@ -357,11 +379,16 @@ export default {
}
-.gap {
- + .gap {
+.gap-left {
+ + .gap-left {
margin-left: 20px;
}
}
+.gap-top {
+ + .gap-top {
+ margin-top: 10px;
+ }
+}
.theme {
display: flex;