Compare commits

..

27 Commits

Author SHA1 Message Date
lyswhut
9d0bf50931 发布0.7.0版本 2019-10-07 22:22:32 +08:00
lyswhut
843e453b21 新增我的音乐列表歌曲源显示 2019-10-07 22:17:13 +08:00
lyswhut
f7546b0090 新增咪咕源搜索、歌单、排行榜 2019-10-07 21:51:16 +08:00
lyswhut
ed12aac7d8 新增QQ音乐源搜索及其128k试听 2019-10-07 13:07:16 +08:00
lyswhut
15f4053241 修复试听音乐时试听列表id传递错误的Bug 2019-10-07 01:35:20 +08:00
lyswhut
7a334f0099 新增缓存清理功能 2019-10-06 02:14:05 +08:00
lyswhut
4a510393ab 更新依赖到最新 2019-10-05 19:35:44 +08:00
lyswhut
52b0638258 修复strMediaMid获取错误 2019-10-05 16:10:40 +08:00
lyswhut
b198b1945d 尝试优化选我的音乐列表内容很多时多选的卡顿问题 2019-10-04 18:04:01 +08:00
lyswhut
10784e95bb 优化选择框动画效果 2019-10-04 10:13:26 +08:00
lyswhut
f4c65516d0 修复对多列表滚动条位置恢复的支持 2019-10-03 18:42:26 +08:00
lyswhut
6498305ec8 把我喜欢列表改名成我的收藏 2019-10-03 18:14:59 +08:00
lyswhut
7a91e6efef 完成我喜欢播放列表 2019-10-03 18:11:21 +08:00
lyswhut
4204b62f8f 重构列表功能,使其支持多列表,新增我喜欢列表 2019-10-03 02:00:31 +08:00
lyswhut
70b718d372 发布0.6.2版本 2019-10-01 16:36:44 +08:00
lyswhut
2b5d6f3592 移除static全局路径 2019-10-01 13:04:02 +08:00
lyswhut
8e48d5ba68 解除酷狗封面、歌词对接口服务器的依赖 2019-10-01 12:06:18 +08:00
lyswhut
3cec62d1a9 Merge branch 'openKg' into dev 2019-10-01 10:40:19 +08:00
lyswhut
b1650bcbee Merge branch 'master' into dev 2019-09-30 20:21:57 +08:00
lyswhut
492e3d8965 恢复酷狗其他音质播放 2019-09-30 20:20:28 +08:00
lyswhut
6d7be78b70 开放腾讯源128k音源直接播放 2019-09-30 15:24:00 +08:00
lyswhut
bac9439f8e 新增QQ音乐源搜索 2019-09-30 14:49:27 +08:00
lyswhut
5b612bfa0f 修复百度源搜索结果为空时的接口处理Bug 2019-09-30 13:14:55 +08:00
lyswhut
1f77b3dd4b 新增QQ音乐源歌单 2019-09-30 13:04:35 +08:00
lyswhut
b0d7a53d15 Update issue templates 2019-09-29 17:09:36 +08:00
lyswhut
c029eccdd3 修复当试听列表为空时,无法切到其他界面的Bug 2019-09-29 15:48:47 +08:00
lyswhut
7236f8929c 修正火影皮肤名字 2019-09-28 17:17:35 +08:00
53 changed files with 2119 additions and 380 deletions

17
.github/ISSUE_TEMPLATE/----.md vendored Normal file
View File

@@ -0,0 +1,17 @@
---
name: 功能请求
about: 为这个项目提出一个想法
title: 例如添加xxx功能、优化xxx功能
labels: ''
assignees: ''
---
**描述您想要的解决方案**
简洁明了地描述您要发生的事情。
**描述您考虑过的替代方案**
对您考虑过的所有替代解决方案或功能的简洁明了的描述。
**其他内容**
在此处添加有关功能请求的任何其他上下文或屏幕截图。

31
.github/ISSUE_TEMPLATE/--bug.md vendored Normal file
View File

@@ -0,0 +1,31 @@
---
name: 报告Bug
about: 创建报告以帮助我们改进
title: 例如:音乐无法播放
labels: ''
assignees: ''
---
**描述错误**
清楚简洁地说明错误是什么。
**重现**
重现行为的步骤:
1.转到“ ...”
2.点击“ ....”
3.向下滚动到“ ....”
4.看到错误
**预期行为**
对您期望发生的事情的简洁明了的描述。
**截图**
如果适用,请添加屏幕截图以帮助解释您的问题。
**环境:**
  -操作系统及版本:[例如Windows 10 64位 18362.156]
  -软件安装包及版本:[例如Windows 64位绿色版 1.0.0]
**其他内容**
在此处添加有关该问题的任何其他上下文。

View File

