You've already forked lx-music-desktop
Compare commits
49 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c0cbe3253 | ||
|
|
462dc5da51 | ||
|
|
40fad5f785 | ||
|
|
c0791acbf6 | ||
|
|
3cb0a56647 | ||
|
|
95f38e8048 | ||
|
|
a3493a6c74 | ||
|
|
3535bb4e4e | ||
|
|
3be6242cb5 | ||
|
|
64a53830e4 | ||
|
|
b3e3860b23 | ||
|
|
4db560fb4b | ||
|
|
b00de4d976 | ||
|
|
ac162103a7 | ||
|
|
16876502d1 | ||
|
|
4cdd2110a6 | ||
|
|
b820adf0bf | ||
|
|
1cee2febf4 | ||
|
|
43f8d9d72b | ||
|
|
66ffe03224 | ||
|
|
5c96c83f98 | ||
|
|
6d1ddece92 | ||
|
|
897107ca23 | ||
|
|
0baaffdad8 | ||
|
|
784d2fda6d | ||
|
|
19817249db | ||
|
|
240260e598 | ||
|
|
fcf92f06ef | ||
|
|
fe1c2a1896 | ||
|
|
d55c65e275 | ||
|
|
93064bb18b | ||
|
|
dec1b24c86 | ||
|
|
8c76c3d81c | ||
|
|
8d8cabd5b3 | ||
|
|
aa948b0149 | ||
|
|
a25ef6e2a0 | ||
|
|
c404d3ac8d | ||
|
|
8eb71495a1 | ||
|
|
db824c4601 | ||
|
|
029886cc87 | ||
|
|
42604ec737 | ||
|
|
caaa62db30 | ||
|
|
0f135e0587 | ||
|
|
dae6826cc1 | ||
|
|
ddf2ac7ece | ||
|
|
5e011356f2 | ||
|
|
82e047dc66 | ||
|
|
7720b416d5 | ||
|
|
c40dc0fa50 |
58
CHANGELOG.md
58
CHANGELOG.md
@@ -6,6 +6,64 @@ 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/).
|
||||
|
||||
## [1.4.1](https://github.com/lyswhut/lx-music-desktop/compare/v1.4.0...v1.4.1) - 2020-11-25
|
||||
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复有歌词翻译与无歌词的音乐间切换会导致歌词翻译残留显示的问题
|
||||
- 修复歌曲URL过期时,等待刷新URL的自动切换歌曲时间间隔太短的问题
|
||||
- 修复某些电脑上的某些歌曲没有声音的问题(升级Electron9.3.4导致的,现降级到9.3.3)
|
||||
|
||||
## [1.4.0](https://github.com/lyswhut/lx-music-desktop/compare/v1.3.0...v1.4.0) - 2020-11-21
|
||||
|
||||
### 新增
|
||||
|
||||
- 托盘菜单新增显示、隐藏主界面选项,为Linux、MAC版添加托盘菜单
|
||||
- 新增播放进度信息保存
|
||||
|
||||
### 优化
|
||||
|
||||
- 移除kg源的歌词文件开头的空白字符串
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复专辑图片无法嵌入的问题
|
||||
- 修复播放状态栏切换“上一首”歌曲按钮提示错误的问题
|
||||
- 修复移动单首歌曲时,如果目标列表存在该歌曲,会导致将源列表与目标列表里的目标歌曲移除
|
||||
- 修复kg源歌曲信息带有单引号等特殊字符被转义的问题
|
||||
|
||||
## [1.3.0](https://github.com/lyswhut/lx-music-desktop/compare/v1.2.2...v1.3.0) - 2020-11-01
|
||||
|
||||
### 新增
|
||||
|
||||
- 播放详情页新增歌曲评论加载显示(某些平台暂不支持显示子评论)
|
||||
|
||||
### 优化
|
||||
|
||||
- 修改播放详情页的歌曲图片的显示效果
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复小芸源音乐搜索结果最多只有20条搜索结果的问题
|
||||
|
||||
## [1.2.2](https://github.com/lyswhut/lx-music-desktop/compare/v1.2.1...v1.2.2) - 2020-10-18
|
||||
|
||||
### 修复
|
||||
|
||||
- 降级 Electron 到 9.x.x 版本修复 Linux 版桌面歌词窗口变白的问题
|
||||
|
||||
## [1.2.1](https://github.com/lyswhut/lx-music-desktop/compare/v1.2.0...v1.2.1) - 2020-10-18
|
||||
|
||||
### 优化
|
||||
|
||||
- Linux版的软件界面默认使用圆角与阴影,顺便修复了桌面歌词窗口变白的问题,已在Ubuntu 18.10测试正常,若显示异常可尝试添加`-nt`参数启动
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复聚合搜索的分页问题
|
||||
- 修复代理输入框输入的内容不生效的问题
|
||||
|
||||
## [1.2.0](https://github.com/lyswhut/lx-music-desktop/compare/v1.1.1...v1.2.0) - 2020-09-30
|
||||
|
||||
提前祝大家中秋&国庆快乐~
|
||||
|
||||
95
FAQ.md
95
FAQ.md
@@ -2,7 +2,7 @@
|
||||
|
||||
在阅读本常见问题后,仍然无法解决你的问题,请提交issue或者加企鹅群`830125506`反馈(无事勿加,入群先看群公告),反馈时请**注明**已阅读常见问题!
|
||||
|
||||
## 软件为什么没有桌面歌词与自定义列表功能
|
||||
## ~~软件为什么没有桌面歌词与自定义列表功能~~
|
||||
|
||||
洛雪音乐的最初定位不是作为播放器开发的,它主要用于**查找歌曲**,软件的播放功能仅用于试听,不建议用作为常用播放器使用。
|
||||
|
||||
@@ -33,15 +33,61 @@
|
||||
|
||||
用`Shift`或`Ctrl`选择时,鼠标点击未选中的内容会将其选中,点击已选择的内容会将其取消选择,若想全部取消选择,在不按`Shift`或`Alt`键的情况下,随意点击列表里的一项内容即可全部取消选择。(P.S:`Ctrl`键对应Mac OS上的`Command`键)
|
||||
|
||||
注:选完后可用鼠标右击弹出右键菜单操作已选的内容
|
||||
|
||||
## 播放整个歌单或排行榜
|
||||
|
||||
播放在线列表内的歌曲需要将它们都添加到我的列表才能播放,你可以全选列表内的歌曲然后添加到现有列表或者新创建的列表,然后去播放该列表内的歌曲。
|
||||
|
||||
## 无法打开外部歌单
|
||||
|
||||
不支持垮源打开歌单,请**确认**你需要打开的歌单平台是否与软件标签所写的**歌单源**对应(不一样的话请通过右上角切换歌单源);<br>
|
||||
对于分享出来的歌单,若打开失败,可尝试先在浏览器中打开后,再从浏览器地址栏复制URL地址到软件打开;<br>
|
||||
或者如果你知道歌单 id 也可以直接输入歌单 id 打开。<br>
|
||||
|
||||
## Windows 7 下界面异常(界面显示不完整)
|
||||
|
||||
由于软件默认使用了透明窗口,根据Electron官方文档的[说明](https://electronjs.org/docs/api/frameless-window#%E5%B1%80%E9%99%90%E6%80%A7):
|
||||
> 在 windows 操作系统上, 当 DWM 被禁用时, 透明窗口将无法工作。
|
||||
|
||||
因此,当 win7 没有使用**AERO**主题时界面将会显示异常,开启AERO的方法请自行百度:`win7开启aero效果`(开启后可看到任务栏变透明)。<br>
|
||||
从`0.14.0`版本起不再强制要求开启透明效果,若你实在不想开启(若非电脑配置太低,墙裂建议开启!),可通过添加运行参数`-nt`来运行程序即可,例如:`.\lx-music-desktop.exe -nt`,添加方法可自行百度“给快捷方式加参数”,该参数的作用是用来控制程序是否使用非透明窗口运行。
|
||||
|
||||
对于一些完全无法正常显示界面、开启了AERO后问题仍未解决的情况,请阅读下面的 **软件启动后,界面无法显示** 解决
|
||||
|
||||
## 软件启动后,界面无法显示
|
||||
|
||||
对于软件启动后,可以在任务栏看到软件,但软件界面在桌面上无任何显示,或者整个界面偶尔闪烁的情况。<br>
|
||||
原始问题看:<https://github.com/electron/electron/issues/19569#issuecomment-522231083><br>
|
||||
解决办法:下载`.NET Framework 4.7.1`或**更高**版本安装即可(建议安装最新版,若安装过程中遇到问题可尝试自行百度解决)。<br>
|
||||
微软官方下载地址:<https://dotnet.microsoft.com/download/dotnet-framework><br>
|
||||
下载`Runtime(运行时)`版即可,安装完成后可能需要重启才生效。
|
||||
|
||||
若还是不行可尝试以下操作:
|
||||
|
||||
- 更新显卡驱动
|
||||
- 尝试将绿色版的软件放在**桌面**或**我的文档**运行
|
||||
|
||||
## 安装版安装失败,提示安装程序并未成功地运行完成
|
||||
|
||||
对于部分电脑出现安装失败的问题,可以做出以下尝试:
|
||||
|
||||
- 若你之前可以安装成功,但现在安装失败,就去**控制面板-程序和功能**或用第三方卸载工具看下有没有之前的版本残留,若同时在不同路径下安装了多个版本就可能会出现该问题,这种情况卸载掉所有版本重新安装即可
|
||||
- 清理安装路径下的残留文件
|
||||
- 清理注册表(建议用清理工具清理)
|
||||
|
||||
## 软件无法联网
|
||||
|
||||
软件的排行榜、歌单、搜索列表**都**无法加载:
|
||||
|
||||
- 检查是否在设置界面开启了代理(当代理乱设置时软件将无法联网)
|
||||
- 检查软件是否被第三方软件/防火墙阻止联网
|
||||
|
||||
## 桌面歌词显示异常
|
||||
|
||||
### Windows 7 系统桌面歌词显示异常
|
||||
|
||||
Windows 7 未开启 Aero 效果时桌面歌词会有问题,详情看下面的**Windows 7 下界面异常(界面显示不完整)**方法解决。
|
||||
Windows 7 未开启 Aero 效果时桌面歌词会有问题,详情看下面的 **Windows 7 下界面异常(界面显示不完整)** 方法解决。
|
||||
|
||||
### MAC OS 系统、桌面歌词有残留阴影
|
||||
|
||||
@@ -79,37 +125,6 @@ Windows 7 未开启 Aero 效果时桌面歌词会有问题,详情看下面的*
|
||||
注意:**绿色版**的软件自动更新功能**不可用**,建议使用安装版!!<br>
|
||||
注意:**Mac版**、**Linux deb**版不支持自动更新!
|
||||
|
||||
## Windows 7 下界面异常(界面显示不完整)
|
||||
|
||||
由于软件默认使用了透明窗口,根据Electron官方文档的[说明](https://electronjs.org/docs/api/frameless-window#%E5%B1%80%E9%99%90%E6%80%A7):
|
||||
> 在 windows 操作系统上, 当 DWM 被禁用时, 透明窗口将无法工作。
|
||||
|
||||
因此,当 win7 没有使用**AERO**主题时界面将会显示异常,开启AERO的方法请自行百度:`win7开启aero效果`(开启后可看到任务栏变透明)。<br>
|
||||
从`0.14.0`版本起不再强制要求开启透明效果,若你实在不想开启(若非电脑配置太低,墙裂建议开启!),可通过添加运行参数`-nt`来运行程序即可,例如:`.\lx-music-desktop.exe -nt`,添加方法可自行百度“给快捷方式加参数”,该参数的作用是用来控制程序是否使用非透明窗口运行。
|
||||
|
||||
对于一些完全无法正常显示界面的情况,请阅读下面的 **软件启动后,界面无法显示**
|
||||
|
||||
## 软件启动后,界面无法显示
|
||||
|
||||
软件启动后,可以在任务栏看到软件,但软件界面在桌面上无任何显示。<br>
|
||||
原始问题看:<https://github.com/electron/electron/issues/19569#issuecomment-522231083><br>
|
||||
解决办法:下载`.NET Framework 4.7.1`或**更高**版本安装即可(建议安装最新版,若安装过程中遇到问题可尝试自行百度解决)。<br>
|
||||
微软官方下载地址:<https://dotnet.microsoft.com/download/dotnet-framework><br>
|
||||
下载`Runtime(运行时)`版即可,安装完成后可能需要重启才生效。
|
||||
|
||||
若还是不行可尝试以下操作:
|
||||
|
||||
- 更新显卡驱动
|
||||
- 尝试将绿色版的软件放在**桌面**或**我的文档**运行
|
||||
|
||||
## 安装版安装失败,提示安装程序并未成功地运行完成
|
||||
|
||||
对于部分电脑出现安装失败的问题,可以做出以下尝试:
|
||||
|
||||
- 若你之前可以安装成功,但现在安装失败,就去**控制面板-程序和功能**或用第三方卸载工具看下有没有之前的版本残留,若同时在不同路径下安装了多个版本就可能会出现该问题,这种情况卸载掉所有版本重新安装即可
|
||||
- 清理安装路径下的残留文件
|
||||
- 清理注册表(建议用清理工具清理)
|
||||
|
||||
## 缺少`xxx.dll`
|
||||
|
||||
这个是电脑缺少某些dll导致的,正常的系统是没有这个问题的,可以尝试如下几个解决办法:
|
||||
@@ -123,18 +138,6 @@ Windows 7 未开启 Aero 效果时桌面歌词会有问题,详情看下面的*
|
||||
尽管如此,但这不意味着软件是100%安全的,由于软件使用了第三方依赖,当这些依赖存在恶意行为时([供应链攻击](https://docs.microsoft.com/zh-cn/windows/security/threat-protection/intelligence/supply-chain-malware)),软件也将会受到牵连,所以我只能尽量选择使用较多人用、信任度较高的依赖。<br>
|
||||
当然,以上说明建立的前提是在你所用的安装包是从**本项目主页上写的链接**下载的,或者有相关能力者还可以下载源代码自己构建安装包。
|
||||
|
||||
从`0.17.0`起,由于加入了音频输出设备切换功能,该功能调用了 [MediaDevices.enumerateDevices()](https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/enumerateDevices),可能导致安全软件提示洛雪要访问摄像头(目前发现卡巴斯基会提示),但实际上没有用到摄像头,并且摄像头的提示灯也不会亮,你可以选择阻止访问。
|
||||
从`v0.17.0`起,由于加入了音频输出设备切换功能,该功能调用了 [MediaDevices.enumerateDevices()](https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/enumerateDevices),可能导致安全软件提示洛雪要访问摄像头(目前发现卡巴斯基会提示),但实际上没有用到摄像头,并且摄像头的提示灯也不会亮,你可以选择阻止访问。
|
||||
|
||||
最后,若出现杀毒软件报毒、存在恶意行为,请自行判断选择是否继续使用本软件!
|
||||
|
||||
## 软件无法联网
|
||||
|
||||
软件的排行榜、歌单、搜索列表**都**无法加载:
|
||||
|
||||
- 检查是否在设置界面开启了代理(当代理乱设置时软件将无法联网)
|
||||
- 检查软件是否被第三方软件/防火墙阻止联网
|
||||
|
||||
## 无法打开外部歌单
|
||||
|
||||
对于分享出来的歌单,若打开失败,可尝试先在浏览器中打开后,再从浏览器地址栏复制URL地址到软件打开;<br>
|
||||
或者如果你知道歌单 id 也可以直接输入歌单 id 打开。<br>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
所用技术栈:
|
||||
|
||||
- Electron 10
|
||||
- Electron 9
|
||||
- Vue 2
|
||||
|
||||
已支持的平台:
|
||||
@@ -100,7 +100,7 @@ npm run pack:linux
|
||||
5. 由于使用本项目产生的包括由于本协议或由于使用或无法使用本项目而引起的任何性质的任何直接、间接、特殊、偶然或结果性损害(包括但不限于因商誉损失、停工、计算机故障或故障引起的损害赔偿,或任何及所有其他商业损害或损失)由使用者负责。
|
||||
6. 本项目完全免费,且开源发布于 GitHub 面向全世界人用作对技术的学习交流,本项目不对项目内的技术可能存在违反当地法律法规的行为作保证,**禁止在违反当地法律法规的情况下使用本项目**,对于使用者在明知或不知当地法律法规不允许的情况下使用本项目所造成的任何违法违规行为由使用者承担,本项目不承担由此造成的任何直接、间接、特殊、偶然或结果性责任。
|
||||
|
||||
若你使用了本项目,将代表你接收以上协议。
|
||||
若你使用了本项目,将代表你接受以上协议。
|
||||
|
||||
音乐平台不易,请尊重版权,支持正版。<br>
|
||||
若对此有疑问请 mail to: lyswhut+qq.com (请将`+`替换成`@`)
|
||||
|
||||
@@ -23,7 +23,7 @@ module.exports = merge(baseConfig, {
|
||||
onErrors(severity, errors) { // Silent warning from electron-debug
|
||||
if (severity != 'warning') return
|
||||
|
||||
for (let i = errors.length; i > -1; i--) {
|
||||
for (let i = errors.length - 1; i > -1; i--) {
|
||||
const error = errors[i]
|
||||
if (error.file == './node_modules/electron-debug/index.js') errors.splice(i, 1)
|
||||
}
|
||||
|
||||
@@ -32,15 +32,11 @@ module.exports = merge(baseConfig, {
|
||||
NODE_ENV: '"production"',
|
||||
},
|
||||
}),
|
||||
new webpack.NamedChunksPlugin(),
|
||||
],
|
||||
optimization: {
|
||||
chunkIds: 'named',
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
cache: true,
|
||||
parallel: true,
|
||||
sourceMap: false, // set to true if you want JS source maps
|
||||
}),
|
||||
new TerserPlugin(),
|
||||
new OptimizeCSSAssetsPlugin({}),
|
||||
],
|
||||
},
|
||||
|
||||
@@ -32,15 +32,11 @@ module.exports = merge(baseConfig, {
|
||||
NODE_ENV: '"production"',
|
||||
},
|
||||
}),
|
||||
new webpack.NamedChunksPlugin(),
|
||||
],
|
||||
optimization: {
|
||||
chunkIds: 'named',
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
cache: true,
|
||||
parallel: true,
|
||||
sourceMap: false, // set to true if you want JS source maps
|
||||
}),
|
||||
new TerserPlugin(),
|
||||
new OptimizeCSSAssetsPlugin({}),
|
||||
],
|
||||
},
|
||||
|
||||
2859
package-lock.json
generated
2859
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
64
package.json
64
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "lx-music-desktop",
|
||||
"version": "1.2.0",
|
||||
"version": "1.4.1",
|
||||
"description": "一个免费的音乐下载助手",
|
||||
"main": "./dist/electron/main.js",
|
||||
"productName": "lx-music-desktop",
|
||||
@@ -59,7 +59,7 @@
|
||||
"lint:fix": "eslint --ext .js,.vue -f ./node_modules/eslint-formatter-friendly --fix src"
|
||||
},
|
||||
"browserslist": [
|
||||
"Electron 10.1.3"
|
||||
"Electron 9.3.4"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
@@ -158,81 +158,81 @@
|
||||
},
|
||||
"homepage": "https://github.com/lyswhut/lx-music-desktop#readme",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.11.6",
|
||||
"@babel/core": "^7.12.3",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-transform-modules-umd": "^7.10.4",
|
||||
"@babel/plugin-transform-runtime": "^7.11.5",
|
||||
"@babel/polyfill": "^7.11.5",
|
||||
"@babel/preset-env": "^7.11.5",
|
||||
"@babel/plugin-transform-modules-umd": "^7.12.1",
|
||||
"@babel/plugin-transform-runtime": "^7.12.1",
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@babel/preset-env": "^7.12.1",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^8.1.0",
|
||||
"babel-loader": "^8.2.1",
|
||||
"babel-minify-webpack-plugin": "^0.3.1",
|
||||
"babel-preset-minify": "^0.5.1",
|
||||
"cfonts": "^2.8.6",
|
||||
"chalk": "^4.1.0",
|
||||
"changelog-parser": "^2.8.0",
|
||||
"copy-webpack-plugin": "^6.1.1",
|
||||
"core-js": "^3.6.5",
|
||||
"copy-webpack-plugin": "^6.3.1",
|
||||
"core-js": "^3.7.0",
|
||||
"cross-env": "^7.0.2",
|
||||
"css-loader": "^4.3.0",
|
||||
"del": "^6.0.0",
|
||||
"electron": "^10.1.3",
|
||||
"electron-builder": "^22.8.1",
|
||||
"electron": "^9.3.3",
|
||||
"electron-builder": "^22.9.1",
|
||||
"electron-debug": "^3.1.0",
|
||||
"electron-devtools-installer": "^3.1.1",
|
||||
"eslint": "^7.10.0",
|
||||
"eslint": "^7.13.0",
|
||||
"eslint-config-standard": "^14.1.1",
|
||||
"eslint-formatter-friendly": "^7.0.0",
|
||||
"eslint-loader": "^4.0.2",
|
||||
"eslint-plugin-html": "^6.1.0",
|
||||
"eslint-plugin-html": "^6.1.1",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"eslint-plugin-standard": "^4.0.1",
|
||||
"file-loader": "^6.1.0",
|
||||
"eslint-plugin-standard": "^4.1.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"friendly-errors-webpack-plugin": "^1.7.0",
|
||||
"html-webpack-plugin": "^4.5.0",
|
||||
"less": "^3.12.2",
|
||||
"less-loader": "^7.0.1",
|
||||
"markdown-it": "^11.0.1",
|
||||
"mini-css-extract-plugin": "^0.11.2",
|
||||
"less-loader": "^7.1.0",
|
||||
"markdown-it": "^12.0.2",
|
||||
"mini-css-extract-plugin": "^0.12.0",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.4",
|
||||
"postcss-loader": "^4.0.2",
|
||||
"postcss-loader": "^4.0.4",
|
||||
"postcss-pxtorem": "^5.1.1",
|
||||
"pug": "^3.0.0",
|
||||
"pug-loader": "^2.4.0",
|
||||
"pug-plain-loader": "^1.0.0",
|
||||
"raw-loader": "^4.0.1",
|
||||
"raw-loader": "^4.0.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"spinnies": "^0.5.1",
|
||||
"stylus": "^0.54.8",
|
||||
"stylus-loader": "^3.0.2",
|
||||
"terser-webpack-plugin": "^4.2.2",
|
||||
"url-loader": "^4.1.0",
|
||||
"vue-loader": "^15.9.3",
|
||||
"stylus-loader": "^4.3.0",
|
||||
"terser-webpack-plugin": "^4.2.3",
|
||||
"url-loader": "^4.1.1",
|
||||
"vue-loader": "^15.9.5",
|
||||
"vue-template-compiler": "^2.6.12",
|
||||
"webpack": "^4.44.2",
|
||||
"webpack-cli": "^3.3.12",
|
||||
"webpack-dev-server": "^3.11.0",
|
||||
"webpack-hot-middleware": "^2.25.0",
|
||||
"webpack-merge": "^5.1.4"
|
||||
"webpack-merge": "^5.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"crypto-js": "^4.0.0",
|
||||
"dnscache": "^1.0.2",
|
||||
"electron-log": "^4.2.4",
|
||||
"electron-store": "^6.0.0",
|
||||
"electron-log": "^4.3.0",
|
||||
"electron-store": "^6.0.1",
|
||||
"electron-updater": "^4.3.5",
|
||||
"iconv-lite": "^0.6.2",
|
||||
"image-size": "^0.9.1",
|
||||
"image-size": "^0.9.3",
|
||||
"js-htmlencode": "^0.3.0",
|
||||
"lrc-file-parser": "^1.0.5",
|
||||
"needle": "^2.5.2",
|
||||
"node-id3": "^0.1.19",
|
||||
"node-id3": "^0.1.21",
|
||||
"request": "^2.88.2",
|
||||
"vue": "^2.6.12",
|
||||
"vue-i18n": "^8.21.1",
|
||||
"vue-router": "^3.4.5",
|
||||
"vue-i18n": "^8.22.1",
|
||||
"vue-router": "^3.4.9",
|
||||
"vuex": "^3.5.1",
|
||||
"vuex-router-sync": "^5.0.0"
|
||||
}
|
||||
|
||||
@@ -1,25 +1,6 @@
|
||||
提前祝大家中秋&国庆快乐~
|
||||
|
||||
### 新增
|
||||
|
||||
- 播放控制栏开启/关闭桌面歌词按钮 新增右击按钮时锁定/解锁桌面歌词功能
|
||||
|
||||
### 优化
|
||||
|
||||
- 优化我的列表滚动条位置的保存逻辑
|
||||
- 更新设置-备份与恢复功能的描述
|
||||
- 优化软件内鼠标悬停的提示界面
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复桌面歌词窗口不允许拖出桌面之外的位置计算偏移Bug
|
||||
- 修复网易云KTV嗨榜无法加载的问题
|
||||
- 修复初始化搜索历史列表功能
|
||||
- 修复重启软件后试听列表与收藏列表无法恢复上次的滚动位置的问题
|
||||
- 修复歌曲封面无法嵌入的Bug
|
||||
- 修复酷狗歌词格式问题
|
||||
- 修复关闭切换动画时从搜索候选列表点击内容无效的问题
|
||||
|
||||
### 其他
|
||||
|
||||
- 更新 Electron 到 v10.1.3
|
||||
- 修复有歌词翻译与无歌词的音乐间切换会导致歌词翻译残留显示的问题
|
||||
- 修复歌曲URL过期时,等待刷新URL的自动切换歌曲时间间隔太短的问题
|
||||
- 修复某些电脑上的某些歌曲没有声音的问题(升级Electron9.3.4导致的,现降级到9.3.3)
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -17,6 +17,18 @@ class MainWindow extends EventEmitter {
|
||||
toggleHide() {
|
||||
this.emit(MAIN_WINDOW_EVENT_NAME.toggle_hide)
|
||||
}
|
||||
|
||||
readyToShow() {
|
||||
this.emit(MAIN_WINDOW_EVENT_NAME.ready_to_show)
|
||||
}
|
||||
|
||||
show() {
|
||||
this.emit(MAIN_WINDOW_EVENT_NAME.show)
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.emit(MAIN_WINDOW_EVENT_NAME.hide)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MainWindow
|
||||
|
||||
@@ -10,6 +10,9 @@ exports.mainWindow = {
|
||||
quit: 'quit',
|
||||
toggle_minimize: 'toggle_minimize',
|
||||
toggle_hide: 'toggle_hide',
|
||||
ready_to_show: 'ready_to_show',
|
||||
show: 'show',
|
||||
hide: 'hide',
|
||||
}
|
||||
|
||||
exports.tray = {
|
||||
|
||||
@@ -82,7 +82,7 @@ if (isDev) {
|
||||
winURL = 'http://localhost:9080'
|
||||
} else {
|
||||
global.__static = path.join(__dirname, '/static')
|
||||
winURL = `file://${__dirname}/index.html`
|
||||
winURL = `file://${path.join(__dirname, 'index.html')}`
|
||||
}
|
||||
|
||||
function createWindow() {
|
||||
@@ -95,7 +95,7 @@ function createWindow() {
|
||||
useContentSize: true,
|
||||
width: windowSizeInfo.width,
|
||||
frame: false,
|
||||
transparent: !isLinux && !global.envParams.nt,
|
||||
transparent: !global.envParams.nt,
|
||||
enableRemoteModule: false,
|
||||
// icon: path.join(global.__static, isWin ? 'icons/256x256.ico' : 'icons/512x512.png'),
|
||||
resizable: false,
|
||||
@@ -133,7 +133,8 @@ function init() {
|
||||
createWindow()
|
||||
}
|
||||
|
||||
app.on('ready', init)
|
||||
// https://github.com/electron/electron/issues/16809
|
||||
app.on('ready', isLinux ? () => setTimeout(init, 300) : init)
|
||||
|
||||
app.on('activate', () => {
|
||||
if (global.modules.mainWindow) {
|
||||
|
||||
@@ -23,9 +23,11 @@ exports.registerHotkey = ({ key, info }) => {
|
||||
}
|
||||
}
|
||||
global.appHotKey.state[key].info = info
|
||||
let status = global.appHotKey.state[key].status = globalShortcut.isRegistered(transKey) ? false : globalShortcut.register(transKey, () => {
|
||||
handleKeyDown(key)
|
||||
})
|
||||
let status = global.appHotKey.state[key].status = globalShortcut.isRegistered(transKey)
|
||||
? false
|
||||
: globalShortcut.register(transKey, () => {
|
||||
handleKeyDown(key)
|
||||
})
|
||||
return status
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const { app, Tray, Menu } = require('electron')
|
||||
const { isWin } = require('../../common/utils')
|
||||
const { tray: TRAY_EVENT_NAME, common: COMMON_EVENT_NAME } = require('../events/_name')
|
||||
const { tray: TRAY_EVENT_NAME, common: COMMON_EVENT_NAME, mainWindow: MAIN_WINDOW_NAME } = require('../events/_name')
|
||||
const path = require('path')
|
||||
let isEnableTray = null
|
||||
let themeId = null
|
||||
@@ -29,6 +29,16 @@ global.lx_event.common.on(COMMON_EVENT_NAME.config, sourceName => {
|
||||
createMenu(global.modules.tray)
|
||||
})
|
||||
|
||||
global.lx_event.mainWindow.on(MAIN_WINDOW_NAME.ready_to_show, () => {
|
||||
createMenu(global.modules.tray)
|
||||
})
|
||||
global.lx_event.mainWindow.on(MAIN_WINDOW_NAME.show, () => {
|
||||
createMenu(global.modules.tray)
|
||||
})
|
||||
global.lx_event.mainWindow.on(MAIN_WINDOW_NAME.hide, () => {
|
||||
createMenu(global.modules.tray)
|
||||
})
|
||||
|
||||
const createTray = () => {
|
||||
if ((global.modules.tray && !global.modules.tray.isDestroyed()) || !global.appSetting.tray || !global.appSetting.tray.isShow) return
|
||||
|
||||
@@ -58,8 +68,24 @@ const destroyTray = () => {
|
||||
}
|
||||
|
||||
const createMenu = tray => {
|
||||
if (!global.modules.tray || !isWin) return
|
||||
if (!global.modules.tray) return
|
||||
let menu = []
|
||||
global.modules.mainWindow && menu.push(global.modules.mainWindow.isVisible() ? {
|
||||
label: '隐藏主界面',
|
||||
click() {
|
||||
global.modules.mainWindow.hide()
|
||||
},
|
||||
} : {
|
||||
label: '显示主界面',
|
||||
click() {
|
||||
if (!global.modules.mainWindow) return
|
||||
if (!global.modules.mainWindow.isVisible()) {
|
||||
global.modules.mainWindow.show()
|
||||
}
|
||||
global.modules.mainWindow.restore()
|
||||
global.modules.mainWindow.focus()
|
||||
},
|
||||
})
|
||||
menu.push(global.appSetting.desktopLyric.enable ? {
|
||||
label: '关闭桌面歌词',
|
||||
click() {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
const path = require('path')
|
||||
const { BrowserWindow } = require('electron')
|
||||
const { winLyric: WIN_LYRIC_EVENT_NAME } = require('../../events/_name')
|
||||
const { debounce } = require('../../../common/utils')
|
||||
@@ -13,7 +14,7 @@ global.lx_event.winLyric.on(WIN_LYRIC_EVENT_NAME.close, () => {
|
||||
closeWindow()
|
||||
})
|
||||
|
||||
let winURL = global.isDev ? 'http://localhost:9081/lyric.html' : `file://${__dirname}/lyric.html`
|
||||
let winURL = global.isDev ? 'http://localhost:9081/lyric.html' : `file://${path.join(__dirname, 'lyric.html')}`
|
||||
|
||||
const setLyricsConfig = debounce(config => {
|
||||
// if (x != null) bounds.x = x
|
||||
|
||||
@@ -29,5 +29,13 @@ module.exports = mainWindow => {
|
||||
|
||||
mainWindow.once('ready-to-show', () => {
|
||||
mainWindow.show()
|
||||
global.lx_event.mainWindow.readyToShow()
|
||||
})
|
||||
|
||||
mainWindow.on('show', () => {
|
||||
global.lx_event.mainWindow.show()
|
||||
})
|
||||
mainWindow.on('hide', () => {
|
||||
global.lx_event.mainWindow.hide()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -72,9 +72,9 @@ module.exports = (filePath, meta) => {
|
||||
if (respones.statusCode !== 200 && respones.statusCode != 206) return writeMeta(filePath, meta)
|
||||
respones
|
||||
.pipe(fs.createWriteStream(picPath))
|
||||
.on('finish', () => {
|
||||
.on('finish', async() => {
|
||||
if (respones.complete) {
|
||||
writeMeta(filePath, meta, picPath)
|
||||
await writeMeta(filePath, meta, picPath)
|
||||
} else {
|
||||
writeMeta(filePath, meta)
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@ module.exports = (filePath, meta) => {
|
||||
if (err) console.log(err.message)
|
||||
delete meta.APIC
|
||||
handleWriteMeta(meta, filePath)
|
||||
fs.unlink(picPath, err => {
|
||||
if (err) console.log(err.message)
|
||||
})
|
||||
})
|
||||
})
|
||||
.on('error', err => {
|
||||
|
||||
@@ -279,7 +279,7 @@ export default {
|
||||
rendererSend(NAMES.winLyric.close)
|
||||
},
|
||||
setLyric() {
|
||||
window.lrc.setLyric((this.isShowLyricTransition && this.lyrics.tlyric ? this.lyrics.tlyric + '\n' : '') + this.lyrics.lyric)
|
||||
window.lrc.setLyric((this.isShowLyricTransition && this.lyrics.tlyric ? (this.lyrics.tlyric + '\n') : '') + (this.lyrics.lyric || ''))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template lang="pug">
|
||||
#container(v-if="isProd && !isNt" :class="theme" @mouseenter="enableIgnoreMouseEvents" @mouseleave="dieableIgnoreMouseEvents")
|
||||
#container(v-if="isProd && !isNt && !isLinux" :class="theme" @mouseenter="enableIgnoreMouseEvents" @mouseleave="dieableIgnoreMouseEvents")
|
||||
core-aside#left
|
||||
#right
|
||||
core-toolbar#toolbar
|
||||
@@ -42,6 +42,7 @@ export default {
|
||||
return {
|
||||
isProd: process.env.NODE_ENV === 'production',
|
||||
isNt: false,
|
||||
isLinux,
|
||||
globalObj: {
|
||||
apiSource: 'test',
|
||||
proxy: {},
|
||||
@@ -173,6 +174,9 @@ export default {
|
||||
...mapMutations('search', {
|
||||
setSearchHistoryList: 'setHistory',
|
||||
}),
|
||||
...mapMutations('player', {
|
||||
setPlayList: 'setList',
|
||||
}),
|
||||
init() {
|
||||
document.documentElement.style.fontSize = this.windowSizeActive.fontSize
|
||||
|
||||
@@ -275,6 +279,7 @@ export default {
|
||||
if (!loveList.list) loveList.list = []
|
||||
this.initList({ defaultList, loveList, userList })
|
||||
this.initDownloadList(downloadList) // 初始化下载列表
|
||||
this.initPlayInfo()
|
||||
})
|
||||
},
|
||||
initDownloadList(downloadList) {
|
||||
@@ -298,6 +303,27 @@ export default {
|
||||
}
|
||||
})
|
||||
},
|
||||
initPlayInfo() {
|
||||
rendererInvoke(NAMES.mainWindow.get_data, 'playInfo').then(info => {
|
||||
// console.log(info, window.allList)
|
||||
if (!info) return
|
||||
if (info.listId) {
|
||||
const list = window.allList[info.listId]
|
||||
// console.log(list)
|
||||
if (!list) return
|
||||
info.list = list.list
|
||||
}
|
||||
|
||||
window.restorePlayInfo = info
|
||||
this.setPlayList({
|
||||
list: {
|
||||
list: info.list,
|
||||
id: info.listId,
|
||||
},
|
||||
index: info.index,
|
||||
})
|
||||
})
|
||||
},
|
||||
showUpdateModal() {
|
||||
(this.version.newVersion && this.version.newVersion.history
|
||||
? Promise.resolve(this.version.newVersion)
|
||||
@@ -338,12 +364,12 @@ export default {
|
||||
},
|
||||
handleEnvParamsInit(envParams) {
|
||||
this.envParams = envParams
|
||||
this.isNt = isLinux || this.envParams.nt
|
||||
this.isNt = this.envParams.nt
|
||||
if (this.isNt) {
|
||||
document.body.classList.remove('transparent')
|
||||
document.body.classList.add('noTransparent')
|
||||
}
|
||||
if (this.isProd && !this.isNt) {
|
||||
if (this.isProd && !this.isNt && !this.isLinux) {
|
||||
document.body.addEventListener('mouseenter', this.dieableIgnoreMouseEvents)
|
||||
document.body.addEventListener('mouseleave', this.enableIgnoreMouseEvents)
|
||||
}
|
||||
|
||||
BIN
src/renderer/assets/images/defaultUser.jpg
Normal file
BIN
src/renderer/assets/images/defaultUser.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
@@ -23,6 +23,7 @@
|
||||
@color-theme_2-font-label: fadeout(@color-theme_2-font, 50%);
|
||||
// @color-theme_2-line: transparent;
|
||||
@color-theme_2-line: lighten(@color-theme, 35%);
|
||||
@color-reply-floor: fadeout(@color-theme, 95%);
|
||||
@color-theme-sidebar: @color-theme;
|
||||
@color-btn: lighten(@color-theme, 5%);
|
||||
@color-btn-background: fadeout(lighten(@color-theme, 35%), 70%);
|
||||
@@ -91,6 +92,7 @@
|
||||
@color-green-theme_2-font-label: fadeout(@color-green-theme_2-font, 50%);
|
||||
// @color-green-theme_2-line: transparent;
|
||||
@color-green-theme_2-line: lighten(@color-green-theme, 45%);
|
||||
@color-green-reply-floor: fadeout(@color-green-theme, 95%);
|
||||
@color-green-theme-sidebar: @color-green-theme;
|
||||
@color-green-btn: lighten(@color-green-theme, 5%);
|
||||
@color-green-btn-background: fadeout(lighten(@color-green-theme, 35%), 70%);
|
||||
@@ -148,6 +150,7 @@
|
||||
@color-yellow-theme_2-font-label: fadeout(@color-yellow-theme_2-font, 50%);
|
||||
// @color-yellow-theme_2-line: transparent;
|
||||
@color-yellow-theme_2-line: lighten(@color-yellow-theme, 28%);
|
||||
@color-yellow-reply-floor: fadeout(@color-yellow-theme, 94%);
|
||||
@color-yellow-theme-sidebar: @color-yellow-theme;
|
||||
@color-yellow-btn: darken(@color-yellow-theme, 5%);
|
||||
@color-yellow-btn-background: fadeout(lighten(@color-yellow-theme, 25%), 60%);
|
||||
@@ -204,6 +207,7 @@
|
||||
@color-orange-theme_2-font-label: fadeout(@color-orange-theme_2-font, 50%);
|
||||
// @color-orange-theme_2-line: transparent;
|
||||
@color-orange-theme_2-line: lighten(@color-orange-theme, 36%);
|
||||
@color-orange-reply-floor: fadeout(@color-orange-theme, 95%);
|
||||
@color-orange-theme-sidebar: @color-orange-theme;
|
||||
@color-orange-btn: lighten(@color-orange-theme, 5%);
|
||||
@color-orange-btn-background: fadeout(lighten(@color-orange-theme, 25%), 60%);
|
||||
@@ -260,6 +264,7 @@
|
||||
@color-blue-theme_2-font-label: fadeout(@color-blue-theme_2-font, 50%);
|
||||
// @color-blue-theme_2-line: transparent;
|
||||
@color-blue-theme_2-line: lighten(@color-blue-theme, 42%);
|
||||
@color-blue-reply-floor: fadeout(@color-blue-theme, 95%);
|
||||
@color-blue-theme-sidebar: @color-blue-theme;
|
||||
@color-blue-btn: lighten(@color-blue-theme, 5%);
|
||||
@color-blue-btn-background: fadeout(lighten(@color-blue-theme, 35%), 50%);
|
||||
@@ -316,6 +321,7 @@
|
||||
@color-red-theme_2-font-label: fadeout(@color-red-theme_2-font, 50%);
|
||||
// @color-red-theme_2-line: transparent;
|
||||
@color-red-theme_2-line: lighten(@color-red-theme, 42%);
|
||||
@color-red-reply-floor: fadeout(@color-red-theme, 95%);
|
||||
@color-red-theme-sidebar: @color-red-theme;
|
||||
@color-red-btn: lighten(@color-red-theme, 5%);
|
||||
@color-red-btn-background: fadeout(lighten(@color-red-theme, 35%), 70%);
|
||||
@@ -374,6 +380,7 @@
|
||||
@color-pink-theme_2-font-label: fadeout(@color-pink-theme_2-font, 50%);
|
||||
// @color-pink-theme_2-line: transparent;
|
||||
@color-pink-theme_2-line: lighten(@color-pink-theme, 25%);
|
||||
@color-pink-reply-floor: fadeout(@color-pink-theme, 93%);
|
||||
@color-pink-theme-sidebar: @color-pink-theme;
|
||||
@color-pink-btn: darken(@color-pink-theme, 3%);
|
||||
@color-pink-btn-background: fadeout(lighten(@color-pink-theme, 20%), 50%);
|
||||
@@ -430,6 +437,7 @@
|
||||
@color-purple-theme_2-font-label: fadeout(@color-purple-theme_2-font, 50%);
|
||||
// @color-purple-theme_2-line: transparent;
|
||||
@color-purple-theme_2-line: lighten(@color-purple-theme, 43%);
|
||||
@color-purple-reply-floor: fadeout(@color-purple-theme, 95%);
|
||||
@color-purple-theme-sidebar: @color-purple-theme;
|
||||
@color-purple-btn: lighten(@color-purple-theme, 5%);
|
||||
@color-purple-btn-background: fadeout(lighten(@color-purple-theme, 35%), 70%);
|
||||
@@ -486,6 +494,7 @@
|
||||
@color-grey-theme_2-font-label: fadeout(@color-grey-theme_2-font, 50%);
|
||||
// @color-grey-theme_2-line: transparent;
|
||||
@color-grey-theme_2-line: lighten(@color-grey-theme, 47%);
|
||||
@color-grey-reply-floor: fadeout(@color-grey-theme, 95%);
|
||||
@color-grey-theme-sidebar: @color-grey-theme;
|
||||
@color-grey-btn: lighten(@color-grey-theme, 5%);
|
||||
@color-grey-btn-background: fadeout(lighten(@color-grey-theme, 35%), 70%);
|
||||
@@ -543,6 +552,7 @@
|
||||
@color-ming-theme_2-font-label: fadeout(@color-ming-theme_2-font, 50%);
|
||||
// @color-ming-theme_2-line: transparent;
|
||||
@color-ming-theme_2-line: lighten(@color-ming-theme, 60%);
|
||||
@color-ming-reply-floor: fadeout(@color-ming-theme, 95%);
|
||||
@color-ming-theme-sidebar: @color-ming-theme;
|
||||
@color-ming-btn: lighten(@color-ming-theme, 5%);
|
||||
@color-ming-btn-background: fadeout(lighten(@color-ming-theme, 35%), 75%);
|
||||
@@ -602,6 +612,7 @@
|
||||
@color-blue2-theme_2-font-label: fadeout(@color-blue2-theme_2-font, 50%);
|
||||
// @color-blue2-theme_2-line: transparent;
|
||||
@color-blue2-theme_2-line: lighten(@color-blue2-theme, 41%);
|
||||
@color-blue2-reply-floor: fadeout(@color-blue2-theme, 95%);
|
||||
@color-blue2-theme-sidebar: @color-blue2-theme;
|
||||
@color-blue2-btn: lighten(@color-blue2-theme, 5%);
|
||||
@color-blue2-btn-background: fadeout(lighten(@color-blue2-theme, 30%), 70%);
|
||||
@@ -651,7 +662,7 @@
|
||||
@color-mid_autumn-theme-font: rgba(246, 233, 255, 0.9);
|
||||
@color-mid_autumn-theme-font-label: fadeout(lighten(@color-mid_autumn-theme, 20%), 20%);
|
||||
@color-mid_autumn-theme_2: rgba(255, 255, 255, .9);
|
||||
@color-mid_autumn-theme_2-background_1: #e7e7e9;
|
||||
@color-mid_autumn-theme_2-background_1: #ececec;
|
||||
@color-mid_autumn-theme_2-background_2: fadeout(@color-mid_autumn-theme_2-background_1, 2%);
|
||||
@color-mid_autumn-theme_2-hover: fadeout(lighten(@color-mid_autumn-theme, 15%), 80%);
|
||||
@color-mid_autumn-theme_2-active: fadeout(lighten(@color-mid_autumn-theme, 15%), 70%);
|
||||
@@ -659,6 +670,7 @@
|
||||
@color-mid_autumn-theme_2-font-label: desaturate(lighten(@color-mid_autumn-theme, 30%), 45%);
|
||||
// @color-mid_autumn-theme_2-line: transparent;
|
||||
@color-mid_autumn-theme_2-line: lighten(@color-mid_autumn-theme, 61%);
|
||||
@color-mid_autumn-reply-floor: fadeout(@color-mid_autumn-theme, 95%);
|
||||
@color-mid_autumn-theme-sidebar: rgba(255, 255, 255, 0);
|
||||
@color-mid_autumn-btn: lighten(@color-mid_autumn-theme, 10%);
|
||||
@color-mid_autumn-btn-background: fadeout(lighten(@color-mid_autumn-theme, 35%), 70%);
|
||||
@@ -716,6 +728,7 @@
|
||||
@color-mid_autumn-theme_2-font-label: desaturate(lighten(@color-mid_autumn-theme, 30%), 45%);
|
||||
// @color-mid_autumn-theme_2-line: transparent;
|
||||
@color-mid_autumn-theme_2-line: darken(@color-mid_autumn-theme, 18%);
|
||||
@color-mid_autumn-reply-floor: fadeout(@color-mid_autumn-theme, 95%);
|
||||
@color-mid_autumn-theme-sidebar: rgba(255, 255, 255, 0);
|
||||
@color-mid_autumn-btn: darken(@color-mid_autumn-theme, 10%);
|
||||
@color-mid_autumn-btn-background: fadeout(lighten(@color-mid_autumn-theme, 35%), 70%);
|
||||
@@ -772,6 +785,7 @@
|
||||
@color-naruto-theme_2-font-label: desaturate(lighten(@color-naruto-theme, 10%), 45%);
|
||||
// @color-naruto-theme_2-line: transparent;
|
||||
@color-naruto-theme_2-line: fadeout(lighten(@color-naruto-theme, 36%), 70%);
|
||||
@color-naruto-reply-floor: fadeout(lighten(@color-naruto-theme, 12%), 90%);
|
||||
@color-naruto-theme-sidebar: rgba(255, 255, 255, .3);
|
||||
@color-naruto-btn: lighten(@color-naruto-theme, 2%);
|
||||
@color-naruto-btn-background: fadeout(lighten(@color-naruto-theme, 35%), 70%);
|
||||
@@ -828,6 +842,7 @@
|
||||
@color-happy_new_year-theme_2-font-label: desaturate(darken(@color-happy_new_year-theme, 5%), 50%);
|
||||
// @color-happy_new_year-theme_2-line: transparent;
|
||||
@color-happy_new_year-theme_2-line: fadeout(lighten(@color-happy_new_year-theme, 16%), 70%);
|
||||
@color-happy_new_year-reply-floor: fadeout(lighten(@color-happy_new_year-theme, 12%), 85%);
|
||||
@color-happy_new_year-theme-sidebar: rgba(119, 37, 18, 0.1);
|
||||
@color-happy_new_year-btn: desaturate(@color-happy_new_year-theme, 10%);
|
||||
@color-happy_new_year-btn-background: fadeout(lighten(@color-happy_new_year-theme, 15%), 60%);
|
||||
|
||||
@@ -75,8 +75,8 @@ svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/19
|
||||
// 0 0 512 512
|
||||
path(d='M511.563,434.259c-1.728-142.329-124.42-258.242-277.087-263.419V95.999c0-17.645-14.342-31.999-31.974-31.999 c-7.931,0-15.591,3.042-21.524,8.562c0,0-134.828,124.829-173.609,163.755C2.623,241.109,0,248.088,0,255.994 c0,7.906,2.623,14.885,7.369,19.687c38.781,38.915,173.609,163.745,173.609,163.745c5.933,5.521,13.593,8.562,21.524,8.562 c17.631,0,31.974-14.354,31.974-31.999v-74.591c153.479,2.156,255.792,50.603,255.792,95.924c0,5.896,4.767,10.666,10.658,10.666 c0.167,0.021,0.333,0.01,0.416,0c5.891,0,10.658-4.771,10.658-10.666C512,436.259,511.854,435.228,511.563,434.259z')
|
||||
g#icon-refresh(fill='currentColor')
|
||||
// 0 0 512 512
|
||||
path(d='M440.65 12.57l4 82.77A247.16 247.16 0 0 0 255.83 8C134.73 8 33.91 94.92 12.29 209.82A12 12 0 0 0 24.09 224h49.05a12 12 0 0 0 11.67-9.26 175.91 175.91 0 0 1 317-56.94l-101.46-4.86a12 12 0 0 0-12.57 12v47.41a12 12 0 0 0 12 12H500a12 12 0 0 0 12-12V12a12 12 0 0 0-12-12h-47.37a12 12 0 0 0-11.98 12.57zM255.83 432a175.61 175.61 0 0 1-146-77.8l101.8 4.87a12 12 0 0 0 12.57-12v-47.4a12 12 0 0 0-12-12H12a12 12 0 0 0-12 12V500a12 12 0 0 0 12 12h47.35a12 12 0 0 0 12-12.6l-4.15-82.57A247.17 247.17 0 0 0 255.83 504c121.11 0 221.93-86.92 243.55-201.82a12 12 0 0 0-11.8-14.18h-49.05a12 12 0 0 0-11.67 9.26A175.86 175.86 0 0 1 255.83 432z')
|
||||
// 0 0 24 24
|
||||
path(d='M12,6V9L16,5L12,1V4A8,8 0 0,0 4,12C4,13.57 4.46,15.03 5.24,16.26L6.7,14.8C6.25,13.97 6,13 6,12A6,6 0 0,1 12,6M18.76,7.74L17.3,9.2C17.74,10.04 18,11 18,12A6,6 0 0,1 12,18V15L8,19L12,23V20A8,8 0 0,0 20,12C20,10.43 19.54,8.97 18.76,7.74Z')
|
||||
g#icon-eraser(fill='currentColor')
|
||||
// 0 0 512 512
|
||||
path(d='M497.941 273.941c18.745-18.745 18.745-49.137 0-67.882l-160-160c-18.745-18.745-49.136-18.746-67.883 0l-256 256c-18.745 18.745-18.745 49.137 0 67.882l96 96A48.004 48.004 0 0 0 144 480h356c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12H355.883l142.058-142.059zm-302.627-62.627l137.373 137.373L265.373 416H150.628l-80-80 124.686-124.686z')
|
||||
@@ -206,5 +206,16 @@ svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/19
|
||||
path(d='M256,170s-62.469-76.808-141-24C44.762,222.824,84.909,325.08,256,415c21.339-8.361,44-17,44-17,19-6.392,28.155,20.742,16,26-27.589,11.935,5.974-4.141-60,28C-35.524,313.85,43.993,149.031,95,117c86.8-65.89,162,10,162,10s58.158-60.523,140-23c104.032,58.528,64,161.9,45,196-9.152,15.154-39.559-4.159-32-16,20.34-37.888,45.522-107.349-25-150C314.919,103.92,256,170,256,170Z')
|
||||
path(d='M383,368c-8.1.01-24.77-.155-40,0-15.713.16-15.282,34.964,0,35,15.1,0.035,40,0,40,0s-0.068,42.8,0,48c0.208,15.961,32.261,15.791,32-1-0.072-4.649,0-47,0-47s38.008-.031,43,0c15.732,0.046,14.947-33.98-1-34-4.884.093-42,0-42,0s-0.053-28.341,0-46c0.046-15.189-32.028-15.512-32,0C383.027,337.74,382.782,365.139,383,368Z')
|
||||
|
||||
g#icon-thumbs-up(fill='currentColor')
|
||||
// 0 0 512 512
|
||||
path(d='M466.27 286.69C475.04 271.84 480 256 480 236.85c0-44.015-37.218-85.58-85.82-85.58H357.7c4.92-12.81 8.85-28.13 8.85-46.54C366.55 31.936 328.86 0 271.28 0c-61.607 0-58.093 94.933-71.76 108.6-22.747 22.747-49.615 66.447-68.76 83.4H32c-17.673 0-32 14.327-32 32v240c0 17.673 14.327 32 32 32h64c14.893 0 27.408-10.174 30.978-23.95 44.509 1.001 75.06 39.94 177.802 39.94 7.22 0 15.22.01 22.22.01 77.117 0 111.986-39.423 112.94-95.33 13.319-18.425 20.299-43.122 17.34-66.99 9.854-18.452 13.664-40.343 8.99-62.99zm-61.75 53.83c12.56 21.13 1.26 49.41-13.94 57.57 7.7 48.78-17.608 65.9-53.12 65.9h-37.82c-71.639 0-118.029-37.82-171.64-37.82V240h10.92c28.36 0 67.98-70.89 94.54-97.46 28.36-28.36 18.91-75.63 37.82-94.54 47.27 0 47.27 32.98 47.27 56.73 0 39.17-28.36 56.72-28.36 94.54h103.99c21.11 0 37.73 18.91 37.82 37.82.09 18.9-12.82 37.81-22.27 37.81 13.489 14.555 16.371 45.236-5.21 65.62zM88 432c0 13.255-10.745 24-24 24s-24-10.745-24-24 10.745-24 24-24 24 10.745 24 24z')
|
||||
|
||||
g#icon-close(fill='currentColor')
|
||||
// 0 0 24 24
|
||||
path(d='M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z')
|
||||
|
||||
g#icon-comment(fill='currentColor')
|
||||
// 0 0 24 24
|
||||
path(d='M16 11H8V9H16V11M22 4V16C22 17.11 21.11 18 20 18H13.9L10.2 21.71C10 21.9 9.75 22 9.5 22H9C8.45 22 8 21.55 8 21V18H4C2.9 18 2 17.11 2 16V4C2 2.89 2.9 2 4 2H20C21.11 2 22 2.9 22 4M20 4H4V16H10V19.08L13.08 16H20V4')
|
||||
</template>
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@ div(:class="$style.player")
|
||||
div(:class="$style.volumeMask" @mousedown="handleVolumeMsDown" ref="dom_volumeMask" :tips="`${$t('core.player.volume')}${parseInt(volume * 100)}%`")
|
||||
div(:class="$style.titleBtn" @click='toggleDesktopLyric' @contextmenu="handleToggleLockDesktopLyric" :tips="toggleDesktopLyricBtnTitle")
|
||||
svg(v-if="setting.desktopLyric.enable" version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 512 512' space='preserve')
|
||||
use(xlink:href='#icon-desktop-lyric-off')
|
||||
svg(v-else version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 512 512' space='preserve')
|
||||
use(xlink:href='#icon-desktop-lyric-on')
|
||||
svg(v-else version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 512 512' space='preserve')
|
||||
use(xlink:href='#icon-desktop-lyric-off')
|
||||
div(:class="$style.titleBtn" @click='toggleNextPlayMode' :tips="nextTogglePlayName")
|
||||
svg(v-if="setting.player.togglePlayMethod == 'listLoop'" version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='80%' viewBox='0 0 24 24' space='preserve')
|
||||
use(xlink:href='#icon-list-loop')
|
||||
@@ -49,7 +49,7 @@ div(:class="$style.player")
|
||||
span(style="margin: 0 5px;") /
|
||||
span {{maxPlayTimeStr}}
|
||||
div(:class="$style.right")
|
||||
div(:class="$style.playBtn" @click='handlePrev' :tips="$t('core.player.next')" style="transform: rotate(180deg);")
|
||||
div(:class="$style.playBtn" @click='handlePrev' :tips="$t('core.player.prev')" style="transform: rotate(180deg);")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 220.847 220.847' space='preserve')
|
||||
use(xlink:href='#icon-nextMusic')
|
||||
div(:class="$style.playBtn" :tips="isPlay ? $t('core.player.pause') : $t('core.player.play')" @click='togglePlay')
|
||||
@@ -63,10 +63,12 @@ div(:class="$style.player")
|
||||
//- transition(enter-active-class="animated lightSpeedIn"
|
||||
transition(enter-active-class="animated lightSpeedIn"
|
||||
leave-active-class="animated slideOutDown")
|
||||
core-player-detail(v-if="isShowPlayerDetail" :musicInfo="musicInfo"
|
||||
core-player-detail(v-if="isShowPlayerDetail" :musicInfo="listId == 'download' ? targetSong.musicInfo : targetSong"
|
||||
:lyric="lyric" :list="list" :listId="listId"
|
||||
:playInfo="{ nowPlayTimeStr, maxPlayTimeStr, progress, nowPlayTime, status }"
|
||||
:isPlay="isPlay" @action="handlePlayDetailAction")
|
||||
:isPlay="isPlay" @action="handlePlayDetailAction"
|
||||
:nextTogglePlayName="nextTogglePlayName"
|
||||
@toggle-next-play-mode="toggleNextPlayMode" @add-music-to="addMusicTo")
|
||||
|
||||
material-list-add-modal(:show="isShowAddMusicTo" :musicInfo="listId == 'download' ? targetSong.musicInfo : targetSong" @close="isShowAddMusicTo = false")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' style="display: none;")
|
||||
@@ -85,7 +87,7 @@ div(:class="$style.player")
|
||||
<script>
|
||||
import Lyric from 'lrc-file-parser'
|
||||
import { rendererSend, rendererOn, NAMES } from '../../../common/ipc'
|
||||
import { formatPlayTime2, getRandom, checkPath, setTitle, clipboardWriteText, debounce, assertApiSupport } from '../../utils'
|
||||
import { formatPlayTime2, getRandom, checkPath, setTitle, clipboardWriteText, debounce, throttle, assertApiSupport } from '../../utils'
|
||||
import { mapGetters, mapActions, mapMutations } from 'vuex'
|
||||
import { requestMsg } from '../../utils/message'
|
||||
import { isMac } from '../../../common/utils'
|
||||
@@ -128,7 +130,7 @@ export default {
|
||||
line: 0,
|
||||
},
|
||||
delayNextTimeout: null,
|
||||
audioErrorTime: 0,
|
||||
restorePlayTime: 0,
|
||||
retryNum: 0,
|
||||
isMac,
|
||||
volumeEvent: {
|
||||
@@ -193,6 +195,12 @@ export default {
|
||||
this.handleSaveVolume = debounce(volume => {
|
||||
this.setVolume(volume)
|
||||
}, 300)
|
||||
this.savePlayInfo = throttle(n => {
|
||||
rendererSend(NAMES.mainWindow.save_data, {
|
||||
path: 'playInfo',
|
||||
data: n,
|
||||
})
|
||||
}, 2000)
|
||||
|
||||
rendererOn(NAMES.mainWindow.get_lyric_info, (event, info) => {
|
||||
switch (info.action) {
|
||||
@@ -285,6 +293,12 @@ export default {
|
||||
},
|
||||
nowPlayTime(n, o) {
|
||||
if (Math.abs(n - o) > 2) this.isActiveTransition = true
|
||||
this.savePlayInfo({
|
||||
time: n,
|
||||
listId: this.listId,
|
||||
list: this.listId == null ? this.list : null,
|
||||
index: this.playIndex,
|
||||
})
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
@@ -297,6 +311,7 @@ export default {
|
||||
'clearPlayedList',
|
||||
'setPlayedList',
|
||||
'removePlayedList',
|
||||
'setList',
|
||||
]),
|
||||
...mapMutations(['setVolume', 'setPlayNextMode', 'setVisibleDesktopLyric', 'setLockDesktopLyric']),
|
||||
...mapMutations('list', ['updateMusicInfo']),
|
||||
@@ -346,7 +361,7 @@ export default {
|
||||
this.stopPlay()
|
||||
if (this.listId != 'download' && audio.error.code !== 1 && this.retryNum < 2) { // 若音频URL无效则尝试刷新2次URL
|
||||
// console.log(this.retryNum)
|
||||
if (!this.audioErrorTime) this.audioErrorTime = audio.currentTime // 记录出错的播放时间
|
||||
if (!this.restorePlayTime) this.restorePlayTime = audio.currentTime // 记录出错的播放时间
|
||||
this.retryNum++
|
||||
this.setUrl(this.list[this.playIndex], true)
|
||||
this.status = this.statusText = this.$t('core.player.refresh_url')
|
||||
@@ -358,15 +373,24 @@ export default {
|
||||
this.addDelayNextTimeout()
|
||||
})
|
||||
audio.addEventListener('loadeddata', () => {
|
||||
console.log('loadeddata')
|
||||
this.clearLoadingTimeout()
|
||||
this.status = this.statusText = this.$t('core.player.loading')
|
||||
this.maxPlayTime = audio.duration
|
||||
if (this.audioErrorTime) {
|
||||
audio.currentTime = this.audioErrorTime
|
||||
this.audioErrorTime = 0
|
||||
if (window.restorePlayInfo) {
|
||||
audio.currentTime = window.restorePlayInfo.time
|
||||
window.restorePlayInfo = null
|
||||
audio.pause()
|
||||
this.stopPlay()
|
||||
} else if (this.restorePlayTime) {
|
||||
audio.currentTime = this.restorePlayTime
|
||||
this.restorePlayTime = 0
|
||||
}
|
||||
if (!this.targetSong.interval && this.listId != 'download') this.updateMusicInfo({ id: this.listId, index: this.playIndex, data: { interval: formatPlayTime2(this.maxPlayTime) } })
|
||||
this.status = this.statusText = this.$t('core.player.loading')
|
||||
})
|
||||
audio.addEventListener('loadstart', () => {
|
||||
console.log('loadstart')
|
||||
this.startLoadingTimeout()
|
||||
this.status = this.statusText = this.$t('core.player.loading')
|
||||
})
|
||||
audio.addEventListener('canplay', () => {
|
||||
@@ -376,11 +400,10 @@ export default {
|
||||
this.mediaBuffer.playTime = 0
|
||||
audio.currentTime = playTime
|
||||
}
|
||||
if (this.mediaBuffer.timeout) {
|
||||
this.clearBufferTimeout()
|
||||
}
|
||||
this.clearBufferTimeout()
|
||||
|
||||
// if (this.musicInfo.lrc) window.lrc.play(audio.currentTime * 1000)
|
||||
this.status = this.statusText = this.$t('core.player.loading')
|
||||
this.status = this.statusText = ''
|
||||
})
|
||||
// audio.addEventListener('canplaythrough', () => {
|
||||
// console.log('音乐加载完毕')
|
||||
@@ -389,6 +412,7 @@ export default {
|
||||
// })
|
||||
audio.addEventListener('emptied', () => {
|
||||
this.mediaBuffer.playTime = 0
|
||||
this.clearLoadingTimeout()
|
||||
this.clearBufferTimeout()
|
||||
|
||||
// console.log('媒介资源元素突然为空,网络错误 or 切换歌曲?')
|
||||
@@ -430,7 +454,7 @@ export default {
|
||||
let targetSong = this.targetSong = this.list[this.playIndex]
|
||||
if (this.setting.player.togglePlayMethod == 'random') this.setPlayedList(targetSong)
|
||||
this.retryNum = 0
|
||||
this.audioErrorTime = 0
|
||||
this.restorePlayTime = 0
|
||||
|
||||
if (this.listId == 'download') {
|
||||
const filePath = path.join(this.setting.download.savePath, targetSong.fileName)
|
||||
@@ -515,14 +539,17 @@ export default {
|
||||
if (this.setting.player.togglePlayMethod == 'random' && this.playedList.length) {
|
||||
let index = this.playedList.indexOf(this.targetSong)
|
||||
index -= 1
|
||||
if (index > -1) {
|
||||
let listIndex = this.list.indexOf(this.playedList[index])
|
||||
if (listIndex < 0) {
|
||||
this.removePlayedList(index)
|
||||
return this.handlePrev()
|
||||
while (true) {
|
||||
if (index > -1) {
|
||||
let listIndex = this.list.indexOf(this.playedList[index])
|
||||
if (listIndex < 0) {
|
||||
this.removePlayedList(index)
|
||||
continue
|
||||
}
|
||||
this.setPlayIndex(listIndex)
|
||||
return
|
||||
}
|
||||
this.setPlayIndex(listIndex)
|
||||
return
|
||||
break
|
||||
}
|
||||
}
|
||||
let list = await this.filterList()
|
||||
@@ -550,14 +577,17 @@ export default {
|
||||
if (this.setting.player.togglePlayMethod == 'random' && this.playedList.length) {
|
||||
let index = this.playedList.indexOf(this.targetSong)
|
||||
index += 1
|
||||
if (index < this.playedList.length) {
|
||||
let listIndex = this.list.indexOf(this.playedList[index])
|
||||
if (listIndex < 0) {
|
||||
this.removePlayedList(index)
|
||||
return this.handleNext()
|
||||
while (true) {
|
||||
if (index < this.playedList.length) {
|
||||
let listIndex = this.list.indexOf(this.playedList[index])
|
||||
if (listIndex < 0) {
|
||||
this.removePlayedList(index)
|
||||
continue
|
||||
}
|
||||
this.setPlayIndex(listIndex)
|
||||
return
|
||||
}
|
||||
this.setPlayIndex(listIndex)
|
||||
return
|
||||
break
|
||||
}
|
||||
}
|
||||
let list = await this.filterList()
|
||||
@@ -605,7 +635,7 @@ export default {
|
||||
setProgress(pregress) {
|
||||
if (!audio.src) return
|
||||
const time = pregress * this.maxPlayTime
|
||||
if (this.audioErrorTime) this.audioErrorTime = time
|
||||
if (this.restorePlayTime) this.restorePlayTime = time
|
||||
if (this.mediaBuffer.playTime) {
|
||||
this.clearBufferTimeout()
|
||||
this.mediaBuffer.playTime = time
|
||||
@@ -665,23 +695,15 @@ export default {
|
||||
}
|
||||
},
|
||||
setLrc(targetSong) {
|
||||
this.musicInfo.lrc = targetSong.lrc
|
||||
this.musicInfo.tlrc = targetSong.tlrc
|
||||
|
||||
let lrcP = this.musicInfo.lrc && this.musicInfo.tlrc != null
|
||||
? Promise.resolve()
|
||||
: this.getLrc(targetSong).then(() => {
|
||||
this.musicInfo.lrc = targetSong.lrc
|
||||
this.musicInfo.tlrc = targetSong.tlrc
|
||||
})
|
||||
|
||||
lrcP
|
||||
.catch(() => {
|
||||
this.status = this.statusText = this.$t('core.player.lyric_error')
|
||||
}).finally(() => {
|
||||
this.handleUpdateWinLyricInfo('lyric', { lrc: this.musicInfo.lrc, tlrc: this.musicInfo.tlrc })
|
||||
this.setLyric()
|
||||
})
|
||||
this.getLrc(targetSong).then(() => {
|
||||
this.musicInfo.lrc = targetSong.lrc
|
||||
this.musicInfo.tlrc = targetSong.tlrc
|
||||
}).catch(() => {
|
||||
this.status = this.statusText = this.$t('core.player.lyric_error')
|
||||
}).finally(() => {
|
||||
this.handleUpdateWinLyricInfo('lyric', { lrc: this.musicInfo.lrc, tlrc: this.musicInfo.tlrc })
|
||||
this.setLyric()
|
||||
})
|
||||
},
|
||||
handleRemoveMusic() {
|
||||
this.stopPlay()
|
||||
@@ -692,6 +714,7 @@ export default {
|
||||
this.status = this.musicInfo.name = this.musicInfo.singer = ''
|
||||
this.musicInfo.songmid = null
|
||||
this.musicInfo.lrc = null
|
||||
this.musicInfo.tlrc = null
|
||||
this.musicInfo.url = null
|
||||
this.nowPlayTime = 0
|
||||
this.maxPlayTime = 0
|
||||
@@ -767,14 +790,27 @@ export default {
|
||||
})
|
||||
},
|
||||
showPlayerDetail() {
|
||||
if (!this.targetSong) return
|
||||
this.visiblePlayerDetail(true)
|
||||
},
|
||||
handleTransitionEnd(e) {
|
||||
// console.log(e)
|
||||
this.isActiveTransition = false
|
||||
},
|
||||
startLoadingTimeout() {
|
||||
// console.log('start load timeout')
|
||||
this.loadingTimeout = setTimeout(() => {
|
||||
this.handleNext()
|
||||
}, 10000)
|
||||
},
|
||||
clearLoadingTimeout() {
|
||||
if (!this.loadingTimeout) return
|
||||
// console.log('clear load timeout')
|
||||
clearTimeout(this.loadingTimeout)
|
||||
this.loadingTimeout = null
|
||||
},
|
||||
startBuffering() {
|
||||
console.log('start t')
|
||||
console.error('start t')
|
||||
if (this.mediaBuffer.timeout) return
|
||||
this.mediaBuffer.timeout = setTimeout(() => {
|
||||
this.mediaBuffer.timeout = null
|
||||
@@ -869,7 +905,7 @@ export default {
|
||||
})
|
||||
},
|
||||
setLyric() {
|
||||
window.lrc.setLyric((this.setting.player.isShowLyricTransition && this.musicInfo.tlrc ? this.musicInfo.tlrc + '\n' : '') + this.musicInfo.lrc)
|
||||
window.lrc.setLyric((this.setting.player.isShowLyricTransition && this.musicInfo.tlrc ? (this.musicInfo.tlrc + '\n') : '') + (this.musicInfo.lrc || ''))
|
||||
if (this.isPlay && (this.musicInfo.url || this.listId == 'download')) {
|
||||
window.lrc.play(audio.currentTime * 1000)
|
||||
this.handleUpdateWinLyricInfo('play', audio.currentTime * 1000)
|
||||
|
||||
@@ -16,25 +16,44 @@
|
||||
svg(:class="$style.controBtnIcon" version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' width='100%' viewBox='0 0 24 24' space='preserve')
|
||||
use(xlink:href='#icon-window-close')
|
||||
|
||||
div(:class="$style.main")
|
||||
div(:class="[$style.main, isShowComment ? $style.showComment : null]")
|
||||
div(:class="$style.left")
|
||||
//- div(:class="$style.info")
|
||||
div(:class="$style.info")
|
||||
div(:class="$style.img")
|
||||
img(:src="musicInfo.img" v-if="musicInfo.img")
|
||||
img(:class="$style.img" :src="musicInfo.img" v-if="musicInfo.img")
|
||||
div(:class="$style.description")
|
||||
p {{$t('core.player.name')}}{{musicInfo.name}}
|
||||
p {{$t('core.player.singer')}}{{musicInfo.singer}}
|
||||
p(v-if="musicInfo.album") {{$t('core.player.album')}}{{musicInfo.album}}
|
||||
//- div(:class="$style.list")
|
||||
ul
|
||||
|
||||
div(:class="$style.right")
|
||||
div(:class="[$style.lyric, lyricEvent.isMsDown ? $style.draging : null]" @wheel="handleWheel" @mousedown="handleLyricMouseDown" ref="dom_lyric")
|
||||
div(:class="$style.lyricSpace")
|
||||
p(v-for="(info, index) in lyricLines" :key="index" :class="lyric.line == index ? $style.lrcActive : null") {{info.text}}
|
||||
div(:class="$style.lyricSpace")
|
||||
|
||||
material-music-comment(:class="$style.comment" :titleFormat="this.setting.download.fileName" :musicInfo="musicInfo" v-model="isShowComment")
|
||||
|
||||
div(:class="$style.footer")
|
||||
div(:class="$style.left")
|
||||
div(:class="$style.footerLeft")
|
||||
div(:class="$style.footerLeftControlBtns")
|
||||
div(:class="[$style.footerLeftControlBtn, isShowComment ? $style.active : null]" @click="isShowComment = !isShowComment" :tips="$t('core.player.comment_show')")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' width='95%' viewBox='0 0 24 24' space='preserve')
|
||||
use(xlink:href='#icon-comment')
|
||||
div(:class="$style.footerLeftControlBtn" @click="$emit('toggle-next-play-mode')" :tips="nextTogglePlayName")
|
||||
svg(v-if="setting.player.togglePlayMethod == 'listLoop'" version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' viewBox='0 0 24 24' space='preserve')
|
||||
use(xlink:href='#icon-list-loop')
|
||||
svg(v-else-if="setting.player.togglePlayMethod == 'random'" version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' viewBox='0 0 24 24' space='preserve')
|
||||
use(xlink:href='#icon-list-random')
|
||||
svg(v-else-if="setting.player.togglePlayMethod == 'list'" version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' width='120%' viewBox='0 0 24 24' space='preserve')
|
||||
use(xlink:href='#icon-list-order')
|
||||
svg(v-else-if="setting.player.togglePlayMethod == 'singleLoop'" version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' width='110%' viewBox='0 0 24 24' space='preserve')
|
||||
use(xlink:href='#icon-single-loop')
|
||||
svg(v-else version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' width='120%' viewBox='0 0 24 24' space='preserve')
|
||||
use(xlink:href='#icon-single')
|
||||
div(:class="$style.footerLeftControlBtn" @click="$emit('add-music-to', musicInfo)" :tips="$t('core.player.add_music_to')")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' viewBox='0 0 512 512' space='preserve')
|
||||
use(xlink:href='#icon-add-2')
|
||||
div(:class="$style.progressContainer")
|
||||
div(:class="$style.progressContent")
|
||||
div(:class="$style.progress")
|
||||
@@ -124,6 +143,7 @@ export default {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
nextTogglePlayName: String,
|
||||
},
|
||||
watch: {
|
||||
// 'musicInfo.img': {
|
||||
@@ -205,6 +225,7 @@ export default {
|
||||
_lyricLines: [],
|
||||
lyricLines: [],
|
||||
isSetedLines: false,
|
||||
isShowComment: false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -452,33 +473,56 @@ export default {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
padding: 0 30px;
|
||||
|
||||
&.showComment {
|
||||
.left {
|
||||
flex-basis: 18%;
|
||||
.description p {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
.right {
|
||||
flex-basis: 30%;
|
||||
.lyric {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
.comment {
|
||||
flex-basis: 50%;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.left {
|
||||
flex: 0 0 40%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.info {
|
||||
flex: 40%;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
align-items: center;
|
||||
padding: 13px;
|
||||
overflow: hidden;
|
||||
transition: flex-basis @transition-theme;
|
||||
}
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
justify-content: flex-start;
|
||||
max-width: 300px;
|
||||
|
||||
}
|
||||
.img {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
border: 5px solid @color-theme-hover;
|
||||
// border-radius: @radius-border;
|
||||
// border: 5px solid #fff;
|
||||
}
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
min-width: 100%;
|
||||
box-shadow: 0 0 4px @color-theme-hover;
|
||||
border-radius: 6px;
|
||||
opacity: .8;
|
||||
// border: 5px solid @color-theme-hover;
|
||||
// border-radius: @radius-border;
|
||||
// border: 5px solid #fff;
|
||||
}
|
||||
.description {
|
||||
width: 300px;
|
||||
max-width: 300px;
|
||||
padding: 15px 0;
|
||||
overflow: hidden;
|
||||
p {
|
||||
@@ -492,6 +536,8 @@ export default {
|
||||
flex: 0 0 60%;
|
||||
// padding: 0 30px;
|
||||
position: relative;
|
||||
transition: flex-basis @transition-theme;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -537,18 +583,51 @@ export default {
|
||||
color: @color-theme;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.comment {
|
||||
flex: 0 0 0;
|
||||
opacity: 0;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
flex: 0 0 100px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.left {
|
||||
.footerLeft {
|
||||
flex: auto;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
align-items: center;
|
||||
padding-top: 13px;
|
||||
padding: 13px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.footerLeftControlBtns {
|
||||
color: @color-theme_2-font;
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.footerLeftControlBtn {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
opacity: .5;
|
||||
cursor: pointer;
|
||||
transition: opacity @transition-theme;
|
||||
|
||||
&:hover {
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
+.footerLeftControlBtn {
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: @color-theme;
|
||||
opacity: .8;
|
||||
}
|
||||
}
|
||||
.progress-container {
|
||||
width: 100%;
|
||||
@@ -608,6 +687,7 @@ export default {
|
||||
}
|
||||
.time-label {
|
||||
width: 100%;
|
||||
height: 18px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
span {
|
||||
@@ -686,13 +766,20 @@ each(@themes, {
|
||||
}
|
||||
}
|
||||
.img {
|
||||
img {
|
||||
border-color: ~'@{color-@{value}-theme-hover}';
|
||||
}
|
||||
box-shadow: 0 0 4px ~'@{color-@{value}-theme-hover}';
|
||||
// border-color: ~'@{color-@{value}-theme-hover}';
|
||||
}
|
||||
.lrc-active {
|
||||
color: ~'@{color-@{value}-theme}';
|
||||
}
|
||||
.footerLeftControlBtns {
|
||||
color: ~'@{color-@{value}-theme_2-font}';
|
||||
}
|
||||
.footerLeftControlBtn {
|
||||
&.active {
|
||||
color: ~'@{color-@{value}-theme}';
|
||||
}
|
||||
}
|
||||
.progress {
|
||||
background-color: ~'@{color-@{value}-player-progress}';
|
||||
}
|
||||
|
||||
162
src/renderer/components/material/CommentFloor.vue
Normal file
162
src/renderer/components/material/CommentFloor.vue
Normal file
@@ -0,0 +1,162 @@
|
||||
<template lang="pug">
|
||||
div(:class="$style.container")
|
||||
ul
|
||||
li(v-for="(item, index) in comments" :key="item.id" :class="$style.listItem")
|
||||
div(:class="$style.content")
|
||||
div(:class="$style.left")
|
||||
img( :class="$style.avatar" :src="item.avatar || commentDefImg" @error="handleUserImg")
|
||||
div(:class="$style.right")
|
||||
div(:class="$style.info")
|
||||
div.select(:class="$style.name") {{item.userName}}
|
||||
time(:class="$style.time" v-if="item.timeStr") {{timeFormat(item.timeStr)}}
|
||||
div(:class="$style.likes" v-if="item.likedCount != null")
|
||||
svg(:class="$style.likesIcon" version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' viewBox='0 0 512 512' space='preserve')
|
||||
use(xlink:href='#icon-thumbs-up')
|
||||
| {{item.likedCount}}
|
||||
div.select(:class="$style.comment_text")
|
||||
p(v-for="text in item.text") {{text}}
|
||||
material-comment-floor(v-if="item.reply && item.reply.length" :class="$style.reply_floor" :comments="item.reply")
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import commentDefImg from '../../assets/images/defaultUser.jpg'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
comments: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
commentDefImg,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
timeFormat(time) {
|
||||
return time
|
||||
// return formatTime(new Date(time), true)
|
||||
},
|
||||
handleUserImg(event) {
|
||||
event.target.src = this.commentDefImg
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" module>
|
||||
@import '../../assets/styles/layout.less';
|
||||
|
||||
@padding: 15px;
|
||||
|
||||
.container {
|
||||
|
||||
}
|
||||
|
||||
.listItem {
|
||||
border-bottom: 1px dashed @color-theme_2-line;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 12px 0;
|
||||
font-size: 13px;
|
||||
color: @color-theme_2-font;
|
||||
display: flex;
|
||||
}
|
||||
.left {
|
||||
flex: none;
|
||||
}
|
||||
.avatar {
|
||||
width: 40px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, .15);
|
||||
}
|
||||
.right {
|
||||
flex: auto;
|
||||
min-width: 0;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
align-items: flex-end;
|
||||
min-width: 0;
|
||||
line-height: 1.3;
|
||||
color: @color-theme_2-font-label;
|
||||
}
|
||||
.name {
|
||||
flex: 0 1 auto;
|
||||
min-width: 0;
|
||||
.mixin-ellipsis-1;
|
||||
}
|
||||
.time {
|
||||
flex: none;
|
||||
font-size: 11px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.likes {
|
||||
flex: 1 0 auto;
|
||||
margin-left: 10px;
|
||||
font-size: 11px;
|
||||
align-self: flex-end;
|
||||
text-align: right;
|
||||
}
|
||||
.likesIcon {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-right: 3px;
|
||||
color: @color-theme-active;
|
||||
}
|
||||
.comment_text {
|
||||
text-align: justify;
|
||||
font-size: 14px;
|
||||
padding-top: 5px;
|
||||
p {
|
||||
line-height: 1.5;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
|
||||
.reply_floor {
|
||||
padding: 0 0 0 @padding;
|
||||
margin-left: @padding * 2;
|
||||
border-radius: .5rem;
|
||||
&:last-child {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.listItem:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
.right {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
background-color: @color-reply-floor;
|
||||
}
|
||||
|
||||
|
||||
each(@themes, {
|
||||
:global(#container.@{value}) {
|
||||
.listItem {
|
||||
border-bottom-color: ~'@{color-@{value}-theme_2-active}';
|
||||
}
|
||||
.content {
|
||||
color: ~'@{color-@{value}-theme_2-font}';
|
||||
}
|
||||
.info {
|
||||
color: ~'@{color-@{value}-theme_2-font-label}';
|
||||
}
|
||||
.likesIcon {
|
||||
color: ~'@{color-@{value}-theme-active}';
|
||||
}
|
||||
.reply_floor {
|
||||
background-color: ~'@{color-@{value}-reply-floor}';
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
</style>
|
||||
@@ -1,7 +1,7 @@
|
||||
<template lang="pug">
|
||||
input(:class="$style.input" :type="type" :placeholder="placeholder" :value="value" :disabled="disabled"
|
||||
@focus="$emit('focus', $event)" @blur="$emit('blur', $event)" @input="$emit('input', $event.trim())" @change="$emit('change', text)"
|
||||
@keyup.enter="$emit('submit', text)")
|
||||
@focus="$emit('focus', $event)" @blur="$emit('blur', $event)" @input="$emit('input', $event.target.value.trim())" @change="$emit('change', $event.target.value.trim())"
|
||||
@keyup.enter="$emit('submit', $event.target.value.trim())")
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
270
src/renderer/components/material/MusicComment.vue
Normal file
270
src/renderer/components/material/MusicComment.vue
Normal file
@@ -0,0 +1,270 @@
|
||||
<template lang="pug">
|
||||
div(:class="$style.comment")
|
||||
div(:class="$style.commentHeader")
|
||||
h3 {{$t('core.player.comment_title', { name: title })}}
|
||||
div(:class="$style.commentHeaderBtns")
|
||||
div(:class="$style.commentHeaderBtn" @click="handleShowComment" :tips="$t('core.player.comment_refresh')")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' style='transform: rotate(45deg);' viewBox='0 0 24 24' space='preserve')
|
||||
use(xlink:href='#icon-refresh')
|
||||
div(:class="$style.commentHeaderBtn" @click="$emit('input', false)")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' viewBox='0 0 24 24' space='preserve')
|
||||
use(xlink:href='#icon-close')
|
||||
|
||||
div.scroll(:class="$style.commentMain" ref="dom_comment")
|
||||
div(v-if="page == 1")
|
||||
h2(:class="$style.commentType") {{$t('core.player.comment_hot_title')}}
|
||||
p(:class="$style.commentLabel" style="cursor: pointer;" v-if="isHotLoadError" @click="handleGetHotComment(currentMusicInfo)") {{$t('core.player.comment_hot_load_error')}}
|
||||
p(:class="$style.commentLabel" v-else-if="isHotLoading && !hotComments.length") {{$t('core.player.comment_hot_loading')}}
|
||||
material-comment-floor(v-if="!isHotLoadError && hotComments.length" :class="[$style.commentFloor, isHotLoading ? $style.loading : null]" :comments="hotComments")
|
||||
p(:class="$style.commentLabel" v-else-if="!isHotLoadError && !isHotLoading") {{$t('core.player.comment_no_content')}}
|
||||
div
|
||||
h2(:class="$style.commentType") {{$t('core.player.comment_new_title')}} ({{total}})
|
||||
p(:class="$style.commentLabel" style="cursor: pointer;" v-if="isNewLoadError" @click="handleGetNewComment(currentMusicInfo, nextPage, limit)") {{$t('core.player.comment_new_load_error')}}
|
||||
p(:class="$style.commentLabel" v-else-if="isNewLoading && !newComments.length") {{$t('core.player.comment_new_loading')}}
|
||||
material-comment-floor(v-if="!isNewLoadError && newComments.length" :class="[$style.commentFloor, isNewLoading ? $style.loading : null]" :comments="newComments")
|
||||
p(:class="$style.commentLabel" v-else-if="!isNewLoadError && !isNewLoading") {{$t('core.player.comment_no_content')}}
|
||||
div(:class="$style.pagination")
|
||||
material-pagination(:count="total" :btnLength="5" :limit="limit" :page="page" @btn-click="handleToggleCommentPage")
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { scrollTo } from '../../utils'
|
||||
import music from '../../utils/music'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: Boolean,
|
||||
titleFormat: {
|
||||
type: String,
|
||||
default: '歌名 - 歌手',
|
||||
},
|
||||
musicInfo: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentMusicInfo: {
|
||||
name: '',
|
||||
singer: '',
|
||||
},
|
||||
page: 1,
|
||||
total: 10,
|
||||
maxPage: 1,
|
||||
limit: 20,
|
||||
isHotLoading: true,
|
||||
isNewLoading: false,
|
||||
isHotLoadError: true,
|
||||
isNewLoadError: false,
|
||||
nextPage: 1,
|
||||
newComments: [
|
||||
// {
|
||||
// text: ['123123hhh'],
|
||||
// userName: 'dsads',
|
||||
// avatar: 'http://img4.kuwo.cn/star/userhead/39/52/1602393411654_512039239s.jpg',
|
||||
// time: '2020-10-22 22:14:17',
|
||||
// timeStr: '2020-10-22 22:14:17',
|
||||
// likedCount: 100,
|
||||
// reply: [],
|
||||
// },
|
||||
],
|
||||
hotComments: [
|
||||
// {
|
||||
// text: ['123123hhh'],
|
||||
// userName: 'dsads',
|
||||
// avatar: 'http://img4.kuwo.cn/star/userhead/39/52/1602393411654_512039239s.jpg',
|
||||
// time: '2020-10-22 22:14:17',
|
||||
// timeStr: '2020-10-22 22:14:17',
|
||||
// likedCount: 100,
|
||||
// reply: [
|
||||
// {
|
||||
// text: ['123123hhh'],
|
||||
// userName: 'dsads',
|
||||
// avatar: 'http://img4.kuwo.cn/star/userhead/39/52/1602393411654_512039239s.jpg',
|
||||
// time: '2020-10-22 22:14:17',
|
||||
// timeStr: '2020-10-22 22:14:17',
|
||||
// likedCount: 100,
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
return this.currentMusicInfo.name
|
||||
? this.titleFormat.replace('歌名', this.currentMusicInfo.name).replace('歌手', this.currentMusicInfo.singer)
|
||||
: '^-^'
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
value(n) {
|
||||
if (n) this.handleShowComment()
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async getComment(musicInfo, page, limit, retryNum = 0) {
|
||||
let resp
|
||||
try {
|
||||
resp = await music[musicInfo.source].comment.getComment(musicInfo, page, limit)
|
||||
} catch (error) {
|
||||
if (error.message == '取消请求' || ++retryNum > 2) throw error
|
||||
resp = await this.getComment(musicInfo, page, limit, retryNum)
|
||||
}
|
||||
return resp
|
||||
},
|
||||
async getHotComment(musicInfo, retryNum = 0) {
|
||||
let resp
|
||||
try {
|
||||
resp = await music[musicInfo.source].comment.getHotComment(musicInfo)
|
||||
} catch (error) {
|
||||
if (error.message == '取消请求' || ++retryNum > 2) throw error
|
||||
resp = await this.getHotComment(musicInfo, retryNum)
|
||||
}
|
||||
return resp
|
||||
},
|
||||
handleGetNewComment(musicInfo, page, limit) {
|
||||
this.isNewLoadError = false
|
||||
this.isNewLoading = true
|
||||
this.getComment(musicInfo, page, limit).then(comment => {
|
||||
this.isNewLoading = false
|
||||
this.total = comment.total
|
||||
this.maxPage = comment.maxPage
|
||||
this.page = page
|
||||
this.newComments = comment.comments
|
||||
this.$nextTick(() => {
|
||||
scrollTo(this.$refs.dom_comment, 0, 300)
|
||||
})
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
if (err.message == '取消请求') return
|
||||
this.isNewLoadError = true
|
||||
this.isNewLoading = false
|
||||
})
|
||||
},
|
||||
handleGetHotComment(musicInfo) {
|
||||
this.isHotLoadError = false
|
||||
this.isHotLoading = true
|
||||
this.getHotComment(musicInfo).then(hotComment => {
|
||||
this.isHotLoading = false
|
||||
this.hotComments = hotComment.comments
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
if (err.message == '取消请求') return
|
||||
this.isHotLoadError = true
|
||||
this.isHotLoading = false
|
||||
})
|
||||
},
|
||||
handleShowComment() {
|
||||
if (!this.musicInfo.songmid || !music[this.musicInfo.source].comment) return
|
||||
// if (this.musicInfo.songmid != this.currentMusicInfo.songmid) {
|
||||
this.page = 1
|
||||
this.total = 0
|
||||
this.maxPage = 1
|
||||
this.nextPage = 1
|
||||
// }
|
||||
this.isShowComment = true
|
||||
this.currentMusicInfo = this.musicInfo
|
||||
|
||||
if (this.page == 1) this.handleGetHotComment(this.currentMusicInfo)
|
||||
this.handleGetNewComment(this.currentMusicInfo, this.page, this.limit)
|
||||
},
|
||||
handleToggleCommentPage(page) {
|
||||
this.nextPage = page
|
||||
this.handleGetNewComment(this.currentMusicInfo, page, this.limit)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" module>
|
||||
@import '../../assets/styles/layout.less';
|
||||
|
||||
.comment {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
transition: @transition-theme;
|
||||
transition-property: flex-basis opacity;
|
||||
overflow: hidden;
|
||||
}
|
||||
.commentHeader {
|
||||
flex: none;
|
||||
padding-bottom: 5px;
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
// border-bottom: 1px solid #eee;
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
.mixin-ellipsis-1;
|
||||
line-height: 1.2;
|
||||
}
|
||||
}
|
||||
.commentHeaderBtns {
|
||||
flex: 1 0 auto;
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: flex-end;
|
||||
color: @color-theme;
|
||||
}
|
||||
.commentHeaderBtn {
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
cursor: pointer;
|
||||
transition: opacity @transition-theme;
|
||||
|
||||
+.commentHeaderBtn {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
opacity: .7;
|
||||
}
|
||||
}
|
||||
.commentMain {
|
||||
flex: auto;
|
||||
padding-left: 15px;
|
||||
padding-right: 10px;
|
||||
background-color: @color-reply-floor;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.commentLabel {
|
||||
padding: 15px;
|
||||
color: @color-theme_2-font-label;
|
||||
font-size: 14px;
|
||||
}
|
||||
.commentType {
|
||||
padding: 10px 0;
|
||||
font-size: 13px;
|
||||
color: @color-theme;
|
||||
}
|
||||
.commentFloor {
|
||||
opacity: 1;
|
||||
transition: opacity @transition-theme;
|
||||
|
||||
&.loading {
|
||||
opacity: .4;
|
||||
}
|
||||
}
|
||||
.pagination {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
each(@themes, {
|
||||
:global(#container.@{value}) {
|
||||
.commentHeaderBtns {
|
||||
color: ~'@{color-@{value}-theme}';
|
||||
}
|
||||
.commentMain {
|
||||
background-color: ~'@{color-@{value}-reply-floor}';
|
||||
}
|
||||
.commentLabel {
|
||||
color: ~'@{color-@{value}-theme_2-font-label}';
|
||||
}
|
||||
.commentType {
|
||||
color: ~'@{color-@{value}-theme}';
|
||||
}
|
||||
}
|
||||
})
|
||||
</style>
|
||||
5
src/renderer/lang/en-us/base.json
Normal file
5
src/renderer/lang/en-us/base.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"date_format_second": "{num} seconds ago",
|
||||
"date_format_minute": "{num} minutes ago",
|
||||
"date_format_hour": "{num} hours ago"
|
||||
}
|
||||
@@ -27,5 +27,16 @@
|
||||
"play_toggle_mode_random": "List Random",
|
||||
"play_toggle_mode_list": "Play in order",
|
||||
"play_toggle_mode_single_loop": "Single Loop",
|
||||
"play_toggle_mode_off": "Disable"
|
||||
"play_toggle_mode_off": "Disable",
|
||||
|
||||
"comment_show": "Song comments",
|
||||
"comment_hot_loading": "Hot comments are loading",
|
||||
"comment_new_loading": "Latest comments are loading",
|
||||
"comment_hot_load_error": "Hot comments failed to load, click to try to reload",
|
||||
"comment_new_load_error": "The latest comment failed to load, click to try to reload",
|
||||
"comment_refresh": "Refresh comments",
|
||||
"comment_no_content": "No comments yet",
|
||||
"comment_hot_title": "Hot Comment",
|
||||
"comment_new_title": "Latest comment",
|
||||
"comment_title": "{name} comment"
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
"hot_key_desktop_lyric_toggle_always_top": "Top Desktop Lyrics Switch",
|
||||
|
||||
"network": "Network",
|
||||
"network_proxy_title": "Proxy (False setting would block Internet connections)",
|
||||
"network_proxy_title": "HTTP Proxy (False setting would block Internet connections)",
|
||||
"network_proxy_host": "Host",
|
||||
"network_proxy_port": "Port",
|
||||
"network_proxy_username": "Username",
|
||||
|
||||
5
src/renderer/lang/zh-cn/base.json
Normal file
5
src/renderer/lang/zh-cn/base.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"date_format_second": "{num}秒前",
|
||||
"date_format_minute": "{num}分钟前",
|
||||
"date_format_hour": "{num}小时前"
|
||||
}
|
||||
@@ -27,5 +27,16 @@
|
||||
"play_toggle_mode_random": "列表随机",
|
||||
"play_toggle_mode_list": "顺序播放",
|
||||
"play_toggle_mode_single_loop": "单曲循环",
|
||||
"play_toggle_mode_off": "禁用"
|
||||
"play_toggle_mode_off": "禁用",
|
||||
|
||||
"comment_show": "歌曲评论",
|
||||
"comment_hot_loading": "热门评论加载中",
|
||||
"comment_new_loading": "最新评论加载中",
|
||||
"comment_hot_load_error": "热门评论加载失败,点击尝试重新加载",
|
||||
"comment_new_load_error": "最新评论加载失败,点击尝试重新加载",
|
||||
"comment_refresh": "刷新评论",
|
||||
"comment_no_content": "暂无评论",
|
||||
"comment_hot_title": "热门评论",
|
||||
"comment_new_title": "最新评论",
|
||||
"comment_title": "{name} 的评论"
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
"hot_key_desktop_lyric_toggle_always_top": "桌面歌词置顶切换",
|
||||
|
||||
"network": "网络设置",
|
||||
"network_proxy_title": "代理设置(乱设置软件将无法联网)",
|
||||
"network_proxy_title": "HTTP代理设置(乱设置软件将无法联网)",
|
||||
"network_proxy_host": "主机",
|
||||
"network_proxy_port": "端口",
|
||||
"network_proxy_username": "用户名",
|
||||
|
||||
5
src/renderer/lang/zh-tw/base.json
Normal file
5
src/renderer/lang/zh-tw/base.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"date_format_second": "{num}秒前",
|
||||
"date_format_minute": "{num}分鐘前",
|
||||
"date_format_hour": "{num}小時前"
|
||||
}
|
||||
@@ -27,5 +27,16 @@
|
||||
"play_toggle_mode_random": "列表隨機",
|
||||
"play_toggle_mode_list": "順序播放",
|
||||
"play_toggle_mode_single_loop": "單曲循環",
|
||||
"play_toggle_mode_off": "禁用"
|
||||
"play_toggle_mode_off": "禁用",
|
||||
|
||||
"comment_show": "歌曲評論",
|
||||
"comment_hot_loading": "熱門評論加載中",
|
||||
"comment_new_loading": "最新評論加載中",
|
||||
"comment_hot_load_error": "熱門評論加載失敗,點擊嘗試重新加載",
|
||||
"comment_new_load_error": "最新評論加載失敗,點擊嘗試重新加載",
|
||||
"comment_refresh": "刷新評論",
|
||||
"comment_no_content": "暫無評論",
|
||||
"comment_hot_title": "熱門評論",
|
||||
"comment_new_title": "最新評論",
|
||||
"comment_title": "{name} 的評論"
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
"hot_key_desktop_lyric_toggle_lock": "桌面歌詞鎖定切換",
|
||||
"hot_key_desktop_lyric_toggle_always_top": "桌面歌詞置頂切換",
|
||||
"network": "網絡設置",
|
||||
"network_proxy_title": "代理設置(亂設置軟件將無法聯網)",
|
||||
"network_proxy_title": "HTTP代理設置(亂設置軟件將無法聯網)",
|
||||
"network_proxy_host": "主機",
|
||||
"network_proxy_port": "端口",
|
||||
"network_proxy_username": "用戶名",
|
||||
|
||||
@@ -377,11 +377,13 @@ const actions = {
|
||||
},
|
||||
}
|
||||
commit('setStatusText', { downloadInfo, text: '获取URL中...' })
|
||||
let p = options.url ? Promise.resolve() : getUrl(downloadInfo).then(result => {
|
||||
commit('updateUrl', { downloadInfo, url: result.url })
|
||||
if (!result.url) return Promise.reject(new Error('获取URL失败'))
|
||||
options.url = result.url
|
||||
})
|
||||
let p = options.url
|
||||
? Promise.resolve()
|
||||
: getUrl(downloadInfo).then(result => {
|
||||
commit('updateUrl', { downloadInfo, url: result.url })
|
||||
if (!result.url) return Promise.reject(new Error('获取URL失败'))
|
||||
options.url = result.url
|
||||
})
|
||||
p.then(() => {
|
||||
tryNum[downloadInfo.key] = 0
|
||||
dls[downloadInfo.key] = download(options)
|
||||
|
||||
@@ -92,8 +92,7 @@ const mutations = {
|
||||
if (!fromList || !toList) return
|
||||
fromList.list.splice(fromList.list.indexOf(musicInfo), 1)
|
||||
let index = toList.list.findIndex(s => s.songmid === musicInfo.songmid)
|
||||
if (index > -1) return toList.list.splice(index, 1)
|
||||
toList.list.push(musicInfo)
|
||||
if (index < 0) toList.list.push(musicInfo)
|
||||
},
|
||||
listAddMultiple(state, { id, list }) {
|
||||
let targetList = allList[id]
|
||||
@@ -110,7 +109,7 @@ const mutations = {
|
||||
},
|
||||
// { fromId, toId, list }
|
||||
listMoveMultiple(state, { fromId, toId, list }) {
|
||||
console.log(state.commit)
|
||||
// console.log(state.commit)
|
||||
this.commit('list/listRemoveMultiple', { id: fromId, list })
|
||||
this.commit('list/listAddMultiple', { id: toId, list })
|
||||
},
|
||||
|
||||
@@ -59,6 +59,15 @@ const actions = {
|
||||
},
|
||||
getLrc({ commit, state }, musicInfo) {
|
||||
if (lrcRequest && lrcRequest.cancelHttp) lrcRequest.cancelHttp()
|
||||
if (musicInfo.lrc && musicInfo.tlrc != null) {
|
||||
if (musicInfo.lrc.startsWith('\ufeff[id:$00000000]')) {
|
||||
let str = musicInfo.lrc.replace('\ufeff[id:$00000000]\n', '')
|
||||
commit('setLrc', { musicInfo, lyric: str, tlyric: musicInfo.tlrc })
|
||||
}
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
|
||||
lrcRequest = music[musicInfo.source].getLyric(musicInfo)
|
||||
return lrcRequest.promise.then(({ lyric, tlyric }) => {
|
||||
lrcRequest = null
|
||||
|
||||
@@ -85,10 +85,12 @@ const actions = {
|
||||
let source = rootState.setting.songList.source
|
||||
const loadData = (id, page) => {
|
||||
let key = `sdetail__${source}__${id}__${page}`
|
||||
return cache.has(key) ? Promise.resolve(cache.get(key)) : music[source].songList.getListDetail(id, page).then(result => {
|
||||
cache.set(key, result)
|
||||
return result
|
||||
})
|
||||
return cache.has(key)
|
||||
? Promise.resolve(cache.get(key))
|
||||
: music[source].songList.getListDetail(id, page).then(result => {
|
||||
cache.set(key, result)
|
||||
return result
|
||||
})
|
||||
}
|
||||
return loadData(id, 1).then(result => {
|
||||
if (result.total <= result.limit) return result.list
|
||||
|
||||
@@ -20,6 +20,39 @@ export const sizeFormate = size => {
|
||||
return `${(size / Math.pow(1024, Math.floor(number))).toFixed(2)} ${units[number]}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期格式化
|
||||
* @param {*} date 时间
|
||||
* @param {String} format 时间格式,默认YYYY-MM-DD hh:mm:ss
|
||||
*/
|
||||
export const dateFormat = (date = new Date(), format = 'YYYY-MM-DD hh:mm:ss') => {
|
||||
if (typeof date != 'object') date = new Date(date)
|
||||
const munFix = (n) => n < 10 ? ('0' + n) : n
|
||||
return format
|
||||
.replace('YYYY', date.getFullYear())
|
||||
.replace('MM', munFix(date.getMonth() + 1))
|
||||
.replace('DD', munFix(date.getDate()))
|
||||
.replace('hh', munFix(date.getHours()))
|
||||
.replace('mm', munFix(date.getMinutes()))
|
||||
.replace('ss', munFix(date.getSeconds()))
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间格式化
|
||||
*/
|
||||
export const dateFormat2 = time => {
|
||||
let differ = parseInt((Date.now() - time) / 1000)
|
||||
if (differ < 60) {
|
||||
return window.i18n.t('base.date_format_second', { num: differ })
|
||||
} else if (differ < 3600) {
|
||||
return window.i18n.t('base.date_format_minute', { num: parseInt(differ / 60) })
|
||||
} else if (differ < 86400) {
|
||||
return window.i18n.t('base.date_format_hour', { num: parseInt(differ / 3600) })
|
||||
} else {
|
||||
return dateFormat(time)
|
||||
}
|
||||
}
|
||||
|
||||
export const formatPlayTime = time => {
|
||||
let m = parseInt(time / 60)
|
||||
let s = parseInt(time % 60)
|
||||
@@ -45,8 +78,9 @@ const encodeNames = {
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
''': "'",
|
||||
''': "'",
|
||||
}
|
||||
export const decodeName = str => str.replace(/(?:&|<|>|"|')/g, s => encodeNames[s])
|
||||
export const decodeName = str => str.replace(/(?:&|<|>|"|'|')/gm, s => encodeNames[s])
|
||||
|
||||
const easeInOutQuad = (t, b, c, d) => {
|
||||
t /= d / 2
|
||||
@@ -99,7 +133,7 @@ const handleScroll = (element, to, duration = 300, fn = () => {}) => {
|
||||
* @param {*} fn 滚动完成后的回调
|
||||
* @param {*} delay 延迟执行时间
|
||||
*/
|
||||
export const scrollTo = (element, to, duration = 300, fn = () => {}, delay) => {
|
||||
export const scrollTo = (element, to, duration = 300, fn = () => {}, delay = 0) => {
|
||||
let cancelFn
|
||||
let timeout
|
||||
if (delay) {
|
||||
|
||||
75
src/renderer/utils/music/kg/comment.js
Normal file
75
src/renderer/utils/music/kg/comment.js
Normal file
@@ -0,0 +1,75 @@
|
||||
import { httpFetch } from '../../request'
|
||||
import { decodeName, dateFormat2 } from '../../'
|
||||
|
||||
export default {
|
||||
_requestObj: null,
|
||||
_requestObj2: null,
|
||||
async getComment({ hash }, page = 1, limit = 20) {
|
||||
if (this._requestObj) this._requestObj.cancelHttp()
|
||||
|
||||
const _requestObj = httpFetch(`http://comment.service.kugou.com/index.php?r=commentsv2/getCommentWithLike&code=fc4be23b4e972707f36b8a828a93ba8a&extdata=${hash}&p=${page}&pagesize=${limit}&ver=1.01&clientver=8373&appid=1001&kugouid=687373022`, {
|
||||
headers: {
|
||||
'User-Agent': 'Android712-AndroidPhone-8983-18-0-COMMENT-wifi',
|
||||
},
|
||||
})
|
||||
const { body, statusCode } = await _requestObj.promise
|
||||
// console.log(body)
|
||||
if (statusCode != 200 || body.err_code !== 0) throw new Error('获取评论失败')
|
||||
return { source: 'kg', comments: this.filterComment(body.list || []), total: body.count, page, limit, maxPage: Math.ceil(body.count / limit) || 1 }
|
||||
},
|
||||
async getHotComment({ hash, songmid }, page = 1, limit = 100) {
|
||||
// console.log(songmid)
|
||||
if (this._requestObj2) this._requestObj2.cancelHttp()
|
||||
|
||||
const _requestObj2 = httpFetch(`http://comment.service.kugou.com/index.php?r=commentsv2/getCommentWithLike&code=fc4be23b4e972707f36b8a828a93ba8a&extdata=${hash}&p=${page}&pagesize=${limit}&ver=1.01&clientver=8373&appid=1001&kugouid=687373022`, {
|
||||
headers: {
|
||||
'User-Agent': 'Android712-AndroidPhone-8983-18-0-COMMENT-wifi',
|
||||
},
|
||||
})
|
||||
const { body, statusCode } = await _requestObj2.promise
|
||||
// console.log(body)
|
||||
if (statusCode != 200 || body.err_code !== 0) throw new Error('获取热门评论失败')
|
||||
return { source: 'kg', comments: this.filterComment(body.weightList || []) }
|
||||
},
|
||||
async getReplyComment({ songmid }, replyId, page = 1, limit = 100) {
|
||||
if (this._requestObj2) this._requestObj2.cancelHttp()
|
||||
|
||||
const _requestObj2 = httpFetch(`http://comment.service.kugou.com/index.php?r=commentsv2/getReplyWithLike&code=fc4be23b4e972707f36b8a828a93ba8a&p=${page}&pagesize=${limit}&ver=1.01&clientver=8373&kugouid=687373022&appid=1001&childrenid=${songmid}&tid=${replyId}`, {
|
||||
headers: {
|
||||
'User-Agent': 'Android712-AndroidPhone-8983-18-0-COMMENT-wifi',
|
||||
},
|
||||
})
|
||||
const { body, statusCode } = await _requestObj2.promise
|
||||
// console.log(body)
|
||||
if (statusCode != 200 || body.err_code !== 0) throw new Error('获取回复评论失败')
|
||||
return { source: 'kg', comments: this.filterComment(body.list || []) }
|
||||
},
|
||||
filterComment(rawList) {
|
||||
return rawList.map(item => {
|
||||
let data = {
|
||||
id: item.id,
|
||||
text: decodeName(item.content || '').split('\n'),
|
||||
time: item.addtime,
|
||||
timeStr: dateFormat2(new Date(item.addtime).getTime()),
|
||||
userName: item.user_name,
|
||||
avatar: item.user_pic,
|
||||
userId: item.user_id,
|
||||
likedCount: item.like.likenum,
|
||||
replyNum: item.reply_num,
|
||||
reply: [],
|
||||
}
|
||||
|
||||
return item.pcontent ? {
|
||||
id: item.id,
|
||||
text: decodeName(item.pcontent).split('\n'),
|
||||
time: null,
|
||||
userName: item.puser,
|
||||
avatar: null,
|
||||
userId: item.puser_id,
|
||||
likedCount: null,
|
||||
replyNum: null,
|
||||
reply: [data],
|
||||
} : data
|
||||
})
|
||||
},
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { httpFetch } from '../../request'
|
||||
import { decodeName } from '../..'
|
||||
|
||||
export default {
|
||||
_requestObj: null,
|
||||
@@ -25,7 +26,7 @@ export default {
|
||||
filterList(rawList) {
|
||||
const list = []
|
||||
rawList.forEach(item => {
|
||||
item.keywords.map(k => list.push(k.keyword))
|
||||
item.keywords.map(k => list.push(decodeName(k.keyword)))
|
||||
})
|
||||
return list
|
||||
},
|
||||
|
||||
@@ -5,12 +5,14 @@ import musicSearch from './musicSearch'
|
||||
import pic from './pic'
|
||||
import lyric from './lyric'
|
||||
import hotSearch from './hotSearch'
|
||||
import comment from './comment'
|
||||
|
||||
const kg = {
|
||||
leaderboard,
|
||||
songList,
|
||||
musicSearch,
|
||||
hotSearch,
|
||||
comment,
|
||||
getMusicUrl(songInfo, type) {
|
||||
return apis('kg').getMusicUrl(songInfo, type)
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { httpGet, cancelHttp, httpFetch } from '../../request'
|
||||
import { formatPlayTime, sizeFormate } from '../../index'
|
||||
import { decodeName, formatPlayTime, sizeFormate } from '../../index'
|
||||
|
||||
let boardList = [{ id: 'kg__8888', name: '酷狗TOP500', bangid: '8888' }, { id: 'kg__6666', name: '酷狗飙升榜', bangid: '6666' }, { id: 'kg__37361', name: '酷狗雷达榜', bangid: '37361' }, { id: 'kg__23784', name: '网络红歌榜', bangid: '23784' }, { id: 'kg__24971', name: 'DJ热歌榜', bangid: '24971' }, { id: 'kg__35811', name: '会员专享热歌榜', bangid: '35811' }, { id: 'kg__31308', name: '华语新歌榜', bangid: '31308' }, { id: 'kg__31310', name: '欧美新歌榜', bangid: '31310' }, { id: 'kg__31311', name: '韩国新歌榜', bangid: '31311' }, { id: 'kg__31312', name: '日本新歌榜', bangid: '31312' }, { id: 'kg__31313', name: '粤语新歌榜', bangid: '31313' }, { id: 'kg__33162', name: 'ACG新歌榜', bangid: '33162' }, { id: 'kg__21101', name: '酷狗分享榜', bangid: '21101' }, { id: 'kg__30972', name: '腾讯音乐人原创榜', bangid: '30972' }, { id: 'kg__22603', name: '5sing音乐榜', bangid: '22603' }, { id: 'kg__33160', name: '电音热歌榜', bangid: '33160' }, { id: 'kg__21335', name: '繁星音乐榜', bangid: '21335' }, { id: 'kg__33161', name: '古风新歌榜', bangid: '33161' }, { id: 'kg__33163', name: '影视金曲榜', bangid: '33163' }, { id: 'kg__33166', name: '欧美金曲榜', bangid: '33166' }, { id: 'kg__33165', name: '粤语金曲榜', bangid: '33165' }, { id: 'kg__36107', name: '小语种热歌榜', bangid: '36107' }, { id: 'kg__4681', name: '美国BillBoard榜', bangid: '4681' }, { id: 'kg__4680', name: '英国单曲榜', bangid: '4680' }, { id: 'kg__4673', name: '日本公信榜', bangid: '4673' }, { id: 'kg__38623', name: '韩国Melon音乐榜', bangid: '38623' }, { id: 'kg__42807', name: 'joox本地热歌榜', bangid: '42807' }, { id: 'kg__42808', name: '台湾KKBOX风云榜', bangid: '42808' }]
|
||||
|
||||
@@ -134,9 +134,9 @@ export default {
|
||||
}
|
||||
}
|
||||
return {
|
||||
singer: item.singername,
|
||||
name: item.songname,
|
||||
albumName: item.album_name,
|
||||
singer: decodeName(item.singername),
|
||||
name: decodeName(item.songname),
|
||||
albumName: decodeName(item.album_name),
|
||||
albumId: item.album_id,
|
||||
songmid: item.audio_id,
|
||||
source: 'kg',
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { httpFetch } from '../../request'
|
||||
import { decodeLyric } from './util'
|
||||
import { decodeName } from '../..'
|
||||
|
||||
const parseLyric = str => {
|
||||
str = str.replace(/(?:<\d+,\d+,\d+>|\r)/g, '')
|
||||
if (str.startsWith('\ufeff[id:$00000000]')) str = str.replace('\ufeff[id:$00000000]\n', '')
|
||||
let trans = str.match(/\[language:([\w=\\/+]+)\]/)
|
||||
let tlyric
|
||||
if (trans) {
|
||||
@@ -29,6 +31,8 @@ const parseLyric = str => {
|
||||
return str.replace(result[1], time)
|
||||
})
|
||||
tlyric = tlyric ? tlyric.join('\n') : ''
|
||||
lyric = decodeName(lyric)
|
||||
tlyric = decodeName(tlyric)
|
||||
return {
|
||||
lyric,
|
||||
tlyric,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// import '../../polyfill/array.find'
|
||||
// import jshtmlencode from 'js-htmlencode'
|
||||
import { httpFetch } from '../../request'
|
||||
import { formatPlayTime, sizeFormate } from '../../index'
|
||||
import { decodeName, formatPlayTime, sizeFormate } from '../../index'
|
||||
// import { debug } from '../../utils/env'
|
||||
// import { formatSinger } from './util'
|
||||
|
||||
@@ -50,9 +50,9 @@ export default {
|
||||
}
|
||||
}
|
||||
list.push({
|
||||
singer: item.singername,
|
||||
name: item.songname,
|
||||
albumName: item.album_name,
|
||||
singer: decodeName(item.singername),
|
||||
name: decodeName(item.songname),
|
||||
albumName: decodeName(item.album_name),
|
||||
albumId: item.album_id,
|
||||
songmid: item.audio_id,
|
||||
source: 'kg',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { httpFetch } from '../../request'
|
||||
import { formatPlayTime, sizeFormate } from '../../index'
|
||||
import { decodeName, formatPlayTime, sizeFormate } from '../../index'
|
||||
import { toMD5 } from '../utils'
|
||||
|
||||
export default {
|
||||
@@ -454,9 +454,9 @@ export default {
|
||||
}
|
||||
}
|
||||
return {
|
||||
singer: item.singername,
|
||||
name: item.songname,
|
||||
albumName: item.album_name,
|
||||
singer: decodeName(item.singername),
|
||||
name: decodeName(item.songname),
|
||||
albumName: decodeName(item.album_name),
|
||||
albumId: item.album_id,
|
||||
songmid: item.audio_id,
|
||||
source: 'kg',
|
||||
@@ -507,9 +507,9 @@ export default {
|
||||
}
|
||||
}
|
||||
list.push({
|
||||
singer: item.author_name,
|
||||
name: item.ori_audio_name,
|
||||
albumName: item.album_info.album_name,
|
||||
singer: decodeName(item.author_name),
|
||||
name: decodeName(item.ori_audio_name),
|
||||
albumName: decodeName(item.album_info.album_name),
|
||||
albumId: item.album_info.album_id,
|
||||
songmid: item.audio_info.audio_id,
|
||||
source: 'kg',
|
||||
|
||||
61
src/renderer/utils/music/kw/comment.js
Normal file
61
src/renderer/utils/music/kw/comment.js
Normal file
@@ -0,0 +1,61 @@
|
||||
import { httpFetch } from '../../request'
|
||||
import { dateFormat2 } from '../../'
|
||||
|
||||
export default {
|
||||
_requestObj: null,
|
||||
_requestObj2: null,
|
||||
async getComment({ songmid }, page = 1, limit = 20) {
|
||||
if (this._requestObj) this._requestObj.cancelHttp()
|
||||
|
||||
const _requestObj = httpFetch(`http://comment.kuwo.cn/com.s?type=get_comment&uid=0&digest=15&sid=${songmid}&page=${page}&rows=${limit}&f=web&prod=MUSIC_8.7.7.0_BCS37&devid=28556413`, {
|
||||
headers: {
|
||||
'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 9;)',
|
||||
},
|
||||
})
|
||||
const { body, statusCode } = await _requestObj.promise
|
||||
if (statusCode != 200 || body.result !== 'ok') throw new Error('获取评论失败')
|
||||
// console.log(body)
|
||||
return { source: 'kw', comments: this.filterComment(body.rows), total: body.total, page, limit, maxPage: Math.ceil(body.total / limit) || 1 }
|
||||
},
|
||||
async getHotComment({ songmid }, page = 1, limit = 100) {
|
||||
if (this._requestObj2) this._requestObj2.cancelHttp()
|
||||
|
||||
const _requestObj2 = httpFetch(`http://comment.kuwo.cn/com.s?type=get_rec_comment&uid=0&digest=15&sid=${songmid}&page=${page}&rows=${limit}&f=web&prod=MUSIC_8.7.7.0_BCS37&devid=28556413`, {
|
||||
headers: {
|
||||
'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 9;)',
|
||||
},
|
||||
})
|
||||
const { body, statusCode } = await _requestObj2.promise
|
||||
if (statusCode != 200 || body.result !== 'ok') throw new Error('获取热门评论失败')
|
||||
// console.log(body)
|
||||
return { source: 'kw', comments: this.filterComment(body.rows) }
|
||||
},
|
||||
filterComment(rawList) {
|
||||
if (!rawList) return []
|
||||
return rawList.map(item => {
|
||||
let data = {
|
||||
id: item.id,
|
||||
text: item.msg.split('\n'),
|
||||
time: item.time,
|
||||
timeStr: dateFormat2(new Date(item.time).getTime()),
|
||||
userName: decodeURIComponent(item.u_name),
|
||||
avatar: item.u_pic,
|
||||
userId: item.u_id,
|
||||
likedCount: item.like_num,
|
||||
reply: [],
|
||||
}
|
||||
return item.reply ? {
|
||||
id: item.id,
|
||||
rootId: item.reply.id,
|
||||
text: item.reply.msg.split('\n'),
|
||||
time: item.reply.time,
|
||||
timeStr: dateFormat2(new Date(item.reply.time).getTime()),
|
||||
userName: decodeURIComponent(item.reply.u_name),
|
||||
avatar: item.reply.u_pic,
|
||||
userId: item.reply.u_id,
|
||||
likedCount: item.reply.like_num,
|
||||
reply: [data],
|
||||
} : data
|
||||
})
|
||||
},
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import pic from './pic'
|
||||
import { apis } from '../api-source'
|
||||
import songList from './songList'
|
||||
import hotSearch from './hotSearch'
|
||||
import comment from './comment'
|
||||
|
||||
const kw = {
|
||||
_musicInfoRequestObj: null,
|
||||
@@ -36,6 +37,7 @@ const kw = {
|
||||
leaderboard,
|
||||
songList,
|
||||
hotSearch,
|
||||
comment,
|
||||
getLyric(songInfo, isGetLyricx) {
|
||||
// let singer = songInfo.singer.indexOf('、') > -1 ? songInfo.singer.split('、')[0] : songInfo.singer
|
||||
return lyric.getLyric(songInfo.songmid, isGetLyricx)
|
||||
|
||||
30
src/renderer/utils/music/mg/album.js
Normal file
30
src/renderer/utils/music/mg/album.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import { httpFetch } from '../../request'
|
||||
|
||||
export default {
|
||||
getAlbum(songInfo, tryNum = 0) {
|
||||
let requestObj = httpFetch(`http://app.c.nf.migu.cn/MIGUM2.0/v1.0/content/queryAlbumSong?albumId=${songInfo.albumId}&pageNo=1`, {
|
||||
headers: {
|
||||
sign: '46DB65104950B98FE451AD41047CC6C4',
|
||||
timestamp: 1603451430776,
|
||||
appId: 'yyapp2',
|
||||
mode: 'android',
|
||||
ua: 'Android_migu',
|
||||
version: '6.9.4',
|
||||
osVersion: 'android 7.0',
|
||||
'User-Agent': 'okhttp/3.9.1',
|
||||
channel: '0146832',
|
||||
},
|
||||
})
|
||||
requestObj.promise = requestObj.promise.then(({ body }) => {
|
||||
if (body.code !== '000000') {
|
||||
if (tryNum > 5) return Promise.reject('获取专辑失败')
|
||||
let tryRequestObj = this.getAlbum(songInfo, ++tryNum)
|
||||
requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj)
|
||||
return tryRequestObj.promise
|
||||
}
|
||||
console.log(body)
|
||||
return body.songList
|
||||
})
|
||||
return requestObj
|
||||
},
|
||||
}
|
||||
95
src/renderer/utils/music/mg/comment.js
Normal file
95
src/renderer/utils/music/mg/comment.js
Normal file
@@ -0,0 +1,95 @@
|
||||
import { httpFetch } from '../../request'
|
||||
import album from './album'
|
||||
import { dateFormat2 } from '../../'
|
||||
|
||||
export default {
|
||||
_requestObj: null,
|
||||
_requestObj2: null,
|
||||
_requestObj3: null,
|
||||
async getSongId(musicInfo) {
|
||||
if (this._requestObj3) this._requestObj3.cancelHttp()
|
||||
this.requestObj3 = album.getAlbum(musicInfo)
|
||||
const list = await this.requestObj3.promise
|
||||
const copyrightId = musicInfo.copyrightId
|
||||
let info = list.find(s => s.copyrightId == copyrightId)
|
||||
const songmid = musicInfo.songmid
|
||||
if (!info) info = list.find(s => s.songId == songmid)
|
||||
return info ? info.songId : null
|
||||
},
|
||||
async getComment(musicInfo, page = 1, limit = 20) {
|
||||
if (this._requestObj) this._requestObj.cancelHttp()
|
||||
if (!musicInfo.songId) {
|
||||
let id = await this.getSongId(musicInfo)
|
||||
if (!id) throw new Error('获取评论失败')
|
||||
musicInfo.songId = id
|
||||
}
|
||||
|
||||
const _requestObj = httpFetch(`https://music.migu.cn/v3/api/comment/listComments?targetId=${musicInfo.songId}&pageSize=${limit}&pageNo=${page}`, {
|
||||
headers: {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4195.1 Safari/537.36',
|
||||
Referer: 'https://music.migu.cn',
|
||||
},
|
||||
})
|
||||
const { body, statusCode } = await _requestObj.promise
|
||||
console.log(body)
|
||||
if (statusCode != 200 || body.returnCode !== '000000') throw new Error('获取评论失败')
|
||||
return { source: 'mg', comments: this.filterComment(body.data.items), total: body.data.itemTotal, page, limit, maxPage: Math.ceil(body.data.itemTotal / limit) || 1 }
|
||||
},
|
||||
async getHotComment(musicInfo, page = 1, limit = 100) {
|
||||
if (this._requestObj2) this._requestObj2.cancelHttp()
|
||||
|
||||
if (!musicInfo.songId) {
|
||||
let id = await this.getSongId(musicInfo)
|
||||
if (!id) throw new Error('获取评论失败')
|
||||
musicInfo.songId = id
|
||||
}
|
||||
|
||||
const _requestObj2 = httpFetch(`https://music.migu.cn/v3/api/comment/listTopComments?targetId=${musicInfo.songId}&pageSize=${limit}&pageNo=${page}`, {
|
||||
headers: {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4195.1 Safari/537.36',
|
||||
Referer: 'https://music.migu.cn',
|
||||
},
|
||||
})
|
||||
const { body, statusCode } = await _requestObj2.promise
|
||||
// console.log(body)
|
||||
if (statusCode != 200 || body.returnCode !== '000000') throw new Error('获取热门评论失败')
|
||||
return { source: 'mg', comments: this.filterComment(body.data.items) }
|
||||
},
|
||||
async getReplyComment(musicInfo, replyId, page = 1, limit = 100) {
|
||||
if (this._requestObj2) this._requestObj2.cancelHttp()
|
||||
|
||||
const _requestObj2 = httpFetch(`https://music.migu.cn/v3/api/comment/listCommentsById?commentId=${replyId}&pageSize=${limit}&pageNo=${page}`, {
|
||||
headers: {
|
||||
'User-Agent': 'Android712-AndroidPhone-8983-18-0-COMMENT-wifi',
|
||||
},
|
||||
})
|
||||
const { body, statusCode } = await _requestObj2.promise
|
||||
// console.log(body)
|
||||
if (statusCode != 200 || body.returnCode !== '000000') throw new Error('获取回复评论失败')
|
||||
return { source: 'mg', comments: this.filterComment(body.data.items) }
|
||||
},
|
||||
filterComment(rawList) {
|
||||
return rawList.map(item => ({
|
||||
id: item.commentId,
|
||||
text: item.body.split('\n'),
|
||||
time: item.createTime,
|
||||
timeStr: dateFormat2(new Date(item.createTime).getTime()),
|
||||
userName: item.author.name,
|
||||
avatar: item.author.avatar,
|
||||
userId: item.author.id,
|
||||
likedCount: item.praiseCount,
|
||||
replyNum: item.replyTotal,
|
||||
reply: item.replyCommentList.map(c => ({
|
||||
id: c.commentId,
|
||||
text: c.body.split('\n'),
|
||||
time: c.createTime,
|
||||
timeStr: dateFormat2(new Date(c.createTime).getTime()),
|
||||
userName: c.author.name,
|
||||
avatar: c.author.avatar,
|
||||
userId: c.author.id,
|
||||
likedCount: c.praiseCount,
|
||||
replyNum: c.replyTotal,
|
||||
})),
|
||||
}))
|
||||
},
|
||||
}
|
||||
@@ -5,12 +5,14 @@ import musicSearch from './musicSearch'
|
||||
import pic from './pic'
|
||||
import lyric from './lyric'
|
||||
import hotSearch from './hotSearch'
|
||||
import comment from './comment'
|
||||
|
||||
const mg = {
|
||||
songList,
|
||||
musicSearch,
|
||||
leaderboard,
|
||||
hotSearch,
|
||||
comment,
|
||||
getMusicUrl(songInfo, type) {
|
||||
return apis('mg').getMusicUrl(songInfo, type)
|
||||
},
|
||||
|
||||
@@ -137,6 +137,7 @@ export default {
|
||||
albumName: item.album,
|
||||
albumId: item.albumId,
|
||||
songmid: item.copyrightId,
|
||||
songId: item.songId,
|
||||
copyrightId: item.copyrightId,
|
||||
source: 'mg',
|
||||
interval: null,
|
||||
@@ -195,7 +196,7 @@ export default {
|
||||
getList(bangid, page, retryNum = 0) {
|
||||
if (++retryNum > 3) return Promise.reject(new Error('try max num'))
|
||||
return this.getData(this.getUrl(bangid, page)).then(({ statusCode, body }) => {
|
||||
// console.log(body)
|
||||
console.log(body)
|
||||
if (statusCode !== 200 || body.code !== this.successCode) return this.getList(bangid, page, retryNum)
|
||||
const list = this.filterData(body.data.columnInfo.dataList)
|
||||
return {
|
||||
|
||||
@@ -36,7 +36,7 @@ export default {
|
||||
return arr.join('、')
|
||||
},
|
||||
handleResult(rawData) {
|
||||
// console.log(rawData)
|
||||
console.log(rawData)
|
||||
let ids = new Set()
|
||||
const list = []
|
||||
rawData.forEach(item => {
|
||||
@@ -82,6 +82,7 @@ export default {
|
||||
albumName: albumNInfo.name,
|
||||
albumId: albumNInfo.id,
|
||||
songmid: item.id,
|
||||
songId: item.songId,
|
||||
copyrightId: item.copyrightId,
|
||||
source: 'mg',
|
||||
interval: null,
|
||||
|
||||
@@ -24,25 +24,25 @@ export default {
|
||||
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>/,
|
||||
|
||||
// http://music.migu.cn/v3/music/playlist/161044573?page=1
|
||||
// https://music.migu.cn/v3/music/playlist/161044573?page=1
|
||||
listDetailLink: /^.+\/playlist\/(\d+)(?:\?.*|&.*$|#.*$|$)/,
|
||||
},
|
||||
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`
|
||||
// ? `https://music.migu.cn/v3/music/playlist?page=${page}&from=migu`
|
||||
// : `https://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`
|
||||
// return `https://music.migu.cn/v3/music/playlist?tagId=${tagId}&page=${page}&from=migu`
|
||||
if (tagId == null) {
|
||||
// return `http://app.c.nf.migu.cn/MIGUM2.0/v2.0/content/getMusicData.do?count=${this.limit_list}&start=${page}&templateVersion=5&type=1`
|
||||
// return `https://app.c.nf.migu.cn/MIGUM2.0/v2.0/content/getMusicData.do?count=${this.limit_list}&start=${page}&templateVersion=5&type=1`
|
||||
// return `https://c.musicapp.migu.cn/MIGUM2.0/v2.0/content/getMusicData.do?count=${this.limit_list}&start=${page}&templateVersion=5&type=${sortId}`
|
||||
// http://app.c.nf.migu.cn/MIGUM2.0/v2.0/content/getMusicData.do?count=50&start=2&templateVersion=5&type=1
|
||||
return `http://m.music.migu.cn/migu/remoting/playlist_bycolumnid_tag?playListType=2&type=1&columnId=${sortId}&startIndex=${(page - 1) * 10}`
|
||||
// https://app.c.nf.migu.cn/MIGUM2.0/v2.0/content/getMusicData.do?count=50&start=2&templateVersion=5&type=1
|
||||
return `https://m.music.migu.cn/migu/remoting/playlist_bycolumnid_tag?playListType=2&type=1&columnId=${sortId}&startIndex=${(page - 1) * 10}`
|
||||
}
|
||||
// return `https://app.c.nf.migu.cn/MIGUM2.0/v2.0/content/getMusicData.do?area=2&count=${this.limit_list}&start=${page}&tags=${tagId}&templateVersion=5&type=3`
|
||||
return `http://m.music.migu.cn/migu/remoting/playlist_bycolumnid_tag?playListType=2&type=1&tagId=${tagId}&startIndex=${(page - 1) * 10}`
|
||||
return `https://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}`
|
||||
@@ -74,7 +74,7 @@ export default {
|
||||
return this._requestObj_listDetail.promise.then(({ body }) => {
|
||||
if (body.code !== this.successCode) return this.getListDetail(id, page, ++tryNum)
|
||||
// console.log(JSON.stringify(body))
|
||||
console.log(body)
|
||||
// console.log(body)
|
||||
return {
|
||||
list: this.filterListDetail(body.list),
|
||||
page,
|
||||
@@ -135,6 +135,7 @@ export default {
|
||||
albumId: item.albumId,
|
||||
songmid: item.copyrightId,
|
||||
copyrightId: item.copyrightId,
|
||||
songId: item.songId,
|
||||
source: 'mg',
|
||||
interval: null,
|
||||
img: item.albumImgs && item.albumImgs.length ? item.albumImgs[0].img : null,
|
||||
@@ -185,7 +186,6 @@ export default {
|
||||
// })
|
||||
return this._requestObj_list.promise.then(({ body }) => {
|
||||
if (body.retCode !== '100000' || body.retMsg.code !== this.successCode) return this.getList(sortId, tagId, page, ++tryNum)
|
||||
// console.log(body)
|
||||
return {
|
||||
list: this.filterList(body.retMsg.playlist),
|
||||
total: parseInt(body.retMsg.countSize),
|
||||
|
||||
187
src/renderer/utils/music/tx/comment.js
Normal file
187
src/renderer/utils/music/tx/comment.js
Normal file
@@ -0,0 +1,187 @@
|
||||
import { httpFetch } from '../../request'
|
||||
import { dateFormat2 } from '../../'
|
||||
|
||||
const emojis = {
|
||||
e400846: '😘',
|
||||
e400874: '😴',
|
||||
e400825: '😃',
|
||||
e400847: '😙',
|
||||
e400835: '😍',
|
||||
e400873: '😳',
|
||||
e400836: '😎',
|
||||
e400867: '😭',
|
||||
e400832: '😊',
|
||||
e400837: '😏',
|
||||
e400875: '😫',
|
||||
e400831: '😉',
|
||||
e400855: '😡',
|
||||
e400823: '😄',
|
||||
e400862: '😨',
|
||||
e400844: '😖',
|
||||
e400841: '😓',
|
||||
e400830: '😈',
|
||||
e400828: '😆',
|
||||
e400833: '😋',
|
||||
e400822: '😀',
|
||||
e400843: '😕',
|
||||
e400829: '😇',
|
||||
e400824: '😂',
|
||||
e400834: '😌',
|
||||
e400877: '😷',
|
||||
e400132: '🍉',
|
||||
e400181: '🍺',
|
||||
e401067: '☕️',
|
||||
e400186: '🥧',
|
||||
e400343: '🐷',
|
||||
e400116: '🌹',
|
||||
e400126: '🍃',
|
||||
e400613: '💋',
|
||||
e401236: '❤️',
|
||||
e400622: '💔',
|
||||
e400637: '💣',
|
||||
e400643: '💩',
|
||||
e400773: '🔪',
|
||||
e400102: '🌛',
|
||||
e401328: '🌞',
|
||||
e400420: '👏',
|
||||
e400914: '🙌',
|
||||
e400408: '👍',
|
||||
e400414: '👎',
|
||||
e401121: '✋',
|
||||
e400396: '👋',
|
||||
e400384: '👉',
|
||||
e401115: '✊',
|
||||
e400402: '👌',
|
||||
e400905: '🙈',
|
||||
e400906: '🙉',
|
||||
e400907: '🙊',
|
||||
e400562: '👻',
|
||||
e400932: '🙏',
|
||||
e400644: '💪',
|
||||
e400611: '💉',
|
||||
e400185: '🎁',
|
||||
e400655: '💰',
|
||||
e400325: '🐥',
|
||||
e400612: '💊',
|
||||
e400198: '🎉',
|
||||
e401685: '⚡️',
|
||||
e400631: '💝',
|
||||
e400768: '🔥',
|
||||
e400432: '👑',
|
||||
}
|
||||
|
||||
export default {
|
||||
_requestObj: null,
|
||||
_requestObj2: null,
|
||||
async getComment({ songId }, page = 1, limit = 20) {
|
||||
if (this._requestObj) this._requestObj.cancelHttp()
|
||||
|
||||
const _requestObj = httpFetch('http://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg', {
|
||||
headers: {
|
||||
'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)',
|
||||
},
|
||||
form: {
|
||||
uin: '0',
|
||||
format: 'json',
|
||||
cid: '205360772',
|
||||
reqtype: '2',
|
||||
biztype: '1',
|
||||
topid: songId,
|
||||
cmd: '8',
|
||||
needmusiccrit: '1',
|
||||
pagenum: page - 1,
|
||||
pagesize: limit,
|
||||
},
|
||||
})
|
||||
const { body, statusCode } = await _requestObj.promise
|
||||
if (statusCode != 200 || body.code !== 0) throw new Error('获取评论失败')
|
||||
// console.log(body, statusCode)
|
||||
const comment = body.comment
|
||||
return {
|
||||
source: 'tx',
|
||||
comments: this.filterComment(comment.commentlist),
|
||||
total: comment.commenttotal,
|
||||
page,
|
||||
limit,
|
||||
maxPage: Math.ceil(comment.commenttotal / limit) || 1,
|
||||
}
|
||||
},
|
||||
async getHotComment({ songId }, page = 1, limit = 100) {
|
||||
if (this._requestObj2) this._requestObj2.cancelHttp()
|
||||
|
||||
const _requestObj2 = httpFetch('http://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg', {
|
||||
headers: {
|
||||
'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)',
|
||||
},
|
||||
form: {
|
||||
uin: '0',
|
||||
format: 'json',
|
||||
cid: '205360772',
|
||||
reqtype: '2',
|
||||
biztype: '1',
|
||||
topid: songId,
|
||||
cmd: '9',
|
||||
needmusiccrit: '1',
|
||||
pagenum: page - 1,
|
||||
pagesize: limit,
|
||||
},
|
||||
})
|
||||
const { body, statusCode } = await _requestObj2.promise
|
||||
if (statusCode != 200 || body.code !== 0) throw new Error('获取热门评论失败')
|
||||
// console.log(body, statusCode)
|
||||
const comment = body.comment
|
||||
return {
|
||||
source: 'tx',
|
||||
comments: this.filterComment(comment.commentlist),
|
||||
total: comment.commenttotal,
|
||||
}
|
||||
},
|
||||
replaceEmoji(msg) {
|
||||
let rxp = /^\[em\](e\d+)\[\/em\]$/
|
||||
let result = msg.match(/\[em\]e\d+\[\/em\]/g)
|
||||
if (!result) return msg
|
||||
result = Array.from(new Set(result))
|
||||
for (let item of result) {
|
||||
let code = item.replace(rxp, '$1')
|
||||
msg = msg.replace(new RegExp(item.replace('[em]', '\\[em\\]').replace('[/em]', '\\[\\/em\\]'), 'g'), emojis[code] || '')
|
||||
}
|
||||
return msg
|
||||
},
|
||||
filterComment(rawList) {
|
||||
return rawList.map(item => {
|
||||
let time = item.rootcommentid ? parseInt(item.rootcommentid.substring(item.rootcommentid.lastIndexOf('_') + 1) + '000') : null
|
||||
if (item.middlecommentcontent) {
|
||||
let firstItem = item.middlecommentcontent[0]
|
||||
firstItem.avatarurl = item.avatarurl
|
||||
firstItem.praisenum = item.praisenum
|
||||
item.avatarurl = null
|
||||
item.praisenum = null
|
||||
item.middlecommentcontent.reverse()
|
||||
}
|
||||
return {
|
||||
id: item.subcommentid,
|
||||
rootId: item.rootcommentid,
|
||||
text: item.rootcommentcontent ? this.replaceEmoji(item.rootcommentcontent).replace(/\\n/g, '\n').split('\n') : [],
|
||||
time,
|
||||
timeStr: time ? dateFormat2(time) : null,
|
||||
userName: item.rootcommentnick ? item.rootcommentnick.substring(1) : '',
|
||||
avatar: item.avatarurl,
|
||||
userId: item.encrypt_rootcommentuin,
|
||||
likedCount: item.praisenum,
|
||||
reply: item.middlecommentcontent ? item.middlecommentcontent.map(c => {
|
||||
let index = c.subcommentid.lastIndexOf('_')
|
||||
return {
|
||||
id: c.subcommentid,
|
||||
text: this.replaceEmoji(c.subcommentcontent).replace(/\\n/g, '\n').split('\n'),
|
||||
time: parseInt(c.subcommentid.substring(index + 1) + '000'),
|
||||
timeStr: dateFormat2(parseInt(c.subcommentid.substring(index + 1) + '000')),
|
||||
userName: c.replynick.substring(1),
|
||||
avatar: c.avatarurl,
|
||||
userId: c.encrypt_replyuin,
|
||||
likedCount: c.praisenum,
|
||||
}
|
||||
}) : [],
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
@@ -4,12 +4,14 @@ import songList from './songList'
|
||||
import musicSearch from './musicSearch'
|
||||
import { apis } from '../api-source'
|
||||
import hotSearch from './hotSearch'
|
||||
import comment from './comment'
|
||||
|
||||
const tx = {
|
||||
leaderboard,
|
||||
songList,
|
||||
musicSearch,
|
||||
hotSearch,
|
||||
comment,
|
||||
|
||||
getMusicUrl(songInfo, type) {
|
||||
return apis('tx').getMusicUrl(songInfo, type)
|
||||
|
||||
138
src/renderer/utils/music/wy/comment.js
Normal file
138
src/renderer/utils/music/wy/comment.js
Normal file
@@ -0,0 +1,138 @@
|
||||
import { httpFetch } from '../../request'
|
||||
import { weapi } from './utils/crypto'
|
||||
import { dateFormat2 } from '../../'
|
||||
|
||||
let cursorTools = {
|
||||
cache: {},
|
||||
getCursor(id, page, limit) {
|
||||
let cacheData = this.cache[id]
|
||||
if (!cacheData) cacheData = this.cache[id] = {}
|
||||
let orderType
|
||||
let cursor
|
||||
let offset
|
||||
if (page == 1) {
|
||||
cacheData.page = 1
|
||||
cursor = cacheData.cursor = cacheData.prevCursor = Date.now()
|
||||
orderType = 1
|
||||
offset = 0
|
||||
} else if (cacheData.page) {
|
||||
cursor = cacheData.cursor
|
||||
if (page > cacheData.page) {
|
||||
orderType = 1
|
||||
offset = (page - cacheData.page - 1) * limit
|
||||
} else if (page < cacheData.page) {
|
||||
orderType = 0
|
||||
offset = (cacheData.page - page - 1) * limit
|
||||
} else {
|
||||
cursor = cacheData.cursor = cacheData.prevCursor
|
||||
offset = cacheData.offset
|
||||
orderType = cacheData.orderType
|
||||
}
|
||||
}
|
||||
return {
|
||||
orderType,
|
||||
cursor,
|
||||
offset,
|
||||
}
|
||||
},
|
||||
setCursor(id, cursor, orderType, offset, page) {
|
||||
let cacheData = this.cache[id]
|
||||
if (!cacheData) cacheData = this.cache[id] = {}
|
||||
cacheData.prevCursor = cacheData.cursor
|
||||
cacheData.cursor = cursor
|
||||
cacheData.orderType = orderType
|
||||
cacheData.offset = offset
|
||||
cacheData.page = page
|
||||
},
|
||||
}
|
||||
|
||||
export default {
|
||||
_requestObj: null,
|
||||
_requestObj2: null,
|
||||
async getComment({ songmid }, page = 1, limit = 20) {
|
||||
if (this._requestObj) this._requestObj.cancelHttp()
|
||||
|
||||
const id = 'R_SO_4_' + songmid
|
||||
|
||||
const cursorInfo = cursorTools.getCursor(songmid, page, limit)
|
||||
|
||||
const _requestObj = httpFetch('https://music.163.com/weapi/comment/resource/comments/get', {
|
||||
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',
|
||||
origin: 'https://music.163.com',
|
||||
Refere: 'http://music.163.com/',
|
||||
},
|
||||
form: weapi({
|
||||
cursor: cursorInfo.cursor,
|
||||
offset: cursorInfo.offset,
|
||||
orderType: cursorInfo.orderType,
|
||||
pageNo: page,
|
||||
pageSize: limit,
|
||||
rid: id,
|
||||
threadId: id,
|
||||
}),
|
||||
})
|
||||
const { body, statusCode } = await _requestObj.promise
|
||||
// console.log(body)
|
||||
if (statusCode != 200 || body.code !== 200) throw new Error('获取评论失败')
|
||||
cursorTools.setCursor(songmid, body.data.cursor, cursorInfo.orderType, cursorInfo.offset, page)
|
||||
return { source: 'wy', comments: this.filterComment(body.data.comments), total: body.data.totalCount, page, limit, maxPage: Math.ceil(body.data.totalCount / limit) || 1 }
|
||||
},
|
||||
async getHotComment({ songmid }, page = 1, limit = 100) {
|
||||
if (this._requestObj2) this._requestObj2.cancelHttp()
|
||||
|
||||
const id = 'R_SO_4_' + songmid
|
||||
|
||||
const _requestObj2 = httpFetch('https://music.163.com/weapi/comment/resource/comments/get', {
|
||||
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',
|
||||
origin: 'https://music.163.com',
|
||||
Refere: 'http://music.163.com/',
|
||||
},
|
||||
form: weapi({
|
||||
cursor: Date.now().toString(),
|
||||
offset: 0,
|
||||
orderType: 1,
|
||||
pageNo: page,
|
||||
pageSize: limit,
|
||||
rid: id,
|
||||
threadId: id,
|
||||
}),
|
||||
})
|
||||
const { body, statusCode } = await _requestObj2.promise
|
||||
if (statusCode != 200 || body.code !== 200) throw new Error('获取热门评论失败')
|
||||
// console.log(body)
|
||||
return { source: 'wy', comments: this.filterComment(body.data.hotComments) }
|
||||
},
|
||||
filterComment(rawList) {
|
||||
return rawList.map(item => {
|
||||
let data = {
|
||||
id: item.commentId,
|
||||
text: item.content ? item.content.split('\n') : '',
|
||||
time: item.time ? item.time : '',
|
||||
timeStr: item.time ? dateFormat2(item.time) : '',
|
||||
userName: item.user.nickname,
|
||||
avatar: item.user.avatarUrl,
|
||||
userId: item.user.userId,
|
||||
likedCount: item.likedCount,
|
||||
reply: [],
|
||||
}
|
||||
|
||||
let replyData = item.beReplied && item.beReplied[0]
|
||||
return replyData ? {
|
||||
id: item.commentId,
|
||||
rootId: replyData.beRepliedCommentId,
|
||||
text: replyData.content ? replyData.content.split('\n') : '',
|
||||
time: item.time,
|
||||
timeStr: null,
|
||||
userName: replyData.user.nickname,
|
||||
avatar: replyData.user.avatarUrl,
|
||||
userId: replyData.user.userId,
|
||||
likedCount: null,
|
||||
reply: [data],
|
||||
} : data
|
||||
})
|
||||
},
|
||||
}
|
||||
@@ -5,12 +5,14 @@ import getMusicInfo from './musicInfo'
|
||||
import musicSearch from './musicSearch'
|
||||
import songList from './songList'
|
||||
import hotSearch from './hotSearch'
|
||||
import comment from './comment'
|
||||
|
||||
const wy = {
|
||||
leaderboard,
|
||||
musicSearch,
|
||||
songList,
|
||||
hotSearch,
|
||||
comment,
|
||||
getMusicUrl(songInfo, type) {
|
||||
return apis('wy').getMusicUrl(songInfo, type)
|
||||
},
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { httpFetch } from '../../request'
|
||||
import { weapi } from './utils/crypto'
|
||||
import { sizeFormate, formatPlayTime } from '../../index'
|
||||
// import { sizeFormate, formatPlayTime } from '../../index'
|
||||
import musicDetailApi from './musicDetail'
|
||||
|
||||
let searchRequest
|
||||
export default {
|
||||
@@ -10,8 +11,12 @@ export default {
|
||||
allPage: 1,
|
||||
musicSearch(str, page) {
|
||||
if (searchRequest && searchRequest.cancelHttp) searchRequest.cancelHttp()
|
||||
searchRequest = httpFetch('http://music.163.com/weapi/cloudsearch/get/web?csrf_token=', {
|
||||
searchRequest = httpFetch('https://music.163.com/weapi/search/get', {
|
||||
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',
|
||||
origin: 'https://music.163.com',
|
||||
},
|
||||
form: weapi({
|
||||
s: str,
|
||||
type: 1, // 1: 单曲, 10: 专辑, 100: 歌手, 1000: 歌单, 1002: 用户, 1004: MV, 1006: 歌词, 1009: 电台, 1014: 视频
|
||||
@@ -19,7 +24,24 @@ export default {
|
||||
offset: this.limit * (page - 1),
|
||||
}),
|
||||
})
|
||||
return searchRequest.promise.then(({ body }) => body)
|
||||
return searchRequest.promise.then(({ body }) =>
|
||||
body && body.code === 200
|
||||
? musicDetailApi.getList(body.result.songs.map(s => s.id)).then(({ list }) => {
|
||||
this.total = body.result.songCount || 0
|
||||
this.page = page
|
||||
this.allPage = Math.ceil(this.total / this.limit)
|
||||
return {
|
||||
code: 200,
|
||||
data: {
|
||||
list,
|
||||
allPage: this.allPage,
|
||||
limit: this.limit,
|
||||
total: this.total,
|
||||
source: 'wy',
|
||||
},
|
||||
}
|
||||
})
|
||||
: body)
|
||||
},
|
||||
getSinger(singers) {
|
||||
let arr = []
|
||||
@@ -28,7 +50,7 @@ export default {
|
||||
})
|
||||
return arr.join('、')
|
||||
},
|
||||
handleResult(rawList) {
|
||||
/* handleResult(rawList) {
|
||||
// console.log(rawList)
|
||||
if (!rawList) return []
|
||||
return rawList.map(item => {
|
||||
@@ -78,28 +100,29 @@ export default {
|
||||
typeUrl: {},
|
||||
}
|
||||
})
|
||||
},
|
||||
}, */
|
||||
search(str, page = 1, { limit } = {}, retryNum = 0) {
|
||||
if (++retryNum > 3) return Promise.reject(new Error('try max num'))
|
||||
if (limit != null) this.limit = limit
|
||||
return this.musicSearch(str, page).then(result => {
|
||||
// console.log(result)
|
||||
if (!result || result.code !== 200) return this.search(str, page, { limit }, retryNum)
|
||||
// console.log(result.result)
|
||||
let list = this.handleResult(result.result.songs)
|
||||
// let list = this.handleResult(result.result.songs || [])
|
||||
|
||||
if (list == null) return this.search(str, page, { limit }, retryNum)
|
||||
// if (list == null) return this.search(str, page, { limit }, retryNum)
|
||||
|
||||
this.total = result.result.songCount
|
||||
this.page = page
|
||||
this.allPage = Math.ceil(this.total / this.limit)
|
||||
// this.total = result.result.songCount || 0
|
||||
// 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',
|
||||
})
|
||||
// return Promise.resolve({
|
||||
// list,
|
||||
// allPage: this.allPage,
|
||||
// limit: this.limit,
|
||||
// total: this.total,
|
||||
// source: 'wy',
|
||||
// })
|
||||
return result.data
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
47
src/renderer/utils/music/xm/comment.js
Normal file
47
src/renderer/utils/music/xm/comment.js
Normal file
@@ -0,0 +1,47 @@
|
||||
import { xmRequest } from './util'
|
||||
import { dateFormat2 } from '../../'
|
||||
|
||||
export default {
|
||||
_requestObj: null,
|
||||
_requestObj2: null,
|
||||
async getComment({ songmid }, page = 1, limit = 20) {
|
||||
if (this._requestObj) this._requestObj.cancelHttp()
|
||||
|
||||
const _requestObj = xmRequest('/api/comment/getCommentList', { objectId: songmid, objectType: 'song', pagingVO: { page, pageSize: limit } })
|
||||
const { body, statusCode } = await _requestObj.promise
|
||||
// console.log(body)
|
||||
if (statusCode != 200 || body.code !== 'SUCCESS') throw new Error('获取评论失败')
|
||||
return { source: 'xm', comments: this.filterComment(body.result.data.commentList), total: body.result.data.pagingVO.count, page, limit, maxPage: Math.ceil(body.result.data.pagingVO.count / limit) || 1 }
|
||||
},
|
||||
async getHotComment({ songmid }, page = 1, limit = 100) {
|
||||
if (this._requestObj2) this._requestObj2.cancelHttp()
|
||||
if (!songmid) throw new Error('获取失败')
|
||||
const _requestObj2 = xmRequest('/api/comment/getHotCommentList', { objectId: songmid, objectType: 'song', pagingVO: { page, pageSize: limit } })
|
||||
const { body, statusCode } = await _requestObj2.promise
|
||||
// console.log(body)
|
||||
if (statusCode != 200 || body.code !== 'SUCCESS') throw new Error('获取热门评论失败')
|
||||
return { source: 'xm', comments: this.filterComment(body.result.data.hotList) }
|
||||
},
|
||||
filterComment(rawList) {
|
||||
return rawList.map(item => ({
|
||||
id: item.commentId,
|
||||
text: item.message.split('\n').filter(t => !!t),
|
||||
time: item.gmtCreate,
|
||||
timeStr: dateFormat2(item.gmtCreate),
|
||||
userName: item.nickName,
|
||||
avatar: item.avatar,
|
||||
userId: item.userId,
|
||||
likedCount: item.likes,
|
||||
reply: item.replyData ? item.replyData.map(c => ({
|
||||
id: c.commentId,
|
||||
text: c.message.split('\n').filter(t => !!t),
|
||||
time: c.gmtCreate,
|
||||
timeStr: dateFormat2(c.gmtCreate),
|
||||
userName: c.nickName,
|
||||
avatar: c.avatar,
|
||||
userId: c.userId,
|
||||
likedCount: c.likes,
|
||||
})) : [],
|
||||
}))
|
||||
},
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import musicSearch from './musicSearch'
|
||||
// import pic from './pic'
|
||||
import lyric from './lyric'
|
||||
import hotSearch from './hotSearch'
|
||||
import comment from './comment'
|
||||
import musicInfo from './musicInfo'
|
||||
import { closeVerifyModal } from './util'
|
||||
|
||||
const xm = {
|
||||
@@ -13,6 +15,7 @@ const xm = {
|
||||
leaderboard,
|
||||
hotSearch,
|
||||
closeVerifyModal,
|
||||
comment,
|
||||
getMusicUrl(songInfo, type) {
|
||||
return apis('xm').getMusicUrl(songInfo, type)
|
||||
},
|
||||
@@ -24,7 +27,12 @@ const xm = {
|
||||
// return pic.getPic(songInfo)
|
||||
},
|
||||
getMusicDetailPageUrl(songInfo) {
|
||||
return songInfo.songStringId ? `https://www.xiami.com/song/${songInfo.songStringId}` : null
|
||||
if (songInfo.songStringId) return `https://www.xiami.com/song/${songInfo.songStringId}`
|
||||
|
||||
musicInfo.getMusicInfo(songInfo).then(({ data }) => {
|
||||
songInfo.songStringId = data.songStringId
|
||||
})
|
||||
return `https://www.xiami.com/song/${songInfo.songmid}`
|
||||
},
|
||||
// init() {
|
||||
// getToken()
|
||||
|
||||
14
src/renderer/utils/music/xm/musicInfo.js
Normal file
14
src/renderer/utils/music/xm/musicInfo.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { xmRequest } from './util'
|
||||
|
||||
export default {
|
||||
_requestObj: null,
|
||||
async getMusicInfo({ songmid }, page = 1, limit = 20) {
|
||||
if (this._requestObj) this._requestObj.cancelHttp()
|
||||
|
||||
const _requestObj = xmRequest('/api/song/initialize', { songId: songmid })
|
||||
const { body, statusCode } = await _requestObj.promise
|
||||
// console.log(body)
|
||||
if (statusCode != 200 || body.code !== 'SUCCESS') throw new Error('获取歌曲信息失败')
|
||||
return { source: 'xm', data: body.result.data.songDetail }
|
||||
},
|
||||
}
|
||||
@@ -382,7 +382,8 @@ export default {
|
||||
return this.searchSourceId == 'all'
|
||||
? list.filter(s => this.assertApiSupport(s.source))
|
||||
: this.assertApiSupport(this.searchSourceId)
|
||||
? [...list] : []
|
||||
? [...list]
|
||||
: []
|
||||
},
|
||||
handleListAddModalClose() {
|
||||
this.isShowListAdd = false
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
<template lang="pug">
|
||||
div.scroll(:class="$style.setting")
|
||||
dl
|
||||
dt {{$t('view.setting.basic')}}
|
||||
//- div(:class="$style.main")
|
||||
div.scroll(:class="$style.toc")
|
||||
ul(:class="$style.tocList")
|
||||
li(:class="$style.tocListItem" v-for="h2 in toc" :key="h2.id")
|
||||
h2(:class="$style.tocH2" :tips="h2.title")
|
||||
a(:href="'#' + h2.id") {{h2.title}}
|
||||
ul(:class="$style.tocList" v-if="h2.children.length")
|
||||
li(:class="$style.tocSubListItem" v-for="h3 in h2.children" :key="h3.id")
|
||||
h3(:class="$style.tocH3" :tips="h3.title")
|
||||
a(:href="'#' + h3.id") {{h3.title}}
|
||||
div.scroll(:class="$style.setting" ref="dom_setting")
|
||||
dl(ref="dom_setting_list")
|
||||
dt#basic {{$t('view.setting.basic')}}
|
||||
dd
|
||||
h3 {{$t('view.setting.basic_theme')}}
|
||||
h3#basic_theme {{$t('view.setting.basic_theme')}}
|
||||
div
|
||||
ul(:class="$style.theme")
|
||||
li(v-for="theme in themes.list" :key="theme.id" :tips="$t('store.state.theme_' + theme.class)" @click="current_setting.themeId = theme.id" :class="[theme.class, themes.active == theme.id ? $style.active : '']")
|
||||
@@ -11,79 +21,79 @@ div.scroll(:class="$style.setting")
|
||||
label {{$t('store.state.theme_' + theme.class)}}
|
||||
|
||||
dd
|
||||
h3 {{$t('view.setting.basic_show_animation')}}
|
||||
h3#basic_show_animation {{$t('view.setting.basic_show_animation')}}
|
||||
div
|
||||
material-checkbox(id="setting_show_animate" v-model="current_setting.isShowAnimation" :label="$t('view.setting.is_show')")
|
||||
|
||||
dd(:tips="$t('view.setting.basic_animation_title')")
|
||||
h3 {{$t('view.setting.basic_animation')}}
|
||||
h3#basic_animation {{$t('view.setting.basic_animation')}}
|
||||
div
|
||||
material-checkbox(id="setting_animate" v-model="current_setting.randomAnimate" :label="$t('view.setting.is_enable')")
|
||||
|
||||
dd(:tips="$t('view.setting.basic_source_title')")
|
||||
h3 {{$t('view.setting.basic_source')}}
|
||||
h3#basic_source {{$t('view.setting.basic_source')}}
|
||||
div
|
||||
div(v-for="item in apiSources" :key="item.id" :class="$style.gapTop")
|
||||
material-checkbox(:id="`setting_api_source_${item.id}`" name="setting_api_source" @change="handleAPISourceChange(item.id)"
|
||||
need v-model="current_setting.apiSource" :disabled="item.disabled" :value="item.id" :label="item.label")
|
||||
|
||||
dd(:tips="$t('view.setting.basic_to_tray_title')")
|
||||
h3 {{$t('view.setting.basic_to_tray')}}
|
||||
h3#basic_to_tray {{$t('view.setting.basic_to_tray')}}
|
||||
div
|
||||
material-checkbox(id="setting_to_tray" v-model="current_setting.tray.isShow" @change="handleTrayShowChange" :label="$t('view.setting.is_enable')")
|
||||
|
||||
dd(:tips="$t('view.setting.basic_window_size_title')")
|
||||
h3 {{$t('view.setting.basic_window_size')}}
|
||||
h3#basic_window_size {{$t('view.setting.basic_window_size')}}
|
||||
div
|
||||
material-checkbox(v-for="(item, index) in windowSizeList" :id="`setting_window_size_${item.id}`" name="setting_window_size" @change="handleWindowSizeChange" :class="$style.gapLeft"
|
||||
need v-model="current_setting.windowSizeId" :value="item.id" :label="$t('view.setting.basic_window_size_' + item.name)" :key="item.id")
|
||||
|
||||
dd(:tips="$t('view.setting.basic_lang_title')")
|
||||
h3 {{$t('view.setting.basic_lang')}}
|
||||
h3#basic_lang {{$t('view.setting.basic_lang')}}
|
||||
div
|
||||
material-checkbox(v-for="item in languageList" :key="item.locale" :id="`setting_lang_${item.locale}`" name="setting_lang"
|
||||
@change="handleLangChange(item.locale)" :class="$style.gapLeft"
|
||||
need v-model="current_setting.langId" :value="item.locale" :label="item.name")
|
||||
|
||||
dd(:tips="$t('view.setting.basic_sourcename_title')")
|
||||
h3 {{$t('view.setting.basic_sourcename')}}
|
||||
h3#basic_sourcename {{$t('view.setting.basic_sourcename')}}
|
||||
div
|
||||
material-checkbox(v-for="item in sourceNameTypes" :key="item.id" :class="$style.gapLeft" :id="`setting_abasic_sourcename_${item.id}`"
|
||||
name="setting_basic_sourcename" need v-model="current_setting.sourceNameType" :value="item.id" :label="item.label")
|
||||
|
||||
dd
|
||||
h3 {{$t('view.setting.basic_control_btn_position')}}
|
||||
h3#basic_control_btn_position {{$t('view.setting.basic_control_btn_position')}}
|
||||
div
|
||||
material-checkbox(v-for="item in controlBtnPositionList" :key="item.id" :class="$style.gapLeft" :id="`setting_basic_control_btn_position_${item.id}`"
|
||||
name="setting_basic_control_btn_position" need v-model="current_setting.controlBtnPosition" :value="item.id" :label="item.name")
|
||||
|
||||
dt {{$t('view.setting.play')}}
|
||||
dt#play {{$t('view.setting.play')}}
|
||||
dd(:tips="$t('view.setting.play_toggle_title')")
|
||||
h3 {{$t('view.setting.play_toggle')}}
|
||||
h3#play_toggle {{$t('view.setting.play_toggle')}}
|
||||
div
|
||||
material-checkbox(:id="`setting_player_togglePlay_${item.value}`" :class="$style.gapLeft" :value="item.value" :key="item.value"
|
||||
v-model="current_setting.player.togglePlayMethod" v-for="item in togglePlayMethods" :label="item.name")
|
||||
dd
|
||||
h3 {{$t('view.setting.play_lyric_transition')}}
|
||||
h3#play_lyric_transition {{$t('view.setting.play_lyric_transition')}}
|
||||
div
|
||||
material-checkbox(id="setting_player_lyric_transition" v-model="current_setting.player.isShowLyricTransition" :label="$t('view.setting.is_show')")
|
||||
dd(:tips="$t('view.setting.play_quality_title')")
|
||||
h3 {{$t('view.setting.play_quality')}}
|
||||
h3#play_quality {{$t('view.setting.play_quality')}}
|
||||
div
|
||||
material-checkbox(id="setting_player_highQuality" v-model="current_setting.player.highQuality" :label="$t('view.setting.is_enable')")
|
||||
dd(:tips="$t('view.setting.play_task_bar_title')")
|
||||
h3 {{$t('view.setting.play_task_bar')}}
|
||||
h3#play_task_bar {{$t('view.setting.play_task_bar')}}
|
||||
div
|
||||
material-checkbox(id="setting_player_showTaskProgess" v-model="current_setting.player.isShowTaskProgess" :label="$t('view.setting.is_enable')")
|
||||
dd(:tips="$t('view.setting.play_mediaDevice_remove_stop_play_title')")
|
||||
h3 {{$t('view.setting.play_mediaDevice_remove_stop_play')}}
|
||||
h3#play_mediaDevice_remove_stop_play {{$t('view.setting.play_mediaDevice_remove_stop_play')}}
|
||||
div
|
||||
material-checkbox(id="setting_player_isMediaDeviceRemovedStopPlay" v-model="current_setting.player.isMediaDeviceRemovedStopPlay" :label="$t('view.setting.is_enable')")
|
||||
dd(:tips="$t('view.setting.play_mediaDevice_title')")
|
||||
h3 {{$t('view.setting.play_mediaDevice')}}
|
||||
h3#play_mediaDevice {{$t('view.setting.play_mediaDevice')}}
|
||||
div
|
||||
material-selection(:list="mediaDevices" :class="$style.gapLeft" v-model="current_setting.player.mediaDeviceId" item-key="deviceId" item-name="label")
|
||||
dt {{$t('view.setting.desktop_lyric')}}
|
||||
dt#desktop_lyric {{$t('view.setting.desktop_lyric')}}
|
||||
dd
|
||||
div(:class="$style.gapTop")
|
||||
material-checkbox(id="setting_desktop_lyric_enable" v-model="current_setting.desktopLyric.enable" :label="$t('view.setting.desktop_lyric_enable')")
|
||||
@@ -93,38 +103,38 @@ div.scroll(:class="$style.setting")
|
||||
material-checkbox(id="setting_desktop_lyric_alwaysOnTop" v-model="current_setting.desktopLyric.isAlwaysOnTop" :label="$t('view.setting.desktop_lyric_always_on_top')")
|
||||
div(:class="$style.gapTop")
|
||||
material-checkbox(id="setting_desktop_lyric_lockScreen" v-model="current_setting.desktopLyric.isLockScreen" :label="$t('view.setting.desktop_lyric_lock_screen')")
|
||||
dt {{$t('view.setting.search')}}
|
||||
dt#search {{$t('view.setting.search')}}
|
||||
dd(:tips="$t('view.setting.search_hot_title')")
|
||||
h3 {{$t('view.setting.search_hot')}}
|
||||
h3#search_hot {{$t('view.setting.search_hot')}}
|
||||
div
|
||||
material-checkbox(id="setting_search_showHot_enable" v-model="current_setting.search.isShowHotSearch" :label="$t('view.setting.is_show')")
|
||||
dd(:tips="$t('view.setting.search_history_title')")
|
||||
h3 {{$t('view.setting.search_history')}}
|
||||
h3#search_history {{$t('view.setting.search_history')}}
|
||||
div
|
||||
material-checkbox(id="setting_search_showHistory_enable" v-model="current_setting.search.isShowHistorySearch" :label="$t('view.setting.is_show')")
|
||||
dd(:tips="$t('view.setting.search_focus_search_box_title')")
|
||||
h3 {{$t('view.setting.search_focus_search_box')}}
|
||||
h3#search_focus_search_box {{$t('view.setting.search_focus_search_box')}}
|
||||
div
|
||||
material-checkbox(id="setting_search_focusSearchBox_enable" v-model="current_setting.search.isFocusSearchBox" :label="$t('view.setting.is_enable')")
|
||||
|
||||
dt {{$t('view.setting.list')}}
|
||||
dt#list {{$t('view.setting.list')}}
|
||||
dd(:tips="$t('view.setting.list_source_title')")
|
||||
h3 {{$t('view.setting.list_source')}}
|
||||
h3#list_source {{$t('view.setting.list_source')}}
|
||||
div
|
||||
material-checkbox(id="setting_list_showSource_enable" v-model="current_setting.list.isShowSource" :label="$t('view.setting.is_show')")
|
||||
dd(:tips="$t('view.setting.list_scroll_title')")
|
||||
h3 {{$t('view.setting.list_scroll')}}
|
||||
h3#list_scroll {{$t('view.setting.list_scroll')}}
|
||||
div
|
||||
material-checkbox(id="setting_list_scroll_enable" v-model="current_setting.list.isSaveScrollLocation" :label="$t('view.setting.is_enable')")
|
||||
//- dd(:tips="播放列表是否显示专辑栏")
|
||||
h3 专辑栏
|
||||
div
|
||||
material-checkbox(id="setting_list_showalbum" v-model="current_setting.list.isShowAlbumName" label="是否显示专辑栏")
|
||||
dt {{$t('view.setting.download')}}
|
||||
dt#download {{$t('view.setting.download')}}
|
||||
dd
|
||||
material-checkbox(id="setting_download_enable" v-model="current_setting.download.enable" :label="$t('view.setting.download_enable')")
|
||||
dd(:tips="$t('view.setting.download_path_title')")
|
||||
h3 {{$t('view.setting.download_path')}}
|
||||
h3#download_path {{$t('view.setting.download_path')}}
|
||||
div
|
||||
p
|
||||
| {{$t('view.setting.download_path_label')}}
|
||||
@@ -132,24 +142,24 @@ div.scroll(:class="$style.setting")
|
||||
p
|
||||
material-btn(:class="$style.btn" min @click="handleChangeSavePath") {{$t('view.setting.download_path_change_btn')}}
|
||||
dd(:tips="$t('view.setting.download_name_title')")
|
||||
h3 {{$t('view.setting.download_name')}}
|
||||
h3#download_name {{$t('view.setting.download_name')}}
|
||||
div
|
||||
material-checkbox(:id="`setting_download_musicName_${item.value}`" :class="$style.gapLeft" name="setting_download_musicName" :value="item.value" :key="item.value" need
|
||||
v-model="current_setting.download.fileName" v-for="item in musicNames" :label="item.name")
|
||||
dd
|
||||
h3 {{$t('view.setting.download_data_embed')}}
|
||||
h3#download_data_embed {{$t('view.setting.download_data_embed')}}
|
||||
div(:class="$style.gapTop")
|
||||
material-checkbox(id="setting_download_isEmbedPic" v-model="current_setting.download.isEmbedPic" :label="$t('view.setting.download_embed_pic')")
|
||||
div(:class="$style.gapTop")
|
||||
material-checkbox(id="setting_download_isEmbedLyric" v-model="current_setting.download.isEmbedLyric" :label="$t('view.setting.download_embed_lyric')")
|
||||
dd(:tips="$t('view.setting.download_lyric_title')")
|
||||
h3 {{$t('view.setting.download_lyric')}}
|
||||
h3#download_lyric {{$t('view.setting.download_lyric')}}
|
||||
div
|
||||
material-checkbox(id="setting_download_isDownloadLrc" v-model="current_setting.download.isDownloadLrc" :label="$t('view.setting.is_enable')")
|
||||
|
||||
dt {{$t('view.setting.hot_key')}}
|
||||
dt#hot_key {{$t('view.setting.hot_key')}}
|
||||
dd
|
||||
h3 {{$t('view.setting.hot_key_local_title')}}
|
||||
h3#hot_key_local_title {{$t('view.setting.hot_key_local_title')}}
|
||||
div
|
||||
material-checkbox(id="setting_download_hotKeyLocal" v-model="current_hot_key.local.enable" :label="$t('view.setting.is_enable')" @change="handleHotKeySaveConfig")
|
||||
div(:class="$style.hotKeyContainer" :style="{ opacity: current_hot_key.local.enable ? 1 : .6 }")
|
||||
@@ -160,7 +170,7 @@ div.scroll(:class="$style.setting")
|
||||
@focus="handleHotKeyFocus($event, item, 'local')"
|
||||
@blur="handleHotKeyBlur($event, item, 'local')")
|
||||
|
||||
h3 {{$t('view.setting.hot_key_global_title')}}
|
||||
h3#hot_key_global_title {{$t('view.setting.hot_key_global_title')}}
|
||||
div
|
||||
material-checkbox(id="setting_download_hotKeyGlobal" v-model="current_hot_key.global.enable" :label="$t('view.setting.is_enable')" @change="handleEnableHotKey")
|
||||
div(:class="$style.hotKeyContainer" :style="{ opacity: current_hot_key.global.enable ? 1 : .6 }")
|
||||
@@ -171,9 +181,9 @@ div.scroll(:class="$style.setting")
|
||||
@focus="handleHotKeyFocus($event, item, 'global')"
|
||||
@blur="handleHotKeyBlur($event, item, 'global')")
|
||||
|
||||
dt {{$t('view.setting.network')}}
|
||||
dt#network {{$t('view.setting.network')}}
|
||||
dd
|
||||
h3 {{$t('view.setting.network_proxy_title')}}
|
||||
h3#network_proxy_title {{$t('view.setting.network_proxy_title')}}
|
||||
div
|
||||
p
|
||||
material-checkbox(id="setting_network_proxy_enable" v-model="current_setting.network.proxy.enable" @change="handleProxyChange('enable')" :label="$t('view.setting.is_enable')")
|
||||
@@ -183,43 +193,43 @@ div.scroll(:class="$style.setting")
|
||||
p
|
||||
material-input(:class="$style.gapLeft" v-model="current_setting.network.proxy.username" @change="handleProxyChange('username')" :placeholder="$t('view.setting.network_proxy_username')")
|
||||
material-input(:class="$style.gapLeft" v-model="current_setting.network.proxy.password" @change="handleProxyChange('password')" type="password" :placeholder="$t('view.setting.network_proxy_password')")
|
||||
dt {{$t('view.setting.odc')}}
|
||||
dt#odc {{$t('view.setting.odc')}}
|
||||
dd
|
||||
h3 {{$t('view.setting.odc_clear_search_input')}}
|
||||
h3#odc_clear_search_input {{$t('view.setting.odc_clear_search_input')}}
|
||||
div
|
||||
material-checkbox(id="setting_odc_isAutoClearSearchInput" v-model="current_setting.odc.isAutoClearSearchInput" :label="$t('view.setting.is_enable')")
|
||||
dd
|
||||
h3 {{$t('view.setting.odc_clear_search_list')}}
|
||||
h3#odc_clear_search_list {{$t('view.setting.odc_clear_search_list')}}
|
||||
div
|
||||
material-checkbox(id="setting_odc_isAutoClearSearchList" v-model="current_setting.odc.isAutoClearSearchList" :label="$t('view.setting.is_enable')")
|
||||
dt {{$t('view.setting.backup')}}
|
||||
dt#backup {{$t('view.setting.backup')}}
|
||||
dd
|
||||
h3 {{$t('view.setting.backup_part')}}
|
||||
h3#backup_part {{$t('view.setting.backup_part')}}
|
||||
div
|
||||
material-btn(:class="[$style.btn, $style.gapLeft]" min @click="handleImportPlayList") {{$t('view.setting.backup_part_import_list')}}
|
||||
material-btn(:class="[$style.btn, $style.gapLeft]" min @click="handleExportPlayList") {{$t('view.setting.backup_part_export_list')}}
|
||||
material-btn(:class="[$style.btn, $style.gapLeft]" min @click="handleImportSetting") {{$t('view.setting.backup_part_import_setting')}}
|
||||
material-btn(:class="[$style.btn, $style.gapLeft]" min @click="handleExportSetting") {{$t('view.setting.backup_part_export_setting')}}
|
||||
dd
|
||||
h3 {{$t('view.setting.backup_all')}}
|
||||
h3#backup_all {{$t('view.setting.backup_all')}}
|
||||
div
|
||||
material-btn(:class="[$style.btn, $style.gapLeft]" min @click="handleImportAllData") {{$t('view.setting.backup_all_import')}}
|
||||
material-btn(:class="[$style.btn, $style.gapLeft]" min @click="handleExportAllData") {{$t('view.setting.backup_all_export')}}
|
||||
dt {{$t('view.setting.other')}}
|
||||
dt#other {{$t('view.setting.other')}}
|
||||
dd
|
||||
h3 {{$t('view.setting.other_tray_theme')}}
|
||||
h3#other_tray_theme {{$t('view.setting.other_tray_theme')}}
|
||||
div
|
||||
material-checkbox(:id="'setting_tray_theme_' + item.id" v-model="current_setting.tray.themeId" name="setting_tray_theme" need :class="$style.gapLeft"
|
||||
:label="$t('view.setting.other_tray_theme_' + item.name)" :key="item.id" :value="item.id" v-for="item in trayThemeList")
|
||||
dd
|
||||
h3 {{$t('view.setting.other_cache')}}
|
||||
h3#other_cache {{$t('view.setting.other_cache')}}
|
||||
div
|
||||
p
|
||||
| {{$t('view.setting.other_cache_label')}}
|
||||
span.auto-hidden(:tips="$t('view.setting.other_cache_label_title')") {{cacheSize}}
|
||||
p
|
||||
material-btn(:class="$style.btn" min @click="clearCache") {{$t('view.setting.other_cache_clear_btn')}}
|
||||
dt {{$t('view.setting.update')}}
|
||||
dt#update {{$t('view.setting.update')}}
|
||||
dd
|
||||
p.small
|
||||
| {{$t('view.setting.update_latest_label')}}{{version.newVersion ? version.newVersion.version : $t('view.setting.update_unknown')}}
|
||||
@@ -232,7 +242,7 @@ div.scroll(:class="$style.setting")
|
||||
span(v-if="version.isLatestVer") {{$t('view.setting.update_latest')}}
|
||||
material-btn(v-else :class="[$style.btn, $style.gapLeft]" min @click="showUpdateModal") {{$t('view.setting.update_open_version_modal_btn')}}
|
||||
p.small(v-else) {{$t('view.setting.update_checking')}}
|
||||
dt {{$t('view.setting.about')}}
|
||||
dt#about {{$t('view.setting.about')}}
|
||||
dd
|
||||
p.small
|
||||
| 本软件完全免费,代码已开源,开源地址:
|
||||
@@ -582,6 +592,7 @@ export default {
|
||||
|
||||
},
|
||||
isEditHotKey: false,
|
||||
toc: [],
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -641,12 +652,43 @@ export default {
|
||||
init() {
|
||||
this.current_setting = JSON.parse(JSON.stringify(this.setting))
|
||||
if (!window.currentWindowSizeId) window.currentWindowSizeId = this.setting.windowSizeId
|
||||
// this.initTOC()
|
||||
this.getCacheSize()
|
||||
this.getMediaDevice()
|
||||
this.current_hot_key = window.appHotKeyConfig
|
||||
this.initHotKeyConfig()
|
||||
this.getHotKeyStatus()
|
||||
},
|
||||
// initTOC() {
|
||||
// const list = this.$refs.dom_setting_list.children
|
||||
// const toc = []
|
||||
// let prevTitle
|
||||
// for (const item of list) {
|
||||
// if (item.tagName == 'DT') {
|
||||
// prevTitle = {
|
||||
// title: item.innerText.replace(/[((].+?[))]/, ''),
|
||||
// id: item.getAttribute('id'),
|
||||
// dom: item,
|
||||
// children: [],
|
||||
// }
|
||||
// toc.push(prevTitle)
|
||||
// continue
|
||||
// }
|
||||
// const h3 = item.querySelector('h3')
|
||||
// if (h3) {
|
||||
// prevTitle.children.push({
|
||||
// title: h3.innerText.replace(/[((].+?[))]/, ''),
|
||||
// id: h3.getAttribute('id'),
|
||||
// dom: h3,
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// console.log(toc)
|
||||
// this.toc = toc
|
||||
// },
|
||||
// handleListScroll(event) {
|
||||
// // console.log(event.target.scrollTop)
|
||||
// },
|
||||
handleChangeSavePath() {
|
||||
selectDir({
|
||||
title: this.$t('view.setting.download_select_save_path'),
|
||||
@@ -851,6 +893,7 @@ export default {
|
||||
},
|
||||
handleLangChange(id) {
|
||||
this.$i18n.locale = id
|
||||
// this.$nextTick(() => this.initTOC())
|
||||
},
|
||||
async getMediaDevice() {
|
||||
const devices = await navigator.mediaDevices.enumerateDevices()
|
||||
@@ -1047,12 +1090,56 @@ export default {
|
||||
<style lang="less" module>
|
||||
@import '../assets/styles/layout.less';
|
||||
|
||||
// .main {
|
||||
// display: flex;
|
||||
// flex-flow: row nowrap;
|
||||
// height: 100%;
|
||||
// border-top: 1px solid rgba(0, 0, 0, 0.12);
|
||||
// }
|
||||
|
||||
// .toc {
|
||||
// flex: 0 0 15%;
|
||||
// overflow-y: scroll;
|
||||
// padding: 10px;
|
||||
// a {
|
||||
// text-decoration: none;
|
||||
// display: block;
|
||||
// line-height: 1.5;
|
||||
// .mixin-ellipsis-1;
|
||||
// }
|
||||
// }
|
||||
// .tocH2 {
|
||||
// font-size: 14px;
|
||||
// a {
|
||||
// color: @color-theme;
|
||||
// }
|
||||
// }
|
||||
// .tocH3 {
|
||||
// font-size: 13px;
|
||||
// opacity: .8;
|
||||
// }
|
||||
|
||||
// .tocList {
|
||||
// .tocList {
|
||||
// padding-left: 15px;
|
||||
// }
|
||||
// }
|
||||
// .tocListItem {
|
||||
// +.tocListItem {
|
||||
// padding-top: 10px;
|
||||
// }
|
||||
// }
|
||||
// .tocSubListItem {
|
||||
// padding-top: 10px;
|
||||
// }
|
||||
|
||||
.setting {
|
||||
padding: 0 15px 30px 15px;
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
|
||||
dt {
|
||||
border-left: 5px solid @color-theme;
|
||||
@@ -1243,8 +1330,22 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
// :global(dt):target, :global(h3):target {
|
||||
// animation: highlight 1s ease;
|
||||
// }
|
||||
|
||||
// @keyframes highlight {
|
||||
// from { background: yellow; }
|
||||
// to { background: transparent; }
|
||||
// }
|
||||
|
||||
each(@themes, {
|
||||
:global(#container.@{value}) {
|
||||
// .tocH2 {
|
||||
// a {
|
||||
// color: ~'@{color-@{value}-theme}';
|
||||
// }
|
||||
// }
|
||||
.tbody {
|
||||
tr {
|
||||
&.active {
|
||||
|
||||
Reference in New Issue
Block a user