mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/lyswhut/lx-music-desktop.git
synced 2026-09-20 08:04:00 +08:00
Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
74f8e9544b | ||
|
|
0a5e7c44ff | ||
|
|
5c32160a58 | ||
|
|
2fc81c03ec | ||
|
|
cc485df42f | ||
|
|
d575dd24ca | ||
|
|
e47586cea3 | ||
|
|
1ce63c7550 | ||
|
|
36d69da3b7 | ||
|
|
529be08420 | ||
|
|
ffe11c7015 | ||
|
|
76b796bde7 | ||
|
|
f81715f07f | ||
|
|
ec3f667b75 | ||
|
|
87f0b4fd17 | ||
|
|
c7e95c5166 | ||
|
|
6ea0837cce | ||
|
|
59627e048f | ||
|
|
45fea5726b | ||
|
|
e539f29f6d | ||
|
|
1d2810e98f | ||
|
|
1cbafc9750 | ||
|
|
e675f7ac06 | ||
|
|
9dc9d3b1b7 | ||
|
|
a104ce688e | ||
|
|
2dd1ceb0b9 | ||
|
|
9379328d96 | ||
|
|
d8969c327c | ||
|
|
c3624fb7d6 | ||
|
|
b2de230100 | ||
|
|
9d0bf50931 | ||
|
|
843e453b21 | ||
|
|
f7546b0090 | ||
|
|
ed12aac7d8 | ||
|
|
15f4053241 | ||
|
|
7a334f0099 | ||
|
|
4a510393ab | ||
|
|
52b0638258 | ||
|
|
b198b1945d | ||
|
|
10784e95bb | ||
|
|
f4c65516d0 | ||
|
|
6498305ec8 | ||
|
|
7a91e6efef | ||
|
|
4204b62f8f | ||
|
|
70b718d372 | ||
|
|
2b5d6f3592 | ||
|
|
8e48d5ba68 | ||
|
|
3cec62d1a9 | ||
|
|
b1650bcbee | ||
|
|
492e3d8965 | ||
|
|
6d7be78b70 | ||
|
|
bac9439f8e | ||
|
|
5b612bfa0f | ||
|
|
1f77b3dd4b | ||
|
|
b0d7a53d15 | ||
|
|
c029eccdd3 | ||
|
|
7236f8929c |
17
.github/ISSUE_TEMPLATE/----.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE/----.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
name: 功能请求
|
||||
about: 为这个项目提出一个想法
|
||||
title: 例如:添加xxx功能、优化xxx功能
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**描述您想要的解决方案**
|
||||
简洁明了地描述您要发生的事情。
|
||||
|
||||
**描述您考虑过的替代方案**
|
||||
对您考虑过的所有替代解决方案或功能的简洁明了的描述。
|
||||
|
||||
**其他内容**
|
||||
在此处添加有关功能请求的任何其他上下文或屏幕截图。
|
||||
31
.github/ISSUE_TEMPLATE/--bug.md
vendored
Normal file
31
.github/ISSUE_TEMPLATE/--bug.md
vendored
Normal 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]
|
||||
|
||||
**其他内容**
|
||||
在此处添加有关该问题的任何其他上下文。
|
||||
72
CHANGELOG.md
72
CHANGELOG.md
@@ -6,6 +6,78 @@ 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.8.2](https://github.com/lyswhut/lx-music-desktop/compare/v0.8.1...v0.8.2) - 2019-10-20
|
||||
|
||||
#### 修复
|
||||
|
||||
- 兼容旧版酷我源搜索列表过滤128k音质的bug(注:0.8.1版本仅修复了酷我源的歌曲过滤问题,该修复仅对以后添加的歌曲有效,如果是之前添加的歌曲仍会出现这个问题,现修复对之前旧列表数据的兼容处理)
|
||||
|
||||
## [0.8.1](https://github.com/lyswhut/lx-music-desktop/compare/v0.8.0...v0.8.1) - 2019-10-20
|
||||
|
||||
#### 修复
|
||||
|
||||
- 修复酷我源搜索歌曲结果未添加128k音质导致播放128k音质时显示“该歌曲没有可播放的音频”的问题
|
||||
|
||||
## [0.8.0](https://github.com/lyswhut/lx-music-desktop/compare/v0.7.0...v0.8.0) - 2019-10-19
|
||||
|
||||
#### 新增
|
||||
|
||||
- 新增网易云源歌曲搜索
|
||||
- 新增网易云源歌单
|
||||
- 新增各平台通过输入歌单链接或歌单ID打开歌单详情列表,目前只适配了**网页版歌单链接**,其他方式的歌单链接可能无法解析,但你可想办法获取歌单ID后输入打开。注:各平台歌单ID均为纯数字,若遇到链接里存在歌单ID但无法解析的歌单链接,可以到GitHub提交issue或发送邮件或加群830125506反馈!
|
||||
- 新增音量调整滑动功能,现在支持鼠标左右拖动调整音量了
|
||||
|
||||
#### 优化
|
||||
|
||||
- 优化搜索框搜索体验
|
||||
- 优化音量条交互视觉效果
|
||||
- 缓存歌单详情列表数据
|
||||
|
||||
#### 修复
|
||||
|
||||
- 修复QQ源歌单无法翻页Bug
|
||||
- 修复默认列表没有创建时无法显示收藏列表的Bug
|
||||
- 修复网易云128k直接试听
|
||||
- 修复歌曲音质不存在时仍然播放或下载的Bug
|
||||
- 修复调整音量时,调整的位置与鼠标点击的位置不一致的问题
|
||||
|
||||
## [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
|
||||
|
||||
### 新增
|
||||
|
||||
60
FAQ.md
Normal file
60
FAQ.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# lx-music-desktop 常见问题
|
||||
|
||||
在阅读本常见问题后,仍然无法解决你的问题,请提交issue或者加企鹅群`830125506`反馈,反馈时请**注明**已阅读常见问题!
|
||||
|
||||
## 软件为什么没有桌面歌词与自定义列表功能
|
||||
|
||||
洛雪音乐的最初定位不是作为播放器开发的,它主要用于**查找歌曲**,软件的播放功能仅用于试听,不建议用作为常用播放器使用,因此无桌面、界面歌词,不可自定义列表。
|
||||
|
||||
## 歌曲无法试听与下载
|
||||
|
||||
该问题解决顺序如下:
|
||||
|
||||
1. 尝试更新到最新版本
|
||||
2. 尝试切换其他歌曲(或直接搜索该歌曲),若全部歌曲都无法试听与下载则进行下一步
|
||||
3. 尝试到设置-接口来源切换到其他接口
|
||||
4. 尝试切换网络,比如用手机开热点(目前存在某些网络无法访问接口服务器的情况)
|
||||
5. 若还不行请到这个链接查看详情:<https://github.com/lyswhut/lx-music-desktop/issues/5>
|
||||
6. 若没有在第5条链接中的第一条评论中看到接口无法使用的说明,则应该是你网络无法访问接口服务器的问题,如果接口有问题我会在那里说明。
|
||||
|
||||
想要知道是不是自己网络的问题可以看看`https://ts.tempmusic.tk`能不能在浏览器打开,浏览器显示404是正常的,如果不是404那就证明所在网络无法访问接口服务器。
|
||||
若网页无法打开或打来不是404,则应该是DNS的问题,可以尝试以下办法:
|
||||
|
||||
1. 改成自动获取试试
|
||||
2. 手动把DNS改一下,不要用360的DNS,可以把DNS改成`114.114.114.114`、`8.8.8.8`
|
||||
3. 软件设置里面的代理不要勾起来
|
||||
|
||||
## 软件安装包说明
|
||||
|
||||
软件发布页及网盘中有多个类型的安装文件,以下是对这些类型文件的说明:
|
||||
|
||||
文件名带 `win_` 的是在Windows系统上运行的版本,<br>
|
||||
其中安装版(Setup)可自动更新软件,<br>
|
||||
绿色版(green)为免安装版,自动更新功能不可用;
|
||||
|
||||
以 **`.dmg`** 结尾的文件为 MAC 版本;
|
||||
|
||||
以 **`.AppImage`**、**`.deb`** 结尾的为 Linux 版本。
|
||||
|
||||
带有`x64`的为64位的系统版本,带`x86`的为32位的系统版本;若两个都带有的则为集合版,安装时会自动根据系统位数选择对应的版本安装。
|
||||
|
||||
## 软件更新
|
||||
|
||||
软件启动时若发现新版本时会自动从本仓库下载安装包,下载完毕会弹窗提示更新。<br>
|
||||
若下载未完成时软件被关闭,下次启动软件会再次自动下载。<br>
|
||||
若还是**更新失败**,可能是无法访问GitHub导致的,这时需要手动更新,即下载最新安装包直接覆盖安装即可。<br>
|
||||
注意:**绿色版**的软件自动更新功能**不可用**,建议使用安装版!!<br>
|
||||
注意:**Mac版**、**Linux deb**版不支持自动更新!
|
||||
|
||||
## Windows 7 下界面异常
|
||||
|
||||
当 win7 没有开启**透明效果**时界面将会显示异常,开启方法请自行百度。<br>
|
||||
对于一些开启透明效果后仍然无法正常显示界面的系统,我也不知道是什么原因导致的,只能说正常的系统是没有这个问题的,如果你知道原因导致的欢迎反馈!
|
||||
|
||||
## 安装版安装失败,提示应用未安装
|
||||
|
||||
对于部分电脑出现安装失败的问题我也不懂什么原因,,可以尝试清理下安装文件,或者重启电脑试试。
|
||||
|
||||
## 缺少`xxx.dll`
|
||||
|
||||
这个是电脑缺少某些dll导致的,正常的系统是没有这个问题的,解决办法需自行百度弹出的错误信息看下别人是怎么解决的。
|
||||
50
README.md
50
README.md
@@ -49,11 +49,6 @@
|
||||
或者到网盘下载(网盘内有MAC、windows版):`https://www.lanzous.com/b906260/` 密码:`glqw`<br>
|
||||
使用常见问题请转至:[常见问题](https://github.com/lyswhut/lx-music-desktop#常见问题)
|
||||
|
||||
#### TODO
|
||||
|
||||
- [ ] 新增拉取各大平台歌单
|
||||
- [ ] 新增聚合搜索
|
||||
|
||||
### 源码使用方法
|
||||
|
||||
环境要求:Node.js 12.x
|
||||
@@ -76,50 +71,7 @@ npm run pack
|
||||
|
||||
### 常见问题
|
||||
|
||||
#### 歌曲无法试听与下载
|
||||
|
||||
该问题解决顺序如下:
|
||||
|
||||
1. 尝试更新到最新版本
|
||||
2. 尝试切换其他歌曲(或直接搜索该歌曲),若全部歌曲都无法试听与下载则进行下一步
|
||||
3. 尝试到设置-接口来源切换到其他接口
|
||||
4. 尝试切换网络,比如用手机开热点(目前存在某些网络无法访问接口服务器的情况)
|
||||
5. 若还不行请到这个链接查看详情:<https://github.com/lyswhut/lx-music-desktop/issues/5>
|
||||
6. 若没有在第5条链接中的第一条评论中看到接口无法使用的说明,则应该是你网络无法访问接口服务器的问题,如果接口有问题我会在那里说明。
|
||||
|
||||
#### 软件安装包说明
|
||||
|
||||
软件发布页及网盘中有多个类型的安装文件,以下是对这些类型文件的说明:
|
||||
|
||||
文件名带 `win_` 的是在Windows系统上运行的版本,<br>
|
||||
其中安装版(Setup)可自动更新软件,<br>
|
||||
绿色版(green)为免安装版,自动更新功能不可用;
|
||||
|
||||
以 **`.dmg`** 结尾的文件为 MAC 版本;
|
||||
|
||||
以 **`.AppImage`**、**`.deb`** 结尾的为 Linux 版本。
|
||||
|
||||
带有`x64`的为64位的系统版本,带`x86`的为32位的系统版本;若两个都带有的则为集合版,安装时会自动根据系统位数选择对应的版本安装。
|
||||
|
||||
#### 软件更新
|
||||
|
||||
软件启动时若发现新版本时会自动从本仓库下载安装包,下载完毕会弹窗提示更新。<br>
|
||||
若下载未完成时软件被关闭,下次启动软件会再次自动下载。<br>
|
||||
若还是**更新失败**,可能是无法访问GitHub导致的,这时需要手动更新,即下载最新安装包直接覆盖安装即可。<br>
|
||||
注意:**绿色版**的软件自动更新功能**不可用**,建议使用安装版!!<br>
|
||||
注意:**Mac版**、**Linux deb**版不支持自动更新!
|
||||
|
||||
#### Windows 7 下界面异常
|
||||
|
||||
当 win7 没有开启**透明效果**时界面将会显示异常,开启方法请自行百度。
|
||||
|
||||
#### 安装版安装失败,提示应用未安装
|
||||
|
||||
对于部分电脑出现安装失败的问题我也不懂什么原因,,可以尝试清理下安装文件,或者重启电脑试试。
|
||||
|
||||
#### 缺少`xxx.dll`
|
||||
|
||||
这个是电脑缺少某些dll导致的,正常的系统是没有这个问题的,解决办法需自行百度弹出的错误信息看下别人是怎么解决的。
|
||||
常见问题已移至:<https://github.com/lyswhut/lx-music-desktop/blob/master/FAQ.md>
|
||||
|
||||
### 致谢
|
||||
|
||||
|
||||
495
package-lock.json
generated
495
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "lx-music-desktop",
|
||||
"version": "0.6.0",
|
||||
"version": "0.7.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -26,18 +26,18 @@
|
||||
}
|
||||
},
|
||||
"@babel/core": {
|
||||
"version": "7.6.2",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/core/download/@babel/core-7.6.2.tgz",
|
||||
"integrity": "sha1-Bpp3bo1enu//diNryIRVZr0x3ZE=",
|
||||
"version": "7.6.4",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/core/download/@babel/core-7.6.4.tgz",
|
||||
"integrity": "sha1-br2f4Akl9sPhd7tyahiLX1eAiP8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.5.5",
|
||||
"@babel/generator": "^7.6.2",
|
||||
"@babel/generator": "^7.6.4",
|
||||
"@babel/helpers": "^7.6.2",
|
||||
"@babel/parser": "^7.6.2",
|
||||
"@babel/parser": "^7.6.4",
|
||||
"@babel/template": "^7.6.0",
|
||||
"@babel/traverse": "^7.6.2",
|
||||
"@babel/types": "^7.6.0",
|
||||
"@babel/traverse": "^7.6.3",
|
||||
"@babel/types": "^7.6.3",
|
||||
"convert-source-map": "^1.1.0",
|
||||
"debug": "^4.1.0",
|
||||
"json5": "^2.1.0",
|
||||
@@ -57,43 +57,54 @@
|
||||
}
|
||||
},
|
||||
"@babel/generator": {
|
||||
"version": "7.6.2",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/generator/download/@babel/generator-7.6.2.tgz",
|
||||
"integrity": "sha1-2sijwt8RgzTCop/zRG2hY2qPjAM=",
|
||||
"version": "7.6.4",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/generator/download/@babel/generator-7.6.4.tgz?cache=0&sync_timestamp=1570717897603&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fgenerator%2Fdownload%2F%40babel%2Fgenerator-7.6.4.tgz",
|
||||
"integrity": "sha1-pPhDcoe/lnGwf0g7duO7cxvJdnE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.6.0",
|
||||
"@babel/types": "^7.6.3",
|
||||
"jsesc": "^2.5.1",
|
||||
"lodash": "^4.17.13",
|
||||
"source-map": "^0.5.0"
|
||||
}
|
||||
},
|
||||
"@babel/parser": {
|
||||
"version": "7.6.2",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/parser/download/@babel/parser-7.6.2.tgz?cache=0&sync_timestamp=1569286082477&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fparser%2Fdownload%2F%40babel%2Fparser-7.6.2.tgz",
|
||||
"integrity": "sha1-IF6cleFro7i5YJBnemfJ1gdbcKE=",
|
||||
"version": "7.6.4",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/parser/download/@babel/parser-7.6.4.tgz?cache=0&sync_timestamp=1570718702664&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fparser%2Fdownload%2F%40babel%2Fparser-7.6.4.tgz",
|
||||
"integrity": "sha1-y5s2p0ghECgtXLbdQk7JJitHPYE=",
|
||||
"dev": true
|
||||
},
|
||||
"@babel/traverse": {
|
||||
"version": "7.6.2",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/traverse/download/@babel/traverse-7.6.2.tgz",
|
||||
"integrity": "sha1-sOK/1AHTOc4ObAVpAgbR4RUCziw=",
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/traverse/download/@babel/traverse-7.6.3.tgz",
|
||||
"integrity": "sha1-ZtfboUawhnA8D7EN1Yi3NkzsR/k=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.5.5",
|
||||
"@babel/generator": "^7.6.2",
|
||||
"@babel/generator": "^7.6.3",
|
||||
"@babel/helper-function-name": "^7.1.0",
|
||||
"@babel/helper-split-export-declaration": "^7.4.4",
|
||||
"@babel/parser": "^7.6.2",
|
||||
"@babel/types": "^7.6.0",
|
||||
"@babel/parser": "^7.6.3",
|
||||
"@babel/types": "^7.6.3",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0",
|
||||
"lodash": "^4.17.13"
|
||||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/types/download/@babel/types-7.6.3.tgz",
|
||||
"integrity": "sha1-PwfZb4VPmOL71FxksMuULRHougk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esutils": "^2.0.2",
|
||||
"lodash": "^4.17.13",
|
||||
"to-fast-properties": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
@@ -101,9 +112,9 @@
|
||||
}
|
||||
},
|
||||
"json5": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npm.taobao.org/json5/download/json5-2.1.0.tgz",
|
||||
"integrity": "sha1-56DGLEgoXGKNIKELhcibuAfDKFA=",
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npm.taobao.org/json5/download/json5-2.1.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson5%2Fdownload%2Fjson5-2.1.1.tgz",
|
||||
"integrity": "sha1-gbbLBOm6SW8ccAXQe0NoomOPkLY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "^1.2.0"
|
||||
@@ -357,38 +368,64 @@
|
||||
}
|
||||
},
|
||||
"@babel/generator": {
|
||||
"version": "7.6.2",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/generator/download/@babel/generator-7.6.2.tgz",
|
||||
"integrity": "sha1-2sijwt8RgzTCop/zRG2hY2qPjAM=",
|
||||
"version": "7.6.4",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/generator/download/@babel/generator-7.6.4.tgz?cache=0&sync_timestamp=1570717897603&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fgenerator%2Fdownload%2F%40babel%2Fgenerator-7.6.4.tgz",
|
||||
"integrity": "sha1-pPhDcoe/lnGwf0g7duO7cxvJdnE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.6.0",
|
||||
"@babel/types": "^7.6.3",
|
||||
"jsesc": "^2.5.1",
|
||||
"lodash": "^4.17.13",
|
||||
"source-map": "^0.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/types": {
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/types/download/@babel/types-7.6.3.tgz",
|
||||
"integrity": "sha1-PwfZb4VPmOL71FxksMuULRHougk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esutils": "^2.0.2",
|
||||
"lodash": "^4.17.13",
|
||||
"to-fast-properties": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/parser": {
|
||||
"version": "7.6.2",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/parser/download/@babel/parser-7.6.2.tgz?cache=0&sync_timestamp=1569286082477&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fparser%2Fdownload%2F%40babel%2Fparser-7.6.2.tgz",
|
||||
"integrity": "sha1-IF6cleFro7i5YJBnemfJ1gdbcKE=",
|
||||
"version": "7.6.4",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/parser/download/@babel/parser-7.6.4.tgz?cache=0&sync_timestamp=1570718702664&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fparser%2Fdownload%2F%40babel%2Fparser-7.6.4.tgz",
|
||||
"integrity": "sha1-y5s2p0ghECgtXLbdQk7JJitHPYE=",
|
||||
"dev": true
|
||||
},
|
||||
"@babel/traverse": {
|
||||
"version": "7.6.2",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/traverse/download/@babel/traverse-7.6.2.tgz",
|
||||
"integrity": "sha1-sOK/1AHTOc4ObAVpAgbR4RUCziw=",
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/traverse/download/@babel/traverse-7.6.3.tgz",
|
||||
"integrity": "sha1-ZtfboUawhnA8D7EN1Yi3NkzsR/k=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.5.5",
|
||||
"@babel/generator": "^7.6.2",
|
||||
"@babel/generator": "^7.6.3",
|
||||
"@babel/helper-function-name": "^7.1.0",
|
||||
"@babel/helper-split-export-declaration": "^7.4.4",
|
||||
"@babel/parser": "^7.6.2",
|
||||
"@babel/types": "^7.6.0",
|
||||
"@babel/parser": "^7.6.3",
|
||||
"@babel/types": "^7.6.3",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0",
|
||||
"lodash": "^4.17.13"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/types": {
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/types/download/@babel/types-7.6.3.tgz",
|
||||
"integrity": "sha1-PwfZb4VPmOL71FxksMuULRHougk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esutils": "^2.0.2",
|
||||
"lodash": "^4.17.13",
|
||||
"to-fast-properties": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
@@ -568,9 +605,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/plugin-transform-block-scoping": {
|
||||
"version": "7.6.2",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-block-scoping/download/@babel/plugin-transform-block-scoping-7.6.2.tgz",
|
||||
"integrity": "sha1-lsM6uXqa5QDMb1sZ4Ep+ZVM2Cnk=",
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-block-scoping/download/@babel/plugin-transform-block-scoping-7.6.3.tgz?cache=0&sync_timestamp=1570565315466&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-block-scoping%2Fdownload%2F%40babel%2Fplugin-transform-block-scoping-7.6.3.tgz",
|
||||
"integrity": "sha1-boVOUfu6qENRsV1N2v40LzpdVCo=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-plugin-utils": "^7.0.0",
|
||||
@@ -723,9 +760,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/plugin-transform-named-capturing-groups-regex": {
|
||||
"version": "7.6.2",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-named-capturing-groups-regex/download/@babel/plugin-transform-named-capturing-groups-regex-7.6.2.tgz",
|
||||
"integrity": "sha1-wcoLuEuU84XKMCw5MuhwsPsOUis=",
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-named-capturing-groups-regex/download/@babel/plugin-transform-named-capturing-groups-regex-7.6.3.tgz",
|
||||
"integrity": "sha1-qqbkCd1PsuULbiqR9+OjFJ284M8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"regexpu-core": "^4.6.0"
|
||||
@@ -865,9 +902,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/preset-env": {
|
||||
"version": "7.6.2",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/preset-env/download/@babel/preset-env-7.6.2.tgz?cache=0&sync_timestamp=1569273953853&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fpreset-env%2Fdownload%2F%40babel%2Fpreset-env-7.6.2.tgz",
|
||||
"integrity": "sha1-q7s+14XH/kIg1MgqU2IdcfwMddM=",
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/preset-env/download/@babel/preset-env-7.6.3.tgz",
|
||||
"integrity": "sha1-nhvwWi4taHA20kxA5GOdxGzvInE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-module-imports": "^7.0.0",
|
||||
@@ -886,7 +923,7 @@
|
||||
"@babel/plugin-transform-arrow-functions": "^7.2.0",
|
||||
"@babel/plugin-transform-async-to-generator": "^7.5.0",
|
||||
"@babel/plugin-transform-block-scoped-functions": "^7.2.0",
|
||||
"@babel/plugin-transform-block-scoping": "^7.6.2",
|
||||
"@babel/plugin-transform-block-scoping": "^7.6.3",
|
||||
"@babel/plugin-transform-classes": "^7.5.5",
|
||||
"@babel/plugin-transform-computed-properties": "^7.2.0",
|
||||
"@babel/plugin-transform-destructuring": "^7.6.0",
|
||||
@@ -901,7 +938,7 @@
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.6.0",
|
||||
"@babel/plugin-transform-modules-systemjs": "^7.5.0",
|
||||
"@babel/plugin-transform-modules-umd": "^7.2.0",
|
||||
"@babel/plugin-transform-named-capturing-groups-regex": "^7.6.2",
|
||||
"@babel/plugin-transform-named-capturing-groups-regex": "^7.6.3",
|
||||
"@babel/plugin-transform-new-target": "^7.4.4",
|
||||
"@babel/plugin-transform-object-super": "^7.5.5",
|
||||
"@babel/plugin-transform-parameters": "^7.4.4",
|
||||
@@ -914,12 +951,25 @@
|
||||
"@babel/plugin-transform-template-literals": "^7.4.4",
|
||||
"@babel/plugin-transform-typeof-symbol": "^7.2.0",
|
||||
"@babel/plugin-transform-unicode-regex": "^7.6.2",
|
||||
"@babel/types": "^7.6.0",
|
||||
"@babel/types": "^7.6.3",
|
||||
"browserslist": "^4.6.0",
|
||||
"core-js-compat": "^3.1.1",
|
||||
"invariant": "^2.2.2",
|
||||
"js-levenshtein": "^1.1.3",
|
||||
"semver": "^5.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/types": {
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/types/download/@babel/types-7.6.3.tgz",
|
||||
"integrity": "sha1-PwfZb4VPmOL71FxksMuULRHougk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esutils": "^2.0.2",
|
||||
"lodash": "^4.17.13",
|
||||
"to-fast-properties": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/template": {
|
||||
@@ -1315,9 +1365,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": {
|
||||
@@ -1626,7 +1676,7 @@
|
||||
"dependencies": {
|
||||
"inherits": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.1.tgz?cache=0&sync_timestamp=1560975547815&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Finherits%2Fdownload%2Finherits-2.0.1.tgz",
|
||||
"resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.1.tgz",
|
||||
"integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
|
||||
"dev": true
|
||||
},
|
||||
@@ -1694,24 +1744,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.5",
|
||||
"resolved": "https://registry.npm.taobao.org/autoprefixer/download/autoprefixer-9.6.5.tgz?cache=0&sync_timestamp=1571040005147&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fautoprefixer%2Fdownload%2Fautoprefixer-9.6.5.tgz",
|
||||
"integrity": "sha1-mPSv5+k8zPMjKHUV1CYBlhl3Xl4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"browserslist": "^4.6.3",
|
||||
"caniuse-lite": "^1.0.30000980",
|
||||
"browserslist": "^4.7.0",
|
||||
"caniuse-lite": "^1.0.30000999",
|
||||
"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",
|
||||
"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.282",
|
||||
"resolved": "https://registry.npm.taobao.org/electron-to-chromium/download/electron-to-chromium-1.3.282.tgz?cache=0&sync_timestamp=1570911575715&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felectron-to-chromium%2Fdownload%2Felectron-to-chromium-1.3.282.tgz",
|
||||
"integrity": "sha1-FhGK6ceaMuqToXWR1bFuKNEPwI0=",
|
||||
"dev": true
|
||||
},
|
||||
"node-releases": {
|
||||
"version": "1.1.35",
|
||||
"resolved": "https://registry.npm.taobao.org/node-releases/download/node-releases-1.1.35.tgz",
|
||||
"integrity": "sha1-MqdKPNSXqnfyPVCfSDR1/RYOTEg=",
|
||||
"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",
|
||||
"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
|
||||
}
|
||||
}
|
||||
@@ -3937,9 +4036,9 @@
|
||||
}
|
||||
},
|
||||
"core-js": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npm.taobao.org/core-js/download/core-js-3.2.1.tgz",
|
||||
"integrity": "sha1-zUHzhTTabMWffbBQ/mcwfemGiwk=",
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npm.taobao.org/core-js/download/core-js-3.3.2.tgz",
|
||||
"integrity": "sha1-zULaHXsLsz7xEya+OnIZNCd860I=",
|
||||
"dev": true
|
||||
},
|
||||
"core-js-compat": {
|
||||
@@ -3954,7 +4053,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 +4163,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 +4915,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.12",
|
||||
"resolved": "https://registry.npm.taobao.org/electron/download/electron-6.0.12.tgz",
|
||||
"integrity": "sha1-hb8AYeMvZgJWz96VSI8ct1JTvJQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "^10.12.18",
|
||||
@@ -5203,9 +5302,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 +5383,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 +5473,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 +6564,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",
|
||||
@@ -8914,9 +9023,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"lrc-file-parser": {
|
||||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npm.taobao.org/lrc-file-parser/download/lrc-file-parser-0.1.12.tgz",
|
||||
"integrity": "sha1-sM/lhxqufWctaW8C2gBXlTjUKZ0="
|
||||
"version": "0.1.14",
|
||||
"resolved": "https://registry.npm.taobao.org/lrc-file-parser/download/lrc-file-parser-0.1.14.tgz",
|
||||
"integrity": "sha1-FW00nV/f01XNJMp/JqYMPeDscgE="
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "4.1.5",
|
||||
@@ -9217,6 +9326,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 +9601,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 +10023,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 +11862,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": {
|
||||
@@ -11876,7 +12032,7 @@
|
||||
},
|
||||
"sha.js": {
|
||||
"version": "2.4.11",
|
||||
"resolved": "https://registry.npm.taobao.org/sha.js/download/sha.js-2.4.11.tgz",
|
||||
"resolved": "https://registry.npm.taobao.org/sha.js/download/sha.js-2.4.11.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsha.js%2Fdownload%2Fsha.js-2.4.11.tgz",
|
||||
"integrity": "sha1-N6XPC4HsvGlD3hCbopYNGyZYSuc=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -12805,9 +12961,9 @@
|
||||
}
|
||||
},
|
||||
"terser": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npm.taobao.org/terser/download/terser-4.3.1.tgz",
|
||||
"integrity": "sha1-CYILyzOYKZxLSNmoau/GUSfQ7WU=",
|
||||
"version": "4.3.8",
|
||||
"resolved": "https://registry.npm.taobao.org/terser/download/terser-4.3.8.tgz",
|
||||
"integrity": "sha1-cH8F8/TBxwyEDmJq3f2xwVihcTY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"commander": "^2.20.0",
|
||||
@@ -12816,50 +12972,53 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.20.0",
|
||||
"resolved": "https://registry.npm.taobao.org/commander/download/commander-2.20.0.tgz",
|
||||
"integrity": "sha1-1YuytcHuj4ew00ACfp6U4iLFpCI=",
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npm.taobao.org/commander/download/commander-2.20.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcommander%2Fdownload%2Fcommander-2.20.3.tgz",
|
||||
"integrity": "sha1-/UhehMA+tIgcIHIrpIA16FMa6zM=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"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.3",
|
||||
"resolved": "https://registry.npm.taobao.org/terser-webpack-plugin/download/terser-webpack-plugin-2.1.3.tgz",
|
||||
"integrity": "sha1-hUMNpxuoimAHK/ZZWJ6vr2oA3CI=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cacache": "^12.0.3",
|
||||
"cacache": "^13.0.1",
|
||||
"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.8",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"find-cache-dir": {
|
||||
@@ -12883,6 +13042,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 +13109,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 +13130,16 @@
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"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 +13628,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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13525,7 +13700,7 @@
|
||||
"dependencies": {
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz?cache=0&sync_timestamp=1560975547815&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Finherits%2Fdownload%2Finherits-2.0.3.tgz",
|
||||
"resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
||||
"dev": true
|
||||
}
|
||||
@@ -13782,9 +13957,9 @@
|
||||
}
|
||||
},
|
||||
"webpack": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npm.taobao.org/webpack/download/webpack-4.41.0.tgz",
|
||||
"integrity": "sha1-22olS95nF2n3wU6QoaVec2Avxws=",
|
||||
"version": "4.41.2",
|
||||
"resolved": "https://registry.npm.taobao.org/webpack/download/webpack-4.41.2.tgz",
|
||||
"integrity": "sha1-w07Hbao6hGjJthpQM22OMwPc504=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@webassemblyjs/ast": "1.8.5",
|
||||
@@ -13820,7 +13995,7 @@
|
||||
},
|
||||
"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",
|
||||
"resolved": "https://registry.npm.taobao.org/cacache/download/cacache-12.0.3.tgz",
|
||||
"integrity": "sha1-vpmruk4b9d9GHNWiwQcfxDJXM5A=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -13843,7 +14018,7 @@
|
||||
},
|
||||
"eslint-scope": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npm.taobao.org/eslint-scope/download/eslint-scope-4.0.3.tgz?cache=0&sync_timestamp=1563679289211&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-scope%2Fdownload%2Feslint-scope-4.0.3.tgz",
|
||||
"resolved": "https://registry.npm.taobao.org/eslint-scope/download/eslint-scope-4.0.3.tgz",
|
||||
"integrity": "sha1-ygODMxD2iJoyZHgaqC5j65z+eEg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -13939,9 +14114,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 +14127,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 +14141,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 +14161,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 +14247,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 +14258,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",
|
||||
|
||||
28
package.json
28
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "lx-music-desktop",
|
||||
"version": "0.6.1",
|
||||
"version": "0.8.2",
|
||||
"description": "一个免费的音乐下载助手",
|
||||
"main": "./dist/electron/main.js",
|
||||
"productName": "lx-music-desktop",
|
||||
@@ -134,11 +134,11 @@
|
||||
},
|
||||
"homepage": "https://github.com/lyswhut/lx-music-desktop#readme",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.6.2",
|
||||
"@babel/core": "^7.6.4",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
|
||||
"@babel/polyfill": "^7.6.0",
|
||||
"@babel/preset-env": "^7.6.2",
|
||||
"autoprefixer": "^9.6.1",
|
||||
"@babel/preset-env": "^7.6.3",
|
||||
"autoprefixer": "^9.6.5",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"babel-loader": "^8.0.6",
|
||||
"babel-minify-webpack-plugin": "^0.3.1",
|
||||
@@ -147,19 +147,19 @@
|
||||
"chalk": "^2.4.2",
|
||||
"changelog-parser": "^2.8.0",
|
||||
"copy-webpack-plugin": "^5.0.4",
|
||||
"core-js": "^3.2.1",
|
||||
"core-js": "^3.3.2",
|
||||
"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.12",
|
||||
"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.3",
|
||||
"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": "^4.41.2",
|
||||
"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"
|
||||
},
|
||||
@@ -202,7 +202,7 @@
|
||||
"electron-updater": "^4.1.2",
|
||||
"flac-metadata": "^0.1.1",
|
||||
"js-htmlencode": "^0.3.0",
|
||||
"lrc-file-parser": "^0.1.12",
|
||||
"lrc-file-parser": "^0.1.14",
|
||||
"node-downloader-helper": "^1.0.10",
|
||||
"node-id3": "^0.1.11",
|
||||
"request": "^2.88.0",
|
||||
|
||||
@@ -1,21 +1,3 @@
|
||||
### 新增
|
||||
#### 修复
|
||||
|
||||
- 新增试听列表**滚动条位置恢复**设置(可自动恢复到上次离开时的列表滚动位置),本功能默认开启,若不需要可到设置-列表设置将其关闭
|
||||
- 新增 **《海贼王》** 皮肤,喜欢个性化的可以试试~
|
||||
|
||||
### 优化
|
||||
|
||||
- 新增DNS解析缓存,加快请求速度
|
||||
- 优化代码逻辑,减少软件对系统资源的占用
|
||||
- 优化新版本信息检测,尽量减少弹出版本获取失败弹窗弹出的概率
|
||||
- 优化下拉列表动画效果
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复请求超时的逻辑处理Bug,尝试修复请求无法取消导致的正在播放的歌曲与界面显示的信息不一致的问题
|
||||
- 修复其他一些小Bug
|
||||
|
||||
### 移除
|
||||
|
||||
- 移除 `192k` 音质
|
||||
- 移除酷我音源 `ape` 音质,无损推荐 `flac` 格式
|
||||
- 兼容旧版酷我源搜索列表过滤128k音质的bug(注:0.8.1版本仅修复了酷我源的歌曲过滤问题,该修复仅对以后添加的歌曲有效,如果是之前添加的歌曲仍会出现这个问题,现修复对之前旧列表数据的兼容处理)
|
||||
|
||||
@@ -1,7 +1,27 @@
|
||||
{
|
||||
"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.8.2",
|
||||
"desc": "<h4>修复</h4>\n<ul>\n<li>兼容旧版酷我源搜索列表过滤128k音质的bug(注:0.8.1版本仅修复了酷我源的歌曲过滤问题,该修复仅对以后添加的歌曲有效,如果是之前添加的歌曲仍会出现这个问题,现修复对之前旧列表数据的兼容处理)</li>\n</ul>\n",
|
||||
"history": [
|
||||
{
|
||||
"version": "0.8.1",
|
||||
"desc": "<h4>修复</h4>\n<ul>\n<li>修复酷我源搜索歌曲结果未添加128k音质导致播放128k音质时显示“该歌曲没有可播放的音频”的问题</li>\n</ul>\n"
|
||||
},
|
||||
{
|
||||
"version": "0.8.0",
|
||||
"desc": "<h4>新增</h4>\n<ul>\n<li>新增网易云源歌曲搜索</li>\n<li>新增网易云源歌单</li>\n<li>新增各平台通过输入歌单链接或歌单ID打开歌单详情列表,目前只适配了<strong>网页版歌单链接</strong>,其他方式的歌单链接可能无法解析,但你可想办法获取歌单ID后输入打开。注:各平台歌单ID均为纯数字,若遇到链接里存在歌单ID但无法解析的歌单链接,可以到GitHub提交issue或发送邮件或加群830125506反馈!</li>\n<li>新增音量调整滑动功能,现在支持鼠标左右拖动调整音量了</li>\n</ul>\n<h4>优化</h4>\n<ul>\n<li>优化搜索框搜索体验</li>\n<li>优化音量条交互视觉效果</li>\n<li>缓存歌单详情列表数据</li>\n</ul>\n<h4>修复</h4>\n<ul>\n<li>修复QQ源歌单无法翻页Bug</li>\n<li>修复默认列表没有创建时无法显示收藏列表的Bug</li>\n<li>修复网易云128k直接试听</li>\n<li>修复歌曲音质不存在时仍然播放或下载的Bug</li>\n<li>修复调整音量时,调整的位置与鼠标点击的位置不一致的问题</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"
|
||||
},
|
||||
{
|
||||
"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"
|
||||
|
||||
@@ -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, '\\\\')
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
require('./request')
|
||||
// require('./appName')
|
||||
require('./progressBar')
|
||||
require('./trafficLight')
|
||||
require('./musicMeta')
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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,8 @@ export default {
|
||||
},
|
||||
initPlayList() {
|
||||
let defaultList = this.electronStore.get('list.defaultList')
|
||||
// console.log(defaultList)
|
||||
if (defaultList) {
|
||||
// defaultList.list.forEach(m => {
|
||||
// m.typeUrl = {}
|
||||
// })
|
||||
this.initDefaultList(defaultList)
|
||||
}
|
||||
let loveList = this.electronStore.get('list.loveList')
|
||||
this.initList({ defaultList, loveList })
|
||||
},
|
||||
initDownloadList() {
|
||||
let downloadList = this.electronStore.get('download.list')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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: {},
|
||||
}
|
||||
|
||||
@@ -9,8 +9,9 @@ div(:class="$style.player")
|
||||
div(:class="$style.container")
|
||||
div(:class="$style.title" @click="handleCopy(title)" :title="title + '(点击复制)'") {{title}}
|
||||
div(:class="$style.volumeContent")
|
||||
div(:class="$style.volume" @click.stop='handleChangeVolume' :title="`当前音量:${parseInt(volume * 100)}%`")
|
||||
div(:class="$style.volume")
|
||||
div(:class="$style.volumeBar" :style="{ transform: `scaleX(${volume || 0})` }")
|
||||
div(:class="$style.volumeMask" @mousedown="handleVolumeMsDown" ref="dom_volumeMask" :title="`当前音量:${parseInt(volume * 100)}%`")
|
||||
|
||||
//- div(:class="$style.playBtn" @click='handleNext' title="音量")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 291.063 291.064' space='preserve')
|
||||
@@ -48,9 +49,10 @@ div(:class="$style.player")
|
||||
<script>
|
||||
import Lyric from 'lrc-file-parser'
|
||||
import { rendererSend } from '../../../common/icp'
|
||||
import { formatPlayTime2, getRandom, checkPath, setTitle, clipboardWriteText } from '../../utils'
|
||||
import { formatPlayTime2, getRandom, checkPath, setTitle, clipboardWriteText, debounce } from '../../utils'
|
||||
import { mapGetters, mapActions, mapMutations } from 'vuex'
|
||||
import { requestMsg } from '../../utils/message'
|
||||
import { isMac } from '../../../common/utils'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@@ -80,6 +82,14 @@ export default {
|
||||
delayNextTimeout: null,
|
||||
audioErrorTime: 0,
|
||||
retryNum: 0,
|
||||
isMac,
|
||||
volumeEvent: {
|
||||
isMsDown: false,
|
||||
msDownX: 0,
|
||||
msDownVolume: 0,
|
||||
},
|
||||
handleVolumeMsMoveFn: null,
|
||||
handleVolumeMsUpFn: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -111,6 +121,16 @@ export default {
|
||||
this.$nextTick(() => {
|
||||
this.setProgessWidth()
|
||||
})
|
||||
this.handleSaveVolume = debounce(volume => {
|
||||
this.setVolume(volume)
|
||||
}, 300)
|
||||
|
||||
document.addEventListener('mousemove', this.handleVolumeMsMoveFn = this.handleVolumeMsMove.bind(this))
|
||||
document.addEventListener('mouseup', this.handleVolumeMsUpFn = this.handleVolumeMsUp.bind(this))
|
||||
},
|
||||
beforeDestroy() {
|
||||
document.removeEventListener('mousemove', this.handleVolumeMsMoveFn)
|
||||
document.removeEventListener('mouseup', this.handleVolumeMsUpFn)
|
||||
},
|
||||
watch: {
|
||||
changePlay(n) {
|
||||
@@ -210,7 +230,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,10 +387,11 @@ 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'
|
||||
let type = '128k'
|
||||
if (highQuality && songInfo._types['320k']) type = '320k'
|
||||
return type
|
||||
},
|
||||
@@ -441,16 +462,29 @@ export default {
|
||||
clearAppTitle() {
|
||||
setTitle()
|
||||
},
|
||||
handleChangeVolume(e) {
|
||||
handleVolumeMsDown(e) {
|
||||
this.volumeEvent.isMsDown = true
|
||||
this.volumeEvent.isMsMoved = false
|
||||
this.volumeEvent.msDownX = e.clientX
|
||||
|
||||
let val = e.offsetX / 70
|
||||
if (val < 0) val = 0
|
||||
if (val > 1) val = 1
|
||||
if (val > 0.97) val = 1
|
||||
|
||||
this.volume = val
|
||||
this.volumeEvent.msDownVolume = val
|
||||
// console.log(val)
|
||||
if (this.audio) this.audio.volume = this.volume
|
||||
},
|
||||
handleSaveVolume(volume) {
|
||||
this.setVolume(volume)
|
||||
handleVolumeMsUp(e) {
|
||||
this.volumeEvent.isMsDown = false
|
||||
},
|
||||
handleVolumeMsMove(e) {
|
||||
if (!this.volumeEvent.isMsDown) return
|
||||
let val = this.volumeEvent.msDownVolume + (e.clientX - this.volumeEvent.msDownX) / 70
|
||||
this.volume = val < 0 ? 0 : val > 1 ? 1 : val
|
||||
if (this.audio) this.audio.volume = this.volume
|
||||
// console.log(val)
|
||||
},
|
||||
handleCopy(text) {
|
||||
clipboardWriteText(text)
|
||||
@@ -482,6 +516,7 @@ export default {
|
||||
transition: @transition-theme;
|
||||
transition-property: color;
|
||||
flex: none;
|
||||
padding: 2px;
|
||||
|
||||
svg {
|
||||
fill: currentColor;
|
||||
@@ -491,7 +526,7 @@ export default {
|
||||
max-height: 100%;
|
||||
transition: @transition-theme;
|
||||
transition-property: border-color;
|
||||
border: 2px solid @color-theme_2-background_1;
|
||||
// border: 2px solid @color-theme_2-background_1;
|
||||
}
|
||||
}
|
||||
.right {
|
||||
@@ -526,14 +561,20 @@ export default {
|
||||
}
|
||||
|
||||
.volume-content {
|
||||
position: relative;
|
||||
width: 100px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 15px;
|
||||
opacity: .5;
|
||||
transition: opacity @transition-theme;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.volume {
|
||||
cursor: pointer;
|
||||
// cursor: pointer;
|
||||
width: 100%;
|
||||
height: 0.25em;
|
||||
border-radius: 10px;
|
||||
@@ -560,7 +601,16 @@ export default {
|
||||
transition-duration: 0.2s;
|
||||
background-color: @color-theme;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.volume-mask {
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
right: 15px;
|
||||
top: 0;
|
||||
width: 70%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.play-btn {
|
||||
@@ -575,7 +625,7 @@ export default {
|
||||
transition: @transition-theme;
|
||||
transition-property: color;
|
||||
color: @color-theme;
|
||||
transition: opacity 0.2s ease;
|
||||
transition: opacity 0.1s ease;
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
|
||||
@@ -683,9 +733,9 @@ each(@themes, {
|
||||
}
|
||||
.left {
|
||||
color: ~'@{color-@{value}-theme}';
|
||||
img {
|
||||
border-color: ~'@{color-@{value}-theme_2-background_1}';
|
||||
}
|
||||
// img {
|
||||
// border-color: ~'@{color-@{value}-theme_2-background_1}';
|
||||
// }
|
||||
}
|
||||
.play-btn {
|
||||
color: ~'@{color-@{value}-theme}';
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
div(:class="$style.toolbar")
|
||||
//- img(v-if="icon")
|
||||
//- h1 {{title}}
|
||||
material-search-input(:class="$style.input")
|
||||
material-search-input(:class="$style.input"
|
||||
@event="handleEvent" :list="tipList" :visibleList="visibleList"
|
||||
v-model="searchText")
|
||||
div(:class="$style.control")
|
||||
button(type="button" :class="$style.min" title="最小化" @click="min")
|
||||
//- button(type="button" :class="$style.max" @click="max")
|
||||
@@ -11,22 +13,93 @@
|
||||
|
||||
<script>
|
||||
import { rendererSend } from 'common/icp'
|
||||
// import { mapGetters } from 'vuex'
|
||||
import { mapGetters } from 'vuex'
|
||||
import music from '../../utils/music'
|
||||
import { debounce } from '../../utils'
|
||||
export default {
|
||||
// props: {
|
||||
// color: {
|
||||
// type: String,
|
||||
// default: color,
|
||||
// },
|
||||
// icon: {
|
||||
// type: Boolean,
|
||||
// default: false,
|
||||
// },
|
||||
// },
|
||||
data() {
|
||||
return {
|
||||
searchText: '',
|
||||
visibleList: false,
|
||||
tipList: [],
|
||||
tipSearch: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// ...mapGetters(['theme']),
|
||||
...mapGetters(['route', 'setting']),
|
||||
...mapGetters('search', {
|
||||
storeSearchText: 'searchText',
|
||||
}),
|
||||
source() {
|
||||
return this.setting.search.tempSearchSource
|
||||
},
|
||||
isAutoClearInput() {
|
||||
return this.setting.odc.isAutoClearSearchInput
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
route(n) {
|
||||
if (this.isAutoClearInput && n.name != 'search' && this.searchText) this.searchText = ''
|
||||
},
|
||||
'storeSearchText'(n) {
|
||||
if (n !== this.searchText) this.searchText = n
|
||||
},
|
||||
searchText(n) {
|
||||
this.handleTipSearch()
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.tipSearch = debounce(() => {
|
||||
if (this.searchText === '') {
|
||||
this.tipList.splice(0, this.tipList.length)
|
||||
music[this.source].tempSearch.cancelTempSearch()
|
||||
return
|
||||
}
|
||||
music[this.source].tempSearch.search(this.searchText).then(list => {
|
||||
this.tipList = list
|
||||
}).catch(() => {})
|
||||
}, 50)
|
||||
},
|
||||
methods: {
|
||||
handleEvent({ action, data }) {
|
||||
switch (action) {
|
||||
case 'focus':
|
||||
if (!this.visibleList) this.visibleList = true
|
||||
if (this.searchText) this.handleTipSearch()
|
||||
break
|
||||
case 'blur':
|
||||
setTimeout(() => {
|
||||
if (this.visibleList) this.visibleList = false
|
||||
}, 50)
|
||||
break
|
||||
case 'submit':
|
||||
this.handleSearch()
|
||||
break
|
||||
case 'listClick':
|
||||
this.searchText = this.tipList[data]
|
||||
this.$nextTick(() => {
|
||||
this.handleSearch()
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
handleTipSearch() {
|
||||
if (!this.visibleList) this.visibleList = true
|
||||
this.tipSearch()
|
||||
},
|
||||
|
||||
handleSearch() {
|
||||
if (this.visibleList) this.visibleList = false
|
||||
setTimeout(() => {
|
||||
this.$router.push({
|
||||
path: 'search',
|
||||
query: {
|
||||
text: this.searchText,
|
||||
},
|
||||
}).catch(_ => _)
|
||||
}, 200)
|
||||
},
|
||||
|
||||
min() {
|
||||
rendererSend('min')
|
||||
},
|
||||
@@ -56,6 +129,9 @@ export default {
|
||||
}
|
||||
.input {
|
||||
-webkit-app-region: no-drag;
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
top: 13px;
|
||||
}
|
||||
|
||||
// img {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,7 @@ export default {
|
||||
checkSource(type) {
|
||||
switch (this.musicInfo.source) {
|
||||
case 'wy':
|
||||
case 'kg':
|
||||
case 'tx':
|
||||
return type == '128k'
|
||||
|
||||
default:
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1,31 +1,54 @@
|
||||
<template lang="pug">
|
||||
div(:class="[$style.search, focus ? $style.active : '']")
|
||||
div(:class="[$style.search, focus ? $style.active : '', big ? $style.big : '', small ? $style.small : '']")
|
||||
div(:class="$style.form")
|
||||
input(placeholder="Search for something..." v-model.trim="text"
|
||||
@focus="handleFocus" @blur="handleBlur" @input="handleInput"
|
||||
input(:placeholder="placeholder" v-model.trim="text"
|
||||
@focus="handleFocus" @blur="handleBlur" @input="$emit('input', text)"
|
||||
@change="sendEvent('change')"
|
||||
@keyup.enter="handleSearch")
|
||||
button(type="button" @click="handleSearch")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 30.239 30.239' space='preserve')
|
||||
use(xlink:href='#icon-search')
|
||||
slot
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 30.239 30.239' space='preserve')
|
||||
use(xlink:href='#icon-search')
|
||||
//- transition(name="custom-classes-transition"
|
||||
//- enter-active-class="animated flipInX"
|
||||
//- leave-active-class="animated flipOutX")
|
||||
div(:class="$style.list" :style="listStyle")
|
||||
div(v-if="list" :class="$style.list" :style="listStyle")
|
||||
ul(ref="dom_list")
|
||||
li(v-for="(item, index) in list" :key="item" @click="handleTemplistClick(index)")
|
||||
span {{item}}
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import music from '../../utils/music'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: 'Search for something...',
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
},
|
||||
visibleList: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
big: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
small: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isShow: false,
|
||||
text: '',
|
||||
list: [],
|
||||
index: null,
|
||||
focus: false,
|
||||
listStyle: {
|
||||
@@ -33,64 +56,35 @@ export default {
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['route', 'setting']),
|
||||
...mapGetters('search', ['searchText']),
|
||||
isAutoClearInput() {
|
||||
return this.setting.odc.isAutoClearSearchInput
|
||||
},
|
||||
source() {
|
||||
return this.setting.search.tempSearchSource
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
list(n) {
|
||||
if (!this.visibleList) return
|
||||
this.$nextTick(() => {
|
||||
this.listStyle.height = this.$refs.dom_list.scrollHeight + 'px'
|
||||
})
|
||||
},
|
||||
'searchText'(n) {
|
||||
if (n !== this.text) this.text = n
|
||||
value(n) {
|
||||
this.text = n
|
||||
},
|
||||
route(n) {
|
||||
if (this.isAutoClearInput && n.name != 'search' && this.text) this.text = ''
|
||||
visibleList(n) {
|
||||
n ? this.showList() : this.hideList()
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleTemplistClick(index) {
|
||||
this.text = this.list[index]
|
||||
this.handleSearch()
|
||||
this.sendEvent('listClick', index)
|
||||
},
|
||||
handleFocus() {
|
||||
this.focus = true
|
||||
if (this.text) this.handleInput()
|
||||
this.showList()
|
||||
this.sendEvent('focus')
|
||||
},
|
||||
handleBlur() {
|
||||
setTimeout(() => {
|
||||
this.focus = false
|
||||
this.hideList()
|
||||
}, 200)
|
||||
this.focus = false
|
||||
this.sendEvent('blur')
|
||||
},
|
||||
handleSearch() {
|
||||
this.hideList()
|
||||
this.$router.push({
|
||||
path: 'search',
|
||||
query: {
|
||||
text: this.text,
|
||||
},
|
||||
}).catch(_ => _)
|
||||
},
|
||||
handleInput() {
|
||||
if (this.text === '') {
|
||||
this.list.splice(0, this.list.length)
|
||||
music[this.source].tempSearch.cancelTempSearch()
|
||||
return
|
||||
}
|
||||
if (!this.isShow) this.showList()
|
||||
music[this.source].tempSearch.search(this.text).then(list => {
|
||||
this.list = list
|
||||
}).catch(() => {})
|
||||
this.sendEvent('submit')
|
||||
},
|
||||
showList() {
|
||||
this.isShow = true
|
||||
@@ -100,6 +94,12 @@ export default {
|
||||
this.isShow = false
|
||||
this.listStyle.height = 0
|
||||
},
|
||||
sendEvent(action, data) {
|
||||
this.$emit('event', {
|
||||
action,
|
||||
data,
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -109,9 +109,6 @@ export default {
|
||||
@import '../../assets/styles/layout.less';
|
||||
|
||||
.search {
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
top: 13px;
|
||||
border-radius: 3px;
|
||||
transition: box-shadow .4s ease, background-color @transition-theme;
|
||||
display: flex;
|
||||
@@ -201,6 +198,19 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.big {
|
||||
width: 500px;
|
||||
// input {
|
||||
// line-height: 30px;
|
||||
// }
|
||||
.form {
|
||||
height: 30px;
|
||||
button {
|
||||
padding: 6px 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
each(@themes, {
|
||||
:global(#container.@{value}) {
|
||||
|
||||
|
||||
@@ -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)"
|
||||
:play-btn="item.source == 'kw' || (!isAPITemp)"
|
||||
:download-btn="item.source == 'kw' || (!isAPITemp)")
|
||||
//- 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) ? 'testPlay' : 'search', index)
|
||||
this.clickTime = 0
|
||||
this.clickIndex = -1
|
||||
},
|
||||
|
||||
103
src/renderer/components/material/listAddModal.vue
Normal file
103
src/renderer/components/material/listAddModal.vue
Normal file
@@ -0,0 +1,103 @@
|
||||
<template lang="pug">
|
||||
material-modal(:show="show" :bg-close="bgClose" @close="handleClose")
|
||||
main(:class="$style.main")
|
||||
h2
|
||||
| 添加
|
||||
span(:class="$style.name") {{this.musicInfo && `${musicInfo.name}`}}
|
||||
| 到...
|
||||
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>
|
||||
97
src/renderer/components/material/listAddMultipleModal.vue
Normal file
97
src/renderer/components/material/listAddMultipleModal.vue
Normal 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>
|
||||
@@ -75,6 +75,12 @@ const addTask = (list, type, store) => {
|
||||
|
||||
const getUrl = (downloadInfo, isRefresh) => {
|
||||
const url = downloadInfo.musicInfo.typeUrl[downloadInfo.type]
|
||||
if (!downloadInfo.musicInfo._types[downloadInfo.type]) {
|
||||
// 兼容旧版酷我源搜索列表过滤128k音质的bug
|
||||
if (!(downloadInfo.musicInfo.source == 'kw' && downloadInfo.type == '128k')) return Promise.reject(new Error('该歌曲没有可下载的音频'))
|
||||
|
||||
// return Promise.reject(new Error('该歌曲没有可下载的音频'))
|
||||
}
|
||||
return url && !isRefresh ? Promise.resolve({ url }) : music[downloadInfo.musicInfo.source].getMusicUrl(downloadInfo.musicInfo, downloadInfo.type).promise
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,12 @@ const getters = {
|
||||
// actions
|
||||
const actions = {
|
||||
getUrl({ commit, state }, { musicInfo, type, isRefresh }) {
|
||||
if (!musicInfo._types[type]) {
|
||||
// 兼容旧版酷我源搜索列表过滤128k音质的bug
|
||||
if (!(musicInfo.source == 'kw' && type == '128k')) return Promise.reject(new Error('该歌曲没有可播放的音频'))
|
||||
|
||||
// return Promise.reject(new Error('该歌曲没有可播放的音频'))
|
||||
}
|
||||
if (urlRequest && urlRequest.cancelHttp) urlRequest.cancelHttp()
|
||||
if (musicInfo.typeUrl[type] && !isRefresh) return Promise.resolve()
|
||||
urlRequest = music[musicInfo.source].getMusicUrl(musicInfo, type)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import music from '../../utils/music'
|
||||
const sortList = {}
|
||||
const sources = []
|
||||
const cache = new Map()
|
||||
for (const source of music.sources) {
|
||||
const songList = music[source.id].songList
|
||||
if (!songList) continue
|
||||
@@ -20,10 +21,12 @@ const state = {
|
||||
},
|
||||
listDetail: {
|
||||
list: [],
|
||||
desc: null,
|
||||
total: 0,
|
||||
page: 1,
|
||||
limit: 30,
|
||||
key: null,
|
||||
info: {},
|
||||
},
|
||||
selectListInfo: {},
|
||||
isVisibleListDetail: false,
|
||||
@@ -59,16 +62,45 @@ const actions = {
|
||||
let tabId = rootState.setting.songList.tagInfo.id
|
||||
let sortId = rootState.setting.songList.sortId
|
||||
// console.log(sortId)
|
||||
let key = `${source}${sortId}${tabId}${page}`
|
||||
if (state.list.list.length && state.list.key == key) return true
|
||||
return music[source].songList.getList(sortId, tabId, page).then(result => commit('setList', { result, key, page }))
|
||||
let key = `slist__${source}__${sortId}__${tabId}__${page}`
|
||||
if (state.list.list.length && state.list.key == key) return
|
||||
return (cache.has(key) ? Promise.resolve(cache.get(key)) : music[source].songList.getList(sortId, tabId, page)).then(result => commit('setList', { result, key, page }))
|
||||
},
|
||||
getListDetail({ state, rootState, commit }, { id, page }) {
|
||||
let source = rootState.setting.songList.source
|
||||
let key = `${source}${id}${page}`
|
||||
let key = `sdetail__${source}__${id}__${page}`
|
||||
if (state.listDetail.list.length && state.listDetail.key == key) return true
|
||||
return music[source].songList.getListDetail(id, page).then(result => commit('setListDetail', { result, key, page }))
|
||||
return (cache.has(key) ? Promise.resolve(cache.get(key)) : music[source].songList.getListDetail(id, page)).then(result => commit('setListDetail', { result, key, page }))
|
||||
},
|
||||
/* getListDetailAll({ state, rootState }, id) {
|
||||
let source = rootState.setting.songList.source
|
||||
let key = `sdetail__${source}__${id}__all`
|
||||
if (cache.has(key)) return Promise.resolve(cache.get(key))
|
||||
music[source].songList.getListDetail(id, 1).then(result => {
|
||||
let data = { list: result.list, id }
|
||||
if (result.total <= result.limit) {
|
||||
data = { list: result.list, id }
|
||||
cache.set(key, data)
|
||||
return data
|
||||
}
|
||||
|
||||
let maxPage = Math.ceil(result.total / result.limit)
|
||||
const loadDetail = (loadPage = 1) => {
|
||||
let task = []
|
||||
let loadNum = 0
|
||||
while (loadPage <= maxPage && loadNum < 3) {
|
||||
task.push(music[source].songList.getListDetail(id, ++loadPage))
|
||||
loadNum++
|
||||
}
|
||||
return loadPage == maxPage
|
||||
? Promise.all(task)
|
||||
: Promise.all(task).then(result => loadDetail(loadPage).then(result2 => [...result, ...result2]))
|
||||
}
|
||||
return loadDetail().then(result2 => {
|
||||
console.log(result2)
|
||||
})
|
||||
})
|
||||
}, */
|
||||
}
|
||||
|
||||
// mitations
|
||||
@@ -82,6 +114,7 @@ const mutations = {
|
||||
state.list.limit = result.limit
|
||||
state.list.page = page
|
||||
state.list.key = key
|
||||
cache.set(key, result)
|
||||
},
|
||||
setListDetail(state, { result, key, page }) {
|
||||
state.listDetail.list = result.list
|
||||
@@ -89,8 +122,11 @@ const mutations = {
|
||||
state.listDetail.limit = result.limit
|
||||
state.listDetail.page = page
|
||||
state.listDetail.key = key
|
||||
state.listDetail.info = result.info || {}
|
||||
cache.set(key, result)
|
||||
},
|
||||
setVisibleListDetail(state, bool) {
|
||||
if (!bool) state.listDetail.list = []
|
||||
state.isVisibleListDetail = bool
|
||||
},
|
||||
setSelectListInfo(state, info) {
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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,68 @@ export const throttle = (fn, delay = 100) => {
|
||||
}, delay)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成防抖函数
|
||||
* @param {*} fn
|
||||
* @param {*} delay
|
||||
*/
|
||||
export const debounce = (fn, delay = 100) => {
|
||||
let timer = null
|
||||
let _args = null
|
||||
return function(...args) {
|
||||
_args = args
|
||||
if (timer) clearTimeout(timer)
|
||||
timer = setTimeout(() => {
|
||||
timer = null
|
||||
fn.apply(this, _args)
|
||||
}, 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()
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -8,7 +8,7 @@ export default {
|
||||
_requestObj_listRecommend: null,
|
||||
_requestObj_listDetail: null,
|
||||
limit_list: 20,
|
||||
limit_song: 25,
|
||||
limit_song: 1000,
|
||||
successCode: 22000,
|
||||
sortList: [
|
||||
{
|
||||
@@ -108,11 +108,12 @@ export default {
|
||||
},
|
||||
|
||||
// 获取标签
|
||||
getTags() {
|
||||
getTags(tryNum = 0) {
|
||||
if (this._requestObj_tags) this._requestObj_tags.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
this._requestObj_tags = httpFetch(this.getTagsUrl())
|
||||
return this._requestObj_tags.promise.then(({ body }) => {
|
||||
if (body.error_code !== this.successCode) return this.getTags()
|
||||
if (body.error_code !== this.successCode) return this.getTags(++tryNum)
|
||||
return {
|
||||
hotTag: this.filterInfoHotTag(body.result.hot),
|
||||
tags: this.filterTagInfo(body.result.tags),
|
||||
@@ -141,13 +142,14 @@ export default {
|
||||
},
|
||||
|
||||
// 获取列表数据
|
||||
getList(sortId, tagId, page) {
|
||||
getList(sortId, tagId, page, tryNum = 0) {
|
||||
if (this._requestObj_list) this._requestObj_list.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
this._requestObj_list = httpFetch(
|
||||
this.getListUrl(sortId, tagId, page)
|
||||
)
|
||||
return this._requestObj_list.promise.then(({ body }) => {
|
||||
// if (body.error_code !== this.successCode) return this.getList(sortId, tagId, page)
|
||||
if (body.error_code !== this.successCode) return this.getList(sortId, tagId, page, ++tryNum)
|
||||
return {
|
||||
list: this.filterList(body.diyInfo),
|
||||
total: body.nums,
|
||||
@@ -183,13 +185,14 @@ export default {
|
||||
},
|
||||
|
||||
// 获取歌曲列表内的音乐
|
||||
getListDetail(id, page) {
|
||||
getListDetail(id, page, tryNum = 0) {
|
||||
if (this._requestObj_listDetail) {
|
||||
this._requestObj_listDetail.cancelHttp()
|
||||
}
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
this._requestObj_listDetail = httpFetch(this.getListDetailUrl(id, page))
|
||||
return this._requestObj_listDetail.promise.then(({ body }) => {
|
||||
if (body.error_code !== this.successCode) return this.getListDetail(id, page)
|
||||
if (body.error_code !== this.successCode) return this.getListDetail(id, page, ++tryNum)
|
||||
let listData = this.filterData(body.result.songlist)
|
||||
return {
|
||||
list: listData,
|
||||
@@ -197,6 +200,13 @@ export default {
|
||||
limit: this.limit_song,
|
||||
total: body.result.song_num,
|
||||
source: 'bd',
|
||||
info: {
|
||||
name: body.result.info.list_title,
|
||||
img: body.result.info.list_pic,
|
||||
desc: body.result.info.list_desc,
|
||||
author: body.result.info.userinfo.username,
|
||||
play_count: this.formatPlayCount(body.result.listen_num),
|
||||
},
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
33
src/renderer/utils/music/kg/lyric.js
Normal file
33
src/renderer/utils/music/kg/lyric.js
Normal 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
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
44
src/renderer/utils/music/kg/pic.js
Normal file
44
src/renderer/utils/music/kg/pic.js
Normal 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.imgsize ? info.image.replace('{size}', info.imgsize[0]) : info.image
|
||||
})
|
||||
return requestObj
|
||||
},
|
||||
}
|
||||
@@ -35,6 +35,7 @@ export default {
|
||||
],
|
||||
regExps: {
|
||||
listData: /global\.data = (\[.+\]);/,
|
||||
listInfo: /global = {[\s\S]+?name: "(.+)"[\s\S]+?pic: "(.+)"[\s\S]+?};/,
|
||||
},
|
||||
getInfoUrl(tagId) {
|
||||
return tagId
|
||||
@@ -87,18 +88,20 @@ export default {
|
||||
return result
|
||||
},
|
||||
|
||||
getSongList(sortId, tagId, page) {
|
||||
getSongList(sortId, tagId, page, tryNum = 0) {
|
||||
if (this._requestObj_list) this._requestObj_list.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
this._requestObj_list = httpFetch(
|
||||
this.getSongListUrl(sortId, tagId, page)
|
||||
)
|
||||
return this._requestObj_list.promise.then(({ body }) => {
|
||||
if (body.status !== 1) return this.getSongList(sortId, tagId, page)
|
||||
if (body.status !== 1) return this.getSongList(sortId, tagId, page, ++tryNum)
|
||||
return this.filterList(body.special_db)
|
||||
})
|
||||
},
|
||||
getSongListRecommend() {
|
||||
getSongListRecommend(tryNum = 0) {
|
||||
if (this._requestObj_listRecommend) this._requestObj_listRecommend.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
this._requestObj_listRecommend = httpFetch(
|
||||
'http://everydayrec.service.kugou.com/guess_special_recommend',
|
||||
{
|
||||
@@ -120,7 +123,7 @@ export default {
|
||||
}
|
||||
)
|
||||
return this._requestObj_listRecommend.promise.then(({ body }) => {
|
||||
if (body.status !== 1) return this.getSongListRecommend()
|
||||
if (body.status !== 1) return this.getSongListRecommend(++tryNum)
|
||||
return this.filterList(body.data.special_list)
|
||||
})
|
||||
},
|
||||
@@ -138,18 +141,34 @@ export default {
|
||||
}))
|
||||
},
|
||||
|
||||
getListDetail(id, page) { // 获取歌曲列表内的音乐
|
||||
getListDetail(id, page, tryNum = 0) { // 获取歌曲列表内的音乐
|
||||
if (this._requestObj_listDetail) this._requestObj_listDetail.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
this._requestObj_listDetail = httpFetch(this.getSongListDetailUrl(id))
|
||||
return this._requestObj_listDetail.promise.then(({ body }) => {
|
||||
let listData = body.match(this.regExps.listData)
|
||||
if (listData) listData = this.filterData(JSON.parse(RegExp.$1))
|
||||
let listInfo = body.match(this.regExps.listInfo)
|
||||
if (!listData) return this.getListDetail(id, page, ++tryNum)
|
||||
listData = this.filterData(JSON.parse(listData[1]))
|
||||
let name
|
||||
let pic
|
||||
if (listInfo) {
|
||||
name = listInfo[1]
|
||||
pic = listInfo[2]
|
||||
}
|
||||
return {
|
||||
list: listData,
|
||||
page: 1,
|
||||
limit: 10000,
|
||||
total: listData.length,
|
||||
source: 'kg',
|
||||
info: {
|
||||
name,
|
||||
img: pic,
|
||||
// desc: body.result.info.list_desc,
|
||||
// author: body.result.info.userinfo.username,
|
||||
// play_count: this.formatPlayCount(body.result.listen_num),
|
||||
},
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -209,11 +228,12 @@ export default {
|
||||
},
|
||||
|
||||
// 获取列表信息
|
||||
getListInfo(tagId) {
|
||||
getListInfo(tagId, tryNum = 0) {
|
||||
if (this._requestObj_listInfo) this._requestObj_listInfo.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
this._requestObj_listInfo = httpFetch(this.getInfoUrl(tagId))
|
||||
return this._requestObj_listInfo.promise.then(({ body }) => {
|
||||
if (body.status !== 1) return this.getListInfo(tagId)
|
||||
if (body.status !== 1) return this.getListInfo(tagId, ++tryNum)
|
||||
return {
|
||||
limit: body.data.params.pagesize,
|
||||
page: body.data.params.p,
|
||||
@@ -246,11 +266,12 @@ export default {
|
||||
},
|
||||
|
||||
// 获取标签
|
||||
getTags() {
|
||||
getTags(tryNum = 0) {
|
||||
if (this._requestObj_tags) this._requestObj_tags.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
this._requestObj_tags = httpFetch(this.getInfoUrl())
|
||||
return this._requestObj_tags.promise.then(({ body }) => {
|
||||
if (body.status !== 1) return this.getTags()
|
||||
if (body.status !== 1) return this.getTags(++tryNum)
|
||||
return {
|
||||
hotTag: this.filterInfoHotTag(body.data.hotTag),
|
||||
tags: this.filterTagInfo(body.data.tagids),
|
||||
|
||||
@@ -80,7 +80,7 @@ export default {
|
||||
size: info[3].toLocaleUpperCase(),
|
||||
}
|
||||
break
|
||||
// case '192':
|
||||
case '192':
|
||||
// types.push({ type: '192k', size: info[3] })
|
||||
// _types['192k'] = {
|
||||
// size: info[3].toLocaleUpperCase(),
|
||||
|
||||
@@ -8,7 +8,7 @@ export default {
|
||||
_requestObj_list: null,
|
||||
_requestObj_listDetail: null,
|
||||
limit_list: 25,
|
||||
limit_song: 100,
|
||||
limit_song: 1000,
|
||||
successCode: 200,
|
||||
sortList: [
|
||||
{
|
||||
@@ -38,20 +38,22 @@ export default {
|
||||
|
||||
// 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() {
|
||||
getTag(tryNum = 0) {
|
||||
if (this._requestObj_tags) this._requestObj_tags.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
this._requestObj_tags = httpFetch(this.tagsUrl)
|
||||
return this._requestObj_tags.promise.then(({ body }) => {
|
||||
if (body.code !== this.successCode) return this.getTag()
|
||||
if (body.code !== this.successCode) return this.getTag(++tryNum)
|
||||
return this.filterTagInfo(body.data)
|
||||
})
|
||||
},
|
||||
// 获取标签
|
||||
getHotTag() {
|
||||
getHotTag(tryNum = 0) {
|
||||
if (this._requestObj_hotTags) this._requestObj_hotTags.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
this._requestObj_hotTags = httpFetch(this.hotTagUrl)
|
||||
return this._requestObj_hotTags.promise.then(({ body }) => {
|
||||
if (body.code !== this.successCode) return this.getHotTag()
|
||||
if (body.code !== this.successCode) return this.getHotTag(++tryNum)
|
||||
return this.filterInfoHotTag(body.data[0].data)
|
||||
})
|
||||
},
|
||||
@@ -76,8 +78,9 @@ export default {
|
||||
},
|
||||
|
||||
// 获取列表数据
|
||||
getList(sortId, tagId, page) {
|
||||
getList(sortId, tagId, page, tryNum = 0) {
|
||||
if (this._requestObj_list) this._requestObj_list.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
let id
|
||||
let type
|
||||
if (tagId) {
|
||||
@@ -90,7 +93,7 @@ export default {
|
||||
this._requestObj_list = httpFetch(this.getListUrl({ sortId, id, type, page }))
|
||||
return this._requestObj_list.promise.then(({ body }) => {
|
||||
if (!id || type == '10000') {
|
||||
if (body.code !== this.successCode) return this.getListUrl({ sortId, id, type, page })
|
||||
if (body.code !== this.successCode) return this.getList(sortId, id, type, page, ++tryNum)
|
||||
return {
|
||||
list: this.filterList(body.data.data),
|
||||
total: body.data.total,
|
||||
@@ -99,7 +102,7 @@ export default {
|
||||
source: 'kw',
|
||||
}
|
||||
} else if (!body.length) {
|
||||
return this.getListUrl({ sortId, id, type, page })
|
||||
return this.getList(sortId, id, type, page, ++tryNum)
|
||||
}
|
||||
return {
|
||||
list: this.filterList2(body),
|
||||
@@ -153,19 +156,27 @@ export default {
|
||||
},
|
||||
|
||||
// 获取歌曲列表内的音乐
|
||||
getListDetail(id, page) {
|
||||
getListDetail(id, page, tryNum = 0) {
|
||||
if (this._requestObj_listDetail) {
|
||||
this._requestObj_listDetail.cancelHttp()
|
||||
}
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
this._requestObj_listDetail = httpFetch(this.getListDetailUrl(id, page))
|
||||
return this._requestObj_listDetail.promise.then(({ body }) => {
|
||||
if (body.result !== 'ok') return this.getListDetail(id, page)
|
||||
if (body.result !== 'ok') return this.getListDetail(id, page, ++tryNum)
|
||||
return {
|
||||
list: this.filterListDetail(body.musiclist),
|
||||
page,
|
||||
limit: body.rn,
|
||||
total: body.total,
|
||||
source: 'kw',
|
||||
info: {
|
||||
name: body.title,
|
||||
img: body.pic,
|
||||
desc: body.info,
|
||||
author: body.uname,
|
||||
play_count: this.formatPlayCount(body.playnum),
|
||||
},
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -211,7 +222,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' }))
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
20
src/renderer/utils/music/mg/api-test.js
Normal file
20
src/renderer/utils/music/mg/api-test.js
Normal 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
|
||||
23
src/renderer/utils/music/mg/index.js
Normal file
23
src/renderer/utils/music/mg/index.js
Normal 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
|
||||
130
src/renderer/utils/music/mg/leaderboard.js
Normal file
130
src/renderer/utils/music/mg/leaderboard.js
Normal 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',
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
36
src/renderer/utils/music/mg/lyric.js
Normal file
36
src/renderer/utils/music/mg/lyric.js
Normal 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
|
||||
}
|
||||
},
|
||||
}
|
||||
108
src/renderer/utils/music/mg/musicSearch.js
Normal file
108
src/renderer/utils/music/mg/musicSearch.js
Normal 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',
|
||||
})
|
||||
})
|
||||
},
|
||||
}
|
||||
21
src/renderer/utils/music/mg/pic.js
Normal file
21
src/renderer/utils/music/mg/pic.js
Normal 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
|
||||
},
|
||||
}
|
||||
224
src/renderer/utils/music/mg/songList.js
Normal file
224
src/renderer/utils/music/mg/songList.js
Normal file
@@ -0,0 +1,224 @@
|
||||
import { httpFetch } from '../../request'
|
||||
import { sizeFormate } from '../../index'
|
||||
|
||||
export default {
|
||||
_requestObj_tags: null,
|
||||
_requestObj_list: null,
|
||||
_requestObj_listDetail: null,
|
||||
limit_list: 10,
|
||||
limit_song: 1000,
|
||||
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, tryNum = 0) { // 获取歌曲列表内的音乐
|
||||
if (this._requestObj_listDetail) this._requestObj_listDetail.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
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, ++tryNum)
|
||||
// console.log(JSON.stringify(body))
|
||||
return {
|
||||
list: this.filterListDetail(body.list),
|
||||
page,
|
||||
limit: this.limit_song,
|
||||
total: body.totalCount,
|
||||
source: 'mg',
|
||||
info: {
|
||||
// name: body.result.info.list_title,
|
||||
// img: body.result.info.list_pic,
|
||||
// desc: body.result.info.list_desc,
|
||||
// author: body.result.info.userinfo.username,
|
||||
// play_count: this.formatPlayCount(body.result.listen_num),
|
||||
},
|
||||
}
|
||||
})
|
||||
},
|
||||
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, tryNum = 0) {
|
||||
if (this._requestObj_list) this._requestObj_list.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
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, ++tryNum)
|
||||
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(tryNum = 0) {
|
||||
if (this._requestObj_tags) this._requestObj_tags.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
this._requestObj_tags = httpFetch(this.tagsUrl, { headers: this.defaultHeaders })
|
||||
return this._requestObj_tags.promise.then(({ body }) => {
|
||||
if (body.code !== this.successCode) return this.getTag(++tryNum)
|
||||
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
|
||||
@@ -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
|
||||
},
|
||||
|
||||
@@ -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)
|
||||
|
||||
106
src/renderer/utils/music/tx/musicSearch.js
Normal file
106
src/renderer/utils/music/tx/musicSearch.js
Normal 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¬ice=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',
|
||||
})
|
||||
})
|
||||
},
|
||||
}
|
||||
270
src/renderer/utils/music/tx/songList.js
Normal file
270
src/renderer/utils/music/tx/songList.js
Normal file
@@ -0,0 +1,270 @@
|
||||
import { httpFetch } from '../../request'
|
||||
import { formatPlayTime, sizeFormate } from '../../index'
|
||||
import jshtmlencode from 'js-htmlencode'
|
||||
|
||||
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¬ice=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¬ice=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: 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¬ice=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: this.limit_list * (page - 1), 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¬ice=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(tryNum = 0) {
|
||||
if (this._requestObj_tags) this._requestObj_tags.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
this._requestObj_tags = httpFetch(this.tagsUrl)
|
||||
return this._requestObj_tags.promise.then(({ body }) => {
|
||||
if (body.code !== this.successCode) return this.getTag(++tryNum)
|
||||
return this.filterTagInfo(body.tags.data.v_group)
|
||||
})
|
||||
},
|
||||
// 获取标签
|
||||
getHotTag(tryNum = 0) {
|
||||
if (this._requestObj_hotTags) this._requestObj_hotTags.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
this._requestObj_hotTags = httpFetch(this.hotTagUrl)
|
||||
return this._requestObj_hotTags.promise.then(({ statusCode, body }) => {
|
||||
if (statusCode !== 200) return this.getHotTag(++tryNum)
|
||||
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, tryNum = 0) {
|
||||
if (this._requestObj_list) this._requestObj_list.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
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, ++tryNum)
|
||||
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: jshtmlencode.htmlDecode(basic.desc).replace(/<br>/g, '\n'),
|
||||
source: 'tx',
|
||||
})),
|
||||
total: content.total_cnt,
|
||||
page,
|
||||
limit: this.limit_list,
|
||||
source: 'tx',
|
||||
}
|
||||
},
|
||||
|
||||
// 获取歌曲列表内的音乐
|
||||
getListDetail(id, tryNum = 0) {
|
||||
if (this._requestObj_listDetail) {
|
||||
this._requestObj_listDetail.cancelHttp()
|
||||
}
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
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, ++tryNum)
|
||||
const cdlist = body.cdlist[0]
|
||||
return {
|
||||
list: this.filterListDetail(cdlist.songlist),
|
||||
page: 1,
|
||||
limit: cdlist.songlist.length + 1,
|
||||
total: cdlist.songlist.length,
|
||||
source: 'tx',
|
||||
info: {
|
||||
name: cdlist.dissname,
|
||||
img: cdlist.logo,
|
||||
desc: jshtmlencode.htmlDecode(cdlist.desc).replace(/<br>/g, '\n'),
|
||||
author: cdlist.nickname,
|
||||
play_count: this.formatPlayCount(cdlist.visitnum),
|
||||
},
|
||||
}
|
||||
})
|
||||
},
|
||||
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
|
||||
@@ -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))
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
import { httpFatch } from '../../request'
|
||||
import { requestMsg } from '../../message'
|
||||
import { headers, timeout } from '../options'
|
||||
|
||||
const api_messoer = {
|
||||
getMusicUrl(songInfo, type) {
|
||||
const requestObj = httpFatch(`https://v1.itooi.cn/netease/url?id=${songInfo.songmid}&quality=${type.replace(/k$/, '')}&isRedirect=0`, {
|
||||
method: 'get',
|
||||
timeout,
|
||||
headers,
|
||||
})
|
||||
requestObj.promise = requestObj.promise.then(({ body }) => {
|
||||
return body.code === 200 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail))
|
||||
})
|
||||
return requestObj
|
||||
},
|
||||
getPic(songInfo) {
|
||||
const requestObj = httpFatch(`https://v1.itooi.cn/netease/pic?id=${songInfo.songmid}&isRedirect=0`, {
|
||||
method: 'get',
|
||||
timeout,
|
||||
headers,
|
||||
})
|
||||
requestObj.promise = requestObj.promise.then(({ body }) => {
|
||||
return body.code === 200 ? Promise.resolve(body.data) : Promise.reject(new Error(requestMsg.fail))
|
||||
})
|
||||
return requestObj
|
||||
},
|
||||
getLyric(songInfo) {
|
||||
const requestObj = httpFatch(`https://v1.itooi.cn/netease/lrc?id=${songInfo.songmid}&isRedirect=0`, {
|
||||
method: 'get',
|
||||
timeout,
|
||||
headers,
|
||||
})
|
||||
requestObj.promise = requestObj.promise.then(({ body }) => {
|
||||
return body ? Promise.resolve(body) : Promise.reject(new Error(requestMsg.fail))
|
||||
})
|
||||
return requestObj
|
||||
},
|
||||
}
|
||||
|
||||
export default api_messoer
|
||||
@@ -15,8 +15,8 @@ const api_test = {
|
||||
})
|
||||
return requestObj
|
||||
},
|
||||
getPic(songInfo) {
|
||||
const requestObj = httpFetch(`http://ts.tempmusic.tk/pic/wy/${songInfo.songmid}`, {
|
||||
/* getPic(songInfo) {
|
||||
const requestObj = httpFetch(`http://localhost:3100/pic/wy/${songInfo.songmid}`, {
|
||||
method: 'get',
|
||||
timeout,
|
||||
headers,
|
||||
@@ -28,7 +28,7 @@ const api_test = {
|
||||
return requestObj
|
||||
},
|
||||
getLyric(songInfo) {
|
||||
const requestObj = httpFetch(`http://ts.tempmusic.tk/lrc/wy/${songInfo.songmid}`, {
|
||||
const requestObj = httpFetch(`http://localhost:3100/lrc/wy/${songInfo.songmid}`, {
|
||||
method: 'get',
|
||||
timeout,
|
||||
headers,
|
||||
@@ -38,7 +38,7 @@ const api_test = {
|
||||
return body.code === 0 ? Promise.resolve(body.data) : Promise.reject(new Error(requestMsg.fail))
|
||||
})
|
||||
return requestObj
|
||||
},
|
||||
}, */
|
||||
}
|
||||
|
||||
export default api_test
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
import leaderboard from './leaderboard'
|
||||
import api_source from '../api-source'
|
||||
import getLyric from './lyric'
|
||||
import getMusicInfo from './musicInfo'
|
||||
import musicSearch from './musicSearch'
|
||||
import songList from './songList'
|
||||
|
||||
const wy = {
|
||||
leaderboard,
|
||||
musicSearch,
|
||||
songList,
|
||||
getMusicUrl(songInfo, type) {
|
||||
return api_source('wy').getMusicUrl(songInfo, type)
|
||||
},
|
||||
getLyric(songInfo) {
|
||||
return api_source('wy').getLyric(songInfo)
|
||||
return getLyric(songInfo.songmid)
|
||||
},
|
||||
getPic(songInfo) {
|
||||
return api_source('wy').getPic(songInfo)
|
||||
return getMusicInfo(songInfo.songmid).then(info => info.al.picUrl)
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
21
src/renderer/utils/music/wy/lyric.js
Normal file
21
src/renderer/utils/music/wy/lyric.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import { httpFetch } from '../../request'
|
||||
import { weapi } from './utils/crypto'
|
||||
|
||||
export default songmid => {
|
||||
const requestObj = httpFetch('http://music.163.com/weapi/song/lyric?csrf_token=', {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36',
|
||||
Referer: 'https://music.163.com/song?id=' + songmid,
|
||||
origin: 'https://music.163.com',
|
||||
},
|
||||
form: weapi({ id: songmid, lv: -1, tv: -1, csrf_token: '' }),
|
||||
})
|
||||
requestObj.promise = requestObj.promise.then(({ body }) => {
|
||||
// console.log(body)
|
||||
if (body.code !== 200) return Promise.reject('获取歌词失败')
|
||||
return body.lrc.lyric
|
||||
})
|
||||
return requestObj
|
||||
}
|
||||
|
||||
25
src/renderer/utils/music/wy/musicInfo.js
Normal file
25
src/renderer/utils/music/wy/musicInfo.js
Normal file
@@ -0,0 +1,25 @@
|
||||
// https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/module/song_detail.js
|
||||
import { httpFetch } from '../../request'
|
||||
import { weapi } from './utils/crypto'
|
||||
|
||||
export default songmid => {
|
||||
const requestObj = httpFetch('https://music.163.com/weapi/v3/song/detail', {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36',
|
||||
Referer: 'https://music.163.com/song?id=' + songmid,
|
||||
origin: 'https://music.163.com',
|
||||
},
|
||||
form: weapi({
|
||||
c: `[{"id":${songmid}}]`,
|
||||
ids: `[${songmid}]`,
|
||||
}),
|
||||
})
|
||||
requestObj.promise = requestObj.promise.then(({ body }) => {
|
||||
// console.log(body)
|
||||
if (body.code !== 200 || !body.songs.length) return Promise.reject('获取歌曲信息失败')
|
||||
return body.songs[0]
|
||||
})
|
||||
return requestObj
|
||||
}
|
||||
|
||||
102
src/renderer/utils/music/wy/musicSearch.js
Normal file
102
src/renderer/utils/music/wy/musicSearch.js
Normal file
@@ -0,0 +1,102 @@
|
||||
import { httpFetch } from '../../request'
|
||||
import { weapi } from './utils/crypto'
|
||||
import { sizeFormate, formatPlayTime } from '../../index'
|
||||
|
||||
let searchRequest
|
||||
export default {
|
||||
limit: 30,
|
||||
total: 0,
|
||||
page: 0,
|
||||
allPage: 1,
|
||||
musicSearch(str, page) {
|
||||
if (searchRequest && searchRequest.cancelHttp) searchRequest.cancelHttp()
|
||||
searchRequest = httpFetch('http://music.163.com/weapi/cloudsearch/get/web?csrf_token=', {
|
||||
method: 'post',
|
||||
form: weapi({
|
||||
s: str,
|
||||
type: 1, // 1: 单曲, 10: 专辑, 100: 歌手, 1000: 歌单, 1002: 用户, 1004: MV, 1006: 歌词, 1009: 电台, 1014: 视频
|
||||
limit: this.limit,
|
||||
offset: this.limit * (page - 1),
|
||||
}),
|
||||
})
|
||||
return searchRequest.promise.then(({ body }) => body)
|
||||
},
|
||||
getSinger(singers) {
|
||||
let arr = []
|
||||
singers.forEach(singer => {
|
||||
arr.push(singer.name)
|
||||
})
|
||||
return arr.join('、')
|
||||
},
|
||||
handleResult(rawList) {
|
||||
// console.log(rawList)
|
||||
return rawList.map(item => {
|
||||
const types = []
|
||||
const _types = {}
|
||||
let size
|
||||
switch (item.privilege.maxbr) {
|
||||
case 999000:
|
||||
size = null
|
||||
types.push({ type: 'flac', size })
|
||||
_types.flac = {
|
||||
size,
|
||||
}
|
||||
case 320000:
|
||||
if (item.h) {
|
||||
size = sizeFormate(item.h.size)
|
||||
types.push({ type: '320k', size })
|
||||
_types['320k'] = {
|
||||
size,
|
||||
}
|
||||
}
|
||||
case 128000:
|
||||
if (item.l) {
|
||||
size = sizeFormate(item.l.size)
|
||||
types.push({ type: '128k', size })
|
||||
_types['128k'] = {
|
||||
size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
types.reverse()
|
||||
|
||||
return {
|
||||
singer: this.getSinger(item.ar),
|
||||
name: item.name,
|
||||
albumName: item.al.name,
|
||||
albumId: item.al.id,
|
||||
source: 'wy',
|
||||
interval: formatPlayTime(item.dt / 1000),
|
||||
songmid: item.id,
|
||||
img: item.al.picUrl,
|
||||
lrc: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
}
|
||||
})
|
||||
},
|
||||
search(str, page = 1, { limit } = {}) {
|
||||
if (limit != null) this.limit = limit
|
||||
return this.musicSearch(str, page).then(result => {
|
||||
// console.log(JSON.stringify(result))
|
||||
if (!result || result.code !== 200) return this.search(str, page, { limit })
|
||||
let list = this.handleResult(result.result.songs)
|
||||
|
||||
if (list == null) return this.search(str, page, { limit })
|
||||
|
||||
this.total = result.result.songCount
|
||||
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: 'wy',
|
||||
})
|
||||
})
|
||||
},
|
||||
}
|
||||
242
src/renderer/utils/music/wy/songList.js
Normal file
242
src/renderer/utils/music/wy/songList.js
Normal file
@@ -0,0 +1,242 @@
|
||||
// https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/module/playlist_catlist.js
|
||||
// https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/module/playlist_hot.js
|
||||
// https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/module/top_playlist.js
|
||||
// https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/module/playlist_detail.js
|
||||
|
||||
import { weapi, linuxapi } from './utils/crypto'
|
||||
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: 30,
|
||||
limit_song: 100000,
|
||||
successCode: 200,
|
||||
sortList: [
|
||||
{
|
||||
name: '最热',
|
||||
id: 'hot',
|
||||
},
|
||||
{
|
||||
name: '最新',
|
||||
id: 'new',
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 格式化播放数量
|
||||
* @param {*} num
|
||||
*/
|
||||
formatPlayCount(num) {
|
||||
if (num > 100000000) return parseInt(num / 10000000) / 10 + '亿'
|
||||
if (num > 10000) return parseInt(num / 1000) / 10 + '万'
|
||||
return num
|
||||
},
|
||||
getSinger(singers) {
|
||||
let arr = []
|
||||
singers.forEach(singer => {
|
||||
arr.push(singer.name)
|
||||
})
|
||||
return arr.join('、')
|
||||
},
|
||||
|
||||
getListDetail(id, page, tryNum = 0) { // 获取歌曲列表内的音乐
|
||||
if (this._requestObj_listDetail) this._requestObj_listDetail.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
this._requestObj_listDetail = httpFetch('https://music.163.com/api/linux/forward', {
|
||||
method: 'post',
|
||||
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36',
|
||||
form: linuxapi({
|
||||
method: 'POST',
|
||||
url: 'https://music.163.com/api/v3/playlist/detail',
|
||||
params: {
|
||||
id,
|
||||
n: this.limit_song,
|
||||
s: 8,
|
||||
},
|
||||
}),
|
||||
})
|
||||
return this._requestObj_listDetail.promise.then(({ body }) => {
|
||||
if (body.code !== this.successCode) return this.getListDetail(id, page, ++tryNum)
|
||||
return {
|
||||
list: this.filterListDetail(body),
|
||||
page,
|
||||
limit: this.limit_song,
|
||||
total: body.playlist.tracks.length,
|
||||
source: 'wy',
|
||||
info: {
|
||||
play_count: this.formatPlayCount(body.playlist.playCount),
|
||||
name: body.playlist.name,
|
||||
img: body.playlist.coverImgUrl,
|
||||
desc: body.playlist.description,
|
||||
author: body.playlist.creator.nickname,
|
||||
},
|
||||
}
|
||||
})
|
||||
},
|
||||
filterListDetail({ playlist: { tracks }, privileges }) {
|
||||
// console.log(tracks, privileges)
|
||||
const list = []
|
||||
tracks.forEach((item, index) => {
|
||||
const types = []
|
||||
const _types = {}
|
||||
let size
|
||||
let privilege = privileges[index]
|
||||
if (privilege.id !== item.id) privilege = privileges.find(p => p.id === item.id)
|
||||
if (!privilege) return
|
||||
|
||||
switch (privilege.maxbr) {
|
||||
case 999000:
|
||||
size = null
|
||||
types.push({ type: 'flac', size })
|
||||
_types.flac = {
|
||||
size,
|
||||
}
|
||||
case 320000:
|
||||
if (item.h) {
|
||||
size = sizeFormate(item.h.size)
|
||||
types.push({ type: '320k', size })
|
||||
_types['320k'] = {
|
||||
size,
|
||||
}
|
||||
}
|
||||
case 128000:
|
||||
if (item.l) {
|
||||
size = sizeFormate(item.l.size)
|
||||
types.push({ type: '128k', size })
|
||||
_types['128k'] = {
|
||||
size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
types.reverse()
|
||||
|
||||
list.push({
|
||||
singer: this.getSinger(item.ar),
|
||||
name: item.name,
|
||||
albumName: item.al.name,
|
||||
albumId: item.al.id,
|
||||
source: 'wy',
|
||||
interval: formatPlayTime(item.dt / 1000),
|
||||
songmid: item.id,
|
||||
img: item.al.picUrl,
|
||||
lrc: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
})
|
||||
})
|
||||
return list
|
||||
},
|
||||
|
||||
// 获取列表数据
|
||||
getList(sortId, tagId, page, tryNum = 0) {
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
if (this._requestObj_list) this._requestObj_list.cancelHttp()
|
||||
this._requestObj_list = httpFetch('https://music.163.com/weapi/playlist/list', {
|
||||
method: 'post',
|
||||
form: weapi({
|
||||
cat: tagId || '全部', // 全部,华语,欧美,日语,韩语,粤语,小语种,流行,摇滚,民谣,电子,舞曲,说唱,轻音乐,爵士,乡村,R&B/Soul,古典,民族,英伦,金属,朋克,蓝调,雷鬼,世界音乐,拉丁,另类/独立,New Age,古风,后摇,Bossa Nova,清晨,夜晚,学习,工作,午休,下午茶,地铁,驾车,运动,旅行,散步,酒吧,怀旧,清新,浪漫,性感,伤感,治愈,放松,孤独,感动,兴奋,快乐,安静,思念,影视原声,ACG,儿童,校园,游戏,70后,80后,90后,网络歌曲,KTV,经典,翻唱,吉他,钢琴,器乐,榜单,00后
|
||||
order: sortId, // hot,new
|
||||
limit: this.limit_list,
|
||||
offset: this.limit_list * (page - 1),
|
||||
total: true,
|
||||
}),
|
||||
})
|
||||
return this._requestObj_list.promise.then(({ body }) => {
|
||||
// console.log(JSON.stringify(body))
|
||||
if (body.code !== this.successCode) return this.getList(sortId, tagId, page, ++tryNum)
|
||||
return {
|
||||
list: this.filterList(body.playlists),
|
||||
total: parseInt(body.total),
|
||||
page,
|
||||
limit: this.limit_list,
|
||||
source: 'wy',
|
||||
}
|
||||
})
|
||||
},
|
||||
filterList(rawData) {
|
||||
return rawData.map(item => ({
|
||||
play_count: this.formatPlayCount(item.playCount),
|
||||
id: item.id,
|
||||
author: item.creator.nickname,
|
||||
name: item.name,
|
||||
time: item.createTime,
|
||||
img: item.coverImgUrl,
|
||||
grade: item.grade,
|
||||
desc: item.description,
|
||||
source: 'wy',
|
||||
}))
|
||||
},
|
||||
|
||||
// 获取标签
|
||||
getTag(tryNum = 0) {
|
||||
if (this._requestObj_tags) this._requestObj_tags.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
this._requestObj_tags = httpFetch('https://music.163.com/weapi/playlist/catalogue', {
|
||||
method: 'post',
|
||||
form: weapi({}),
|
||||
})
|
||||
return this._requestObj_tags.promise.then(({ body }) => {
|
||||
// console.log(JSON.stringify(body))
|
||||
if (body.code !== this.successCode) return this.getTag(++tryNum)
|
||||
return this.filterTagInfo(body)
|
||||
})
|
||||
},
|
||||
filterTagInfo({ sub, categories }) {
|
||||
const subList = {}
|
||||
for (const item of sub) {
|
||||
if (!subList[item.category]) subList[item.category] = []
|
||||
subList[item.category].push({
|
||||
parent_id: categories[item.category],
|
||||
parent_name: categories[item.category],
|
||||
id: item.name,
|
||||
name: item.name,
|
||||
source: 'wy',
|
||||
})
|
||||
}
|
||||
|
||||
const list = []
|
||||
for (const key of Object.keys(categories)) {
|
||||
list.push({
|
||||
name: categories[key],
|
||||
list: subList[key],
|
||||
source: 'wy',
|
||||
})
|
||||
}
|
||||
return list
|
||||
},
|
||||
|
||||
// 获取热门标签
|
||||
getHotTag(tryNum = 0) {
|
||||
if (this._requestObj_hotTags) this._requestObj_hotTags.cancelHttp()
|
||||
if (tryNum > 2) return Promise.reject(new Error('try max num'))
|
||||
this._requestObj_hotTags = httpFetch('https://music.163.com/weapi/playlist/hottags', {
|
||||
method: 'post',
|
||||
form: weapi({}),
|
||||
})
|
||||
return this._requestObj_hotTags.promise.then(({ body }) => {
|
||||
// console.log(JSON.stringify(body))
|
||||
if (body.code !== this.successCode) return this.getTag(++tryNum)
|
||||
return this.filterHotTagInfo(body.tags)
|
||||
})
|
||||
},
|
||||
filterHotTagInfo(rawList) {
|
||||
return rawList.map(item => ({
|
||||
id: item.playlistTag.name,
|
||||
name: item.playlistTag.name,
|
||||
source: 'wy',
|
||||
}))
|
||||
},
|
||||
|
||||
getTags() {
|
||||
return Promise.all([this.getTag(), this.getHotTag()]).then(([tags, hotTag]) => ({ tags, hotTag, source: 'wy' }))
|
||||
},
|
||||
}
|
||||
|
||||
// getList
|
||||
// getTags
|
||||
// getListDetail
|
||||
33
src/renderer/utils/music/wy/utils/crypto.js
Normal file
33
src/renderer/utils/music/wy/utils/crypto.js
Normal file
@@ -0,0 +1,33 @@
|
||||
// https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/util/crypto.js
|
||||
import { createCipheriv, publicEncrypt, constants, randomBytes } from 'crypto'
|
||||
const iv = Buffer.from('0102030405060708')
|
||||
const presetKey = Buffer.from('0CoJUm6Qyw8W8jud')
|
||||
const linuxapiKey = Buffer.from('rFgB&h#%2?^eDg:Q')
|
||||
const base62 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
|
||||
const publicKey = '-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgtQn2JZ34ZC28NWYpAUd98iZ37BUrX/aKzmFbt7clFSs6sXqHauqKWqdtLkF2KexO40H1YTX8z2lSgBBOAxLsvaklV8k4cBFK9snQXE9/DDaFt6Rr7iVZMldczhC0JNgTz+SHXT6CBHuX3e9SdB1Ua44oncaTWz7OBGLbCiK45wIDAQAB\n-----END PUBLIC KEY-----'
|
||||
|
||||
const aesEncrypt = (buffer, mode, key, iv) => {
|
||||
const cipher = createCipheriv('aes-128-' + mode, key, iv)
|
||||
return Buffer.concat([cipher.update(buffer), cipher.final()])
|
||||
}
|
||||
|
||||
const rsaEncrypt = (buffer, key) => {
|
||||
buffer = Buffer.concat([Buffer.alloc(128 - buffer.length), buffer])
|
||||
return publicEncrypt({ key: key, padding: constants.RSA_NO_PADDING }, buffer)
|
||||
}
|
||||
|
||||
export const weapi = object => {
|
||||
const text = JSON.stringify(object)
|
||||
const secretKey = randomBytes(16).map(n => (base62.charAt(n % 62).charCodeAt()))
|
||||
return {
|
||||
params: aesEncrypt(Buffer.from(aesEncrypt(Buffer.from(text), 'cbc', presetKey, iv).toString('base64')), 'cbc', secretKey, iv).toString('base64'),
|
||||
encSecKey: rsaEncrypt(secretKey.reverse(), publicKey).toString('hex'),
|
||||
}
|
||||
}
|
||||
|
||||
export const linuxapi = object => {
|
||||
const text = JSON.stringify(object)
|
||||
return {
|
||||
eparams: aesEncrypt(Buffer.from(text), 'ecb', linuxapiKey, '').toString('hex').toUpperCase(),
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import request from 'request'
|
||||
import { debugRequest } from './env'
|
||||
import { requestMsg } from './message'
|
||||
import { bHh } from './music/options'
|
||||
import { deflateRawSync } from 'zlib'
|
||||
// import fs from 'fs'
|
||||
|
||||
const defaultHeaders = {
|
||||
@@ -222,6 +223,8 @@ const getProxyInfo = () => window.globalObj.proxy.enable
|
||||
? `http://${window.globalObj.proxy.username}:${window.globalObj.proxy.password}@${window.globalObj.proxy.host}:${window.globalObj.proxy.port};`
|
||||
: undefined
|
||||
|
||||
const regx = /(?:\d\w)+/g
|
||||
|
||||
const fetchData = (url, method, {
|
||||
headers = {},
|
||||
format = 'json',
|
||||
@@ -230,11 +233,13 @@ const fetchData = (url, method, {
|
||||
}, callback) => {
|
||||
// console.log(url, options)
|
||||
console.log('---start---', url)
|
||||
headers = Object.assign({}, headers)
|
||||
if (headers[bHh]) {
|
||||
let s = Buffer.from(bHh, 'hex').toString()
|
||||
s = s.replace(s.substr(-1), '')
|
||||
s = Buffer.from(s, 'base64').toString()
|
||||
headers[s] = !!s
|
||||
let v = process.versions.app.split('.').map(n => n.length < 3 ? n.padStart(3, '0') : n).join('')
|
||||
headers[s] = !s || `${deflateRawSync(Buffer.from(JSON.stringify(`${url}${v}`.match(regx), null, 1).concat(v)).toString('base64')).toString('hex')}&${parseInt(v)}`
|
||||
delete headers[bHh]
|
||||
}
|
||||
return request(url, {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,8 @@ export default {
|
||||
},
|
||||
handleAddDownloadMultiple(type) {
|
||||
switch (this.source) {
|
||||
case 'kg':
|
||||
// case 'kg':
|
||||
case 'tx':
|
||||
case 'wy':
|
||||
type = '128k'
|
||||
}
|
||||
@@ -125,6 +134,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 +147,7 @@ export default {
|
||||
this.testPlay()
|
||||
break
|
||||
case 'add':
|
||||
this.defaultListAddMultiple(this.selectdData)
|
||||
this.resetSelect()
|
||||
this.isShowListAddMultiple = true
|
||||
break
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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') ? $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') 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') 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]
|
||||
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}';
|
||||
|
||||
@@ -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"
|
||||
:download-btn="item.source == 'kw' || !isAPITemp"
|
||||
@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') 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]
|
||||
},
|
||||
handleListAddModalClose(isSelect) {
|
||||
if (isSelect) this.resetSelect()
|
||||
this.isShowListAddMultiple = false
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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: {
|
||||
@@ -238,7 +262,7 @@ export default {
|
||||
// },
|
||||
{
|
||||
id: 'test',
|
||||
label: '测试接口(软件的大部分功能可用,该接口访问速度略慢)',
|
||||
label: '测试接口(几乎软件的所有功能都可用,该接口访问速度略慢)',
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
@@ -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()
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,36 +1,49 @@
|
||||
<template lang="pug">
|
||||
div(:class="$style.container")
|
||||
transition(enter-active-class="animated-fast fadeIn" leave-active-class="animated-fast fadeOut")
|
||||
div(:class="$style.songListDetailContent" v-show="isVisibleListDetail")
|
||||
div(:class="$style.songListDetailContent" v-if="isVisibleListDetail")
|
||||
div(:class="$style.songListHeader")
|
||||
div(:class="$style.songListHeaderLeft")
|
||||
img(:src="selectListInfo.img")
|
||||
span(:class="$style.playNum" v-if="selectListInfo.play_count") {{selectListInfo.play_count}}
|
||||
img(:src="listDetail.info.img || selectListInfo.img")
|
||||
span(:class="$style.playNum" v-if="listDetail.info.play_count || selectListInfo.play_count") {{listDetail.info.play_count || selectListInfo.play_count}}
|
||||
div(:class="$style.songListHeaderMiddle")
|
||||
h3(:title="selectListInfo.name") {{selectListInfo.name}}
|
||||
p(:title="selectListInfo.desc") {{selectListInfo.desc}}
|
||||
h3(:title="listDetail.info.name || selectListInfo.name") {{listDetail.info.name || selectListInfo.name}}
|
||||
p(:title="listDetail.info.desc || selectListInfo.desc") {{listDetail.info.desc || selectListInfo.desc}}
|
||||
div(:class="$style.songListHeaderRight")
|
||||
//- material-btn(:class="$style.closeDetailButton" :disabled="detailLoading" @click="addSongListDetail") 添加
|
||||
//- |
|
||||
//- material-btn(:class="$style.closeDetailButton" :disabled="detailLoading" @click="playSongListDetail") 播放
|
||||
//- |
|
||||
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")
|
||||
transition(enter-active-class="animated-fast fadeIn" leave-active-class="animated-fast fadeOut")
|
||||
div(:class="$style.songListContent" v-show="!isVisibleListDetail")
|
||||
div(:class="$style.songListContainer" v-if="!isVisibleListDetail")
|
||||
div(:class="$style.header")
|
||||
material-tag-list(:class="$style.tagList" :list="tagList" v-model="tagInfo")
|
||||
material-tab(:class="$style.tab" :list="sorts" item-key="id" item-name="name" v-model="sortId")
|
||||
material-select(:class="$style.select" :list="sourceInfo.sources" item-key="id" item-name="name" v-model="source")
|
||||
div.scroll(:class="$style.songList" ref="dom_scrollContent")
|
||||
ul
|
||||
li(:class="$style.item" v-for="(item, index) in listData.list" @click="handleItemClick(index)")
|
||||
div(:class="$style.left")
|
||||
img(:src="item.img")
|
||||
div(:class="$style.right" :src="item.img")
|
||||
h4(:title="item.name") {{item.name}}
|
||||
p(:title="item.desc") {{item.desc}}
|
||||
li(:class="$style.item" style="cursor: default;" v-if="listData.list && listData.list.length && listData.list.length % 3 == 2")
|
||||
div(:class="$style.pagination")
|
||||
material-pagination(:count="listData.total" :limit="listData.limit" :page="listData.page" @btn-click="handleToggleListPage")
|
||||
div(:class="$style.songListContent")
|
||||
transition(enter-active-class="animated-fast fadeIn" leave-active-class="animated-fast fadeOut")
|
||||
div.scroll(:class="$style.songList" v-if="sortId !== 'importSongList'" ref="dom_scrollContent")
|
||||
ul
|
||||
li(:class="$style.item" v-for="(item, index) in listData.list" @click="handleItemClick(index)")
|
||||
div(:class="$style.left")
|
||||
img(:src="item.img")
|
||||
div(:class="$style.right" :src="item.img")
|
||||
h4(:title="item.name") {{item.name}}
|
||||
p(:title="item.desc") {{item.desc}}
|
||||
li(:class="$style.item" style="cursor: default;" v-if="listData.list && listData.list.length && listData.list.length % 3 == 2")
|
||||
div(:class="$style.pagination")
|
||||
material-pagination(:count="listData.total" :limit="listData.limit" :page="listData.page" @btn-click="handleToggleListPage")
|
||||
transition(enter-active-class="animated-fast fadeIn" leave-active-class="animated-fast fadeOut")
|
||||
div(:class="$style.importSongListContent" v-show="sortId === 'importSongList'")
|
||||
material-search-input(v-model="importSongListText" @event="handleImportSongListEvent" big placeholder="输入歌单链接或歌单ID")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 451.846 451.847' space='preserve')
|
||||
use(xlink:href='#icon-right')
|
||||
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 +65,10 @@ export default {
|
||||
selectdData: [],
|
||||
isShowDownloadMultiple: false,
|
||||
isToggleSource: false,
|
||||
isShowListAdd: false,
|
||||
isShowListAddMultiple: false,
|
||||
importSongListText: '',
|
||||
// detailLoading: true,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -59,7 +76,21 @@ export default {
|
||||
...mapGetters('songList', ['sourceInfo', 'tags', 'listData', 'isVisibleListDetail', 'selectListInfo', 'listDetail']),
|
||||
...mapGetters('list', ['defaultList']),
|
||||
sorts() {
|
||||
return this.source ? this.sourceInfo.sortList[this.source] : []
|
||||
let list
|
||||
list = this.source ? [...this.sourceInfo.sortList[this.source]] : []
|
||||
switch (this.source) {
|
||||
case 'wy':
|
||||
case 'kw':
|
||||
case 'bd':
|
||||
case 'tx':
|
||||
case 'mg':
|
||||
case 'kg':
|
||||
list.push({
|
||||
name: `打开${this.sourceInfo.sources.find(s => s.id == this.source).name}歌单`,
|
||||
id: 'importSongList',
|
||||
})
|
||||
}
|
||||
return list
|
||||
},
|
||||
isAPITemp() {
|
||||
return this.setting.apiSource == 'temp'
|
||||
@@ -72,6 +103,7 @@ export default {
|
||||
sortId(n, o) {
|
||||
this.setSongList({ sortId: n })
|
||||
if (o === undefined && this.listData.page !== 1) return
|
||||
if (n == 'importSongList') return
|
||||
this.$nextTick(() => {
|
||||
this.getList(1).then(() => {
|
||||
this.$nextTick(() => {
|
||||
@@ -84,6 +116,7 @@ export default {
|
||||
tagInfo(n, o) {
|
||||
this.setSongList({ tagInfo: n })
|
||||
if (!o && this.listData.page !== 1) return
|
||||
if (this.sortId == 'importSongList') this.sortId = this.sorts[0] && this.sorts[0].id
|
||||
if (this.isToggleSource) {
|
||||
this.isToggleSource = false
|
||||
return
|
||||
@@ -100,6 +133,7 @@ export default {
|
||||
source(n, o) {
|
||||
this.setSongList({ source: n })
|
||||
if (!this.tags[n]) this.getTags()
|
||||
this.importSongListText = ''
|
||||
if (o) {
|
||||
this.isToggleSource = true
|
||||
this.tagInfo = {
|
||||
@@ -121,7 +155,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 +171,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 +195,7 @@ export default {
|
||||
if (targetIndex > -1) {
|
||||
this.setList({
|
||||
list: this.defaultList.list,
|
||||
listId: 'test',
|
||||
listId: this.defaultList.id,
|
||||
index: targetIndex,
|
||||
})
|
||||
}
|
||||
@@ -191,7 +229,8 @@ export default {
|
||||
},
|
||||
handleAddDownloadMultiple(type) {
|
||||
switch (this.source) {
|
||||
case 'kg':
|
||||
// case 'kg':
|
||||
case 'tx':
|
||||
case 'wy':
|
||||
type = '128k'
|
||||
}
|
||||
@@ -200,6 +239,7 @@ export default {
|
||||
this.isShowDownloadMultiple = false
|
||||
},
|
||||
handleItemClick(index) {
|
||||
// this.detailLoading = true
|
||||
this.setSelectListInfo(this.listData.list[index])
|
||||
this.setVisibleListDetail(true)
|
||||
this.clearListDetail()
|
||||
@@ -216,8 +256,7 @@ export default {
|
||||
this.testPlay()
|
||||
break
|
||||
case 'add':
|
||||
this.defaultListAddMultiple(this.selectdData)
|
||||
this.resetSelect()
|
||||
this.isShowListAddMultiple = true
|
||||
break
|
||||
}
|
||||
},
|
||||
@@ -241,6 +280,80 @@ export default {
|
||||
hideListDetail() {
|
||||
setTimeout(() => this.setVisibleListDetail(false), 50)
|
||||
},
|
||||
handleListAddModalClose(isSelect) {
|
||||
if (isSelect) this.resetSelect()
|
||||
this.isShowListAddMultiple = false
|
||||
},
|
||||
handleImportSongListEvent({ action }) {
|
||||
switch (action) {
|
||||
case 'submit':
|
||||
this.handleGetSongListDetail()
|
||||
break
|
||||
case 'blur':
|
||||
this.parseImportSongListInputText()
|
||||
break
|
||||
}
|
||||
},
|
||||
handleGetSongListDetail() {
|
||||
this.parseImportSongListInputText()
|
||||
this.setSelectListInfo({
|
||||
play_count: null,
|
||||
id: this.importSongListText,
|
||||
author: '',
|
||||
name: '',
|
||||
img: null,
|
||||
desc: '',
|
||||
source: this.source,
|
||||
})
|
||||
this.clearListDetail()
|
||||
this.$nextTick(() => {
|
||||
this.setVisibleListDetail(true)
|
||||
this.getListDetail({ id: this.importSongListText, page: 1 })
|
||||
})
|
||||
},
|
||||
parseImportSongListInputText() {
|
||||
if (!/[?&:/]/.test(this.importSongListText)) return
|
||||
const text = this.importSongListText
|
||||
let regx
|
||||
switch (this.source) {
|
||||
case 'wy':
|
||||
regx = /^.+(?:\?|&)id=(\d+)(?:&.*$|#.*$|$)/
|
||||
break
|
||||
case 'tx':
|
||||
// https://y.qq.com/n/yqq/playlist/7217720898.html
|
||||
// https://i.y.qq.com/n2/m/share/details/taoge.html?platform=11&appshare=android_qq&appversion=9050006&id=7217720898&ADTAG=qfshare
|
||||
regx = /\/\/i\.y\.qq\.com/.test(text) ? /^.+(?:\?|&)id=(\d+)(?:&.*$|#.*$|$)/ : /^.+\/(\d+)\.html(?:\?.*|&.*$|#.*$|$)/
|
||||
break
|
||||
case 'kw':
|
||||
// http://www.kuwo.cn/playlist_detail/2886046289
|
||||
regx = /^.+\/playlist_detail\/(\d+)(?:\?.*|&.*$|#.*$|$)/
|
||||
break
|
||||
case 'bd':
|
||||
// http://music.taihe.com/songlist/566347741
|
||||
regx = /^.+\/songlist\/(\d+)(?:\?.*|&.*$|#.*$|$)/
|
||||
break
|
||||
case 'mg':
|
||||
// http://music.migu.cn/v3/music/playlist/161044573?page=1
|
||||
regx = /^.+\/playlist\/(\d+)(?:\?.*|&.*$|#.*$|$)/
|
||||
break
|
||||
case 'kg':
|
||||
// https://www.kugou.com/yy/special/single/1067062.html
|
||||
regx = /^.+\/(\d+)\.html(?:\?.*|&.*$|#.*$|$)/
|
||||
break
|
||||
default:
|
||||
return
|
||||
}
|
||||
this.importSongListText = text.replace(regx, '$1')
|
||||
},
|
||||
/* addSongListDetail() {
|
||||
// this.detailLoading = true
|
||||
// this.getListDetailAll(this.selectListInfo.id).then(() => {
|
||||
// this.detailLoading = false
|
||||
// })
|
||||
},
|
||||
playSongListDetail() {
|
||||
|
||||
}, */
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -269,17 +382,28 @@ export default {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.songListContent, .song-list-detail-content {
|
||||
.songListContainer, .song-list-detail-content, .songListContent, .importSongListContent {
|
||||
// flex: auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.songListContent {
|
||||
.songListContainer, .songListContent, .importSongListContent {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
height: 100%;
|
||||
// position: relative;
|
||||
}
|
||||
|
||||
.importSongListContent {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
padding-top: 20%;
|
||||
}
|
||||
|
||||
.song-list-header {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
|
||||
Reference in New Issue
Block a user