@@ -6,6 +6,43 @@ 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.7.0](https://github.com/lyswhut/lx-music-desktop/compare/v0.6.2...v0.7.0) - 2019-10-07
#### 新增
- 新增“我的收藏”本地播放列表
- 新增缓存清理功能,可到**设置-其他**查看与清理软件缓存
- 新增QQ音乐源搜索
- 新增咪咕源搜索
- 新增咪咕源歌单
- 新增咪咕源排行榜
- 新增我的音乐列表歌曲源显示,默认关闭,可到**设置-列表设置**开启
#### 优化
- 优化选择框动画效果
- 尝试优化选我的音乐列表内容很多时多选的卡顿问题
#### 修复
- 修复列表延迟显示的Bug
- 修复QQ音源128k音质试听
## [0.6.2](https://github.com/lyswhut/lx-music-desktop/compare/v0.6.1...v0.6.2) - 2019-10-01
祝贺祖国成立70周年~
#### 新增
- 新增QQ音乐源歌单
#### 修复
- 修正火影皮肤名字
- 修复当试听列表为空时无法切到其他界面的Bug
- 修复百度源搜索结果为空时的接口处理Bug
- 恢复**酷狗**其他音质播放
## [0.6.1](https://github.com/lyswhut/lx-music-desktop/compare/v0.6.0...v0.6.1) - 2019-09-28
### 新增

334
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "lx-music-desktop",
"version": "0.6.0",
"version": "0.6.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -93,7 +93,7 @@
},
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz",
"resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-4.1.1.tgz",
"integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=",
"dev": true,
"requires": {
@@ -1315,9 +1315,9 @@
}
},
"acorn": {
"version": "7.0.0",
"resolved": "https://registry.npm.taobao.org/acorn/download/acorn-7.0.0.tgz",
"integrity": "sha1-JrjRzZqbcANQtxwJBVRvZNEoTno=",
"version": "7.1.0",
"resolved": "https://registry.npm.taobao.org/acorn/download/acorn-7.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Facorn%2Fdownload%2Facorn-7.1.0.tgz",
"integrity": "sha1-lJ028sKSU12mAig1hsJHfFfrLWw=",
"dev": true
},
"acorn-globals": {
@@ -1694,24 +1694,73 @@
"dev": true
},
"autoprefixer": {
"version": "9.6.1",
"resolved": "https://registry.npm.taobao.org/autoprefixer/download/autoprefixer-9.6.1.tgz",
"integrity": "sha1-UZZ6AtLSMAuwGGbBYR7INI01Wkc=",
"version": "9.6.4",
"resolved": "https://registry.npm.taobao.org/autoprefixer/download/autoprefixer-9.6.4.tgz?cache=0&sync_timestamp=1570294713985&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fautoprefixer%2Fdownload%2Fautoprefixer-9.6.4.tgz",
"integrity": "sha1-5kU75HrzFrKSPq6u2Hhg9SrUt+s=",
"dev": true,
"requires": {
"browserslist": "^4.6.3",
"caniuse-lite": "^1.0.30000980",
"browserslist": "^4.7.0",
"caniuse-lite": "^1.0.30000998",
"chalk": "^2.4.2",
"normalize-range": "^0.1.2",
"num2fraction": "^1.2.2",
"postcss": "^7.0.17",
"postcss-value-parser": "^4.0.0"
"postcss": "^7.0.18",
"postcss-value-parser": "^4.0.2"
},
"dependencies": {
"browserslist": {
"version": "4.7.0",
"resolved": "https://registry.npm.taobao.org/browserslist/download/browserslist-4.7.0.tgz?cache=0&sync_timestamp=1567245449635&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbrowserslist%2Fdownload%2Fbrowserslist-4.7.0.tgz",
"integrity": "sha1-nuiSJf/AfbA0CfL+5STcgidFihc=",
"dev": true,
"requires": {
"caniuse-lite": "^1.0.30000989",
"electron-to-chromium": "^1.3.247",
"node-releases": "^1.1.29"
}
},
"caniuse-lite": {
"version": "1.0.30000999",
"resolved": "https://registry.npm.taobao.org/caniuse-lite/download/caniuse-lite-1.0.30000999.tgz",
"integrity": "sha1-QnJTpprXvqSqjYNFaHuO7FHKDkM=",
"dev": true
},
"electron-to-chromium": {
"version": "1.3.275",
"resolved": "https://registry.npm.taobao.org/electron-to-chromium/download/electron-to-chromium-1.3.275.tgz",
"integrity": "sha1-GaOENuNCFvUYIPovQybVzhQfo28=",
"dev": true
},
"node-releases": {
"version": "1.1.34",
"resolved": "https://registry.npm.taobao.org/node-releases/download/node-releases-1.1.34.tgz",
"integrity": "sha1-ztRlXuG6nDosXcusOF4ZQ0FV/UA=",
"dev": true,
"requires": {
"semver": "^6.3.0"
}
},
"postcss": {
"version": "7.0.18",
"resolved": "https://registry.npm.taobao.org/postcss/download/postcss-7.0.18.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss%2Fdownload%2Fpostcss-7.0.18.tgz",
"integrity": "sha1-S5zala5sBpxnpNkzAp7d1IOKwjM=",
"dev": true,
"requires": {
"chalk": "^2.4.2",
"source-map": "^0.6.1",
"supports-color": "^6.1.0"
}
},
"postcss-value-parser": {
"version": "4.0.0",
"resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-4.0.0.tgz",
"integrity": "sha1-mamD02X3sq2ND5uMMJSSbqtLk20=",
"version": "4.0.2",
"resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-4.0.2.tgz?cache=0&sync_timestamp=1565203765685&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-value-parser%2Fdownload%2Fpostcss-value-parser-4.0.2.tgz",
"integrity": "sha1-SCKCwJpCcG0fyaBptz9E7Ag5Hck=",
"dev": true
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npm.taobao.org/semver/download/semver-6.3.0.tgz?cache=0&sync_timestamp=1565627380363&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-6.3.0.tgz",
"integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=",
"dev": true
}
}
@@ -2894,7 +2943,7 @@
},
"buffer": {
"version": "4.9.1",
"resolved": "https://registry.npm.taobao.org/buffer/download/buffer-4.9.1.tgz",
"resolved": "https://registry.npm.taobao.org/buffer/download/buffer-4.9.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbuffer%2Fdownload%2Fbuffer-4.9.1.tgz",
"integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
"dev": true,
"requires": {
@@ -3954,7 +4003,7 @@
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npm.taobao.org/semver/download/semver-6.3.0.tgz?cache=0&sync_timestamp=1565627380363&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-6.3.0.tgz",
"resolved": "https://registry.npm.taobao.org/semver/download/semver-6.3.0.tgz",
"integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=",
"dev": true
}
@@ -4064,9 +4113,9 @@
}
},
"cross-env": {
"version": "6.0.0",
"resolved": "https://registry.npm.taobao.org/cross-env/download/cross-env-6.0.0.tgz",
"integrity": "sha1-PI5xRA6iCqb6r1rsVBI178Vl2sY=",
"version": "6.0.3",
"resolved": "https://registry.npm.taobao.org/cross-env/download/cross-env-6.0.3.tgz?cache=0&sync_timestamp=1570033768127&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcross-env%2Fdownload%2Fcross-env-6.0.3.tgz",
"integrity": "sha1-Qla3HkmzpAY3oM5wdopu9ccq6UE=",
"dev": true,
"requires": {
"cross-spawn": "^7.0.0"
@@ -4816,9 +4865,9 @@
"dev": true
},
"electron": {
"version": "6.0.10",
"resolved": "https://registry.npm.taobao.org/electron/download/electron-6.0.10.tgz",
"integrity": "sha1-NGhUdkDJjtRgYHEcpw9D0LLkCBg=",
"version": "6.0.11",
"resolved": "https://registry.npm.taobao.org/electron/download/electron-6.0.11.tgz",
"integrity": "sha1-ZO/6cTlwRXeaHdv1ExKkHM8m9JE=",
"dev": true,
"requires": {
"@types/node": "^10.12.18",
@@ -5203,9 +5252,9 @@
"dev": true
},
"eslint": {
"version": "6.4.0",
"resolved": "https://registry.npm.taobao.org/eslint/download/eslint-6.4.0.tgz",
"integrity": "sha1-WqkifD++khmCsu2pS6DX+uhYYRo=",
"version": "6.5.1",
"resolved": "https://registry.npm.taobao.org/eslint/download/eslint-6.5.1.tgz",
"integrity": "sha1-go5MRpaX1Du1hhRL4VIZi5HpbtY=",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
@@ -5284,9 +5333,9 @@
}
},
"glob-parent": {
"version": "5.0.0",
"resolved": "https://registry.npm.taobao.org/glob-parent/download/glob-parent-5.0.0.tgz",
"integrity": "sha1-HcmfDzmwBtPpLCwoQGg4Lwwg6VQ=",
"version": "5.1.0",
"resolved": "https://registry.npm.taobao.org/glob-parent/download/glob-parent-5.1.0.tgz?cache=0&sync_timestamp=1569108917227&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglob-parent%2Fdownload%2Fglob-parent-5.1.0.tgz",
"integrity": "sha1-X0wdHnSNMM1zrSlEs1d6gbCB6MI=",
"dev": true,
"requires": {
"is-glob": "^4.0.1"
@@ -5374,21 +5423,22 @@
}
},
"eslint-loader": {
"version": "3.0.0",
"resolved": "https://registry.npm.taobao.org/eslint-loader/download/eslint-loader-3.0.0.tgz",
"integrity": "sha1-+3C8LVUqZ09D8H9eZXUIPlZeeQ0=",
"version": "3.0.2",
"resolved": "https://registry.npm.taobao.org/eslint-loader/download/eslint-loader-3.0.2.tgz",
"integrity": "sha1-WmJzFqUdb0HTV7n28FVOkVBs3W4=",
"dev": true,
"requires": {
"fs-extra": "^8.1.0",
"loader-fs-cache": "^1.0.2",
"loader-utils": "^1.2.3",
"object-hash": "^1.3.1",
"schema-utils": "^2.1.0"
"schema-utils": "^2.2.0"
},
"dependencies": {
"schema-utils": {
"version": "2.2.0",
"resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-2.2.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fschema-utils%2Fdownload%2Fschema-utils-2.2.0.tgz",
"integrity": "sha1-SKBlziGeDKz0YxRzFZA3ssGugto=",
"version": "2.4.1",
"resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-2.4.1.tgz?cache=0&sync_timestamp=1569583621807&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fschema-utils%2Fdownload%2Fschema-utils-2.4.1.tgz",
"integrity": "sha1-6JreXQVtyLyso3dXS7SpxOG4vlY=",
"dev": true,
"requires": {
"ajv": "^6.10.2",
@@ -6464,6 +6514,15 @@
"universalify": "^0.1.0"
}
},
"fs-minipass": {
"version": "2.0.0",
"resolved": "https://registry.npm.taobao.org/fs-minipass/download/fs-minipass-2.0.0.tgz",
"integrity": "sha1-pkFe2rAvrkuekjC8h+4uRHIAPNE=",
"dev": true,
"requires": {
"minipass": "^3.0.0"
}
},
"fs-write-stream-atomic": {
"version": "1.0.10",
"resolved": "https://registry.npm.taobao.org/fs-write-stream-atomic/download/fs-write-stream-atomic-1.0.10.tgz",
@@ -9217,6 +9276,50 @@
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true
},
"minipass": {
"version": "3.0.1",
"resolved": "https://registry.npm.taobao.org/minipass/download/minipass-3.0.1.tgz",
"integrity": "sha1-tP7HO9YeikDws3Td0EJgreLI7CA=",
"dev": true,
"requires": {
"yallist": "^4.0.0"
},
"dependencies": {
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npm.taobao.org/yallist/download/yallist-4.0.0.tgz",
"integrity": "sha1-m7knkNnA7/7GO+c1GeEaNQGaOnI=",
"dev": true
}
}
},
"minipass-collect": {
"version": "1.0.2",
"resolved": "https://registry.npm.taobao.org/minipass-collect/download/minipass-collect-1.0.2.tgz",
"integrity": "sha1-IrgTv3Rdxu26JXa5QAIq1u3Ixhc=",
"dev": true,
"requires": {
"minipass": "^3.0.0"
}
},
"minipass-flush": {
"version": "1.0.5",
"resolved": "https://registry.npm.taobao.org/minipass-flush/download/minipass-flush-1.0.5.tgz",
"integrity": "sha1-gucTXX6JpQ/+ZGEKeHlTxMTLs3M=",
"dev": true,
"requires": {
"minipass": "^3.0.0"
}
},
"minipass-pipeline": {
"version": "1.2.2",
"resolved": "https://registry.npm.taobao.org/minipass-pipeline/download/minipass-pipeline-1.2.2.tgz",
"integrity": "sha1-PctrtKVG4ylpx61xDyx5qGq7qTo=",
"dev": true,
"requires": {
"minipass": "^3.0.0"
}
},
"mississippi": {
"version": "3.0.0",
"resolved": "https://registry.npm.taobao.org/mississippi/download/mississippi-3.0.0.tgz",
@@ -9448,9 +9551,9 @@
"integrity": "sha1-bt5ymVH45yl/HlbkHDgrH7DSPw0="
},
"node-forge": {
"version": "0.8.2",
"resolved": "https://registry.npm.taobao.org/node-forge/download/node-forge-0.8.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-forge%2Fdownload%2Fnode-forge-0.8.2.tgz",
"integrity": "sha1-tLzFn7Es53qIJfxqeD3+MYJJnFo=",
"version": "0.9.0",
"resolved": "https://registry.npm.taobao.org/node-forge/download/node-forge-0.9.0.tgz?cache=0&sync_timestamp=1569524876130&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-forge%2Fdownload%2Fnode-forge-0.9.0.tgz",
"integrity": "sha1-1iQFDtu0SHStyhK7mlLsY8t4JXk=",
"dev": true
},
"node-id3": {
@@ -9870,10 +9973,13 @@
}
},
"p-map": {
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/p-map/download/p-map-2.1.0.tgz?cache=0&sync_timestamp=1563032875018&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-map%2Fdownload%2Fp-map-2.1.0.tgz",
"integrity": "sha1-MQko/u+cnsxltosXaTAYpmXOoXU=",
"dev": true
"version": "3.0.0",
"resolved": "https://registry.npm.taobao.org/p-map/download/p-map-3.0.0.tgz?cache=0&sync_timestamp=1563032875018&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-map%2Fdownload%2Fp-map-3.0.0.tgz",
"integrity": "sha1-1wTZr4orpoTiYA2aIVmD1BQal50=",
"dev": true,
"requires": {
"aggregate-error": "^3.0.0"
}
},
"p-retry": {
"version": "3.0.1",
@@ -11706,12 +11812,12 @@
"dev": true
},
"selfsigned": {
"version": "1.10.6",
"resolved": "https://registry.npm.taobao.org/selfsigned/download/selfsigned-1.10.6.tgz",
"integrity": "sha1-ezzTftnCA0JhoXOvGhquJ9gWm2c=",
"version": "1.10.7",
"resolved": "https://registry.npm.taobao.org/selfsigned/download/selfsigned-1.10.7.tgz",
"integrity": "sha1-2lgZ/QSdVXTyjoipvMbbxubzkGs=",
"dev": true,
"requires": {
"node-forge": "0.8.2"
"node-forge": "0.9.0"
}
},
"semver": {
@@ -12824,44 +12930,53 @@
}
},
"terser-webpack-plugin": {
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/terser-webpack-plugin/download/terser-webpack-plugin-2.1.0.tgz",
"integrity": "sha1-uc7nmaLaK854hUDDc44IG22yjYo=",
"version": "2.1.2",
"resolved": "https://registry.npm.taobao.org/terser-webpack-plugin/download/terser-webpack-plugin-2.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fterser-webpack-plugin%2Fdownload%2Fterser-webpack-plugin-2.1.2.tgz",
"integrity": "sha1-K5uBR6bxiRg0ggCADPlWDFD3Abs=",
"dev": true,
"requires": {
"cacache": "^12.0.3",
"cacache": "^13.0.0",
"find-cache-dir": "^3.0.0",
"jest-worker": "^24.9.0",
"schema-utils": "^2.2.0",
"schema-utils": "^2.4.1",
"serialize-javascript": "^2.1.0",
"source-map": "^0.6.1",
"terser": "^4.3.1",
"terser": "^4.3.4",
"webpack-sources": "^1.4.3"
},
"dependencies": {
"cacache": {
"version": "12.0.3",
"resolved": "https://registry.npm.taobao.org/cacache/download/cacache-12.0.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcacache%2Fdownload%2Fcacache-12.0.3.tgz",
"integrity": "sha1-vpmruk4b9d9GHNWiwQcfxDJXM5A=",
"version": "13.0.1",
"resolved": "https://registry.npm.taobao.org/cacache/download/cacache-13.0.1.tgz",
"integrity": "sha1-qAAMIWlwiQgvhSh6GuxuOCAkpxw=",
"dev": true,
"requires": {
"bluebird": "^3.5.5",
"chownr": "^1.1.1",
"chownr": "^1.1.2",
"figgy-pudding": "^3.5.1",
"fs-minipass": "^2.0.0",
"glob": "^7.1.4",
"graceful-fs": "^4.1.15",
"infer-owner": "^1.0.3",
"graceful-fs": "^4.2.2",
"infer-owner": "^1.0.4",
"lru-cache": "^5.1.1",
"mississippi": "^3.0.0",
"minipass": "^3.0.0",
"minipass-collect": "^1.0.2",
"minipass-flush": "^1.0.5",
"minipass-pipeline": "^1.2.2",
"mkdirp": "^0.5.1",
"move-concurrently": "^1.0.1",
"p-map": "^3.0.0",
"promise-inflight": "^1.0.1",
"rimraf": "^2.6.3",
"ssri": "^6.0.1",
"unique-filename": "^1.1.1",
"y18n": "^4.0.0"
"rimraf": "^2.7.1",
"ssri": "^7.0.0",
"unique-filename": "^1.1.1"
}
},
"commander": {
"version": "2.20.1",
"resolved": "https://registry.npm.taobao.org/commander/download/commander-2.20.1.tgz",
"integrity": "sha1-OGPOPKktCDHc8qEC9ftLWSav0Pk=",
"dev": true
},
"find-cache-dir": {
"version": "3.0.0",
"resolved": "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-3.0.0.tgz",
@@ -12883,6 +12998,12 @@
"path-exists": "^4.0.0"
}
},
"graceful-fs": {
"version": "4.2.2",
"resolved": "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.2.2.tgz",
"integrity": "sha1-bwlSYF0BQMHP2xOO0AV3W5LWewI=",
"dev": true
},
"locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-5.0.0.tgz",
@@ -12944,9 +13065,9 @@
}
},
"schema-utils": {
"version": "2.2.0",
"resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-2.2.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fschema-utils%2Fdownload%2Fschema-utils-2.2.0.tgz",
"integrity": "sha1-SKBlziGeDKz0YxRzFZA3ssGugto=",
"version": "2.4.1",
"resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-2.4.1.tgz?cache=0&sync_timestamp=1569583621807&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fschema-utils%2Fdownload%2Fschema-utils-2.4.1.tgz",
"integrity": "sha1-6JreXQVtyLyso3dXS7SpxOG4vlY=",
"dev": true,
"requires": {
"ajv": "^6.10.2",
@@ -12965,6 +13086,27 @@
"integrity": "sha1-kxAnaBnv0OsSgli7NBlX9usvxXA=",
"dev": true
},
"ssri": {
"version": "7.0.1",
"resolved": "https://registry.npm.taobao.org/ssri/download/ssri-7.0.1.tgz?cache=0&sync_timestamp=1569877716166&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fssri%2Fdownload%2Fssri-7.0.1.tgz",
"integrity": "sha1-sMq3u7EayeoH8ANFPiAR+MvtnzQ=",
"dev": true,
"requires": {
"figgy-pudding": "^3.5.1",
"minipass": "^3.0.0"
}
},
"terser": {
"version": "4.3.6",
"resolved": "https://registry.npm.taobao.org/terser/download/terser-4.3.6.tgz",
"integrity": "sha1-OjauGX1EcOEQaVV7SkvXEvhPmY0=",
"dev": true,
"requires": {
"commander": "^2.20.0",
"source-map": "~0.6.1",
"source-map-support": "~0.5.12"
}
},
"webpack-sources": {
"version": "1.4.3",
"resolved": "https://registry.npm.taobao.org/webpack-sources/download/webpack-sources-1.4.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-sources%2Fdownload%2Fwebpack-sources-1.4.3.tgz",
@@ -13453,24 +13595,24 @@
}
},
"url-loader": {
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/url-loader/download/url-loader-2.1.0.tgz",
"integrity": "sha1-vMHsq70ZfpE+yiP14DeOJLRBKWE=",
"version": "2.2.0",
"resolved": "https://registry.npm.taobao.org/url-loader/download/url-loader-2.2.0.tgz",
"integrity": "sha1-rzIa7OH9DWg63Iqusngp8px1tG4=",
"dev": true,
"requires": {
"loader-utils": "^1.2.3",
"mime": "^2.4.4",
"schema-utils": "^2.0.0"
"schema-utils": "^2.4.1"
},
"dependencies": {
"schema-utils": {
"version": "2.0.1",
"resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-2.0.1.tgz",
"integrity": "sha1-HuwuBZVWr4QbfzqDthrxPXo/kZY=",
"version": "2.4.1",
"resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-2.4.1.tgz?cache=0&sync_timestamp=1569583621807&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fschema-utils%2Fdownload%2Fschema-utils-2.4.1.tgz",
"integrity": "sha1-6JreXQVtyLyso3dXS7SpxOG4vlY=",
"dev": true,
"requires": {
"ajv": "^6.1.0",
"ajv-keywords": "^3.1.0"
"ajv": "^6.10.2",
"ajv-keywords": "^3.4.1"
}
}
}
@@ -13814,7 +13956,7 @@
"dependencies": {
"acorn": {
"version": "6.3.0",
"resolved": "https://registry.npm.taobao.org/acorn/download/acorn-6.3.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Facorn%2Fdownload%2Facorn-6.3.0.tgz",
"resolved": "https://registry.npm.taobao.org/acorn/download/acorn-6.3.0.tgz",
"integrity": "sha1-AIdQkRn/pPwKAEHR6TpBfmjLhW4=",
"dev": true
},
@@ -13871,7 +14013,7 @@
},
"terser-webpack-plugin": {
"version": "1.4.1",
"resolved": "https://registry.npm.taobao.org/terser-webpack-plugin/download/terser-webpack-plugin-1.4.1.tgz",
"resolved": "https://registry.npm.taobao.org/terser-webpack-plugin/download/terser-webpack-plugin-1.4.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fterser-webpack-plugin%2Fdownload%2Fterser-webpack-plugin-1.4.1.tgz",
"integrity": "sha1-YbGOQOruW+l+dxzbsQ7RKAiIwrQ=",
"dev": true,
"requires": {
@@ -13888,7 +14030,7 @@
},
"webpack-sources": {
"version": "1.4.3",
"resolved": "https://registry.npm.taobao.org/webpack-sources/download/webpack-sources-1.4.3.tgz?cache=0&sync_timestamp=1568302837530&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-sources%2Fdownload%2Fwebpack-sources-1.4.3.tgz",
"resolved": "https://registry.npm.taobao.org/webpack-sources/download/webpack-sources-1.4.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-sources%2Fdownload%2Fwebpack-sources-1.4.3.tgz",
"integrity": "sha1-7t2OwLko+/HL/plOItLYkPMwqTM=",
"dev": true,
"requires": {
@@ -13939,9 +14081,9 @@
}
},
"webpack-dev-middleware": {
"version": "3.7.1",
"resolved": "https://registry.npm.taobao.org/webpack-dev-middleware/download/webpack-dev-middleware-3.7.1.tgz",
"integrity": "sha1-EWeuoCr6A0SJhpuDaP6f7RrqfQk=",
"version": "3.7.2",
"resolved": "https://registry.npm.taobao.org/webpack-dev-middleware/download/webpack-dev-middleware-3.7.2.tgz",
"integrity": "sha1-ABnD23FuP6XOy/ZPKriKdLqzMfM=",
"dev": true,
"requires": {
"memory-fs": "^0.4.1",
@@ -13952,9 +14094,9 @@
}
},
"webpack-dev-server": {
"version": "3.8.1",
"resolved": "https://registry.npm.taobao.org/webpack-dev-server/download/webpack-dev-server-3.8.1.tgz?cache=0&sync_timestamp=1568642918966&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-dev-server%2Fdownload%2Fwebpack-dev-server-3.8.1.tgz",
"integrity": "sha1-SFtkxKrcI/YB5yEUtAwbH+ox2fE=",
"version": "3.8.2",
"resolved": "https://registry.npm.taobao.org/webpack-dev-server/download/webpack-dev-server-3.8.2.tgz",
"integrity": "sha1-MpJCe/ZRDamjrC1QC5JKQZdmf/k=",
"dev": true,
"requires": {
"ansi-html": "0.0.7",
@@ -13966,18 +14108,18 @@
"del": "^4.1.1",
"express": "^4.17.1",
"html-entities": "^1.2.1",
"http-proxy-middleware": "^0.19.1",
"http-proxy-middleware": "0.19.1",
"import-local": "^2.0.0",
"internal-ip": "^4.3.0",
"ip": "^1.1.5",
"is-absolute-url": "^3.0.2",
"is-absolute-url": "^3.0.3",
"killable": "^1.0.1",
"loglevel": "^1.6.4",
"opn": "^5.5.0",
"p-retry": "^3.0.1",
"portfinder": "^1.0.24",
"schema-utils": "^1.0.0",
"selfsigned": "^1.10.6",
"selfsigned": "^1.10.7",
"semver": "^6.3.0",
"serve-index": "^1.9.1",
"sockjs": "0.3.19",
@@ -13986,7 +14128,7 @@
"strip-ansi": "^3.0.1",
"supports-color": "^6.1.0",
"url": "^0.11.0",
"webpack-dev-middleware": "^3.7.1",
"webpack-dev-middleware": "^3.7.2",
"webpack-log": "^2.0.0",
"ws": "^6.2.1",
"yargs": "12.0.5"
@@ -14072,9 +14214,9 @@
}
},
"is-absolute-url": {
"version": "3.0.2",
"resolved": "https://registry.npm.taobao.org/is-absolute-url/download/is-absolute-url-3.0.2.tgz?cache=0&sync_timestamp=1568347933983&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-absolute-url%2Fdownload%2Fis-absolute-url-3.0.2.tgz",
"integrity": "sha1-VU8pM+c4XMRulDUZd8oggRcKIG4=",
"version": "3.0.3",
"resolved": "https://registry.npm.taobao.org/is-absolute-url/download/is-absolute-url-3.0.3.tgz?cache=0&sync_timestamp=1569736493122&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-absolute-url%2Fdownload%2Fis-absolute-url-3.0.3.tgz",
"integrity": "sha1-lsaiK2ojkpsR6gr7GDbDatSl1pg=",
"dev": true
},
"ms": {
@@ -14083,6 +14225,12 @@
"integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=",
"dev": true
},
"p-map": {
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/p-map/download/p-map-2.1.0.tgz?cache=0&sync_timestamp=1563032875018&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-map%2Fdownload%2Fp-map-2.1.0.tgz",
"integrity": "sha1-MQko/u+cnsxltosXaTAYpmXOoXU=",
"dev": true
},
"pify": {
"version": "4.0.1",
"resolved": "https://registry.npm.taobao.org/pify/download/pify-4.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpify%2Fdownload%2Fpify-4.0.1.tgz",

View File

@@ -1,6 +1,6 @@
{
"name": "lx-music-desktop",
"version": "0.6.1",
"version": "0.7.0",
"description": "一个免费的音乐下载助手",
"main": "./dist/electron/main.js",
"productName": "lx-music-desktop",
@@ -138,7 +138,7 @@
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/polyfill": "^7.6.0",
"@babel/preset-env": "^7.6.2",
"autoprefixer": "^9.6.1",
"autoprefixer": "^9.6.4",
"babel-eslint": "^10.0.3",
"babel-loader": "^8.0.6",
"babel-minify-webpack-plugin": "^0.3.1",
@@ -149,17 +149,17 @@
"copy-webpack-plugin": "^5.0.4",
"core-js": "^3.2.1",
"cos-nodejs-sdk-v5": "^2.5.12",
"cross-env": "^6.0.0",
"cross-env": "^6.0.3",
"css-loader": "^3.2.0",
"del": "^5.1.0",
"electron": "^6.0.10",
"electron": "^6.0.11",
"electron-builder": "^21.2.0",
"electron-debug": "^3.0.1",
"electron-devtools-installer": "^2.2.4",
"eslint": "^6.4.0",
"eslint": "^6.5.1",
"eslint-config-standard": "^14.1.0",
"eslint-formatter-friendly": "^7.0.0",
"eslint-loader": "^3.0.0",
"eslint-loader": "^3.0.2",
"eslint-plugin-html": "^6.0.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-node": "^10.0.0",
@@ -182,14 +182,14 @@
"rimraf": "^3.0.0",
"stylus": "^0.54.7",
"stylus-loader": "^3.0.2",
"terser-webpack-plugin": "^2.1.0",
"url-loader": "^2.1.0",
"terser-webpack-plugin": "^2.1.2",
"url-loader": "^2.2.0",
"vue-loader": "^15.7.1",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.6.10",
"webpack": "^4.41.0",
"webpack-cli": "^3.3.9",
"webpack-dev-server": "^3.8.1",
"webpack-dev-server": "^3.8.2",
"webpack-hot-middleware": "^2.25.0",
"webpack-merge": "^4.2.2"
},

View File

@@ -1,21 +1,19 @@
### 新增
#### 新增
- 新增试听列表**滚动条位置恢复**设置(可自动恢复到上次离开时的列表滚动位置),本功能默认开启,若不需要可到设置-列表设置将其关闭
- 新增 **《海贼王》** 皮肤,喜欢个性化的可以试试~
- 新增“我的收藏”本地播放列表
- 新增缓存清理功能,可到**设置-其他**查看与清理软件缓存
- 新增QQ音乐源搜索
- 新增咪咕源搜索
- 新增咪咕源歌单
- 新增咪咕源排行榜
- 新增我的音乐列表歌曲源显示,默认关闭,可到**设置-列表设置**开启
### 优化
#### 优化
- 新增DNS解析缓存加快请求速度
- 优化代码逻辑,减少软件对系统资源的占用
- 优化新版本信息检测,尽量减少弹出版本获取失败弹窗弹出的概率
- 优化下拉列表动画效果
- 优化选择框动画效果
- 尝试优化选我的音乐列表内容很多时多选的卡顿问题
### 修复
#### 修复
- 修复请求超时的逻辑处理Bug尝试修复请求无法取消导致的正在播放的歌曲与界面显示的信息不一致的问题
- 修复其他一些小Bug
### 移除
- 移除 `192k` 音质
- 移除酷我音源 `ape` 音质,无损推荐 `flac` 格式
- 修复列表延迟显示的Bug
- 修复QQ音源128k音质试听

View File

@@ -1,7 +1,15 @@
{
"version": "0.6.1",
"desc": "<h3>新增</h3>\n<ul>\n<li>新增试听列表<strong>滚动条位置恢复</strong>设置(可自动恢复到上次离开时的列表滚动位置),本功能默认开启,若不需要可到设置-列表设置将其关闭</li>\n<li>新增 <strong>《海贼王》</strong> 皮肤,喜欢个性化的可以试试~</li>\n</ul>\n<h3>优化</h3>\n<ul>\n<li>新增DNS解析缓存加快请求速度</li>\n<li>优化代码逻辑,减少软件对系统资源的占用</li>\n<li>优化新版本信息检测,尽量减少弹出版本获取失败弹窗弹出的概率</li>\n<li>优化下拉列表动画效果</li>\n</ul>\n<h3>修复</h3>\n<ul>\n<li>修复请求超时的逻辑处理Bug尝试修复请求无法取消导致的正在播放的歌曲与界面显示的信息不一致的问题</li>\n<li>修复其他一些小Bug</li>\n</ul>\n<h3>移除</h3>\n<ul>\n<li>移除 <code>192k</code> 音质</li>\n<li>移除酷我音源 <code>ape</code> 音质,无损推荐 <code>flac</code> 格式</li>\n</ul>\n",
"version": "0.7.0",
"desc": "<h4>新增</h4>\n<ul>\n<li>新增“我的收藏”本地播放列表</li>\n<li>新增缓存清理功能,可到<strong>设置-其他</strong>查看与清理软件缓存</li>\n<li>新增QQ音乐源搜索</li>\n<li>新增咪咕源搜索</li>\n<li>新增咪咕源歌单</li>\n<li>新增咪咕源排行榜</li>\n<li>新增我的音乐列表歌曲源显示,默认关闭,可到<strong>设置-列表设置</strong>开启</li>\n</ul>\n<h4>优化</h4>\n<ul>\n<li>优化选择框动画效果</li>\n<li>尝试优化选我的音乐列表内容很多时多选的卡顿问题</li>\n</ul>\n<h4>修复</h4>\n<ul>\n<li>修复列表延迟显示的Bug</li>\n<li>修复QQ音源128k音质试听</li>\n</ul>\n",
"history": [
{
"version": "0.6.2",
"desc": "<p>祝贺祖国成立70周年~</p>\n<h4>新增</h4>\n<ul>\n<li>新增QQ音乐源歌单</li>\n</ul>\n<h4>修复</h4>\n<ul>\n<li>修正火影皮肤名字</li>\n<li>修复当试听列表为空时无法切到其他界面的Bug</li>\n<li>修复百度源搜索结果为空时的接口处理Bug</li>\n<li>恢复<strong>酷狗</strong>其他音质播放</li>\n</ul>\n"
},
{
"version": "0.6.1",
"desc": "<h3>新增</h3>\n<ul>\n<li>新增试听列表<strong>滚动条位置恢复</strong>设置(可自动恢复到上次离开时的列表滚动位置),本功能默认开启,若不需要可到设置-列表设置将其关闭</li>\n<li>新增 <strong>《海贼王》</strong> 皮肤,喜欢个性化的可以试试~</li>\n</ul>\n<h3>优化</h3>\n<ul>\n<li>新增DNS解析缓存加快请求速度</li>\n<li>优化代码逻辑,减少软件对系统资源的占用</li>\n<li>优化新版本信息检测,尽量减少弹出版本获取失败弹窗弹出的概率</li>\n<li>优化下拉列表动画效果</li>\n</ul>\n<h3>修复</h3>\n<ul>\n<li>修复请求超时的逻辑处理Bug尝试修复请求无法取消导致的正在播放的歌曲与界面显示的信息不一致的问题</li>\n<li>修复其他一些小Bug</li>\n</ul>\n<h3>移除</h3>\n<ul>\n<li>移除 <code>192k</code> 音质</li>\n<li>移除酷我音源 <code>ape</code> 音质,无损推荐 <code>flac</code> 格式</li>\n</ul>\n"
},
{
"version": "0.6.0",
"desc": "<h3>新增</h3>\n<ul>\n<li>新增音乐<strong>聚合搜索</strong>,目前支持酷我、酷狗、百度源搜索</li>\n<li>新增代理功能</li>\n</ul>\n<h3>优化</h3>\n<ul>\n<li>优化从《梦里嫦娥》皮肤切换到其他皮肤时侧栏动画的切换效果</li>\n</ul>\n<h3>修复</h3>\n<ul>\n<li>修复试听列表没有歌曲时会显示列表加载中的Bug</li>\n<li>修复切换歌单列表详情时的UI Bug</li>\n</ul>\n"

View File

@@ -10,6 +10,6 @@ html(lang="cn")
//- if htmlWebpackPlugin.options.isProd
//- script.
//- window.__static = '!{require('path').join(htmlWebpackPlugin.options.__dirname, '/static').replace(/\\/g, '\\\\')}'
if !htmlWebpackPlugin.options.browser && htmlWebpackPlugin.options.isProd
//- if !htmlWebpackPlugin.options.browser && htmlWebpackPlugin.options.isProd
script.
window.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
window.__static = require('path').join(__dirname, '/resources').replace(/\\/g, '\\\\')

View File

@@ -1,5 +1,6 @@
require('./request')
// require('./appName')
require('./progressBar')
require('./trafficLight')
require('./musicMeta')

View File

@@ -16,8 +16,6 @@ app.on('second-instance', (event, argv, cwd) => {
})
require('./events')
require('./events/progressBar')
require('./events/trafficLight')
const autoUpdate = require('./utils/autoUpdate')
const { isLinux, isMac } = require('../common/utils')

View File

@@ -49,7 +49,7 @@ export default {
},
computed: {
...mapGetters(['electronStore', 'setting', 'theme', 'version']),
...mapGetters('list', ['defaultList']),
...mapGetters('list', ['defaultList', 'loveList']),
...mapGetters('download', {
downloadList: 'list',
downloadStatus: 'downloadStatus',
@@ -73,6 +73,13 @@ export default {
},
deep: true,
},
loveList: {
handler(n) {
// console.log(n)
this.electronStore.set('list.loveList', n)
},
deep: true,
},
downloadList: {
handler(n) {
this.electronStore.set('download.list', n)
@@ -90,7 +97,7 @@ export default {
methods: {
...mapActions(['getVersionInfo']),
...mapMutations(['setNewVersion', 'setVersionModalVisible']),
...mapMutations('list', ['initDefaultList']),
...mapMutations('list', ['initList']),
...mapMutations('download', ['updateDownloadList']),
...mapMutations(['setSetting']),
init() {
@@ -156,13 +163,9 @@ export default {
},
initPlayList() {
let defaultList = this.electronStore.get('list.defaultList')
let loveList = this.electronStore.get('list.loveList')
// console.log(defaultList)
if (defaultList) {
// defaultList.list.forEach(m => {
// m.typeUrl = {}
// })
this.initDefaultList(defaultList)
}
if (defaultList) this.initList({ defaultList, loveList })
},
initDownloadList() {
let downloadList = this.electronStore.get('download.list')

View File

@@ -1,6 +1,6 @@
@import './colors.less';
@themes: green, yellow, blue, red, purple, orange, grey, midAutumn, dhHzw;
@themes: green, yellow, blue, red, purple, orange, grey, midAutumn, dhHyrz;
// Colors
@@ -372,44 +372,44 @@
@color-midAutumn-tab-border-top: fadeout(lighten(@color-midAutumn-theme, 5%), 50%);
@color-midAutumn-tab-border-bottom: lighten(@color-midAutumn-theme, 5%);
@color-dhHzw-theme: rgb(87, 144, 167);
@color-dhHzw-theme-bgimg: url(../images/hzwbg.jpeg);
@color-dhHzw-theme-bgposition: center center;
@color-dhHzw-theme-bgsize: auto 100%;
@color-dhHzw-theme-hover: fadeout(lighten(@color-dhHzw-theme, 10%), 45%);
@color-dhHzw-theme-active: fadeout(lighten(@color-dhHzw-theme, 15%), 60%);
@color-dhHzw-theme-font: rgba(67, 118, 148, 0.9);
@color-dhHzw-theme-font-label: fadeout(darken(@color-dhHzw-theme, 20%), 20%);
@color-dhHzw-theme_2: rgba(255, 255, 255, 0.8);
@color-dhHzw-theme_2-background_1: #e9faff;
@color-dhHzw-theme_2-background_2: fadeout(@color-dhHzw-theme_2-background_1, 2%);
@color-dhHzw-theme_2-hover: fadeout(lighten(@color-dhHzw-theme, 10%), 65%);
@color-dhHzw-theme_2-active: fadeout(darken(@color-dhHzw-theme, 5%), 70%);
@color-dhHzw-theme_2-font: darken(@color-dhHzw-theme_2, 80%);
@color-dhHzw-theme_2-font-label: lighten(@color-dhHzw-theme, 10%);
@color-dhHzw-theme_2-line: lighten(@color-dhHzw-theme, 36%);
@color-dhHzw-theme-sidebar: rgba(255, 255, 255, .3);
@color-dhHzw-btn: fadeout(darken(@color-dhHzw-theme, 5%), 15%);
@color-dhHzw-btn-background: fadeout(lighten(@color-dhHzw-theme, 35%), 70%);
@color-dhHzw-pagination-background: fadeout(lighten(@color-dhHzw-theme, 45%), 50%);
@color-dhHzw-pagination-hover: fadeout(lighten(@color-dhHzw-theme, 10%), 70%);
@color-dhHzw-pagination-active: fadeout(darken(@color-dhHzw-theme, 10%), 70%);
@color-dhHzw-pagination-select: fadeout(lighten(@color-dhHzw-theme, 10%), 55%);
@color-dhHzw-search-form-background: fadeout(lighten(@color-dhHzw-theme, 30%), 20%);
@color-dhHzw-search-list-hover: fadeout(darken(@color-dhHzw-theme, 10%), 50%);
@color-dhHzw-scrollbar-track: fadeout(@color-dhHzw-theme, 80%);
@color-dhHzw-scrollbar-thumb: fadeout(@color-dhHzw-theme, 60%);
@color-dhHzw-scrollbar-thumb-hover: fadeout(@color-dhHzw-theme, 40%);
@color-dhHzw-player-pic-c1: fadeout(@color-dhHzw-theme_2, 50%);
@color-dhHzw-player-pic-c2: darken(@color-dhHzw-theme_2, 30%);
@color-dhHzw-player-progress: darken(@color-dhHzw-theme_2, 6%);
@color-dhHzw-player-progress-bar1: darken(@color-dhHzw-theme_2, 12%);
@color-dhHzw-player-progress-bar2: lighten(@color-dhHzw-theme, 12%);
@color-dhHzw-player-status-text: lighten(@color-dhHzw-theme_2-font, 10%);
@color-dhHzw-tab-btn-background: fadeout(lighten(@color-dhHzw-theme, 10%), 80%);
@color-dhHzw-tab-btn-background-hover: @color-dhHzw-theme_2-hover;
@color-dhHzw-tab-border-top: fadeout(lighten(@color-dhHzw-theme, 5%), 50%);
@color-dhHzw-tab-border-bottom: lighten(@color-dhHzw-theme, 5%);
@color-dhHyrz-theme: rgb(87, 144, 167);
@color-dhHyrz-theme-bgimg: url(../images/hzwbg.jpeg);
@color-dhHyrz-theme-bgposition: center center;
@color-dhHyrz-theme-bgsize: auto 100%;
@color-dhHyrz-theme-hover: fadeout(lighten(@color-dhHyrz-theme, 10%), 45%);
@color-dhHyrz-theme-active: fadeout(lighten(@color-dhHyrz-theme, 15%), 60%);
@color-dhHyrz-theme-font: rgba(67, 118, 148, 0.9);
@color-dhHyrz-theme-font-label: fadeout(darken(@color-dhHyrz-theme, 20%), 20%);
@color-dhHyrz-theme_2: rgba(255, 255, 255, 0.8);
@color-dhHyrz-theme_2-background_1: #e9faff;
@color-dhHyrz-theme_2-background_2: fadeout(@color-dhHyrz-theme_2-background_1, 2%);
@color-dhHyrz-theme_2-hover: fadeout(lighten(@color-dhHyrz-theme, 10%), 65%);
@color-dhHyrz-theme_2-active: fadeout(darken(@color-dhHyrz-theme, 5%), 70%);
@color-dhHyrz-theme_2-font: darken(@color-dhHyrz-theme_2, 80%);
@color-dhHyrz-theme_2-font-label: lighten(@color-dhHyrz-theme, 10%);
@color-dhHyrz-theme_2-line: lighten(@color-dhHyrz-theme, 36%);
@color-dhHyrz-theme-sidebar: rgba(255, 255, 255, .3);
@color-dhHyrz-btn: fadeout(darken(@color-dhHyrz-theme, 5%), 15%);
@color-dhHyrz-btn-background: fadeout(lighten(@color-dhHyrz-theme, 35%), 70%);
@color-dhHyrz-pagination-background: fadeout(lighten(@color-dhHyrz-theme, 45%), 50%);
@color-dhHyrz-pagination-hover: fadeout(lighten(@color-dhHyrz-theme, 10%), 70%);
@color-dhHyrz-pagination-active: fadeout(darken(@color-dhHyrz-theme, 10%), 70%);
@color-dhHyrz-pagination-select: fadeout(lighten(@color-dhHyrz-theme, 10%), 55%);
@color-dhHyrz-search-form-background: fadeout(lighten(@color-dhHyrz-theme, 30%), 20%);
@color-dhHyrz-search-list-hover: fadeout(darken(@color-dhHyrz-theme, 10%), 50%);
@color-dhHyrz-scrollbar-track: fadeout(@color-dhHyrz-theme, 80%);
@color-dhHyrz-scrollbar-thumb: fadeout(@color-dhHyrz-theme, 60%);
@color-dhHyrz-scrollbar-thumb-hover: fadeout(@color-dhHyrz-theme, 40%);
@color-dhHyrz-player-pic-c1: fadeout(@color-dhHyrz-theme_2, 50%);
@color-dhHyrz-player-pic-c2: darken(@color-dhHyrz-theme_2, 30%);
@color-dhHyrz-player-progress: darken(@color-dhHyrz-theme_2, 6%);
@color-dhHyrz-player-progress-bar1: darken(@color-dhHyrz-theme_2, 12%);
@color-dhHyrz-player-progress-bar2: lighten(@color-dhHyrz-theme, 12%);
@color-dhHyrz-player-status-text: lighten(@color-dhHyrz-theme_2-font, 10%);
@color-dhHyrz-tab-btn-background: fadeout(lighten(@color-dhHyrz-theme, 10%), 80%);
@color-dhHyrz-tab-btn-background-hover: @color-dhHyrz-theme_2-hover;
@color-dhHyrz-tab-border-top: fadeout(lighten(@color-dhHyrz-theme, 5%), 50%);
@color-dhHyrz-tab-border-bottom: lighten(@color-dhHyrz-theme, 5%);
// Width

View File

@@ -16,8 +16,9 @@ div(:class="$style.aside")
dl
dt 我的音乐
dd
router-link(:active-class="$style.active" to="list") {{defaultList.name}}
router-link(:active-class="$style.active" v-for="item in userList" :to="`list?id=${item._id}`" :key="item._id") {{item.name}}
router-link(:active-class="($route.query.id === defaultList.id || $route.query.id == '') ? $style.active : ''" :to="`list?id=${defaultList.id || ''}`") {{defaultList.name}}
router-link(:active-class="$route.query.id === loveList.id ? $style.active : ''" :to="`list?id=${loveList.id}`") {{loveList.name}}
router-link(:active-class="$route.query.id === item.id ? $style.active : ''" v-for="item in userList" :to="`list?id=${item._id}`" :key="item._id") {{item.name}}
dl
dt 其他
dd
@@ -43,7 +44,7 @@ export default {
}
},
computed: {
...mapGetters('list', ['defaultList', 'userList']),
...mapGetters('list', ['defaultList', 'loveList', 'userList']),
},
methods: {},
}

View File

@@ -210,7 +210,7 @@ export default {
this.audio.currentTime = this.audioErrorTime
this.audioErrorTime = 0
}
if (!this.targetSong.interval && this.listId != 'download') this.updateMusicInfo({ index: this.playIndex, data: { interval: formatPlayTime2(this.maxPlayTime) } })
if (!this.targetSong.interval && this.listId != 'download') this.updateMusicInfo({ id: 'default', index: this.playIndex, data: { interval: formatPlayTime2(this.maxPlayTime) } })
this.status = '音乐加载中...'
})
this.audio.addEventListener('loadstart', () => {
@@ -367,7 +367,8 @@ export default {
getPlayType(highQuality, songInfo) {
switch (songInfo.source) {
case 'wy':
case 'kg':
case 'tx':
// case 'kg':
return '128k'
}
let type = songInfo._types['192k'] ? '192k' : '128k'

View File

@@ -1,16 +1,16 @@
<template lang="pug">
div(:class="$style.checkbox")
input(:type="need ? 'radio' : 'checkbox'" :id="id" :disabled="disabled" :value="value" :name="name" @change="change" v-model="bool")
input(:type="need ? 'radio' : 'checkbox'" :class="$style.input" :id="id" :disabled="disabled" :value="value" :name="name" @change="change" v-model="bool")
label(:for="id" :class="$style.content")
div(v-if="indeterminate")
svg(v-show="indeterminate" 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')
div(v-if="indeterminate" :class="$style.container")
svg(v-show="indeterminate" :class="$style.icon" 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-indeterminate')
svg(v-show="!indeterminate" version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' width="100%" viewBox='0 0 448 512' space='preserve')
svg(v-show="!indeterminate" :class="$style.icon" version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' width="100%" viewBox='0 0 448 512' space='preserve')
use(xlink:href='#icon-check-true')
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')
div(v-else :class="$style.container")
svg(version='1.1' :class="$style.icon" 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')
span(v-if="label != null" v-html="label")
span(v-if="label != null" v-html="label" :class="$style.label")
</template>
<script>
@@ -73,9 +73,9 @@ export default {
let bool = this.bool
if (this.indeterminate) {
bool = true
this.$nextTick(() => {
this.bool = true
})
// this.$nextTick(() => {
this.bool = true
// })
}
checked = bool
}
@@ -113,25 +113,25 @@ export default {
display: inline-block;
// font-size: 56px;
> input {
display: none;
&[disabled] {
+ .content {
opacity: .5;
}
}
.input {
display: none;
&[disabled] {
+ .content {
opacity: .5;
}
&:checked {
+ .content {
> div {
&:after {
border-color: @color-theme;
}
svg {
transform: scale(1);
opacity: 1;
}
}
&:checked {
+ .content {
.container {
&:after {
border-color: @color-theme;
}
}
.icon {
transform: scale(1);
// opacity: 1;
}
}
}
}
@@ -139,41 +139,41 @@ export default {
display: flex;
justify-content: center;
> div {
flex: none;
position: relative;
display: inline-block;
width: 1em;
height: 1em;
cursor: pointer;
display: flex;
color: @color-theme;
// border: 1px solid #ccc;
&:after {
position: absolute;
content: ' ';
top: 0;
bottom: 0;
left: 0;
right: 0;
border: 1px solid @color-theme_2-font-label;
transition: border-color 0.2s ease;
border-radius: 15%;
}
svg {
transition: 0.2s ease;
transition-property: transform, opacity;
transform: scale(0.5);
opacity: 0;
}
}
.container {
flex: none;
position: relative;
display: inline-block;
width: 1em;
height: 1em;
cursor: pointer;
display: flex;
color: @color-theme;
// border: 1px solid #ccc;
&:after {
position: absolute;
content: ' ';
top: 0;
bottom: 0;
left: 0;
right: 0;
border: 1px solid @color-theme_2-font-label;
transition: border-color 0.2s ease;
border-radius: 15%;
}
}
.icon {
transition: 0.3s ease;
transition-property: transform;
transform: scale(0);
// opacity: 0;
}
> span {
flex: auto;
line-height: 1;
margin-left: 5px;
cursor: pointer;
}
.label {
flex: auto;
line-height: 1;
margin-left: 5px;
cursor: pointer;
}
each(@themes, {
@@ -182,7 +182,7 @@ each(@themes, {
> input {
&:checked {
+ .content {
> div {
.container {
&:after {
border-color: ~'@{color-@{value}-theme}';
}
@@ -192,7 +192,7 @@ each(@themes, {
}
}
.content {
> div {
.container {
color: ~'@{color-@{value}-theme}';
// border: 1px solid #ccc;
&:after {

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" :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()}` }}
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>
@@ -52,7 +52,8 @@ export default {
checkSource(type) {
switch (this.musicInfo.source) {
case 'wy':
case 'kg':
return false
case 'tx':
return type == '128k'
default:

View File

@@ -7,7 +7,7 @@ material-modal(:show="show" :bg-close="bgClose" @close="handleClose")
| 请选择要优先下载的音质
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('ape')") 无损音质 - APE
material-btn(:class="$style.btn" @click="handleClick('flac')") 无损音质 - FLAC
</template>

View File

@@ -3,6 +3,9 @@ div(:class="$style.btns")
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="listAddBtn" title="添加到..." @click.stop="handleClick('listAdd')")
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')
@@ -56,6 +59,10 @@ export default {
type: Boolean,
default: true,
},
listAddBtn: {
type: Boolean,
default: true,
},
searchBtn: {
type: Boolean,
default: false,

View File

@@ -11,8 +11,8 @@ div(:class="$style.songList")
:indeterminate="isIndeterminate" :title="isSelectAll && !isIndeterminate ? '全不选' : '全选'")
th.nobreak(style="width: 25%;") 歌曲名
th.nobreak(style="width: 20%;") 歌手
th.nobreak(style="width: 22%;") 专辑
th.nobreak(style="width: 18%;") 操作
th.nobreak(style="width: 20%;") 专辑
th.nobreak(style="width: 20%;") 操作
th.nobreak(style="width: 10%;") 时长
div.scroll(:class="$style.tbody" ref="dom_scrollContent")
table
@@ -25,9 +25,13 @@ div(:class="$style.songList")
span.badge.badge-info(v-if="item._types['320k']") 高品质
span.badge.badge-success(v-if="item._types.ape || item._types.flac") 无损
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' && item.source != 'wy')" :download-btn="item.source == 'kw' || (!isAPITemp && item.source != 'tx' && item.source != 'wy')" :remove-btn="false" @btn-click="handleListBtnClick")
td.break(style="width: 20%;") {{item.albumName}}
td(style="width: 20%; padding-left: 0; padding-right: 0;")
material-list-buttons(:index="index" :search-btn="true"
:remove-btn="false" @btn-click="handleListBtnClick"
:listAdd-btn="item.source == 'kw' || (!isAPITemp && item.source != 'wy')"
:play-btn="item.source == 'kw' || (!isAPITemp && item.source != 'wy')"
:download-btn="item.source == 'kw' || (!isAPITemp && item.source != 'wy')")
//- 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)')
@@ -136,7 +140,7 @@ export default {
this.clickIndex = index
return
}
this.emitEvent((this.source == 'kw' || (!this.isAPITemp && this.list[index].source != 'tx' && this.list[index].source != 'wy')) ? 'testPlay' : 'search', index)
this.emitEvent((this.source == 'kw' || (!this.isAPITemp && this.list[index].source != 'wy')) ? 'testPlay' : 'search', index)
this.clickTime = 0
this.clickIndex = -1
},

View File

@@ -0,0 +1,103 @@
<template lang="pug">
material-modal(:show="show" :bg-close="bgClose" @close="handleClose")
main(:class="$style.main")
h2
| 添加&nbsp;
span(:class="$style.name") {{this.musicInfo && `${musicInfo.name}`}}
| &nbsp;...
material-btn(:class="$style.btn" :title="`把该歌曲添加到 ${item.name}`" :key="item.id" @click="handleClick(index)" v-for="(item, index) in lists") {{item.name}}
</template>
<script>
import { mapGetters, mapMutations } from 'vuex'
export default {
props: {
show: {
type: Boolean,
default: false,
},
musicInfo: {
type: Object,
},
bgClose: {
type: Boolean,
default: true,
},
excludeListId: {
type: Array,
default() {
return []
},
},
},
computed: {
...mapGetters('list', ['defaultList', 'loveList', 'userList']),
lists() {
return [
this.defaultList,
this.loveList,
...this.userList,
].filter(l => !this.excludeListId.includes(l.id))
},
},
methods: {
...mapMutations('list', ['listAdd']),
handleClick(index) {
this.listAdd({ id: this.lists[index].id, musicInfo: this.musicInfo })
this.$nextTick(() => {
this.handleClose()
})
},
handleClose() {
this.$emit('close')
},
},
}
</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;
}
}
.name {
color: @color-theme;
}
.btn {
display: block;
margin-bottom: 15px;
&:last-child {
margin-bottom: 0;
}
}
each(@themes, {
:global(#container.@{value}) {
.main {
h2 {
color: ~'@{color-@{value}-theme_2-font}';
}
}
.name {
color: ~'@{color-@{value}-theme}';
}
}
})
</style>

View File

@@ -0,0 +1,97 @@
<template lang="pug">
material-modal(:show="show" :bg-close="bgClose" @close="handleClose")
main(:class="$style.main")
h2 添加已选的 {{musicList.length}} 首歌曲到...
material-btn(:class="$style.btn" :title="`把该歌曲添加到 ${item.name}`" :key="item.id" @click="handleClick(index)" v-for="(item, index) in lists") {{item.name}}
</template>
<script>
import { mapGetters, mapMutations } from 'vuex'
export default {
props: {
show: {
type: Boolean,
default: false,
},
musicList: {
type: Array,
default() {
return []
},
},
bgClose: {
type: Boolean,
default: true,
},
excludeListId: {
type: Array,
default() {
return []
},
},
},
computed: {
...mapGetters('list', ['defaultList', 'loveList', 'userList']),
lists() {
return [
this.defaultList,
this.loveList,
...this.userList,
].filter(l => !this.excludeListId.includes(l.id))
},
},
methods: {
...mapMutations('list', ['listAddMultiple']),
handleClick(index) {
this.listAddMultiple({ id: this.lists[index].id, list: this.musicList })
this.$nextTick(() => {
this.handleClose(true)
})
},
handleClose(isSelect = false) {
this.$emit('close', isSelect)
},
},
}
</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>

View File

@@ -1,15 +1,22 @@
// state
const state = {
defaultList: {
id: 'default',
name: '试听列表',
list: [],
},
loveList: {
id: 'love',
name: '我的收藏',
list: [],
},
userList: [],
}
// getters
const getters = {
defaultList: state => state.defaultList || {},
loveList: state => state.loveList || {},
userList: state => state.userList,
}
@@ -18,39 +25,72 @@ const actions = {
}
const getList = (state, id) => {
let targetList
switch (id) {
case 'default':
targetList = state.defaultList
break
case 'love':
targetList = state.loveList
break
default:
targetList = state.userList.find(l => l.id === id)
break
}
return targetList
}
// mitations
const mutations = {
initDefaultList(state, data) {
state.defaultList = data
initList(state, { defaultList, loveList }) {
if (defaultList !== undefined) state.defaultList.list = defaultList.list
if (loveList !== undefined) state.loveList.list = loveList.list
},
setDefaultList(state, list) {
state.defaultList.list = list
setList(state, { id, list }) {
const targetList = getList(state, id)
if (!targetList) return
targetList.list = list
},
defaultListAdd(state, musicInfo) {
if (state.defaultList.list.some(s => s.songmid === musicInfo.songmid)) return
state.defaultList.list.push(musicInfo)
listAdd(state, { id, musicInfo }) {
const targetList = getList(state, id)
if (!targetList) return
if (targetList.list.some(s => s.songmid === musicInfo.songmid)) return
targetList.list.push(musicInfo)
},
defaultListAddMultiple(state, list) {
listAddMultiple(state, { id, list }) {
let targetList = getList(state, id)
if (!targetList) return
targetList = targetList.list
list.forEach(musicInfo => {
if (state.defaultList.list.some(s => s.songmid === musicInfo.songmid)) return
state.defaultList.list.push(musicInfo)
if (targetList.some(s => s.songmid === musicInfo.songmid)) return
targetList.push(musicInfo)
})
},
defaultListRemove(state, index) {
state.defaultList.list.splice(index, 1)
listRemove(state, { id, index }) {
let targetList = getList(state, id)
if (!targetList) return
targetList.list.splice(index, 1)
},
updateMusicInfo(state, { index, data }) {
Object.assign(state.defaultList.list[index], data)
},
defaultListRemoveMultiple(state, list) {
listRemoveMultiple(state, { id, list }) {
let targetList = getList(state, id)
if (!targetList) return
targetList = targetList.list
list.forEach(musicInfo => {
let index = state.defaultList.list.indexOf(musicInfo)
let index = targetList.indexOf(musicInfo)
if (index < 0) return
state.defaultList.list.splice(index, 1)
targetList.splice(index, 1)
})
},
defaultListClear(state) {
state.defaultList.list.length = 0
listClear(state, id) {
let targetList = getList(state, id)
if (!targetList) return
targetList.list.length = 0
},
updateMusicInfo(state, { id, index, data }) {
let targetList = getList(state, id)
if (!targetList) return
Object.assign(targetList.list[index], data)
},
}

View File

@@ -20,6 +20,7 @@ const state = {
},
listDetail: {
list: [],
desc: null,
total: 0,
page: 1,
limit: 30,
@@ -83,12 +84,13 @@ const mutations = {
state.list.page = page
state.list.key = key
},
setListDetail(state, { result, key, page }) {
setListDetail(state, { result, key, page, desc }) {
state.listDetail.list = result.list
state.listDetail.total = result.total
state.listDetail.limit = result.limit
state.listDetail.page = page
state.listDetail.key = key
state.listDetail.desc = result.desc
},
setVisibleListDetail(state, bool) {
state.isVisibleListDetail = bool

View File

@@ -18,8 +18,8 @@ export default {
if (sortId != null) state.setting.songList.sortId = sortId
if (source != null) state.setting.songList.source = source
},
setListScroll(state, scrollTop) {
state.setting.list.scroll.location = scrollTop
setListScroll(state, { id, location }) {
state.setting.list.scroll.locations[id] = location
},
setNewVersion(state, val) {
// val.history.forEach(ver => {

View File

@@ -6,6 +6,7 @@ import { version } from '../../../package.json'
let electronStore = new Store()
const setting = updateSetting(electronStore.get('setting'))
electronStore.set('setting', setting)
process.versions.app = version
export default {
themes: [
@@ -51,8 +52,8 @@ export default {
},
{
id: 8,
name: '海贝戎王',
class: 'dhHzw',
name: '木叶之村',
class: 'dhHyrz',
},
],
version: {

View File

@@ -15,8 +15,8 @@ export const getRandom = (min, max) => Math.floor(Math.random() * (max - min)) +
export const sizeFormate = size => {
// https://gist.github.com/thomseddon/3511330
if (!size) return '0 b'
let units = ['b', 'kB', 'MB', 'GB', 'TB']
if (!size) return '0 B'
let units = ['B', 'KB', 'MB', 'GB', 'TB']
let number = Math.floor(Math.log(size) / Math.log(1024))
return `${(size / Math.pow(1024, Math.floor(number))).toFixed(2)} ${units[number]}`
}
@@ -164,7 +164,7 @@ export const isChildren = (parent, children) => {
* @param {*} setting
*/
export const updateSetting = setting => {
const defaultVersion = '1.0.10'
const defaultVersion = '1.0.12'
const defaultSetting = {
version: defaultVersion,
player: {
@@ -175,9 +175,10 @@ export const updateSetting = setting => {
},
list: {
isShowAlbumName: true,
isShowSource: false,
scroll: {
enable: true,
location: 0,
locations: {},
},
},
download: {
@@ -303,3 +304,50 @@ export const throttle = (fn, delay = 100) => {
}, delay)
}
}
const async_removeItem = (arr, num, callback) => window.requestAnimationFrame(() => {
let len = arr.length
if (len > num) {
arr.splice(0, num)
return async_removeItem(arr, num, callback)
} else {
arr.splice(0, len)
return callback()
}
})
const async_addItem = (arr, newArr, num, callback) => window.requestAnimationFrame(() => {
let len = newArr.length
if (len > num) {
arr.push(...newArr.splice(0, num))
return async_addItem(arr, newArr, num, callback)
} else {
arr.push(...newArr.splice(0, len))
return callback()
}
})
/**
* 异步设置数组
* @param {*} from 原数组
* @param {*} to 设置后的数组内容
* @param {*} num 每次设置的个数
*/
export const asyncSetArray = (from, to, num = 100) => new Promise(resolve => {
async_removeItem(from, num, () => {
async_addItem(from, Array.from(to), num, () => {
resolve()
})
})
})
/**
* 获取缓存大小
* @param {*} win
*/
export const getCacheSize = () => remote.getCurrentWindow().webContents.session.getCacheSize()
/**
* 清除缓存
* @param {*} win
*/
export const clearCache = () => remote.getCurrentWindow().webContents.session.clearCache()

View File

@@ -1,9 +1,10 @@
import kw_api_temp from './kw/api-temp'
import kw_api_test from './kw/api-test'
// import tx_api_messoer from './tx/api-messoer'
import tx_api_test from './tx/api-test'
import kg_api_test from './kg/api-test'
import wy_api_test from './wy/api-test'
import bd_api_test from './bd/api-test'
import mg_api_test from './mg/api-test'
// import kw_api_internal from './kw/api-internal'
// import tx_api_internal from './tx/api-internal'
// import kg_api_internal from './kg/api-internal'
@@ -12,10 +13,11 @@ import bd_api_test from './bd/api-test'
const apis = {
kw_api_test,
// tx_api_messoer,
tx_api_test,
kg_api_test,
wy_api_test,
bd_api_test,
mg_api_test,
// kw_api_internal,
// tx_api_internal,
// kg_api_internal,
@@ -46,6 +48,8 @@ export default source => {
return getAPI('wy')
case 'bd':
return getAPI('bd')
case 'mg':
return getAPI('mg')
default:
return getAPI('kw')
}

View File

@@ -19,6 +19,7 @@ export default {
handleResult(rawData) {
let ids = new Set()
const list = []
if (!rawData) return list
rawData.forEach(item => {
if (ids.has(item.song_id)) return
ids.add(item.song_id)

View File

@@ -2,6 +2,7 @@ import kw from './kw'
import kg from './kg'
import tx from './tx'
import wy from './wy'
import mg from './mg'
import bd from './bd'
export default {
sources: [
@@ -21,6 +22,10 @@ export default {
name: '网易音乐',
id: 'wy',
},
{
name: '咪咕音乐',
id: 'mg',
},
{
name: '百度音乐',
id: 'bd',
@@ -30,5 +35,6 @@ export default {
kg,
tx,
wy,
mg,
bd,
}

View File

@@ -2,6 +2,8 @@ import leaderboard from './leaderboard'
import api_source from '../api-source'
import songList from './songList'
import musicSearch from './musicSearch'
import pic from './pic'
import lyric from './lyric'
const kg = {
leaderboard,
@@ -11,11 +13,17 @@ const kg = {
return api_source('kg').getMusicUrl(songInfo, type)
},
getLyric(songInfo) {
return api_source('kg').getLyric(songInfo)
return lyric.getLyric(songInfo)
},
// getLyric(songInfo) {
// return api_source('kg').getLyric(songInfo)
// },
getPic(songInfo) {
return api_source('kg').getPic(songInfo)
return pic.getPic(songInfo)
},
// getPic(songInfo) {
// return api_source('kg').getPic(songInfo)
// },
}
export default kg

View File

@@ -0,0 +1,33 @@
import { httpFetch } from '../../request'
export default {
getIntv(interval) {
let intvArr = interval.split(':')
let intv = 0
let unit = 1
while (intvArr.length) {
intv += (intvArr.pop()) * unit
unit *= 60
}
return parseInt(intv)
},
getLyric(songInfo, tryNum = 0) {
let requestObj = httpFetch(`http://m.kugou.com/app/i/krc.php?cmd=100&keyword=${encodeURIComponent(songInfo.name)}&hash=${songInfo.hash}&timelength=${songInfo._interval || this.getIntv(songInfo.interval)}&d=0.38664927426725626`, {
headers: {
'KG-RC': 1,
'KG-THash': 'expand_search_manager.cpp:852736169:451',
'User-Agent': 'KuGou2012-9020-ExpandSearchManager',
},
})
requestObj.promise = requestObj.promise.then(({ body, statusCode }) => {
if (statusCode !== 200) {
if (tryNum > 5) return Promise.reject('歌词获取失败')
let tryRequestObj = this.getLyric(songInfo, ++tryNum)
requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj)
return tryRequestObj.promise
}
return body
})
return requestObj
},
}

View File

@@ -57,6 +57,7 @@ export default {
songmid: item.audio_id,
source: 'kg',
interval: formatPlayTime(item.duration),
_interval: item.duration,
img: null,
lrc: null,
hash: item.hash,

View File

@@ -0,0 +1,44 @@
import { httpFetch } from '../../request'
export default {
getPic(songInfo) {
const requestObj = httpFetch(
'http://media.store.kugou.com/v1/get_res_privilege',
{
method: 'POST',
headers: {
'KG-RC': 1,
'KG-THash': 'expand_search_manager.cpp:852736169:451',
'User-Agent': 'KuGou2012-9020-ExpandSearchManager',
},
body: {
appid: 1001,
area_code: '1',
behavior: 'play',
clientver: '9020',
need_hash_offset: 1,
relate: 1,
resource: [
{
album_audio_id: songInfo.songmid,
album_id: songInfo.albumId,
hash: songInfo.hash,
id: 0,
name: `${songInfo.singer} - ${songInfo.name}.mp3`,
type: 'audio',
},
],
token: '',
userid: 2626431536,
vip: 1,
},
}
)
requestObj.promise = requestObj.promise.then(({ body }) => {
if (body.error_code !== 0) return Promise.reject('图片获取失败')
let info = body.data[0].info
return info.image.replace('{size}', info.imgsize[0])
})
return requestObj
},
}

View File

@@ -211,7 +211,7 @@ export default {
})
},
getTags() {
return Promise.all([this.getTag(), this.getHotTag()]).then(([tags, hotTag]) => ({ tags, hotTag }))
return Promise.all([this.getTag(), this.getHotTag()]).then(([tags, hotTag]) => ({ tags, hotTag, source: 'kw' }))
},
}

View File

@@ -0,0 +1,20 @@
import { httpFetch } from '../../request'
import { requestMsg } from '../../message'
import { headers, timeout } from '../options'
const api_test = {
getMusicUrl(songInfo, type) {
const requestObj = httpFetch(`http://ts.tempmusic.tk/url/mg/${songInfo.copyrightId}/${type}`, {
method: 'get',
timeout,
headers,
family: 4,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body.code === 0 ? Promise.resolve({ type, url: encodeURI(body.data) }) : Promise.reject(new Error(requestMsg.fail))
})
return requestObj
},
}
export default api_test

View File

@@ -0,0 +1,23 @@
import api_source from '../api-source'
import leaderboard from './leaderboard'
import songList from './songList'
import musicSearch from './musicSearch'
import pic from './pic'
import lyric from './lyric'
const mg = {
songList,
musicSearch,
leaderboard,
getMusicUrl(songInfo, type) {
return api_source('mg').getMusicUrl(songInfo, type)
},
getLyric(songInfo) {
return lyric.getLyric(songInfo)
},
getPic(songInfo) {
return pic.getPic(songInfo)
},
}
export default mg

View File

@@ -0,0 +1,130 @@
import { httpFetch } from '../../request'
// import { formatPlayTime } from '../../index'
// import jshtmlencode from 'js-htmlencode'
export default {
limit: 200,
list: [
{
id: 'mgyyb',
name: '音乐榜',
bangid: '23603703',
},
{
id: 'mgysb',
name: '影视榜',
bangid: '23603721',
},
{
id: 'mghybnd',
name: '华语内地榜',
bangid: '23603926',
},
{
id: 'mghyjqbgt',
name: '华语港台榜',
bangid: '23603954',
},
{
id: 'mgomb',
name: '欧美榜',
bangid: '23603974',
},
{
id: 'mgrhb',
name: '日韩榜',
bangid: '23603982',
},
{
id: 'mgwlb',
name: '网络榜',
bangid: '23604058',
},
{
id: 'mgclb',
name: '彩铃榜',
bangid: '23604023',
},
{
id: 'mgktvb',
name: 'KTV榜',
bangid: '23604040',
},
{
id: 'mgrcb',
name: '原创榜',
bangid: '23604032',
},
],
getUrl(id, page) {
return `http://m.music.migu.cn/migu/remoting/cms_list_tag?nid=${id}&pageSize=${this.limit}&pageNo=${page - 1}`
},
requestObj: null,
getData(url) {
if (this.requestObj) this.requestObj.cancelHttp()
this.requestObj = httpFetch(url)
return this.requestObj.promise
},
filterData(rawList) {
// console.log(rawList)
const list = []
rawList.forEach(({ songData }) => {
if (!songData) return
const types = []
const _types = {}
let size = null
types.push({ type: '128k', size })
_types['128k'] = {
size,
}
if (songData.hasHQqq === '1') {
types.push({ type: '320k', size })
_types['320k'] = {
size,
}
}
if (songData.hasSQqq === '1') {
types.push({ type: 'flac', size })
_types.flac = {
size,
}
}
// types.reverse()
list.push({
singer: songData.singerName.join('、'),
name: songData.songName,
// albumName: songData.album_title,
// albumId: songData.album_id,
source: 'mg',
interval: null,
songmid: songData.songId,
copyrightId: songData.copyrightId,
img: songData.picL || songData.M || songData.picS,
lrc: null,
types,
_types,
typeUrl: {},
})
})
return list
},
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(({ statusCode, body }) => {
if (statusCode !== 200) return Promise.reject(new Error('获取列表失败'))
const list = this.filterData(body.result.results)
return {
total: body.result.totalCount,
list,
limit: body.result.pageSize,
page,
source: 'mg',
}
})
},
}

View File

@@ -0,0 +1,36 @@
import { httpFetch } from '../../request'
export default {
getLyric(songInfo, tryNum = 0) {
console.log(songInfo.copyrightId)
if (songInfo.lrcUrl) {
let requestObj = httpFetch(songInfo.lrcUrl)
requestObj.promise = requestObj.promise.then(({ body, statusCode }) => {
if (statusCode !== 200) {
if (tryNum > 5) return Promise.reject('歌词获取失败')
let tryRequestObj = this.getLyric(songInfo, ++tryNum)
requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj)
return tryRequestObj.promise
}
return body
})
return requestObj
} else {
let requestObj = httpFetch(`http://music.migu.cn/v3/api/music/audioPlayer/getLyric?copyrightId=${songInfo.copyrightId}`, {
headers: {
Referer: 'http://music.migu.cn/v3/music/player/audio?from=migu',
},
})
requestObj.promise = requestObj.promise.then(({ body }) => {
if (body.returnCode !== '000000') {
if (tryNum > 5) return Promise.reject('歌词获取失败')
let tryRequestObj = this.getLyric(songInfo, ++tryNum)
requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj)
return tryRequestObj.promise
}
return body.lyric
})
return requestObj
}
},
}

View File

@@ -0,0 +1,108 @@
// import '../../polyfill/array.find'
// import jshtmlencode from 'js-htmlencode'
import { httpFetch } from '../../request'
import { sizeFormate } from '../../index'
// import { debug } from '../../utils/env'
// import { formatSinger } from './util'
let searchRequest
export default {
limit: 30,
total: 0,
page: 0,
allPage: 1,
musicSearch(str, page) {
if (searchRequest && searchRequest.cancelHttp) searchRequest.cancelHttp()
searchRequest = httpFetch(`https://app.c.nf.migu.cn/MIGUM2.0/v1.0/content/search_all.do?isCopyright=1&isCorrect=1&pageNo=${page}&pageSize=${this.limit}&searchSwitch={%22song%22:1,%22album%22:0,%22singer%22:0,%22tagSong%22:0,%22mvSong%22:0,%22songlist%22:0,%22bestShow%22:0}&sort=0&text=${encodeURIComponent(str)}`)
return searchRequest.promise.then(({ body }) => body)
},
getSinger(singers) {
let arr = []
singers.forEach(singer => {
arr.push(singer.name)
})
return arr.join('、')
},
handleResult(rawData) {
// console.log(rawData)
let ids = new Set()
const list = []
rawData.forEach(item => {
if (ids.has(item.id)) return
ids.add(item.id)
const types = []
const _types = {}
item.rateFormats && item.rateFormats.forEach(type => {
let size
switch (type.formatType) {
case 'PQ':
size = sizeFormate(type.size)
types.push({ type: '128k', size })
_types['128k'] = {
size,
}
break
case 'HQ':
size = sizeFormate(type.size)
types.push({ type: '320k', size })
_types['320k'] = {
size,
}
break
case 'SQ':
size = sizeFormate(type.size)
types.push({ type: 'flac', size })
_types.flac = {
size,
}
break
}
})
const albumNInfo = item.albums && item.albums.length ? {
id: item.albums[0].id,
name: item.albums[0].name,
} : {}
list.push({
singer: this.getSinger(item.singers),
name: item.name,
albumName: albumNInfo.name,
albumId: albumNInfo.id,
songmid: item.id,
copyrightId: item.copyrightId,
source: 'mg',
interval: null,
img: item.imgItems && item.imgItems.length ? item.imgItems[0].img : null,
lrc: null,
lrcUrl: item.lyricUrl,
types,
_types,
typeUrl: {},
})
})
return list
},
search(str, page = 1, { limit } = {}) {
if (limit != null) this.limit = limit
// http://newlyric.kuwo.cn/newlyric.lrc?62355680
return this.musicSearch(str, page).then(result => {
if (!result || result.code !== '000000') return this.search(str, page, { limit })
let list = this.handleResult(result.songResultData.resultList.flat())
if (list == null) return this.search(str, page, { limit })
this.total = parseInt(result.songResultData.totalCount)
this.page = page
this.allPage = Math.ceil(this.total / this.limit)
return Promise.resolve({
list,
allPage: this.allPage,
limit: this.limit,
total: this.total,
source: 'mg',
})
})
},
}

View File

@@ -0,0 +1,21 @@
import { httpFetch } from '../../request'
export default {
getPic(songInfo, tryNum = 0) {
let requestObj = httpFetch(`http://music.migu.cn/v3/api/music/audioPlayer/getSongPic?songId=${songInfo.songmid}`, {
headers: {
Referer: 'http://music.migu.cn/v3/music/player/audio?from=migu',
},
})
requestObj.promise = requestObj.promise.then(({ body }) => {
if (body.returnCode !== '000000') {
if (tryNum > 5) return Promise.reject('图片获取失败')
let tryRequestObj = this.getPic(songInfo, ++tryNum)
requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj)
return tryRequestObj.promise
}
return body.largePic || body.mediumPic || body.smallPic
})
return requestObj
},
}

View File

@@ -0,0 +1,213 @@
import { httpFetch } from '../../request'
import { sizeFormate } from '../../index'
export default {
_requestObj_tags: null,
_requestObj_list: null,
_requestObj_listDetail: null,
limit_list: 10,
limit_song: 100,
successCode: '000000',
sortList: [
{
name: '推荐',
id: '15127315',
},
{
name: '最新',
id: '15127272',
},
],
regExps: {
list: /<li><div class="thumb">.+?<\/li>/g,
listInfo: /.+data-original="(.+?)".*data-id="(\d+)".*<div class="song-list-name"><a\s.*?>(.+?)<\/a>.+<i class="iconfont cf-bofangliang"><\/i>(.+?)<\/div>/,
},
tagsUrl: 'https://app.c.nf.migu.cn/MIGUM2.0/v1.0/content/indexTagPage.do?needAll=0',
getSongListUrl(sortId, tagId, page) {
// if (tagId == null) {
// return sortId == 'recommend'
// ? `http://music.migu.cn/v3/music/playlist?page=${page}&from=migu`
// : `http://music.migu.cn/v3/music/playlist?sort=${sortId}&page=${page}&from=migu`
// }
// return `http://music.migu.cn/v3/music/playlist?tagId=${tagId}&page=${page}&from=migu`
if (tagId == null) {
return `http://m.music.migu.cn/migu/remoting/playlist_bycolumnid_tag?playListType=2&type=1&columnId=${sortId}&startIndex=${(page - 1) * 10}`
}
return `http://m.music.migu.cn/migu/remoting/playlist_bycolumnid_tag?playListType=2&type=1&tagId=${tagId}&startIndex=${(page - 1) * 10}`
},
getSongListDetailUrl(id, page) {
return `https://app.c.nf.migu.cn/MIGUM2.0/v1.0/user/queryMusicListSongs.do?musicListId=${id}&pageNo=${page}&pageSize=${this.limit_song}`
},
defaultHeaders: {
language: 'Chinese',
ua: 'Android_migu',
mode: 'android',
version: '6.8.5',
},
/**
* 格式化播放数量
* @param {*} num
*/
formatPlayCount(num) {
if (num > 100000000) return parseInt(num / 10000000) / 10 + '亿'
if (num > 10000) return parseInt(num / 1000) / 10 + '万'
return num
},
getListDetail(id, page) { // 获取歌曲列表内的音乐
if (this._requestObj_listDetail) this._requestObj_listDetail.cancelHttp()
this._requestObj_listDetail = httpFetch(this.getSongListDetailUrl(id, page), { headers: this.defaultHeaders })
return this._requestObj_listDetail.promise.then(({ body }) => {
if (body.code !== this.successCode) return this.getListDetail(id, page)
return {
list: this.filterListDetail(body.list),
page,
limit: this.limit_song,
total: body.totalCount,
source: 'mg',
}
})
},
filterListDetail(rawList) {
// console.log(rawList)
let ids = new Set()
const list = []
rawList.forEach(item => {
if (ids.has(item.songId)) return
ids.add(item.songId)
const types = []
const _types = {}
item.rateFormats && item.rateFormats.forEach(type => {
let size
switch (type.formatType) {
case 'PQ':
size = sizeFormate(type.size)
types.push({ type: '128k', size })
_types['128k'] = {
size,
}
break
case 'HQ':
size = sizeFormate(type.size)
types.push({ type: '320k', size })
_types['320k'] = {
size,
}
break
case 'SQ':
size = sizeFormate(type.size)
types.push({ type: 'flac', size })
_types.flac = {
size,
}
break
}
})
list.push({
singer: item.singer,
name: item.songName,
albumName: item.album,
albumId: item.albumId,
songmid: item.songId,
copyrightId: item.copyrightId,
source: 'mg',
interval: null,
img: item.albumImgs && item.albumImgs.length ? item.albumImgs[0].img : null,
lrc: null,
lrcUrl: item.lrcUrl,
types,
_types,
typeUrl: {},
})
})
return list
},
// 获取列表数据
getList(sortId, tagId, page) {
if (this._requestObj_list) this._requestObj_list.cancelHttp()
this._requestObj_list = httpFetch(this.getSongListUrl(sortId, tagId, page))
// return this._requestObj_list.promise.then(({ statusCode, body }) => {
// if (statusCode !== 200) return this.getList(sortId, tagId, page)
// let list = body.replace(/[\r\n]/g, '').match(this.regExps.list)
// if (!list) return Promise.reject('获取列表失败')
// return list.map(item => {
// let info = item.match(this.regExps.listInfo)
// return {
// play_count: info[4],
// id: info[2],
// author: '',
// name: info[3],
// time: '',
// img: info[1],
// grade: 0,
// desc: '',
// source: 'mg',
// }
// })
// })
return this._requestObj_list.promise.then(({ body }) => {
if (body.retCode !== '100000' || body.retMsg.code !== this.successCode) return this.getList(sortId, tagId, page)
return {
list: this.filterList(body.retMsg.playlist),
total: parseInt(body.retMsg.countSize),
page,
limit: this.limit_list,
source: 'mg',
}
})
},
filterList(rawData) {
return rawData.map(item => ({
play_count: this.formatPlayCount(item.playCount),
id: item.playListId,
author: item.createName,
name: item.playListName,
time: item.createTime,
img: item.image,
grade: item.grade,
desc: item.summary,
source: 'mg',
}))
},
// 获取标签
getTag() {
if (this._requestObj_tags) this._requestObj_tags.cancelHttp()
this._requestObj_tags = httpFetch(this.tagsUrl, { headers: this.defaultHeaders })
return this._requestObj_tags.promise.then(({ body }) => {
if (body.code !== this.successCode) return this.getTag()
return this.filterTagInfo(body.columnInfo.contents)
})
},
filterTagInfo(rawList) {
return {
hotTag: rawList[0].objectInfo.contents.map(item => ({
id: item.objectInfo.tagId,
name: item.objectInfo.tagName,
source: 'mg',
})),
tags: rawList.slice(1).map(({ objectInfo }) => ({
name: objectInfo.columnTitle,
list: objectInfo.contents.map(item => ({
parent_id: objectInfo.columnId,
parent_name: objectInfo.columnTitle,
id: item.objectInfo.tagId,
name: item.objectInfo.tagName,
source: 'mg',
})),
})),
source: 'mg',
}
},
getTags() {
return this.getTag()
},
}
// getList
// getTags
// getListDetail

View File

@@ -1,17 +1,17 @@
import { httpFetch } from '../../request'
import { requestMsg } from '../../message'
import { headers, timeout } from '../messoer'
import { headers, timeout } from '../options'
const api_messoer = {
getMusicUrl(songInfo, type) {
const requestObj = httpFetch(`https://v1.itooi.cn/tencent/url?id=${songInfo.strMediaMid}&quality=${type.replace(/k$/, '')}`, {
const requestObj = httpFetch(`http://ts.tempmusic.tk/url/tx/${songInfo.strMediaMid}/${type}`, {
method: 'get',
timeout,
headers,
family: 4,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body.code === 200 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail))
return body.code === 0 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail))
})
return requestObj
},

View File

@@ -1,9 +1,13 @@
import leaderboard from './leaderboard'
import lyric from './lyric'
import songList from './songList'
import musicSearch from './musicSearch'
import api_source from '../api-source'
const tx = {
leaderboard,
songList,
musicSearch,
getMusicUrl(songInfo, type) {
return api_source('tx').getMusicUrl(songInfo, type)

View File

@@ -0,0 +1,106 @@
// import '../../polyfill/array.find'
// import jshtmlencode from 'js-htmlencode'
import { httpFetch } from '../../request'
import { formatPlayTime, sizeFormate } from '../../index'
// import { debug } from '../../utils/env'
// import { formatSinger } from './util'
let searchRequest
export default {
limit: 30,
total: 0,
page: 0,
allPage: 1,
successCode: 0,
musicSearch(str, page, retryNum = 0) {
if (searchRequest && searchRequest.cancelHttp) searchRequest.cancelHttp()
if (retryNum > 5) return Promise.reject(new Error('搜索失败'))
searchRequest = httpFetch(`https://c.y.qq.com/soso/fcgi-bin/client_search_cp?ct=24&qqmusic_ver=1298&new_json=1&remoteplace=sizer.yqq.song_next&searchid=49252838123499591&t=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=${page}&n=${this.limit}&w=${encodeURIComponent(str)}&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq&needNewCode=0`)
// searchRequest = httpFetch(`http://ioscdn.kugou.com/api/v3/search/song?keyword=${encodeURIComponent(str)}&page=${page}&pagesize=${this.limit}&showtype=10&plat=2&version=7910&tag=1&correct=1&privilege=1&sver=5`)
return searchRequest.promise.then(({ body }) => {
if (body.code !== this.successCode) return this.musicSearch(str, page, ++retryNum)
return body.data
})
},
getSinger(singers) {
let arr = []
singers.forEach(singer => {
arr.push(singer.name)
})
return arr.join('、')
},
handleResult(rawList) {
// console.log(rawData)
return rawList.map(item => {
let types = []
let _types = {}
if (item.file.size_128mp3 !== 0) {
let size = sizeFormate(item.file.size_128mp3)
types.push({ type: '128k', size })
_types['128k'] = {
size,
}
}
if (item.file.size_320mp3 !== 0) {
let size = sizeFormate(item.file.size_320mp3)
types.push({ type: '320k', size })
_types['320k'] = {
size,
}
}
if (item.file.size_ape !== 0) {
let size = sizeFormate(item.file.size_ape)
types.push({ type: 'ape', size })
_types.ape = {
size,
}
}
if (item.file.size_flac !== 0) {
let size = sizeFormate(item.file.size_flac)
types.push({ type: 'flac', size })
_types.flac = {
size,
}
}
// types.reverse()
return {
singer: this.getSinger(item.singer),
name: item.title,
albumName: item.album.title,
albumId: item.album.mid,
source: 'tx',
interval: formatPlayTime(item.interval),
songId: item.id,
albumMid: item.album.mid,
strMediaMid: item.file.strMediaMid,
songmid: item.mid,
img: (item.album.name === '' || item.album.name === '空')
? `https://y.gtimg.cn/music/photo_new/T001R500x500M000${item.singer[0].mid}.jpg`
: `https://y.gtimg.cn/music/photo_new/T002R500x500M000${item.album.mid}.jpg`,
lrc: null,
types,
_types,
typeUrl: {},
}
})
},
search(str, page = 1, { limit } = {}) {
if (limit != null) this.limit = limit
// http://newlyric.kuwo.cn/newlyric.lrc?62355680
return this.musicSearch(str, page).then(({ song }) => {
let list = this.handleResult(song.list)
this.total = song.totalnum
this.page = page
this.allPage = Math.ceil(this.total / this.limit)
return Promise.resolve({
list,
allPage: this.allPage,
limit: this.limit,
total: this.total,
source: 'tx',
})
})
},
}

View File

@@ -0,0 +1,259 @@
import { httpFetch } from '../../request'
import { formatPlayTime, sizeFormate } from '../../index'
export default {
_requestObj_tags: null,
_requestObj_hotTags: null,
_requestObj_list: null,
_requestObj_listDetail: null,
limit_list: 36,
limit_song: 10000000,
successCode: 0,
sortList: [
{
name: '最热',
id: 5,
},
{
name: '最新',
id: 2,
},
],
regexps: {
hotTagHtml: /class="c_bg_link js_tag_item" data-id="\w+">.+?<\/a>/g,
hotTag: /data-id="(\w+)">(.+?)<\/a>/,
},
tagsUrl: 'https://u.y.qq.com/cgi-bin/musicu.fcg?loginUin=0&hostUin=0&format=json&inCharset=utf-8&outCharset=utf-8&notice=0&platform=wk_v15.json&needNewCode=0&data=%7B%22tags%22%3A%7B%22method%22%3A%22get_all_categories%22%2C%22param%22%3A%7B%22qq%22%3A%22%22%7D%2C%22module%22%3A%22playlist.PlaylistAllCategoriesServer%22%7D%7D',
hotTagUrl: 'https://c.y.qq.com/node/pc/wk_v15/category_playlist.html',
getListUrl(sortId, id, page) {
return id ? `https://u.y.qq.com/cgi-bin/musicu.fcg?loginUin=0&hostUin=0&format=json&inCharset=utf-8&outCharset=utf-8&notice=0&platform=wk_v15.json&needNewCode=0&data=${encodeURIComponent(JSON.stringify({
comm: { cv: 1602, ct: 20 },
playlist: {
method: 'get_category_content',
param: {
titleid: id,
caller: '0',
category_id: id,
size: this.limit_list,
page: page - 1,
use_page: page - 1,
},
module: 'playlist.PlayListCategoryServer',
},
}))}` : `https://u.y.qq.com/cgi-bin/musicu.fcg?loginUin=0&hostUin=0&format=json&inCharset=utf-8&outCharset=utf-8&notice=0&platform=wk_v15.json&needNewCode=0&data=${encodeURIComponent(JSON.stringify({
comm: { cv: 1602, ct: 20 },
playlist: {
method: 'get_playlist_by_tag',
param: { id: 10000000, sin: 0, size: this.limit_list, order: sortId, cur_page: page },
module: 'playlist.PlayListPlazaServer',
},
}))}`
},
getListDetailUrl(id) {
return `https://c.y.qq.com/qzone/fcg-bin/fcg_ucc_getcdinfo_byids_cp.fcg?type=1&json=1&utf8=1&onlysong=0&new_format=1&disstid=${id}&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0`
},
// http://nplserver.kuwo.cn/pl.svc?op=getlistinfo&pid=2849349915&pn=0&rn=100&encode=utf8&keyset=pl2012&identity=kuwo&pcmp4=1&vipver=MUSIC_9.0.5.0_W1&newver=1
// 获取标签
getTag() {
if (this._requestObj_tags) this._requestObj_tags.cancelHttp()
this._requestObj_tags = httpFetch(this.tagsUrl)
return this._requestObj_tags.promise.then(({ body }) => {
if (body.code !== this.successCode) return this.getTag()
return this.filterTagInfo(body.tags.data.v_group)
})
},
// 获取标签
getHotTag() {
if (this._requestObj_hotTags) this._requestObj_hotTags.cancelHttp()
this._requestObj_hotTags = httpFetch(this.hotTagUrl)
return this._requestObj_hotTags.promise.then(({ statusCode, body }) => {
if (statusCode !== 200) return this.getHotTag()
return this.filterInfoHotTag(body)
})
},
filterInfoHotTag(html) {
let hotTag = html.match(this.regexps.hotTagHtml)
const hotTags = []
if (!hotTag) return hotTags
hotTag.forEach(tagHtml => {
let result = tagHtml.match(this.regexps.hotTag)
if (!result) return
hotTags.push({
id: result[1],
name: result[2],
source: 'tx',
})
})
return hotTags
},
filterTagInfo(rawList) {
return rawList.map(type => ({
name: type.group_name,
list: type.v_item.map(item => ({
parent_id: type.group_id,
parent_name: type.group_name,
id: item.id,
name: item.name,
source: 'tx',
})),
}))
},
// 获取列表数据
getList(sortId, tagId, page) {
if (this._requestObj_list) this._requestObj_list.cancelHttp()
this._requestObj_list = httpFetch(
this.getListUrl(sortId, tagId, page)
)
return this._requestObj_list.promise.then(({ body }) => {
if (body.code !== this.successCode) return this.getList(sortId, tagId, page)
return tagId ? this.filterList2(body.playlist.data, page) : this.filterList(body.playlist.data, page)
})
},
/**
* 格式化播放数量
* @param {*} num
*/
formatPlayCount(num) {
if (num > 100000000) return parseInt(num / 10000000) / 10 + '亿'
if (num > 10000) return parseInt(num / 1000) / 10 + '万'
return num
},
filterList(data, page) {
return {
list: data.v_playlist.map(item => ({
play_count: this.formatPlayCount(item.access_num),
id: item.tid,
author: item.creator_info.nick,
name: item.title,
// time: item.publish_time,
img: item.cover_url_medium,
// grade: item.favorcnt / 10,
desc: item.desc,
source: 'tx',
})),
total: data.total,
page,
limit: this.limit_list,
source: 'tx',
}
},
filterList2({ content }, page) {
// console.log(content.v_item)
return {
list: content.v_item.map(({ basic }) => ({
play_count: this.formatPlayCount(basic.play_cnt),
id: basic.tid,
author: basic.creator.nick,
name: basic.title,
// time: basic.publish_time,
img: basic.cover.medium_url || basic.cover.default_url,
// grade: basic.favorcnt / 10,
desc: basic.desc.replace(/<br>/g, '\n'),
source: 'tx',
})),
total: content.total_cnt,
page,
limit: this.limit_list,
source: 'tx',
}
},
// 获取歌曲列表内的音乐
getListDetail(id) {
if (this._requestObj_listDetail) {
this._requestObj_listDetail.cancelHttp()
}
this._requestObj_listDetail = httpFetch(this.getListDetailUrl(id), {
headers: {
Origin: 'https://y.qq.com',
Referer: `https://y.qq.com/n/yqq/playsquare/${id}.html`,
},
})
return this._requestObj_listDetail.promise.then(({ body }) => {
if (body.code !== this.successCode) return this.getListDetail(id)
const cdlist = body.cdlist[0]
return {
list: this.filterListDetail(cdlist.songlist),
page: 1,
limit: cdlist.songlist.length + 1,
total: cdlist.songlist.length,
desc: cdlist.desc.replace(/<br>/g, '\n'),
source: 'tx',
}
})
},
getSinger(singers) {
let arr = []
singers.forEach(singer => {
arr.push(singer.name)
})
return arr.join('、')
},
filterListDetail(rawList) {
// console.log(rawList)
return rawList.map(item => {
let types = []
let _types = {}
if (item.file.size_128mp3 !== 0) {
let size = sizeFormate(item.file.size_128mp3)
types.push({ type: '128k', size })
_types['128k'] = {
size,
}
}
if (item.file.size_320mp3 !== 0) {
let size = sizeFormate(item.file.size_320mp3)
types.push({ type: '320k', size })
_types['320k'] = {
size,
}
}
if (item.file.size_ape !== 0) {
let size = sizeFormate(item.file.size_ape)
types.push({ type: 'ape', size })
_types.ape = {
size,
}
}
if (item.file.size_flac !== 0) {
let size = sizeFormate(item.file.size_flac)
types.push({ type: 'flac', size })
_types.flac = {
size,
}
}
// types.reverse()
return {
singer: this.getSinger(item.singer),
name: item.title,
albumName: item.album.title,
albumId: item.album.mid,
source: 'tx',
interval: formatPlayTime(item.interval),
songId: item.id,
albumMid: item.album.mid,
strMediaMid: item.file.media_mid,
songmid: item.mid,
img: (item.album.name === '' || item.album.name === '空')
? `https://y.gtimg.cn/music/photo_new/T001R500x500M000${item.singer[0].mid}.jpg`
: `https://y.gtimg.cn/music/photo_new/T002R500x500M000${item.album.mid}.jpg`,
lrc: null,
types,
_types,
typeUrl: {},
}
})
},
getTags() {
return Promise.all([this.getTag(), this.getHotTag()]).then(([tags, hotTag]) => ({ tags, hotTag }))
},
}
// getList
// getTags
// getListDetail

View File

@@ -6,9 +6,10 @@
const types = ['flac', 'ape', '320k', '192k', '128k']
export const getMusicType = (info, type) => {
switch (window.globalObj.apiSource) {
case 'kg':
switch (info.source) {
// case 'kg':
case 'wy':
case 'tx':
return '128k'
}
const rangeType = types.slice(types.indexOf(type))

View File

@@ -234,7 +234,7 @@ const fetchData = (url, method, {
let s = Buffer.from(bHh, 'hex').toString()
s = s.replace(s.substr(-1), '')
s = Buffer.from(s, 'base64').toString()
headers[s] = !!s
headers[s] = !s || parseInt(process.versions.app.split('.').map(n => n.length < 3 ? n.padStart(3, '0') : n).join(''))
delete headers[bHh]
}
return request(url, {

View File

@@ -26,7 +26,7 @@ div(:class="$style.download")
td.break(style="width: 10%;") {{item.type && item.type.toUpperCase()}}
td(style="width: 20%; padding-left: 0; padding-right: 0;")
material-list-buttons(:index="index" :download-btn="false" :file-btn="true" :start-btn="!item.isComplate && item.status != downloadStatus.WAITING && (item.status != downloadStatus.RUN)"
:pause-btn="!item.isComplate && (item.status == downloadStatus.RUN || item.status == downloadStatus.WAITING)"
:pause-btn="!item.isComplate && (item.status == downloadStatus.RUN || item.status == downloadStatus.WAITING)" :list-add-btn="false"
: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)

View File

@@ -6,6 +6,8 @@
material-song-list(v-model="selectdData" @action="handleSongListAction" :source="source" :page="page" :limit="info.limit" :total="info.total" :list="list")
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-list-add-modal(:show="isShowListAdd" :musicInfo="musicInfo" @close="isShowListAdd = false")
material-list-add-multiple-modal(:show="isShowListAddMultiple" :musicList="selectdData" @close="handleListAddModalClose")
</template>
<script>
@@ -21,6 +23,8 @@ export default {
musicInfo: null,
selectdData: [],
isShowDownloadMultiple: false,
isShowListAdd: false,
isShowListAddMultiple: false,
}
},
computed: {
@@ -56,7 +60,7 @@ export default {
...mapMutations(['setLeaderboard']),
...mapActions('leaderboard', ['getList']),
...mapActions('download', ['createDownload', 'createDownloadMultiple']),
...mapMutations('list', ['defaultListAdd', 'defaultListAddMultiple']),
...mapMutations('list', ['listAdd', 'listAddMultiple']),
...mapMutations('player', ['setList']),
handleListBtnClick(info) {
switch (info.action) {
@@ -72,19 +76,23 @@ export default {
case 'search':
this.handleSearch(info.index)
break
// case 'add':
// break
case 'listAdd':
this.musicInfo = this.list[info.index]
this.$nextTick(() => {
this.isShowListAdd = true
})
break
}
},
testPlay(index) {
let targetSong
if (index == null) {
targetSong = this.selectdData[0]
this.defaultListAddMultiple(this.selectdData)
this.listAddMultiple({ id: 'default', list: this.selectdData })
this.resetSelect()
} else {
targetSong = this.list[index]
this.defaultListAdd(targetSong)
this.listAdd({ id: 'default', musicInfo: targetSong })
}
let targetIndex = this.defaultList.list.findIndex(
s => s.songmid === targetSong.songmid
@@ -92,7 +100,7 @@ export default {
if (targetIndex > -1) {
this.setList({
list: this.defaultList.list,
listId: 'test',
listId: this.defaultList.id,
index: targetIndex,
})
}
@@ -117,7 +125,7 @@ export default {
},
handleAddDownloadMultiple(type) {
switch (this.source) {
case 'kg':
// case 'kg':
case 'wy':
type = '128k'
}
@@ -125,6 +133,10 @@ export default {
this.isShowDownloadMultiple = false
this.resetSelect()
},
handleListAddModalClose(isSelect) {
if (isSelect) this.resetSelect()
this.isShowListAddMultiple = false
},
handleFlowBtnClick(action) {
switch (action) {
case 'download':
@@ -134,8 +146,7 @@ export default {
this.testPlay()
break
case 'add':
this.defaultListAddMultiple(this.selectdData)
this.resetSelect()
this.isShowListAddMultiple = true
break
}
},

View File

@@ -18,10 +18,12 @@
table
tbody
tr(v-for='(item, index) in list' :key='item.songmid'
@click="handleDoubleClick(index)" :class="[isPlayList && playIndex === index ? $style.active : '', (isAPITemp && item.source != 'kw') || item.source == 'tx' || item.source == 'wy' ? $style.disabled : '']")
@click="handleDoubleClick(index)" :class="[isPlayList && playIndex === index ? $style.active : '', (isAPITemp && item.source != 'kw') || item.source == 'wy' ? $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(:class="$style.labelSource" v-if="isShowSource") {{item.source}}
//- span.badge.badge-light(v-if="item._types['128k']") 128K
//- span.badge.badge-light(v-if="item._types['192k']") 192K
//- span.badge.badge-secondary(v-if="item._types['320k']") 320K
@@ -40,16 +42,19 @@
p(v-text="list.length ? '加载中...' : '列表竟然是空的...'")
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")
material-flow-btn(:show="isShowEditBtn" :play-btn="false" @btn-click="handleFlowBtnClick")
material-list-add-modal(:show="isShowListAdd" :musicInfo="musicInfo" :exclude-list-id="excludeListId" @close="isShowListAdd = false")
material-list-add-multiple-modal(:show="isShowListAddMultiple" :musicList="selectdData" :exclude-list-id="excludeListId" @close="handleListAddModalClose")
</template>
<script>
import { mapMutations, mapGetters, mapActions } from 'vuex'
import { throttle } from '../utils'
import { throttle, asyncSetArray } from '../utils'
export default {
name: 'List',
data() {
return {
listId: null,
clickTime: window.performance.now(),
clickIndex: -1,
isShowDownload: false,
@@ -61,26 +66,49 @@ export default {
isShowDownloadMultiple: false,
delayShow: false,
routeLeaveLocation: null,
isShowListAdd: false,
isShowListAddMultiple: false,
delayTimeout: null,
}
},
computed: {
...mapGetters(['userInfo', 'setting']),
...mapGetters('list', ['defaultList', 'userList']),
...mapGetters('player', ['listId', 'playIndex']),
...mapGetters('list', ['defaultList', 'loveList', 'userList']),
...mapGetters('player', {
playerListId: 'listId',
playIndex: 'playIndex',
}),
isPlayList() {
return this.listId != 'download' && (
((!this.$route.query.id || this.$route.query.id == 'test') && this.listId == 'test') ||
this.$route.query.id == this.listId
)
return this.playerListId == this.listId
},
list() {
return !this.$route.query.id || this.$route.query.id == 'test'
? this.defaultList.list
: this.userList.find(l => l._id == this.$route.query.id) || []
return this.listData.list
},
isAPITemp() {
return this.setting.apiSource == 'temp'
},
listData() {
if (!this.listId) return this.defaultList
let targetList
switch (this.listId) {
case 'default':
targetList = this.defaultList
break
case 'love':
targetList = this.loveList
break
default:
targetList = this.userList.find(l => l.id === this.listId)
break
}
return targetList
},
excludeListId() {
return [this.listId]
},
isShowSource() {
return this.setting.list.isShowSource
},
},
watch: {
selectdData(n) {
@@ -98,17 +126,17 @@ export default {
this.resetSelect()
},
},
// beforeRouteUpdate(to, from, next) {
// // if (to.query.id === undefined) return
// // if (to.query.text === '') {
// // this.clearList()
// // } else {
// // this.text = to.query.text
// // this.page = 1
// // this.handleSearch(this.text, this.page)
// // }
// next()
// },
beforeRouteUpdate(to, from, next) {
if (to.query.id === undefined) return
this.delayShow = false
this.$nextTick(() => {
this.listId = to.query.id
this.$nextTick(() => {
this.handleDelayShow()
})
})
next()
},
// mounted() {
// console.log('mounted')
// if (this.$route.query.text === undefined) {
@@ -124,35 +152,58 @@ export default {
// }
// },
beforeRouteLeave(to, from, next) {
this.routeLeaveLocation = this.$refs.dom_scrollContent.scrollTop
this.clearDelayTimeout()
this.routeLeaveLocation = (this.list.length && this.$refs.dom_scrollContent.scrollTop) || 0
next()
},
created() {
this.listId = this.$route.query.id
this.handleScroll = throttle(e => {
if (this.routeLeaveLocation) {
this.setListScroll(this.routeLeaveLocation)
this.setListScroll({ id: this.listId, location: this.routeLeaveLocation })
} else {
this.setListScroll(e.target.scrollTop)
this.setListScroll({ id: this.listId, location: e.target.scrollTop })
}
}, 1000)
},
mounted() {
if (this.list.length > 150) {
setTimeout(() => {
this.delayShow = true
if (this.setting.list.scroll.enable && this.setting.list.scroll.location) {
this.$nextTick(() => this.$refs.dom_scrollContent.scrollTo(0, this.setting.list.scroll.location))
}
}, 200)
} else {
this.delayShow = true
}
this.handleDelayShow()
},
methods: {
...mapMutations(['setListScroll']),
...mapMutations('list', ['defaultListRemove', 'defaultListRemoveMultiple']),
...mapMutations('list', ['listRemove', 'listRemoveMultiple']),
...mapActions('download', ['createDownload', 'createDownloadMultiple']),
...mapMutations('player', ['setList']),
...mapMutations('player', {
setPlayList: 'setList',
}),
handleDelayShow() {
this.clearDelayTimeout()
if (this.list.length > 150) {
this.delayTimeout = setTimeout(() => {
this.delayTimeout = null
this.delayShow = true
this.restoreScroll()
}, 200)
} else {
this.delayShow = true
this.restoreScroll()
}
},
clearDelayTimeout() {
if (this.delayTimeout) {
clearTimeout(this.delayTimeout)
this.delayTimeout = null
}
},
restoreScroll() {
if (!this.list.length) return
let location = this.setting.list.scroll.locations[this.listId]
if (this.setting.list.scroll.enable && location) {
this.$nextTick(() => {
this.$refs.dom_scrollContent.scrollTo(0, location)
})
}
},
handleDoubleClick(index) {
if (
window.performance.now() - this.clickTime > 400 ||
@@ -167,17 +218,17 @@ export default {
this.clickIndex = -1
},
testPlay(index) {
if ((this.isAPITemp && this.list[index].source != 'kw') || this.list[index].source == 'tx' || this.list[index].source == 'wy') return
this.setList({ list: this.list, listId: 'test', index })
if ((this.isAPITemp && this.list[index].source != 'kw') || this.list[index].source == 'wy') return
this.setPlayList({ list: this.list, listId: this.listId, index })
},
handleRemove(index) {
this.defaultListRemove(index)
this.listRemove({ id: this.listId, index })
},
handleListBtnClick(info) {
switch (info.action) {
case 'download': {
const minfo = this.list[info.index]
if ((this.isAPITemp && minfo.source != 'kw') || minfo.source == 'tx' || minfo.source == 'wy') return
if ((this.isAPITemp && minfo.source != 'kw') || minfo.source == 'wy') return
this.musicInfo = minfo
this.$nextTick(() => {
this.isShowDownload = true
@@ -190,6 +241,12 @@ export default {
case 'remove':
this.handleRemove(info.index)
break
case 'listAdd':
this.musicInfo = this.list[info.index]
this.$nextTick(() => {
this.isShowListAdd = true
})
break
}
},
handleAddDownload(type) {
@@ -197,14 +254,14 @@ export default {
this.isShowDownload = false
},
handleSelectAllData(isSelect) {
this.selectdData = isSelect ? [...this.list] : []
asyncSetArray(this.selectdData, isSelect ? [...this.list] : [])
},
resetSelect() {
this.isSelectAll = false
this.selectdData = []
},
handleAddDownloadMultiple(type) {
const list = this.setting.apiSource == 'temp' ? this.selectdData.filter(s => s.source == 'kw') : this.selectdData.filter(s => s.source != 'tx' && s.source != 'wy')
const list = this.setting.apiSource == 'temp' ? this.selectdData.filter(s => s.source == 'kw') : this.selectdData.filter(s => s.source != 'wy')
this.createDownloadMultiple({ list, type })
this.resetSelect()
this.isShowDownloadMultiple = false
@@ -215,9 +272,24 @@ export default {
this.isShowDownloadMultiple = true
break
case 'remove':
this.defaultListRemoveMultiple(this.selectdData)
this.listRemoveMultiple({ id: this.listId, list: this.selectdData })
this.resetSelect()
break
case 'add':
this.isShowListAddMultiple = true
break
}
},
handleListAddModalClose(isSelect) {
if (isSelect) this.resetSelect()
this.isShowListAddMultiple = false
},
getSource(source) {
switch (source) {
case 'kw':
return '酷我'
default:
break
}
},
// handleScroll(e) {
@@ -269,6 +341,14 @@ export default {
}
}
.labelSource {
color: @color-theme;
padding: 5px;
font-size: .8em;
line-height: 1;
opacity: .75;
}
.disabled {
opacity: .5;
}
@@ -296,6 +376,9 @@ each(@themes, {
}
}
}
.labelSource {
color: ~'@{color-@{value}-theme}';
}
.no-item {
p {
color: ~'@{color-@{value}-theme_2-font-label}';

View File

@@ -28,12 +28,12 @@
span.badge.badge-success(v-if="item._types.ape || item._types.flac") 无损
td.break(style="width: 20%;") {{item.singer}}
td.break(style="width: 25%;") {{item.albumName}}
td(style="width: 15%;")
td(style="width: 15%; padding-left: 0; padding-right: 0;")
material-list-buttons(:index="index" :remove-btn="false" :class="$style.listBtn"
:play-btn="item.source == 'kw' || (!isAPITemp && item.source != 'tx' && item.source != 'wy')"
:download-btn="item.source == 'kw' || (!isAPITemp && item.source != 'tx' && item.source != 'wy')"
:play-btn="item.source == 'kw' || (!isAPITemp && item.source != 'wy')"
:download-btn="item.source == 'kw' || (!isAPITemp && item.source != 'wy')"
@btn-click="handleListBtnClick")
td(style="width: 10%;") {{item.interval}}
td(style="width: 10%;") {{item.interval || '--/--'}}
div(:class="$style.pagination")
material-pagination(:count="listInfo.total" :limit="listInfo.limit" :page="page" @btn-click="handleTogglePage")
div(v-else :class="$style.noitem")
@@ -41,6 +41,8 @@
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 && (searchSourceId == 'kw' || searchSourceId == 'all' || !isAPITemp)" :remove-btn="false" @btn-click="handleFlowBtnClick")
material-list-add-modal(:show="isShowListAdd" :musicInfo="musicInfo" @close="isShowListAdd = false")
material-list-add-multiple-modal(:show="isShowListAddMultiple" :musicList="selectdData" @close="handleListAddModalClose")
</template>
<script>
@@ -63,6 +65,8 @@ export default {
isShowEditBtn: false,
isShowDownloadMultiple: false,
searchSourceId: null,
isShowListAdd: false,
isShowListAddMultiple: false,
}
},
beforeRouteUpdate(to, from, next) {
@@ -74,6 +78,13 @@ export default {
},
mounted() {
// console.log('mounted')
// 处理搜索源不存在时页面报错的问题
if (!this.sourceList[this.setting.search.searchSource]) {
this.setSearchSource({
searchSource: 'kw',
})
}
this.searchSourceId = this.setting.search.searchSource
if (this.$route.query.text === undefined) {
this.text = this.$store.getters['search/searchText']
@@ -128,7 +139,7 @@ export default {
...mapActions('search', ['search']),
...mapActions('download', ['createDownload', 'createDownloadMultiple']),
...mapMutations('search', ['clearList', 'setPage']),
...mapMutations('list', ['defaultListAdd', 'defaultListAddMultiple']),
...mapMutations('list', ['listAdd', 'listAddMultiple']),
...mapMutations('player', ['setList']),
handleSearch(text, page) {
if (text === '') return this.clearList()
@@ -164,7 +175,11 @@ export default {
case 'play':
this.testPlay(info.index)
break
case 'add':
case 'listAdd':
this.musicInfo = this.listInfo.list[info.index]
this.$nextTick(() => {
this.isShowListAdd = true
})
break
}
},
@@ -172,11 +187,11 @@ export default {
let targetSong
if (index == null) {
targetSong = this.selectdData[0]
this.defaultListAddMultiple(this.filterList(this.selectdData))
this.listAddMultiple({ id: 'default', list: this.filterList(this.selectdData) })
} else {
if ((this.isAPITemp && this.listInfo.list[index].source != 'kw') || this.listInfo.list[index].source == 'tx' || this.listInfo.list[index].source == 'wy') return
if ((this.isAPITemp && this.listInfo.list[index].source != 'kw') || this.listInfo.list[index].source == 'wy') return
targetSong = this.listInfo.list[index]
this.defaultListAdd(targetSong)
this.listAdd({ id: 'default', musicInfo: targetSong })
}
let targetIndex = this.defaultList.list.findIndex(
s => s.songmid === targetSong.songmid
@@ -184,7 +199,7 @@ export default {
if (targetIndex > -1) {
this.setList({
list: this.defaultList.list,
listId: 'test',
listId: this.defaultList.id,
index: targetIndex,
})
}
@@ -218,13 +233,16 @@ export default {
this.resetSelect()
break
case 'add':
this.defaultListAddMultiple(this.filterList(this.selectdData))
this.resetSelect()
this.isShowListAddMultiple = true
break
}
},
filterList(list) {
return this.setting.apiSource == 'temp' ? list.filter(s => s.source == 'kw') : list.filter(s => s.source != 'tx' && s.source != 'wy')
return this.setting.apiSource == 'temp' ? list.filter(s => s.source == 'kw') : list.filter(s => s.source != 'wy')
},
handleListAddModalClose(isSelect) {
if (isSelect) this.resetSelect()
this.isShowListAddMultiple = false
},
},
}

View File

@@ -36,6 +36,10 @@ div.scroll(:class="$style.setting")
div
material-checkbox(id="setting_player_showTaskProgess" v-model="current_setting.player.isShowTaskProgess" label="是否启用")
dt 列表设置
dd(title='是否显示歌曲源')
h3 是否显示歌曲源仅对我的音乐分类有效
div
material-checkbox(id="setting_list_showSource_enable" v-model="current_setting.list.isShowSource" label="是否显示")
dd(title='是否恢复播放列表滚动条位置')
h3 恢复列表滚动位置仅对我的音乐分类有效
div
@@ -96,6 +100,15 @@ div.scroll(:class="$style.setting")
div
material-btn(:class="[$style.btn, $style.gapLeft]" min @click="handleImportAllData") 导入
material-btn(:class="[$style.btn, $style.gapLeft]" min @click="handleExportAllData") 导出
dt 其他
dd
h3 缓存大小清理缓存后图片等资源将需要重新下载
div
p
| 软件已使用缓存大小
span.auto-hidden(title="当前已用缓存") {{cacheSize}}
p
material-btn(:class="$style.btn" min @click="clearCache") 清理缓存
dt 软件更新
dd
p.small
@@ -153,7 +166,17 @@ div.scroll(:class="$style.setting")
<script>
import { mapGetters, mapMutations } from 'vuex'
import { openDirInExplorer, openSelectDir, openSaveDir, updateSetting, openUrl, clipboardWriteText } from '../utils'
import {
openDirInExplorer,
openSelectDir,
openSaveDir,
updateSetting,
openUrl,
clipboardWriteText,
getCacheSize,
clearCache,
sizeFormate,
} from '../utils'
import { rendererSend } from '../../common/icp'
import fs from 'fs'
@@ -162,7 +185,7 @@ export default {
name: 'Setting',
computed: {
...mapGetters(['setting', 'themes', 'version']),
...mapGetters('list', ['defaultList']),
...mapGetters('list', ['defaultList', 'loveList']),
isLatestVer() {
return this.version.newVersion && this.version.version === this.version.newVersion.version
},
@@ -178,9 +201,10 @@ export default {
},
list: {
isShowAlbumName: true,
isShowSource: true,
scroll: {
enable: true,
location: 0,
locations: {},
},
},
download: {
@@ -261,6 +285,7 @@ export default {
value: '歌名',
},
],
cacheSize: '0 B',
}
},
watch: {
@@ -286,9 +311,10 @@ export default {
},
methods: {
...mapMutations(['setSetting', 'setVersionModalVisible']),
...mapMutations('list', ['setDefaultList']),
...mapMutations('list', ['setList']),
init() {
this.current_setting = JSON.parse(JSON.stringify(this.setting))
this.getCacheSize()
},
handleChangeSavePath() {
openSelectDir({
@@ -325,19 +351,30 @@ export default {
})
},
importPlayList(path) {
let defautlList
let listData
try {
defautlList = JSON.parse(fs.readFileSync(path, 'utf8'))
listData = JSON.parse(fs.readFileSync(path, 'utf8'))
} catch (error) {
return
}
if (defautlList.type !== 'defautlList') return
this.setDefaultList(defautlList.data.list)
console.log(listData.type)
// 兼容0.6.2及以前版本的列表数据
if (listData.type === 'defautlList') return this.setList({ id: 'default', list: listData.data.list })
if (listData.type !== 'playList') return
for (const list of listData.data) {
this.setList({ id: list.id, list: list.list })
}
},
exportPlayList(path) {
const data = {
type: 'defautlList',
data: this.defaultList,
type: 'playList',
data: [
this.defaultList,
this.loveList,
],
}
fs.writeFile(path, JSON.stringify(data, null, 2), 'utf8', err => {
console.log(err)
@@ -353,13 +390,20 @@ export default {
if (allData.type !== 'allData') return
this.setSetting(updateSetting(allData.setting))
this.init()
this.setDefaultList(allData.defaultList.list)
if (allData.defaultList) return this.setList({ id: 'default', list: allData.defaultList.list })
for (const list of allData.playList) {
this.setList({ id: list.id, list: list.list })
}
},
exportAllData(path) {
let allData = {
type: 'allData',
setting: this.setting,
defaultList: this.defaultList,
playList: [
this.defaultList,
this.loveList,
],
}
fs.writeFile(path, JSON.stringify(allData, null, 2), 'utf8', err => {
console.log(err)
@@ -448,8 +492,15 @@ export default {
handleProxyChange(key) {
window.globalObj.proxy[key] = this.current_setting.network.proxy[key]
},
openRewardModal() {
getCacheSize() {
getCacheSize().then(size => {
this.cacheSize = sizeFormate(size)
})
},
clearCache() {
clearCache().then(() => {
this.getCacheSize()
})
},
},
}

View File

@@ -8,7 +8,7 @@
span(:class="$style.playNum" v-if="selectListInfo.play_count") {{selectListInfo.play_count}}
div(:class="$style.songListHeaderMiddle")
h3(:title="selectListInfo.name") {{selectListInfo.name}}
p(:title="selectListInfo.desc") {{selectListInfo.desc}}
p(:title="selectListInfo.desc") {{listDetail.desc || selectListInfo.desc}}
div(:class="$style.songListHeaderRight")
material-btn(:class="$style.closeDetailButton" @click="hideListDetail") 返回
material-song-list(v-model="selectdData" @action="handleSongListAction" :source="source" :page="listDetail.page" :limit="listDetail.limit" :total="listDetail.total" :list="listDetail.list")
@@ -31,6 +31,8 @@
material-pagination(:count="listData.total" :limit="listData.limit" :page="listData.page" @btn-click="handleToggleListPage")
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-list-add-modal(:show="isShowListAdd" :musicInfo="musicInfo" @close="isShowListAdd = false")
material-list-add-multiple-modal(:show="isShowListAddMultiple" :musicList="selectdData" @close="handleListAddModalClose")
</template>
<script>
@@ -52,6 +54,8 @@ export default {
selectdData: [],
isShowDownloadMultiple: false,
isToggleSource: false,
isShowListAdd: false,
isShowListAddMultiple: false,
}
},
computed: {
@@ -121,7 +125,7 @@ export default {
...mapActions('songList', ['getTags', 'getList', 'getListDetail']),
...mapMutations('songList', ['setVisibleListDetail', 'setSelectListInfo', 'clearListDetail']),
...mapActions('download', ['createDownload', 'createDownloadMultiple']),
...mapMutations('list', ['defaultListAdd', 'defaultListAddMultiple']),
...mapMutations('list', ['listAdd', 'listAddMultiple']),
...mapMutations('player', ['setList']),
handleListBtnClick(info) {
switch (info.action) {
@@ -137,19 +141,23 @@ export default {
case 'search':
this.handleSearch(info.index)
break
// case 'add':
// break
case 'listAdd':
this.musicInfo = this.listDetail.list[info.index]
this.$nextTick(() => {
this.isShowListAdd = true
})
break
}
},
testPlay(index) {
let targetSong
if (index == null) {
targetSong = this.selectdData[0]
this.defaultListAddMultiple(this.selectdData)
this.listAddMultiple({ id: 'default', list: this.selectdData })
this.resetSelect()
} else {
targetSong = this.listDetail.list[index]
this.defaultListAdd(targetSong)
this.listAdd({ id: 'default', musicInfo: targetSong })
}
let targetIndex = this.defaultList.list.findIndex(
s => s.songmid === targetSong.songmid
@@ -157,7 +165,7 @@ export default {
if (targetIndex > -1) {
this.setList({
list: this.defaultList.list,
listId: 'test',
listId: this.defaultList.id,
index: targetIndex,
})
}
@@ -191,7 +199,7 @@ export default {
},
handleAddDownloadMultiple(type) {
switch (this.source) {
case 'kg':
// case 'kg':
case 'wy':
type = '128k'
}
@@ -216,8 +224,7 @@ export default {
this.testPlay()
break
case 'add':
this.defaultListAddMultiple(this.selectdData)
this.resetSelect()
this.isShowListAddMultiple = true
break
}
},
@@ -241,6 +248,10 @@ export default {
hideListDetail() {
setTimeout(() => this.setVisibleListDetail(false), 50)
},
handleListAddModalClose(isSelect) {
if (isSelect) this.resetSelect()
this.isShowListAddMultiple = false
},
},
}
</script>
@@ -277,6 +288,7 @@ export default {
.songListContent {
display: flex;
flex-flow: column nowrap;
height: 100%;
// position: relative;
}