Compare commits

...

60 Commits

Author SHA1 Message Date
lyswhut
70b718d372 发布0.6.2版本 2019-10-01 16:36:44 +08:00
lyswhut
2b5d6f3592 移除static全局路径 2019-10-01 13:04:02 +08:00
lyswhut
8e48d5ba68 解除酷狗封面、歌词对接口服务器的依赖 2019-10-01 12:06:18 +08:00
lyswhut
3cec62d1a9 Merge branch 'openKg' into dev 2019-10-01 10:40:19 +08:00
lyswhut
b1650bcbee Merge branch 'master' into dev 2019-09-30 20:21:57 +08:00
lyswhut
492e3d8965 恢复酷狗其他音质播放 2019-09-30 20:20:28 +08:00
lyswhut
5b612bfa0f 修复百度源搜索结果为空时的接口处理Bug 2019-09-30 13:14:55 +08:00
lyswhut
1f77b3dd4b 新增QQ音乐源歌单 2019-09-30 13:04:35 +08:00
lyswhut
b0d7a53d15 Update issue templates 2019-09-29 17:09:36 +08:00
lyswhut
c029eccdd3 修复当试听列表为空时,无法切到其他界面的Bug 2019-09-29 15:48:47 +08:00
lyswhut
7236f8929c 修正火影皮肤名字 2019-09-28 17:17:35 +08:00
lyswhut
aa114f86e3 发布0.6.1版本 2019-09-28 10:45:26 +08:00
lyswhut
95db349973 移除酷我音源 ape 音质 2019-09-27 11:51:20 +08:00
lyswhut
2acef590b4 更新常见问题内容 2019-09-27 10:55:56 +08:00
lyswhut
29855b2b6e 修复请求超时的逻辑处理Bug 2019-09-27 10:53:24 +08:00
lyswhut
ea10dd68a3 更新常见问题 2019-09-26 13:34:07 +08:00
lyswhut
e1942c66ac 更新依赖到最新 2019-09-26 00:07:13 +08:00
lyswhut
6bd18e8078 优化更新弹窗 2019-09-26 00:06:02 +08:00
lyswhut
f3dd306f54 优化播放组件渲染性能 2019-09-25 13:05:30 +08:00
lyswhut
3cf39ea48b 优化列表展开动画 2019-09-25 09:02:12 +08:00
lyswhut
d57f212c62 分离背景位置控制 2019-09-25 00:57:12 +08:00
lyswhut
b273c52124 移除192k音质 2019-09-24 13:34:14 +08:00
lyswhut
ce0a9afc33 调整皮肤tablist颜色 2019-09-24 13:27:05 +08:00
lyswhut
8437fe1716 新增 《海贼王》皮肤 2019-09-23 22:12:14 +08:00
lyswhut
f63f645696 新增DNS缓存功能 2019-09-23 13:24:32 +08:00
lyswhut
f7267806df 新增列表滚动条位置恢复 2019-09-22 11:33:37 +08:00
lyswhut
bebf1906a2 修正fetch单词的拼写错误 2019-09-22 10:08:37 +08:00
lyswhut
58e61e0bda 发布0.6.0版本 2019-09-21 21:09:15 +08:00
lyswhut
42aa62cff0 调整失败更新提示 2019-09-21 21:07:36 +08:00
lyswhut
bcf7b3fccb 修改更新失败提示 2019-09-21 21:04:45 +08:00
lyswhut
ff09378c6d 去重id 2019-09-21 20:53:03 +08:00
lyswhut
99b0595e50 新增搜索页面接口限制 2019-09-21 20:34:40 +08:00
lyswhut
5321469c1d 完成聚合搜索功能 2019-09-21 20:05:56 +08:00
lyswhut
ef9eb83a75 完善聚合搜索逻辑 2019-09-21 13:41:19 +08:00
lyswhut
c12bbc7f0f 重构搜索页面逻辑 2019-09-20 22:09:18 +08:00
lyswhut
a16c4c3657 更新依赖到最新 2019-09-19 22:30:15 +08:00
lyswhut
c8240448c6 内置百度源歌曲图片、歌词获取 2019-09-17 21:36:46 +08:00
lyswhut
d19569131c 将网络代理密码框设置为password类型 2019-09-16 21:50:41 +08:00
lyswhut
37eec4c971 更换接口地址 2019-09-16 14:08:29 +08:00
lyswhut
65fe679ee2 修复切换歌单列表详情时的UI Bug 2019-09-16 13:31:06 +08:00
lyswhut
a16b825c3b 修复代理bug 2019-09-16 00:24:30 +08:00
lyswhut
b9aedc9165 新增代理功能 2019-09-16 00:00:07 +08:00
lyswhut
8bdbbc562c 修复试听列表没有歌曲时会显示列表加载中的Bug 2019-09-14 11:00:42 +08:00
lyswhut
696f6c096c 优化从《梦里嫦娥》皮肤切换到其他皮肤时侧栏动画的切换效果 2019-09-13 14:51:28 +08:00
lyswhut
d0ef6aef1c 发布0.5.5版本 2019-09-13 14:07:39 +08:00
lyswhut
7204b51439 新增:《月里嫦娥》皮肤 2019-09-13 14:04:52 +08:00
lyswhut
6075a9d22f 更新常见问题 2019-09-12 16:24:28 +08:00
lyswhut
b15cfa1892 新增复制播放标题的功能 2019-09-12 01:35:19 +08:00
lyswhut
955375f423 添加mac退出快捷键 2019-09-11 21:43:30 +08:00
lyswhut
2aa13a499a 修复mac不能复制粘贴的问题 2019-09-11 20:50:34 +08:00
lyswhut
fb0e61f3b0 修复等待事件未清空的bug 2019-09-10 21:49:09 +08:00
lyswhut
16149fdd38 修复:文件名包含特殊符号时导致下载失败的Bug 2019-09-10 13:00:55 +08:00
lyswhut
a432080141 修复 MAC 系统下软件关闭时再次从 dock 打开时报错的Bug 2019-09-10 09:03:57 +08:00
lyswhut
73072daa46 尝试修复Mac系统点击关闭时再打开的BUG 2019-09-10 02:03:09 +08:00
lyswhut
2f57345bd2 更新更新错误时的弹窗下载地址 2019-09-09 09:49:27 +08:00
lyswhut
06075d561d 降级node-downloader-helper包 2019-09-09 08:32:15 +08:00
lyswhut
db8ad7cde5 发布0.5.4版本 2019-09-09 08:29:04 +08:00
lyswhut
cacf39da69 暂时移除FLAC格式的meta信息修改 2019-09-09 08:26:18 +08:00
lyswhut
4dc7937321 修复更新弹窗可能导致的bug 2019-09-09 01:32:14 +08:00
lyswhut
1c462ce152 更新依赖包到最新,发布0.5.3版本 2019-09-09 01:05:30 +08:00
77 changed files with 2904 additions and 1392 deletions

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

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

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

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

View File

@@ -6,6 +6,93 @@ Project versioning adheres to [Semantic Versioning](http://semver.org/).
Commit convention is based on [Conventional Commits](http://conventionalcommits.org).
Change log format is based on [Keep a Changelog](http://keepachangelog.com/).
## [0.6.2](https://github.com/lyswhut/lx-music-desktop/compare/v0.6.1...v0.6.2) - 2019-10-01
祝贺祖国成立70周年~
#### 新增
- 新增QQ音乐源歌单
#### 修复
- 修正火影皮肤名字
- 修复当试听列表为空时无法切到其他界面的Bug
- 修复百度源搜索结果为空时的接口处理Bug
- 恢复**酷狗**其他音质播放
## [0.6.1](https://github.com/lyswhut/lx-music-desktop/compare/v0.6.0...v0.6.1) - 2019-09-28
### 新增
- 新增试听列表**滚动条位置恢复**设置(可自动恢复到上次离开时的列表滚动位置),本功能默认开启,若不需要可到设置-列表设置将其关闭
- 新增 **《海贼王》** 皮肤,喜欢个性化的可以试试~
### 优化
- 新增DNS解析缓存加快请求速度
- 优化代码逻辑,减少软件对系统资源的占用
- 优化新版本信息检测,尽量减少弹出版本获取失败弹窗弹出的概率
- 优化下拉列表动画效果
### 修复
- 修复请求超时的逻辑处理Bug尝试修复请求无法取消导致的正在播放的歌曲与界面显示的信息不一致的问题
- 修复其他一些小Bug
### 移除
- 移除 `192k` 音质
- 移除酷我音源 `ape` 音质,无损推荐 `flac` 格式
## [0.6.0](https://github.com/lyswhut/lx-music-desktop/compare/v0.5.5...v0.6.0) - 2019-09-21
### 新增
- 新增音乐**聚合搜索**,目前支持酷我、酷狗、百度源搜索
- 新增代理功能
### 优化
- 优化从《梦里嫦娥》皮肤切换到其他皮肤时侧栏动画的切换效果
### 修复
- 修复试听列表没有歌曲时会显示列表加载中的Bug
- 修复切换歌单列表详情时的UI Bug
## [0.5.5](https://github.com/lyswhut/lx-music-desktop/compare/v0.5.4...v0.5.5) - 2019-09-13
### 新增
- 月是故乡明,祝大家中秋快乐🥮~~新增个性皮肤 **《月里嫦娥》**,时间仓促,皮肤还不是很完善,可以试试喜不喜欢~😉
- 新增 MAC 版本退出快捷键支持
- 新增点击播放器中的歌曲标题可以复制标题的功能(遇到好听的歌曲方便分享)
### 修复
- 修复 MAC 系统下软件关闭时再次从 dock 打开时报错的Bug
- 修复下载的歌曲文件名中包含命名规则不允许的符号时下载失败的问题(若歌曲名包含这些符号会自动将其移除)
- 修复 MAC 版本不能复制粘贴的问题
## [0.5.4](https://github.com/lyswhut/lx-music-desktop/compare/v0.5.3...v0.5.4) - 2019-09-09
### 移除
- 下载的FLAC文件在修改歌曲信息后软件无法播放但使用本地播放器可以播放
- 为了稳妥起见暂时移除FLAC格式的meta信息修改
- MP3格式无此问题
## [0.5.3](https://github.com/lyswhut/lx-music-desktop/compare/v0.5.2...v0.5.3) - 2019-09-09
### 优化
- 更新所有依赖包到最新
### 修复
- 修复试听酷狗源的音乐仍然获取320k音质导致获取失败的Bug
## [0.5.2](https://github.com/lyswhut/lx-music-desktop/compare/v0.5.1...v0.5.2) - 2019-09-09
### 新增

View File

@@ -82,21 +82,45 @@ npm run pack
1. 尝试更新到最新版本
2. 尝试切换其他歌曲(或直接搜索该歌曲),若全部歌曲都无法试听与下载则进行下一步
3. 尝试切换网络(比如切到移动网络)
4. 若还不行请到这个链接查看详情:<https://github.com/lyswhut/lx-music-desktop/issues/5>
3. 尝试到设置-接口来源切换到其他接口
4. 尝试切换网络,比如用手机开热点(目前存在某些网络无法访问接口服务器的情况)
5. 若还不行请到这个链接查看详情:<https://github.com/lyswhut/lx-music-desktop/issues/5>
6. 若没有在第5条链接中的第一条评论中看到接口无法使用的说明则应该是你网络无法访问接口服务器的问题如果接口有问题我会在那里说明。
#### Windows 7 下界面异常
#### 软件安装包说明
当 win7 没有开启**透明效果**时界面将会显示异常,开启方法请自行百度
软件发布页及网盘中有多个类型的安装文件,以下是对这些类型文件的说明:
文件名带 `win_` 的是在Windows系统上运行的版本<br>
其中安装版Setup可自动更新软件<br>
绿色版green为免安装版自动更新功能不可用
**`.dmg`** 结尾的文件为 MAC 版本;
**`.AppImage`**、**`.deb`** 结尾的为 Linux 版本。
带有`x64`的为64位的系统版本`x86`的为32位的系统版本若两个都带有的则为集合版安装时会自动根据系统位数选择对应的版本安装。
#### 软件更新
软件启动时若发现新版本时会自动从本仓库下载安装包,下载完毕会弹窗提示更新。<br>
若下载未完成时软件被关闭,下次启动软件会再次自动下载。<br>
若还是更新失败可能是无法访问GitHub导致的这时需要手动更新即下载最新安装包直接覆盖安装即可。<br>
注意:**绿色版**的软件更新功能**不可用**为了能及时地获取更新,建议使用安装版!!<br>
若还是**更新失败**可能是无法访问GitHub导致的这时需要手动更新即下载最新安装包直接覆盖安装即可。<br>
注意:**绿色版**的软件自动更新功能**不可用**,建议使用安装版!!<br>
注意:**Mac版**、**Linux deb**版不支持自动更新!
#### Windows 7 下界面异常
当 win7 没有开启**透明效果**时界面将会显示异常,开启方法请自行百度。
#### 安装版安装失败,提示应用未安装
对于部分电脑出现安装失败的问题我也不懂什么原因,,可以尝试清理下安装文件,或者重启电脑试试。
#### 缺少`xxx.dll`
这个是电脑缺少某些dll导致的正常的系统是没有这个问题的解决办法需自行百度弹出的错误信息看下别人是怎么解决的。
### 致谢
感谢 [@messoer](https://github.com/messoer) 曾经提供的部分音乐API

2053
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "lx-music-desktop",
"version": "0.5.2",
"version": "0.6.2",
"description": "一个免费的音乐下载助手",
"main": "./dist/electron/main.js",
"productName": "lx-music-desktop",
@@ -57,7 +57,7 @@
"build": {
"appId": "cn.toside.music.desktop",
"directories": {
"output": "build"
"output": "./build"
},
"files": [
"dist/electron/**/*"
@@ -134,43 +134,43 @@
},
"homepage": "https://github.com/lyswhut/lx-music-desktop#readme",
"devDependencies": {
"@babel/core": "^7.5.5",
"@babel/core": "^7.6.2",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/polyfill": "^7.4.4",
"@babel/preset-env": "^7.5.5",
"@babel/polyfill": "^7.6.0",
"@babel/preset-env": "^7.6.2",
"autoprefixer": "^9.6.1",
"babel-eslint": "^10.0.2",
"babel-eslint": "^10.0.3",
"babel-loader": "^8.0.6",
"babel-minify-webpack-plugin": "^0.3.1",
"babel-preset-minify": "^0.5.0",
"cfonts": "^2.4.4",
"babel-preset-minify": "^0.5.1",
"cfonts": "^2.4.5",
"chalk": "^2.4.2",
"changelog-parser": "^2.8.0",
"copy-webpack-plugin": "^5.0.4",
"core-js": "^3.2.1",
"cos-nodejs-sdk-v5": "^2.5.11",
"cross-env": "^5.2.0",
"cos-nodejs-sdk-v5": "^2.5.12",
"cross-env": "^6.0.0",
"css-loader": "^3.2.0",
"del": "^3.0.0",
"electron": "^6.0.2",
"del": "^5.1.0",
"electron": "^6.0.10",
"electron-builder": "^21.2.0",
"electron-debug": "^3.0.1",
"electron-devtools-installer": "^2.2.4",
"eslint": "^6.1.0",
"eslint-config-standard": "^13.0.1",
"eslint": "^6.4.0",
"eslint-config-standard": "^14.1.0",
"eslint-formatter-friendly": "^7.0.0",
"eslint-loader": "^2.2.1",
"eslint-loader": "^3.0.0",
"eslint-plugin-html": "^6.0.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-node": "^9.1.0",
"eslint-plugin-node": "^10.0.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-standard": "^4.0.1",
"file-loader": "^4.2.0",
"friendly-errors-webpack-plugin": "^1.7.0",
"html-webpack-plugin": "^3.2.0",
"less": "^3.9.0",
"less": "^3.10.3",
"less-loader": "^5.0.0",
"markdown-it": "^9.1.0",
"markdown-it": "^10.0.0",
"mini-css-extract-plugin": "^0.8.0",
"multispinner": "^0.2.1",
"optimize-css-assets-webpack-plugin": "^5.0.3",
@@ -180,24 +180,25 @@
"pug-plain-loader": "^1.0.0",
"raw-loader": "^3.1.0",
"rimraf": "^3.0.0",
"stylus": "^0.54.5",
"stylus": "^0.54.7",
"stylus-loader": "^3.0.2",
"terser-webpack-plugin": "^1.4.1",
"terser-webpack-plugin": "^2.1.0",
"url-loader": "^2.1.0",
"vue-loader": "^15.7.1",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.6.10",
"webpack": "^4.39.2",
"webpack-cli": "^3.3.6",
"webpack-dev-server": "^3.8.0",
"webpack": "^4.41.0",
"webpack-cli": "^3.3.9",
"webpack-dev-server": "^3.8.1",
"webpack-hot-middleware": "^2.25.0",
"webpack-merge": "^4.2.1"
"webpack-merge": "^4.2.2"
},
"dependencies": {
"axios": "^0.19.0",
"crypto-js": "^3.1.9-1",
"electron-log": "^3.0.7",
"electron-store": "^4.0.0",
"dnscache": "^1.0.2",
"electron-log": "^3.0.8",
"electron-store": "^5.0.0",
"electron-updater": "^4.1.2",
"flac-metadata": "^0.1.1",
"js-htmlencode": "^0.3.0",
@@ -207,7 +208,7 @@
"request": "^2.88.0",
"vue": "^2.6.10",
"vue-electron": "^1.0.6",
"vue-router": "^3.1.2",
"vue-router": "^3.1.3",
"vuex": "^3.1.1",
"vuex-electron": "^1.0.3",
"vuex-router-sync": "^5.0.0"

View File

@@ -1,18 +1,12 @@
### 新增
祝贺祖国成立70周年~
- 新增强迫症设置-离开搜索界面时是否清空搜索框
- 设置-关于板块新增常见问题链接
- 歌单左上角的分类按钮添加一个**向下图标**,方便识别该按钮为下拉框(该按钮可选择歌单类型,请自行尝试)
#### 新增
### 优化
- 新增QQ音乐源歌单
- 略微优化最小化按钮字符
- 优化试听列表的加载体验,当歌曲数过多时列表将延迟加载
#### 修复
### 修复
- 修复下载管理的一些Bug
### 移除
- 因接口失效移除网易云音源酷狗音源仅支持播放128k音质
- 修正火影皮肤名字
- 修复当试听列表为空时无法切到其他界面的Bug
- 修复百度源搜索结果为空时的接口处理Bug
- 恢复**酷狗**其他音质播放

View File

@@ -1,7 +1,31 @@
{
"version": "0.5.2",
"desc": "<h3>新增</h3>\n<ul>\n<li>新增强迫症设置-离开搜索界面时是否清空搜索框</li>\n<li>设置-关于板块新增常见问题链接</li>\n<li>歌单左上角的分类按钮添加一个<strong>向下图标</strong>,方便识别该按钮为下拉框(该按钮可选择歌单类型,请自行尝试)</li>\n</ul>\n<h3>优化</h3>\n<ul>\n<li>略微优化最小化按钮字符</li>\n<li>优化试听列表的加载体验,当歌曲数过多时列表将延迟加载</li>\n</ul>\n<h3>修复</h3>\n<ul>\n<li>修复下载管理的一些Bug</li>\n</ul>\n<h3>移除</h3>\n<ul>\n<li>因接口失效移除网易云音源酷狗音源仅支持播放128k音质</li>\n</ul>\n",
"version": "0.6.2",
"desc": "<p>祝贺祖国成立70周年~</p>\n<h4>新增</h4>\n<ul>\n<li>新增QQ音乐源歌单</li>\n</ul>\n<h4>修复</h4>\n<ul>\n<li>修正火影皮肤名字</li>\n<li>修复当试听列表为空时无法切到其他界面的Bug</li>\n<li>修复百度源搜索结果为空时的接口处理Bug</li>\n<li>恢复<strong>酷狗</strong>其他音质播放</li>\n</ul>\n",
"history": [
{
"version": "0.6.1",
"desc": "<h3>新增</h3>\n<ul>\n<li>新增试听列表<strong>滚动条位置恢复</strong>设置(可自动恢复到上次离开时的列表滚动位置),本功能默认开启,若不需要可到设置-列表设置将其关闭</li>\n<li>新增 <strong>《海贼王》</strong> 皮肤,喜欢个性化的可以试试~</li>\n</ul>\n<h3>优化</h3>\n<ul>\n<li>新增DNS解析缓存加快请求速度</li>\n<li>优化代码逻辑,减少软件对系统资源的占用</li>\n<li>优化新版本信息检测,尽量减少弹出版本获取失败弹窗弹出的概率</li>\n<li>优化下拉列表动画效果</li>\n</ul>\n<h3>修复</h3>\n<ul>\n<li>修复请求超时的逻辑处理Bug尝试修复请求无法取消导致的正在播放的歌曲与界面显示的信息不一致的问题</li>\n<li>修复其他一些小Bug</li>\n</ul>\n<h3>移除</h3>\n<ul>\n<li>移除 <code>192k</code> 音质</li>\n<li>移除酷我音源 <code>ape</code> 音质,无损推荐 <code>flac</code> 格式</li>\n</ul>\n"
},
{
"version": "0.6.0",
"desc": "<h3>新增</h3>\n<ul>\n<li>新增音乐<strong>聚合搜索</strong>,目前支持酷我、酷狗、百度源搜索</li>\n<li>新增代理功能</li>\n</ul>\n<h3>优化</h3>\n<ul>\n<li>优化从《梦里嫦娥》皮肤切换到其他皮肤时侧栏动画的切换效果</li>\n</ul>\n<h3>修复</h3>\n<ul>\n<li>修复试听列表没有歌曲时会显示列表加载中的Bug</li>\n<li>修复切换歌单列表详情时的UI Bug</li>\n</ul>\n"
},
{
"version": "0.5.5",
"desc": "<h3>新增</h3>\n<ul>\n<li>月是故乡明,祝大家中秋快乐🥮~~新增个性皮肤**《月里嫦娥》**,时间仓促,皮肤还不是很完善,可以试试喜不喜欢~😉</li>\n<li>新增 MAC 版本退出快捷键支持</li>\n<li>新增点击播放器中的歌曲标题可以复制标题的功能(遇到好听的歌曲方便分享)</li>\n</ul>\n<h3>修复</h3>\n<ul>\n<li>修复 MAC 系统下软件关闭时再次从 dock 打开时报错的Bug</li>\n<li>修复下载的歌曲文件名中包含命名规则不允许的符号时下载失败的问题(若歌曲名包含这些符号会自动将其移除)</li>\n<li>修复 MAC 版本不能复制粘贴的问题</li>\n</ul>\n"
},
{
"version": "0.5.4",
"desc": "<h3>移除</h3>\n<ul>\n<li>下载的FLAC文件在修改歌曲信息后软件无法播放但使用本地播放器可以播放</li>\n<li>为了稳妥起见暂时移除FLAC格式的meta信息修改</li>\n<li>MP3格式无此问题</li>\n</ul>\n"
},
{
"version": "0.5.3",
"desc": "<h3>优化</h3>\n<ul>\n<li>更新所有依赖包到最新</li>\n</ul>\n<h3>修复</h3>\n<ul>\n<li>修复试听酷狗源的音乐仍然获取320k音质导致获取失败的Bug</li>\n</ul>\n"
},
{
"version": "0.5.2",
"desc": "<h3>新增</h3>\n<ul>\n<li>新增强迫症设置-离开搜索界面时是否清空搜索框</li>\n<li>设置-关于板块新增常见问题链接</li>\n<li>歌单左上角的分类按钮添加一个<strong>向下图标</strong>,方便识别该按钮为下拉框(该按钮可选择歌单类型,请自行尝试)</li>\n</ul>\n<h3>优化</h3>\n<ul>\n<li>略微优化最小化按钮字符</li>\n<li>优化试听列表的加载体验,当歌曲数过多时列表将延迟加载</li>\n</ul>\n<h3>修复</h3>\n<ul>\n<li>修复下载管理的一些Bug</li>\n</ul>\n<h3>移除</h3>\n<ul>\n<li>因接口失效移除网易云音源酷狗音源仅支持播放128k音质</li>\n</ul>\n"
},
{
"version": "0.5.1",
"desc": "<h3>新增</h3>\n<ul>\n<li>新增右上角最小化/关闭按钮鼠标滑过符号</li>\n<li>新增下载列表定位文件按钮</li>\n</ul>\n<h3>修复</h3>\n<ul>\n<li>修复百度源歌单全部分类无法加载的问题</li>\n<li>修复更新弹窗无法弹出的问题</li>\n</ul>\n"

View File

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

View File

@@ -1,11 +1,10 @@
const { mainOn } = require('../../common/icp')
module.exports = win => {
mainOn('progress', (event, params) => {
// console.log(params)
win.setProgressBar(params.status, {
mode: params.mode || 'normal',
})
})
}
mainOn('progress', (event, params) => {
// console.log(params)
global.mainWindow && global.mainWindow.setProgressBar(params.status, {
mode: params.mode || 'normal',
})
})

View File

@@ -7,7 +7,7 @@ const tasks = []
mainOn('request', (event, options) => {
// console.log(args)
if (!options) return
let index = fatchData(options, (err, resp) => {
let index = fetchData(options, (err, resp) => {
tasks[index] = null
if (err) {
console.log(err)
@@ -27,7 +27,7 @@ mainOn('cancelRequest', (event, index) => {
tasks[index] = null
})
const fatchData = (options, callback) => pushTask(tasks, request(options.url, {
const fetchData = (options, callback) => pushTask(tasks, request(options.url, {
method: options.method,
headers: options.headers,
Origin: options.origin,

View File

@@ -1,23 +1,22 @@
// const { app } = require('electron')
const { mainOn } = require('../../common/icp')
module.exports = win => {
mainOn('min', event => {
if (win) {
win.minimize()
}
})
// mainOn('max', event => {
// if (win) {
// win.maximize()
// }
// })
mainOn('close', event => {
if (win) {
// window.destroy()
// console.log('close')
// app.quit()
win.close()
}
})
}
mainOn('min', event => {
if (global.mainWindow) {
global.mainWindow.minimize()
}
})
// mainOn('max', event => {
// if (global.mainWindow) {
// global.mainWindow.maximize()
// }
// })
mainOn('close', event => {
if (global.mainWindow) {
// global.mainWindowdow.destroy()
// console.log('close')
// app.quit()
global.mainWindow.close()
}
})

View File

@@ -16,8 +16,8 @@ app.on('second-instance', (event, argv, cwd) => {
})
require('./events')
const progressBar = require('./events/progressBar')
const trafficLight = require('./events/trafficLight')
require('./events/progressBar')
require('./events/trafficLight')
const autoUpdate = require('./utils/autoUpdate')
const { isLinux, isMac } = require('../common/utils')
@@ -30,10 +30,11 @@ const isDev = process.env.NODE_ENV !== 'production'
let mainWindow
let winURL
let isFirstCheckedUpdate = true
if (isDev) {
global.__static = path.join(__dirname, '../static')
winURL = `http://localhost:9080`
winURL = 'http://localhost:9080'
} else {
global.__static = path.join(__dirname, '/static')
winURL = `file://${__dirname}/index.html`
@@ -43,7 +44,7 @@ function createWindow() {
/**
* Initial window options
*/
mainWindow = new BrowserWindow({
mainWindow = global.mainWindow = new BrowserWindow({
height: 590,
useContentSize: true,
width: 920,
@@ -62,27 +63,54 @@ function createWindow() {
mainWindow.loadURL(winURL)
mainWindow.on('close', () => {
mainWindow.setProgressBar(-1)
})
mainWindow.on('closed', () => {
if (!isMac) mainWindow = null
mainWindow = global.mainWindow = null
})
// mainWindow.webContents.openDevTools()
trafficLight(mainWindow)
progressBar(mainWindow)
if (!isDev) autoUpdate(mainWindow)
if (!isDev) {
autoUpdate(isFirstCheckedUpdate)
isFirstCheckedUpdate = false
}
}
if (isMac) {
const template = [
{
label: app.getName(),
submenu: [{ label: '关于洛雪音乐', role: 'about' }, { type: 'separator' }, { label: '隐藏', role: 'hide' }, { label: '显示其他', role: 'hideothers' }, { label: '显示全部', role: 'unhide' }, { type: 'separator' }, { label: '退出', click: () => app.quit() }],
submenu: [
{ label: '关于洛雪音乐', role: 'about' },
{ type: 'separator' },
{ label: '隐藏', role: 'hide' },
{ label: '显示其他', role: 'hideothers' },
{ label: '显示全部', role: 'unhide' },
{ type: 'separator' },
{ label: '退出', accelerator: 'Command+Q', click: () => app.quit() },
],
},
{
label: '窗口',
role: 'window',
submenu: [{ label: '最小化', role: 'minimize' }, { label: '关闭', role: 'close' }],
submenu: [
{ label: '最小化', role: 'minimize' },
{ label: '关闭', role: 'close' },
],
},
{
label: '编辑',
submenu: [
{ label: '撤销', accelerator: 'CmdOrCtrl+Z', role: 'undo' },
{ label: '恢复', accelerator: 'Shift+CmdOrCtrl+Z', role: 'redo' },
{ type: 'separator' },
{ label: '剪切', accelerator: 'CmdOrCtrl+X', role: 'cut' },
{ label: '复制', accelerator: 'CmdOrCtrl+C', role: 'copy' },
{ label: '粘贴', accelerator: 'CmdOrCtrl+V', role: 'paste' },
{ label: '选择全部', accelerator: 'CmdOrCtrl+A', role: 'selectAll' },
],
},
]

View File

@@ -21,7 +21,7 @@ log.info('App starting...')
function sendStatusToWindow(text) {
log.info(text)
// win.webContents.send('message', text)
// global.mainWindow.webContents.send('message', text)
}
@@ -56,35 +56,50 @@ function sendStatusToWindow(text) {
// })
let waitEvent = []
const handleSendEvent = action => {
if (global.mainWindow) {
setTimeout(() => { // 延迟发送事件,过早发送可能渲染进程还没启动完成
global.mainWindow.webContents.send(action.type, action.info)
}, 2000)
} else {
waitEvent.push(action)
}
}
module.exports = win => {
module.exports = isFirstCheckedUpdate => {
if (!isFirstCheckedUpdate) {
if (waitEvent.length) {
waitEvent.forEach((event, index) => {
setTimeout(() => { // 延迟发送事件,过早发送可能渲染进程还没启动完成
global.mainWindow.webContents.send(event.type, event.info)
}, 2000 * (index + 1))
})
waitEvent = []
}
return
}
autoUpdater.on('checking-for-update', () => {
sendStatusToWindow('Checking for update...')
})
autoUpdater.on('update-available', info => {
sendStatusToWindow('Update available.')
win.webContents.send('update-available', info)
handleSendEvent({ type: 'update-available', info })
})
autoUpdater.on('update-not-available', info => {
sendStatusToWindow('Update not available.')
setTimeout(() => { // 延迟发送事件,过早发送可能渲染进程还启动完成
win.webContents.send('update-not-available')
}, 5000)
handleSendEvent({ type: 'update-not-available' })
})
autoUpdater.on('error', () => {
sendStatusToWindow('Error in auto-updater.')
setTimeout(() => { // 延迟发送事件,过早发送可能渲染进程还启动完成
win.webContents.send('update-error')
}, 6000)
handleSendEvent({ type: 'update-error' })
})
autoUpdater.on('download-progress', progressObj => {
sendStatusToWindow('Download progress...')
})
autoUpdater.on('update-downloaded', info => {
sendStatusToWindow('Update downloaded.')
setTimeout(() => { // 延迟发送事件,过早发送可能渲染进程还启动完成
win.webContents.send('update-downloaded')
}, 2000)
handleSendEvent({ type: 'update-downloaded' })
})
mainOn('quit-update', () => {
setTimeout(() => {

View File

@@ -6,7 +6,7 @@ const extReg = /^(\.(?:jpe?g|png)).*$/
module.exports = (filePath, meta) => {
if (!meta.APIC) return NodeID3.write(meta, filePath)
let picPath = path.join(path.dirname(filePath), `${meta.title}-${meta.artist}${path.extname(meta.APIC).replace(extReg, '$1')}`)
let picPath = filePath.replace(/\.mp3$/, '') + path.extname(meta.APIC).replace(extReg, '$1')
request(meta.APIC).pipe(fs.createWriteStream(picPath)).on('finish', () => {
meta.APIC = picPath
NodeID3.write(meta, filePath)

View File

@@ -18,10 +18,16 @@
</template>
<script>
import dnscache from 'dnscache'
import { mapMutations, mapGetters, mapActions } from 'vuex'
import { rendererOn } from '../common/icp'
import { isLinux } from '../common/utils'
window.ELECTRON_DISABLE_SECURITY_WARNINGS = process.env.ELECTRON_DISABLE_SECURITY_WARNINGS
dnscache({
enable: true,
ttl: 21600,
cachesize: 1000,
})
let win
let body
if (!isLinux) {
@@ -35,7 +41,8 @@ export default {
isProd: process.env.NODE_ENV === 'production',
isLinux,
globalObj: {
apiSource: 'messoer',
apiSource: 'test',
proxy: {},
},
updateTimeout: null,
}
@@ -107,6 +114,7 @@ export default {
})
rendererOn('update-downloaded', () => {
this.clearUpdateTimeout()
this.setVersionModalVisible({ isError: false })
this.showUpdateModal()
})
rendererOn('update-not-available', () => {
@@ -128,6 +136,7 @@ export default {
this.initData()
this.globalObj.apiSource = this.setting.apiSource
this.globalObj.proxy = Object.assign({}, this.setting.network.proxy)
window.globalObj = this.globalObj
},
enableIgnoreMouseEvents() {
@@ -224,6 +233,10 @@ body {
display: flex;
height: 100%;
overflow: hidden;
background: @color-theme-bgimg @color-theme-bgposition no-repeat;
background-size: @color-theme-bgsize;
transition: background-color @transition-theme;
background-color: @color-theme;
}
#left {
@@ -234,6 +247,8 @@ body {
flex: auto;
display: flex;
flex-flow: column nowrap;
transition: background-color @transition-theme;
background-color: @color-theme_2;
}
#toolbar, #player {
flex: none;
@@ -242,5 +257,17 @@ body {
flex: auto;
height: 0;
}
each(@themes, {
#container.@{value} {
background-color: ~'@{color-@{value}-theme}';
background-image: ~'@{color-@{value}-theme-bgimg}';
background-size: ~'@{color-@{value}-theme-bgsize}';
background-position: ~'@{color-@{value}-theme-bgposition}';
#right {
background-color: ~'@{color-@{value}-theme_2}';
}
}
})
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@@ -36,11 +36,11 @@ table {
}
tbody {
tr {
border-top: 1px solid #e0e0e0;
border-top: 1px solid @color-theme_2-line;
// border-top: 1px solid rgba(0, 0, 0, 0.12);
transition: background-color 0.2s ease;
&:hover {
background-color: #eee;
background-color: @color-theme_2-hover;
}
&:first-child {
border-top: none;
@@ -172,5 +172,15 @@ each(@themes, {
background-color: ~'@{color-@{value}-scrollbar-thumb-hover}';
}
}
table {
tbody {
tr {
border-top-color: ~'@{color-@{value}-theme_2-line}';
&:hover {
background-color: ~'@{color-@{value}-theme_2-hover}';
}
}
}
}
}
})

View File

@@ -1,21 +1,28 @@
@import './colors.less';
@themes: green, yellow, blue, red, purple, orange, grey;
@themes: green, yellow, blue, red, purple, orange, grey, midAutumn, dhHyrz;
// Colors
// @color-theme: #03a678;
@color-theme: #4daf7c;
@color-theme-bgimg: none;
@color-theme-bgposition: center center;
@color-theme-bgsize: auto auto;
@color-theme-hover: fadeout(lighten(@color-theme, 10%), 30%);
@color-theme-active: fadeout(darken(@color-theme, 20%), 60%);
@color-theme-font: #fff;
@color-theme-font-label: lighten(@color-theme, 35%);
@color-theme_2: #fff;
@color-theme_2: rgba(255, 255, 255, .9);
@color-theme_2-background_1: #fff;
@color-theme_2-background_2: fadeout(@color-theme_2-background_1, 2%);
@color-theme_2-hover: fadeout(lighten(@color-theme, 10%), 70%);
@color-theme_2-active: fadeout(darken(@color-theme, 5%), 70%);
@color-theme_2-font: darken(@color-theme_2, 70%);
@color-theme_2-font-label: lighten(@color-theme, 40%);
@color-theme_2-font-label: fadeout(@color-theme_2-font, 50%);
@color-theme_2-line: lighten(@color-theme, 35%);
@color-theme-sidebar: @color-theme;
@color-btn: fadeout(darken(@color-theme, 5%), 15%);
@color-btn-background: fadeout(lighten(@color-theme, 35%), 70%);
@@ -41,6 +48,7 @@
@color-player-status-text: lighten(@color-theme_2-font, 10%);
@color-tab-btn-background: fadeout(lighten(@color-theme, 10%), 80%);
@color-tab-btn-background-hover: @color-theme_2-hover;
@color-tab-border-top: fadeout(lighten(@color-theme, 5%), 50%);
@color-tab-border-bottom: lighten(@color-theme, 5%);
@@ -50,15 +58,22 @@
@color-green-theme: #4daf7c;
@color-green-theme-bgimg: none;
@color-green-theme-bgposition: center center;
@color-green-theme-bgsize: auto auto;
@color-green-theme-hover: fadeout(lighten(@color-green-theme, 10%), 30%);
@color-green-theme-active: fadeout(darken(@color-green-theme, 20%), 60%);
@color-green-theme-font: #fff;
@color-green-theme-font-label: lighten(@color-green-theme, 35%);
@color-green-theme_2: #fff;
@color-green-theme_2-background_1: #fff;
@color-green-theme_2-background_2: fadeout(@color-green-theme_2-background_1, 2%);
@color-green-theme_2-hover: fadeout(lighten(@color-green-theme, 10%), 70%);
@color-green-theme_2-active: fadeout(darken(@color-green-theme, 5%), 70%);
@color-green-theme_2-font: darken(@color-green-theme_2, 70%);
@color-green-theme_2-font-label: lighten(@color-green-theme, 40%);
@color-green-theme_2-font-label: fadeout(@color-green-theme_2-font, 50%);
@color-green-theme_2-line: lighten(@color-green-theme, 35%);
@color-green-theme-sidebar: @color-green-theme;
@color-green-btn: fadeout(darken(@color-green-theme, 5%), 15%);
@color-green-btn-background: fadeout(lighten(@color-green-theme, 35%), 70%);
@color-green-pagination-background: fadeout(lighten(@color-green-theme, 45%), 30%);
@@ -77,20 +92,28 @@
@color-green-player-progress-bar2: lighten(@color-green-theme, 12%);
@color-green-player-status-text: lighten(@color-green-theme_2-font, 10%);
@color-green-tab-btn-background: fadeout(lighten(@color-green-theme, 10%), 80%);
@color-green-tab-btn-background-hover: @color-green-theme_2-hover;
@color-green-tab-border-top: fadeout(lighten(@color-green-theme, 5%), 50%);
@color-green-tab-border-bottom: lighten(@color-green-theme, 5%);
@color-yellow-theme: #f2d35b;
@color-yellow-theme-bgimg: none;
@color-yellow-theme-bgposition: center center;
@color-yellow-theme-bgsize: auto auto;
@color-yellow-theme-hover: fadeout(lighten(@color-yellow-theme, 10%), 30%);
@color-yellow-theme-active: fadeout(darken(@color-yellow-theme, 20%), 60%);
@color-yellow-theme-font: #fff;
@color-yellow-theme-font-label: lighten(@color-yellow-theme, 35%);
@color-yellow-theme_2: #fff;
@color-yellow-theme_2-background_1: #fff;
@color-yellow-theme_2-background_2: fadeout(@color-yellow-theme_2-background_1, 2%);
@color-yellow-theme_2-hover: fadeout(lighten(@color-yellow-theme, 10%), 70%);
@color-yellow-theme_2-active: fadeout(darken(@color-yellow-theme, 5%), 70%);
@color-yellow-theme_2-font: darken(@color-yellow-theme_2, 70%);
@color-yellow-theme_2-font-label: lighten(@color-yellow-theme, 40%);
@color-yellow-theme_2-font-label: fadeout(@color-yellow-theme_2-font, 50%);
@color-yellow-theme_2-line: lighten(@color-yellow-theme, 35%);
@color-yellow-theme-sidebar: @color-yellow-theme;
@color-yellow-btn: fadeout(darken(@color-yellow-theme, 5%), 15%);
@color-yellow-btn-background: fadeout(lighten(@color-yellow-theme, 25%), 70%);
@color-yellow-pagination-background: fadeout(lighten(@color-yellow-theme, 30%), 30%);
@@ -109,19 +132,27 @@
@color-yellow-player-progress-bar2: lighten(@color-yellow-theme, 12%);
@color-yellow-player-status-text: lighten(@color-yellow-theme_2-font, 10%);
@color-yellow-tab-btn-background: fadeout(lighten(@color-yellow-theme, 10%), 80%);
@color-yellow-tab-btn-background-hover: @color-yellow-theme_2-hover;
@color-yellow-tab-border-top: fadeout(lighten(@color-yellow-theme, 5%), 50%);
@color-yellow-tab-border-bottom: lighten(@color-yellow-theme, 5%);
@color-orange-theme: #f5ab35;
@color-orange-theme-bgimg: none;
@color-orange-theme-bgposition: center center;
@color-orange-theme-bgsize: auto auto;
@color-orange-theme-hover: fadeout(lighten(@color-orange-theme, 10%), 30%);
@color-orange-theme-active: fadeout(darken(@color-orange-theme, 20%), 60%);
@color-orange-theme-font: #fff;
@color-orange-theme-font-label: lighten(@color-orange-theme, 35%);
@color-orange-theme_2: #fff;
@color-orange-theme_2-background_1: #fff;
@color-orange-theme_2-background_2: fadeout(@color-orange-theme_2-background_1, 2%);
@color-orange-theme_2-hover: fadeout(lighten(@color-orange-theme, 10%), 70%);
@color-orange-theme_2-active: fadeout(darken(@color-orange-theme, 5%), 70%);
@color-orange-theme_2-font: darken(@color-orange-theme_2, 70%);
@color-orange-theme_2-font-label: lighten(@color-orange-theme, 40%);
@color-orange-theme_2-font-label: fadeout(@color-orange-theme_2-font, 50%);
@color-orange-theme_2-line: lighten(@color-orange-theme, 35%);
@color-orange-theme-sidebar: @color-orange-theme;
@color-orange-btn: fadeout(darken(@color-orange-theme, 5%), 15%);
@color-orange-btn-background: fadeout(lighten(@color-orange-theme, 35%), 70%);
@color-orange-pagination-background: fadeout(lighten(@color-orange-theme, 35%), 30%);
@@ -140,19 +171,27 @@
@color-orange-player-progress-bar2: lighten(@color-orange-theme, 12%);
@color-orange-player-status-text: lighten(@color-orange-theme_2-font, 10%);
@color-orange-tab-btn-background: fadeout(lighten(@color-orange-theme, 10%), 80%);
@color-orange-tab-btn-background-hover: @color-orange-theme_2-hover;
@color-orange-tab-border-top: fadeout(lighten(@color-orange-theme, 5%), 50%);
@color-orange-tab-border-bottom: lighten(@color-orange-theme, 5%);
@color-blue-theme: #3498db;
@color-blue-theme-bgimg: none;
@color-blue-theme-bgposition: center center;
@color-blue-theme-bgsize: auto auto;
@color-blue-theme-hover: fadeout(lighten(@color-blue-theme, 10%), 30%);
@color-blue-theme-active: fadeout(darken(@color-blue-theme, 20%), 60%);
@color-blue-theme-font: #fff;
@color-blue-theme-font-label: lighten(@color-blue-theme, 35%);
@color-blue-theme_2: #fff;
@color-blue-theme_2-background_1: #fff;
@color-blue-theme_2-background_2: fadeout(@color-blue-theme_2-background_1, 2%);
@color-blue-theme_2-hover: fadeout(lighten(@color-blue-theme, 10%), 70%);
@color-blue-theme_2-active: fadeout(darken(@color-blue-theme, 5%), 70%);
@color-blue-theme_2-font: darken(@color-blue-theme_2, 70%);
@color-blue-theme_2-font-label: lighten(@color-blue-theme, 40%);
@color-blue-theme_2-font-label: fadeout(@color-blue-theme_2-font, 50%);
@color-blue-theme_2-line: lighten(@color-blue-theme, 35%);
@color-blue-theme-sidebar: @color-blue-theme;
@color-blue-btn: fadeout(darken(@color-blue-theme, 5%), 15%);
@color-blue-btn-background: fadeout(lighten(@color-blue-theme, 35%), 70%);
@color-blue-pagination-background: fadeout(lighten(@color-blue-theme, 40%), 30%);
@@ -171,10 +210,14 @@
@color-blue-player-progress-bar2: lighten(@color-blue-theme, 12%);
@color-blue-player-status-text: lighten(@color-blue-theme_2-font, 10%);
@color-blue-tab-btn-background: fadeout(lighten(@color-blue-theme, 10%), 80%);
@color-blue-tab-btn-background-hover: @color-blue-theme_2-hover;
@color-blue-tab-border-top: fadeout(lighten(@color-blue-theme, 5%), 50%);
@color-blue-tab-border-bottom: lighten(@color-blue-theme, 5%);
@color-red-theme: #d64541;
@color-red-theme-bgimg: none;
@color-red-theme-bgposition: center center;
@color-red-theme-bgsize: auto auto;
@color-red-theme-hover: fadeout(lighten(@color-red-theme, 10%), 30%);
@color-red-theme-active: fadeout(darken(@color-red-theme, 20%), 60%);
@color-red-theme-font: #fff;
@@ -182,8 +225,12 @@
@color-red-theme_2: #fff;
@color-red-theme_2-hover: fadeout(lighten(@color-red-theme, 10%), 70%);
@color-red-theme_2-active: fadeout(darken(@color-red-theme, 5%), 70%);
@color-red-theme_2-background_1: #fff;
@color-red-theme_2-background_2: fadeout(@color-red-theme_2-background_1, 2%);
@color-red-theme_2-font: darken(@color-red-theme_2, 70%);
@color-red-theme_2-font-label: lighten(@color-red-theme, 40%);
@color-red-theme_2-font-label: fadeout(@color-red-theme_2-font, 50%);
@color-red-theme_2-line: lighten(@color-red-theme, 35%);
@color-red-theme-sidebar: @color-red-theme;
@color-red-btn: fadeout(darken(@color-red-theme, 5%), 15%);
@color-red-btn-background: fadeout(lighten(@color-red-theme, 35%), 70%);
@color-red-pagination-background: fadeout(lighten(@color-red-theme, 40%), 30%);
@@ -204,19 +251,27 @@
@color-red-tab-border-top: fadeout(lighten(@color-red-theme, 25%), 70%);
@color-red-tab-border-bottom: lighten(@color-red-theme, 35%);
@color-red-tab-btn-background: fadeout(lighten(@color-red-theme, 10%), 80%);
@color-red-tab-btn-background-hover: @color-red-theme_2-hover;
@color-red-tab-border-top: fadeout(lighten(@color-red-theme, 5%), 50%);
@color-red-tab-border-bottom: lighten(@color-red-theme, 5%);
@color-purple-theme: #9b59b6;
@color-purple-theme-bgimg: none;
@color-purple-theme-bgposition: center center;
@color-purple-theme-bgsize: auto auto;
@color-purple-theme-hover: fadeout(lighten(@color-purple-theme, 10%), 30%);
@color-purple-theme-active: fadeout(darken(@color-purple-theme, 20%), 60%);
@color-purple-theme-font: #fff;
@color-purple-theme-font-label: lighten(@color-purple-theme, 35%);
@color-purple-theme_2: #fff;
@color-purple-theme_2-background_1: #fff;
@color-purple-theme_2-background_2: fadeout(@color-purple-theme_2-background_1, 2%);
@color-purple-theme_2-hover: fadeout(lighten(@color-purple-theme, 10%), 70%);
@color-purple-theme_2-active: fadeout(darken(@color-purple-theme, 5%), 70%);
@color-purple-theme_2-font: darken(@color-purple-theme_2, 70%);
@color-purple-theme_2-font-label: lighten(@color-purple-theme, 40%);
@color-purple-theme_2-font-label: fadeout(@color-purple-theme_2-font, 50%);
@color-purple-theme_2-line: lighten(@color-purple-theme, 35%);
@color-purple-theme-sidebar: @color-purple-theme;
@color-purple-btn: fadeout(darken(@color-purple-theme, 5%), 15%);
@color-purple-btn-background: fadeout(lighten(@color-purple-theme, 35%), 70%);
@color-purple-pagination-background: fadeout(lighten(@color-purple-theme, 40%), 30%);
@@ -235,19 +290,27 @@
@color-purple-player-progress-bar2: lighten(@color-purple-theme, 12%);
@color-purple-player-status-text: lighten(@color-purple-theme_2-font, 10%);
@color-purple-tab-btn-background: fadeout(lighten(@color-purple-theme, 10%), 80%);
@color-purple-tab-btn-background-hover: @color-purple-theme_2-hover;
@color-purple-tab-border-top: fadeout(lighten(@color-purple-theme, 5%), 50%);
@color-purple-tab-border-bottom: lighten(@color-purple-theme, 5%);
@color-grey-theme: #6c7a89;
@color-grey-theme-bgimg: none;
@color-grey-theme-bgposition: center center;
@color-grey-theme-bgsize: auto auto;
@color-grey-theme-hover: fadeout(lighten(@color-grey-theme, 10%), 30%);
@color-grey-theme-active: fadeout(darken(@color-grey-theme, 20%), 60%);
@color-grey-theme-font: #fff;
@color-grey-theme-font-label: lighten(@color-grey-theme, 35%);
@color-grey-theme_2: #fff;
@color-grey-theme_2-background_1: #fff;
@color-grey-theme_2-background_2: fadeout(@color-grey-theme_2-background_1, 2%);
@color-grey-theme_2-hover: fadeout(lighten(@color-grey-theme, 10%), 70%);
@color-grey-theme_2-active: fadeout(darken(@color-grey-theme, 5%), 70%);
@color-grey-theme_2-font: darken(@color-grey-theme_2, 70%);
@color-grey-theme_2-font-label: lighten(@color-grey-theme, 40%);
@color-grey-theme_2-font-label: fadeout(@color-grey-theme_2-font, 50%);
@color-grey-theme_2-line: lighten(@color-grey-theme, 35%);
@color-grey-theme-sidebar: @color-grey-theme;
@color-grey-btn: fadeout(darken(@color-grey-theme, 5%), 15%);
@color-grey-btn-background: fadeout(lighten(@color-grey-theme, 35%), 70%);
@color-grey-pagination-background: fadeout(lighten(@color-grey-theme, 45%), 30%);
@@ -266,9 +329,88 @@
@color-grey-player-progress-bar2: lighten(@color-grey-theme, 12%);
@color-grey-player-status-text: lighten(@color-grey-theme_2-font, 10%);
@color-grey-tab-btn-background: fadeout(lighten(@color-grey-theme, 10%), 80%);
@color-grey-tab-btn-background-hover: @color-grey-theme_2-hover;
@color-grey-tab-border-top: fadeout(lighten(@color-grey-theme, 5%), 50%);
@color-grey-tab-border-bottom: lighten(@color-grey-theme, 5%);
@color-midAutumn-theme: rgba(74, 55, 82, 1);
@color-midAutumn-theme-bgimg: url(../images/jqbg.jpg);
@color-midAutumn-theme-bgposition: center center;
@color-midAutumn-theme-bgsize: auto 100%;
@color-midAutumn-theme-hover: fadeout(lighten(@color-midAutumn-theme, 10%), 30%);
@color-midAutumn-theme-active: fadeout(lighten(@color-midAutumn-theme, 15%), 60%);
@color-midAutumn-theme-font: rgba(246, 233, 255, 0.9);
@color-midAutumn-theme-font-label: fadeout(lighten(@color-midAutumn-theme, 20%), 20%);
@color-midAutumn-theme_2: rgba(255, 255, 255, .93);
@color-midAutumn-theme_2-background_1: #eeedef;
@color-midAutumn-theme_2-background_2: fadeout(@color-midAutumn-theme_2-background_1, 2%);
@color-midAutumn-theme_2-hover: fadeout(lighten(@color-midAutumn-theme, 10%), 65%);
@color-midAutumn-theme_2-active: fadeout(darken(@color-midAutumn-theme, 5%), 70%);
@color-midAutumn-theme_2-font: darken(@color-midAutumn-theme_2, 70%);
@color-midAutumn-theme_2-font-label: lighten(@color-midAutumn-theme, 40%);
@color-midAutumn-theme_2-line: lighten(@color-midAutumn-theme, 54%);
@color-midAutumn-theme-sidebar: rgba(255, 255, 255, 0);
@color-midAutumn-btn: fadeout(darken(@color-midAutumn-theme, 5%), 15%);
@color-midAutumn-btn-background: fadeout(lighten(@color-midAutumn-theme, 35%), 70%);
@color-midAutumn-pagination-background: fadeout(lighten(@color-midAutumn-theme, 45%), 50%);
@color-midAutumn-pagination-hover: fadeout(lighten(@color-midAutumn-theme, 10%), 70%);
@color-midAutumn-pagination-active: fadeout(darken(@color-midAutumn-theme, 10%), 70%);
@color-midAutumn-pagination-select: fadeout(lighten(@color-midAutumn-theme, 10%), 55%);
@color-midAutumn-search-form-background: fadeout(lighten(@color-midAutumn-theme, 50%), 10%);
@color-midAutumn-search-list-hover: fadeout(darken(@color-midAutumn-theme, 10%), 70%);
@color-midAutumn-scrollbar-track: fadeout(@color-midAutumn-theme, 80%);
@color-midAutumn-scrollbar-thumb: fadeout(@color-midAutumn-theme, 60%);
@color-midAutumn-scrollbar-thumb-hover: fadeout(@color-midAutumn-theme, 40%);
@color-midAutumn-player-pic-c1: fadeout(@color-midAutumn-theme_2, 50%);
@color-midAutumn-player-pic-c2: darken(@color-midAutumn-theme_2, 30%);
@color-midAutumn-player-progress: darken(@color-midAutumn-theme_2, 6%);
@color-midAutumn-player-progress-bar1: darken(@color-midAutumn-theme_2, 12%);
@color-midAutumn-player-progress-bar2: lighten(@color-midAutumn-theme, 12%);
@color-midAutumn-player-status-text: lighten(@color-midAutumn-theme_2-font, 10%);
@color-midAutumn-tab-btn-background: fadeout(lighten(@color-midAutumn-theme, 10%), 80%);
@color-midAutumn-tab-btn-background-hover: @color-midAutumn-theme_2-hover;
@color-midAutumn-tab-border-top: fadeout(lighten(@color-midAutumn-theme, 5%), 50%);
@color-midAutumn-tab-border-bottom: lighten(@color-midAutumn-theme, 5%);
@color-dhHyrz-theme: rgb(87, 144, 167);
@color-dhHyrz-theme-bgimg: url(../images/hzwbg.jpeg);
@color-dhHyrz-theme-bgposition: center center;
@color-dhHyrz-theme-bgsize: auto 100%;
@color-dhHyrz-theme-hover: fadeout(lighten(@color-dhHyrz-theme, 10%), 45%);
@color-dhHyrz-theme-active: fadeout(lighten(@color-dhHyrz-theme, 15%), 60%);
@color-dhHyrz-theme-font: rgba(67, 118, 148, 0.9);
@color-dhHyrz-theme-font-label: fadeout(darken(@color-dhHyrz-theme, 20%), 20%);
@color-dhHyrz-theme_2: rgba(255, 255, 255, 0.8);
@color-dhHyrz-theme_2-background_1: #e9faff;
@color-dhHyrz-theme_2-background_2: fadeout(@color-dhHyrz-theme_2-background_1, 2%);
@color-dhHyrz-theme_2-hover: fadeout(lighten(@color-dhHyrz-theme, 10%), 65%);
@color-dhHyrz-theme_2-active: fadeout(darken(@color-dhHyrz-theme, 5%), 70%);
@color-dhHyrz-theme_2-font: darken(@color-dhHyrz-theme_2, 80%);
@color-dhHyrz-theme_2-font-label: lighten(@color-dhHyrz-theme, 10%);
@color-dhHyrz-theme_2-line: lighten(@color-dhHyrz-theme, 36%);
@color-dhHyrz-theme-sidebar: rgba(255, 255, 255, .3);
@color-dhHyrz-btn: fadeout(darken(@color-dhHyrz-theme, 5%), 15%);
@color-dhHyrz-btn-background: fadeout(lighten(@color-dhHyrz-theme, 35%), 70%);
@color-dhHyrz-pagination-background: fadeout(lighten(@color-dhHyrz-theme, 45%), 50%);
@color-dhHyrz-pagination-hover: fadeout(lighten(@color-dhHyrz-theme, 10%), 70%);
@color-dhHyrz-pagination-active: fadeout(darken(@color-dhHyrz-theme, 10%), 70%);
@color-dhHyrz-pagination-select: fadeout(lighten(@color-dhHyrz-theme, 10%), 55%);
@color-dhHyrz-search-form-background: fadeout(lighten(@color-dhHyrz-theme, 30%), 20%);
@color-dhHyrz-search-list-hover: fadeout(darken(@color-dhHyrz-theme, 10%), 50%);
@color-dhHyrz-scrollbar-track: fadeout(@color-dhHyrz-theme, 80%);
@color-dhHyrz-scrollbar-thumb: fadeout(@color-dhHyrz-theme, 60%);
@color-dhHyrz-scrollbar-thumb-hover: fadeout(@color-dhHyrz-theme, 40%);
@color-dhHyrz-player-pic-c1: fadeout(@color-dhHyrz-theme_2, 50%);
@color-dhHyrz-player-pic-c2: darken(@color-dhHyrz-theme_2, 30%);
@color-dhHyrz-player-progress: darken(@color-dhHyrz-theme_2, 6%);
@color-dhHyrz-player-progress-bar1: darken(@color-dhHyrz-theme_2, 12%);
@color-dhHyrz-player-progress-bar2: lighten(@color-dhHyrz-theme, 12%);
@color-dhHyrz-player-status-text: lighten(@color-dhHyrz-theme_2-font, 10%);
@color-dhHyrz-tab-btn-background: fadeout(lighten(@color-dhHyrz-theme, 10%), 80%);
@color-dhHyrz-tab-btn-background-hover: @color-dhHyrz-theme_2-hover;
@color-dhHyrz-tab-border-top: fadeout(lighten(@color-dhHyrz-theme, 5%), 50%);
@color-dhHyrz-tab-border-bottom: lighten(@color-dhHyrz-theme, 5%);
// Width
@width-app-left: 180px;

View File

@@ -57,7 +57,7 @@ export default {
// box-shadow: 0 0 5px rgba(0, 0, 0, .3);
transition: @transition-theme;
transition-property: background-color;
background-color: @color-theme;
background-color: @color-theme-sidebar;
// background-color: @color-aside-background;
// border-right: 2px solid @color-theme;
-webkit-app-region: drag;
@@ -122,7 +122,7 @@ export default {
each(@themes, {
:global(#container.@{value}) {
.aside {
background-color: ~'@{color-@{value}-theme}';
background-color: ~'@{color-@{value}-theme-sidebar}';
}
.logo {
color: ~'@{color-@{value}-theme-font}';

View File

@@ -7,10 +7,10 @@ div(:class="$style.player")
div(:class="$style.right")
div(:class="$style.column1")
div(:class="$style.container")
div(:class="$style.title") {{title}}
div(:class="$style.title" @click="handleCopy(title)" :title="title + '(点击复制)'") {{title}}
div(:class="$style.volumeContent")
div(:class="$style.volume" @click.stop='handleChangeVolume' :title="`当前音量:${volumeStr}%`")
div(:class="$style.volumeBar" :style="{ width: volumeStr + '%' }")
div(:class="$style.volume" @click.stop='handleChangeVolume' :title="`当前音量:${parseInt(volume * 100)}%`")
div(:class="$style.volumeBar" :style="{ transform: `scaleX(${volume || 0})` }")
//- div(:class="$style.playBtn" @click='handleNext' title="音量")
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 291.063 291.064' space='preserve')
@@ -23,11 +23,11 @@ div(:class="$style.player")
use(xlink:href='#icon-pause')
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 170 170' space='preserve')
use(xlink:href='#icon-play')
div(:class="$style.column2" @click='setProgess' ref="dom_progress")
div(:class="$style.column2")
div(:class="$style.progress")
//- div(:class="[$style.progressBar, $style.progressBar1]" :style="{ width: progress + '%' }")
div(:class="[$style.progressBar, $style.progressBar2]" :style="{ width: (progress * 100 || 0) + '%' }")
//- div(:class="[$style.progressBar, $style.progressBar1]" :style="{ transform: `scaleX(${progress || 0})` }")
div(:class="[$style.progressBar, $style.progressBar2]" :style="{ transform: `scaleX(${progress || 0})` }")
div(:class="$style.progressMask" @click='setProgess' ref="dom_progress")
div(:class="$style.column3")
span {{nowPlayTimeStr}}
span(:class="$style.statusText") {{status}}
@@ -48,7 +48,7 @@ div(:class="$style.player")
<script>
import Lyric from 'lrc-file-parser'
import { rendererSend } from '../../../common/icp'
import { formatPlayTime2, getRandom, checkPath, setTitle } from '../../utils'
import { formatPlayTime2, getRandom, checkPath, setTitle, clipboardWriteText } from '../../utils'
import { mapGetters, mapActions, mapMutations } from 'vuex'
import { requestMsg } from '../../utils/message'
@@ -100,15 +100,11 @@ export default {
return this.maxPlayTime ? formatPlayTime2(this.maxPlayTime) : '00:00'
},
progress() {
// return 50
return this.nowPlayTime / this.maxPlayTime || 0
},
isAPITemp() {
return this.setting.apiSource == 'temp'
},
volumeStr() {
return parseInt(this.volume * 100)
},
},
mounted() {
this.init()
@@ -195,7 +191,7 @@ export default {
if (!this.musicInfo.songmid) return
console.log('出错')
this.stopPlay()
if (this.audio.error.code !== 1 && this.retryNum < 3) { // 若音频URL无效则尝试刷新3次URL
if (this.listId != 'download' && this.audio.error.code !== 1 && this.retryNum < 3) { // 若音频URL无效则尝试刷新3次URL
// console.log(this.retryNum)
this.audioErrorTime = this.audio.currentTime // 记录出错的播放时间
this.retryNum++
@@ -263,6 +259,7 @@ export default {
this.audioErrorTime = 0
if (this.listId == 'download') {
console.log(targetSong.filePath)
if (!checkPath(targetSong.filePath) || !targetSong.isComplate || /\.ape$/.test(targetSong.filePath)) {
return this.list.length == 1 ? null : this.handleNext()
}
@@ -455,6 +452,9 @@ export default {
handleSaveVolume(volume) {
this.setVolume(volume)
},
handleCopy(text) {
clipboardWriteText(text)
},
},
}
</script>
@@ -467,8 +467,7 @@ export default {
height: @height-player;
// background-color: rgb(245, 245, 245);
transition: @transition-theme;
transition-property: background-color, border-color;
background-color: @color-theme_2;
transition-property: border-color;
border-top: 2px solid @color-theme;
box-sizing: border-box;
display: flex;
@@ -492,7 +491,7 @@ export default {
max-height: 100%;
transition: @transition-theme;
transition-property: border-color;
border: 2px solid @color-theme_2;
border: 2px solid @color-theme_2-background_1;
}
}
.right {
@@ -551,7 +550,11 @@ export default {
position: absolute;
left: 0;
top: 0;
width: 0;
transform: scaleX(0);
transform-origin: 0;
transition-property: transform;
transition-timing-function: ease;
width: 100%;
height: 100%;
border-radius: @radius-progress-border;
transition-duration: 0.2s;
@@ -588,7 +591,7 @@ export default {
.column2 {
flex: none;
padding: 3px 0;
cursor: pointer;
position: relative;
}
.progress {
@@ -603,12 +606,23 @@ export default {
position: relative;
border-radius: @radius-progress-border;
}
.progress-mask {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
cursor: pointer;
}
.progress-bar {
position: absolute;
left: 0;
top: 0;
width: 0;
width: 100%;
height: 100%;
transform-origin: 0;
transition-property: transform;
transition-timing-function: ease-out;
border-radius: @radius-progress-border;
}
.progress-bar1 {
@@ -665,13 +679,12 @@ export default {
each(@themes, {
:global(#container.@{value}) {
.player {
background-color: ~'@{color-@{value}-theme_2}';
border-top-color: ~'@{color-@{value}-theme}';
}
.left {
color: ~'@{color-@{value}-theme}';
img {
border-color: ~'@{color-@{value}-theme_2}';
border-color: ~'@{color-@{value}-theme_2-background_1}';
}
}
.play-btn {

View File

@@ -48,7 +48,6 @@ export default {
display: flex;
height: @height-toolbar;
justify-content: flex-end;
background-color: @color-theme_2;
align-items: center;
padding-left: 15px;
-webkit-app-region: drag;
@@ -58,13 +57,6 @@ export default {
.input {
-webkit-app-region: no-drag;
}
each(@themes, {
:global(#container.@{value}) {
.toolbar {
background-color: ~'@{color-@{value}-theme_2}';
}
}
})
// img {
// flex: none;

View File

@@ -13,7 +13,6 @@ div(:class="$style.view")
.view {
position: relative;
background-color: @color-theme_2;
> * {
position: absolute;
width: 100%;
@@ -22,12 +21,4 @@ div(:class="$style.view")
// overflow: hidden;
}
each(@themes, {
:global(#container.@{value}) {
.view {
background-color: ~'@{color-@{value}-theme_2}';
}
}
})
</style>

View File

@@ -156,7 +156,7 @@ export default {
bottom: 0;
left: 0;
right: 0;
border: 1px solid #ccc;
border: 1px solid @color-theme_2-font-label;
transition: border-color 0.2s ease;
border-radius: 15%;
}
@@ -196,7 +196,7 @@ each(@themes, {
color: ~'@{color-@{value}-theme}';
// border: 1px solid #ccc;
&:after {
border-color: #ccc;
border-color: ~'@{color-@{value}-theme_2-font-label}';
}
}
}

View File

@@ -52,7 +52,7 @@ export default {
checkSource(type) {
switch (this.musicInfo.source) {
case 'wy':
case 'kg':
// case 'kg':
return type == '128k'
default:

View File

@@ -0,0 +1,90 @@
<template lang="pug">
input(:class="$style.input" :type="type" :placeholder="placeholder" v-model.trim="text" :disabled="disabled"
@focus="$emit('focus', $event)" @blur="$emit('blur', $event)" @input="$emit('input', text)" @change="$emit('change', text)"
@keyup.enter="submit")
</template>
<script>
export default {
props: {
placeholder: {
type: String,
default: '',
},
disabled: {
type: Boolean,
default: false,
},
value: {
type: String,
default: '',
},
type: {
type: String,
default: 'text',
},
},
data() {
return {
text: '',
}
},
watch: {
value(n) {
this.text = n
},
},
methods: {
handleInput() {
},
},
}
</script>
<style lang="less" module>
@import '../../assets/styles/layout.less';
.input {
display: inline-block;
border: none;
border-radius: 3px;
padding: 7px 8px;
color: @color-btn;
outline: none;
transition: background-color 0.2s ease;
background-color: @color-btn-background;
&[disabled] {
opacity: .4;
}
&:hover, &:focus {
background-color: @color-theme_2-hover;
}
&:active {
background-color: @color-theme_2-active;
}
}
.min {
padding: 3px 8px;
font-size: 12px;
}
each(@themes, {
:global(#container.@{value}) {
.input {
color: ~'@{color-@{value}-btn}';
background-color: ~'@{color-@{value}-btn-background}';
&:hover, &:focus {
background-color: ~'@{color-@{value}-theme_2-hover}';
}
&:active {
background-color: ~'@{color-@{value}-theme_2-active}';
}
}
}
})
</style>

View File

@@ -134,7 +134,7 @@ export default {
flex-flow: column nowrap;
> * {
background-color: @color-theme_2;
background-color: @color-theme_2-background_2;
}
}
@@ -176,7 +176,7 @@ each(@themes, {
.content {
box-shadow: 0 0 3px rgba(0, 0, 0, .3);
> * {
background-color: ~'@{color-@{value}-theme_2}';
background-color: ~'@{color-@{value}-theme_2-background_2}';
}
}

View File

@@ -34,11 +34,14 @@ export default {
}
},
computed: {
...mapGetters(['source', 'route', 'setting']),
...mapGetters('search', ['info']),
...mapGetters(['route', 'setting']),
...mapGetters('search', ['searchText']),
isAutoClearInput() {
return this.setting.odc.isAutoClearSearchInput
},
source() {
return this.setting.search.tempSearchSource
},
},
watch: {
list(n) {
@@ -46,7 +49,7 @@ export default {
this.listStyle.height = this.$refs.dom_list.scrollHeight + 'px'
})
},
'info.text'(n) {
'searchText'(n) {
if (n !== this.text) this.text = n
},
route(n) {
@@ -76,16 +79,16 @@ export default {
query: {
text: this.text,
},
})
}).catch(_ => _)
},
handleInput() {
if (this.text === '') {
this.list.splice(0, this.list.length)
music[this.source.id].tempSearch.cancelTempSearch()
music[this.source].tempSearch.cancelTempSearch()
return
}
if (!this.isShow) this.showList()
music[this.source.id].tempSearch.search(this.text).then(list => {
music[this.source].tempSearch.search(this.text).then(list => {
this.list = list
}).catch(() => {})
},

View File

@@ -1,7 +1,7 @@
<template lang="pug">
div(:class="$style.select")
div(:class="[$style.select, show ? $style.active : '']")
div(:class="$style.label" ref="dom_btn" @click="handleShow") {{value ? itemName ? list.find(l => l.id == value).name : value : ''}}
ul(:class="$style.list" ref="dom_list" :style="listStyle")
ul(:class="$style.list")
li(v-for="item in list" @click="handleClick(itemKey ? item[itemKey] : item)") {{itemName ? item[itemName] : item}}
</template>
@@ -28,25 +28,8 @@ export default {
data() {
return {
show: false,
listStyle: {
height: 0,
opacity: 0,
},
}
},
watch: {
show(n) {
this.$nextTick(() => {
if (n) {
this.listStyle.height = this.$refs.dom_list.scrollHeight + 'px'
this.listStyle.opacity = 1
} else {
this.listStyle.height = 0
this.listStyle.opacity = 0
}
})
},
},
mounted() {
document.addEventListener('click', this.handleHide)
},
@@ -80,6 +63,13 @@ export default {
.select {
font-size: 12px;
position: relative;
&.active {
.list {
transform: scaleY(1);
opacity: 1;
}
}
}
.label {
@@ -90,7 +80,7 @@ export default {
border-left: 2px solid @color-tab-border-bottom;
box-sizing: border-box;
text-align: center;
border-top-left-radius: 3px;
border-top-left-radius: 4px;
color: @color-btn;
cursor: pointer;
@@ -108,12 +98,13 @@ export default {
left: 0;
border-bottom: 2px solid @color-tab-border-bottom;
border-left: 2px solid @color-tab-border-bottom;
border-bottom-left-radius: 3px;
background-color: @color-theme_2;
overflow: hidden;
border-bottom-left-radius: 4px;
background-color: @color-theme_2-background_2;
opacity: 0;
transform: scaleY(0);
transform-origin: 0 0 0;
transition: .25s ease;
transition-property: height, opacity;
transition-property: transform, opacity;
z-index: 10;
li {
@@ -153,6 +144,7 @@ each(@themes, {
.list {
border-bottom-color: ~'@{color-@{value}-tab-border-bottom}';
border-left-color: ~'@{color-@{value}-tab-border-bottom}';
background-color: ~'@{color-@{value}-theme_2-background_2}';
li {
// color: ~'@{color-@{value}-btn}';
background-color: ~'@{color-@{value}-btn-background}';

View File

@@ -175,7 +175,6 @@ export default {
height: 100%;
display: flex;
flex-flow: column nowrap;
background-color: @color-theme_2;
}
.list {
@@ -220,16 +219,17 @@ export default {
p {
font-size: 24px;
color: #ccc;
color: @color-theme_2-font-label;
}
}
each(@themes, {
:global(#container.@{value}) {
.thead {
background-color: ~'@color-@{value}-theme_2';
.noitem {
p {
color: ~'@{color-@{value}-theme_2-font-label}';
}
}
}
})
</style>

View File

@@ -95,15 +95,15 @@ export default {
margin-left: 0;
button {
border-top-left-radius: 3px;
// border-bottom-left-radius: 3px;
// border-bottom-left-radius: 4px;
}
}
&:last-child {
border-right: 2px solid @color-tab-border-top;
border-top-right-radius: 3px;
border-top-right-radius: 4px;
button {
border-top-right-radius: 3px;
// border-bottom-right-radius: 3px;
// border-bottom-right-radius: 4px;
}
}
button {
@@ -122,7 +122,7 @@ export default {
// border-left-color: @color-theme_2-hover;
// border-right-color: @color-theme_2-hover;
button {
background-color: @color-theme_2-hover;
background-color: @color-tab-btn-background-hover;
}
}
&:active {
@@ -133,7 +133,7 @@ export default {
}
}
&.active {
border-bottom-color: @color-theme_2;
border-bottom-color: @color-theme_2-background_1;
border-top-color: @color-tab-border-bottom;
border-left-color: @color-tab-border-bottom;
border-right-color: @color-tab-border-bottom;
@@ -144,7 +144,7 @@ export default {
width: 0;
}
button {
background-color: @color-theme_2;
background-color: @color-theme_2-background_1;
}
}
}
@@ -193,7 +193,7 @@ each(@themes, {
// border-left-color: ~'@{color-@{value}-theme_2-hover}';
// border-right-color: ~'@{color-@{value}-theme_2-hover}';
button {
background-color: ~'@{color-@{value}-theme_2-hover}';
background-color: ~'@{color-@{value}-tab-btn-background-hover}';
}
}
&:active {
@@ -209,7 +209,7 @@ each(@themes, {
border-left-color: ~'@{color-@{value}-tab-border-bottom}';
border-right-color: ~'@{color-@{value}-tab-border-bottom}';
button {
background-color: ~'@{color-@{value}-theme_2}';
background-color: ~'@{color-@{value}-theme_2-background_1}';
}
}
}

View File

@@ -1,11 +1,11 @@
<template lang="pug">
div(:class="$style.tagList")
div(:class="[$style.tagList, show ? $style.active : '']")
div(:class="$style.label" ref="dom_btn" @click="handleShow")
span {{value.name}}
div(:class="[$style.icon, show ? $style.active : '']")
div(:class="$style.icon")
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 451.847 451.847' space='preserve')
use(xlink:href='#icon-down')
div.scroll(:class="$style.list" @click.stop ref="dom_list" :style="listStyle")
div.scroll(:class="$style.list" @click.stop ref="dom_list")
div(:class="$style.tag" @click="handleClick(null)") 默认
dl(v-for="type in list")
dt(:class="$style.type") {{type.name}}
@@ -29,30 +29,8 @@ export default {
data() {
return {
show: false,
listStyle: {
height: 0,
opacity: 0,
},
}
},
watch: {
show(n) {
this.$nextTick(() => {
if (n) {
let sh = this.$refs.dom_list.scrollHeight
this.listStyle.height = (sh > 250 ? 250 : sh) + 'px'
this.listStyle.opacity = 1
this.listStyle.overflow = 'auto'
} else {
this.listStyle.height = 0
this.listStyle.opacity = 0
}
})
},
list() {
this.$refs.dom_list.scrollTop = 0
},
},
mounted() {
document.addEventListener('click', this.handleHide)
},
@@ -93,6 +71,20 @@ export default {
.tag-list {
font-size: 12px;
position: relative;
&.active {
.label {
.icon {
svg{
transform: rotate(180deg);
}
}
}
.list {
opacity: 1;
transform: scaleY(1);
}
}
}
.label {
@@ -121,11 +113,6 @@ export default {
transition: transform .2s ease;
transform: rotate(0);
}
&.active {
svg{
transform: rotate(180deg);
}
}
}
&:hover {
@@ -144,11 +131,14 @@ export default {
border-bottom: 2px solid @color-tab-border-bottom;
border-right: 2px solid @color-tab-border-bottom;
border-bottom-right-radius: 5px;
background-color: @color-theme_2;
overflow: hidden;
background-color: @color-theme_2-background_2;
opacity: 0;
transform: scaleY(0);
overflow-y: auto;
transform-origin: 0 0 0;
max-height: 250px;
transition: .25s ease;
transition-property: height, opacity;
transition-property: transform, opacity;
z-index: 10;
padding: 10px;
box-sizing: border-box;
@@ -212,6 +202,7 @@ each(@themes, {
.list {
border-bottom-color: ~'@{color-@{value}-tab-border-bottom}';
border-right-color: ~'@{color-@{value}-tab-border-bottom}';
background-color: ~'@{color-@{value}-theme_2-background_2}';
// border-left-color: ~'@{color-@{value}-tab-border-bottom}';
li {
// color: ~'@{color-@{value}-btn}';

View File

@@ -17,17 +17,19 @@ material-modal(:show="version.showModal" @close="handleClose")
div(:class="$style.footer" v-if="version.isError")
div(:class="$style.desc" v-if="!isUnknow")
p 发现有新版本啦但是自动更新功能出问题了
p
| 如果你所用的软件是
strong 安装版
| 可以到QQ群830125506 反馈哦
p 发现有新版本啦但是自动更新功能出问题了
p
| 你现在可以选择继续使用当前版本或
strong 去发布页下载新版本
|
p
| 国内Windows/MAC用户推荐到
strong.hover.underline(@click="handleOpenUrl('https://www.lanzous.com/b906260/')") 网盘(点击打开)
| 下载密码
strong.hover(@click="handleCopy('glqw')" title="点击复制") glqw
div(:class="$style.btns")
material-btn(:class="$style.btn" @click.onec="handleIgnoreClick") 忽略该版本
material-btn(:class="$style.btn" @click.onec="handleOpenPageClick") 下载新版本
material-btn(:class="$style.btn" @click.onec="handleOpenUrl('https://github.com/lyswhut/lx-music-desktop#readme')") 软件发布页
div(:class="$style.footer" v-else)
div(:class="$style.desc")
p 新版本已下载完毕
@@ -44,7 +46,7 @@ material-modal(:show="version.showModal" @close="handleClose")
<script>
import { mapGetters, mapMutations } from 'vuex'
import { rendererSend } from '../../../common/icp'
import { checkVersion, openUrl } from '../../utils'
import { checkVersion, openUrl, clipboardWriteText } from '../../utils'
export default {
computed: {
@@ -75,14 +77,17 @@ export default {
// event.target.disabled = true
this.setSetting(Object.assign({}, this.setting, { ignoreVersion: this.version.newVersion.version }))
},
handleOpenPageClick() {
openUrl('https://github.com/lyswhut/lx-music-desktop')
handleOpenUrl(url) {
openUrl(url)
},
handleRestartClick(event) {
this.handleClose()
event.target.disabled = true
rendererSend('quit-update')
},
handleCopy(text) {
clipboardWriteText(text)
},
},
}
</script>
@@ -124,6 +129,7 @@ export default {
line-height: 1.5;
overflow-y: auto;
height: 100%;
padding-right: 5px;
}
.current {
> p {
@@ -170,12 +176,9 @@ export default {
flex: 0 0 none;
.desc {
font-size: 12px;
padding: 10px 0;
padding-top: 10px;
color: @color-theme;
line-height: 1.2;
strong {
text-decoration: underline;
}
}
}
.btn {
@@ -184,6 +187,7 @@ export default {
}
.btns {
display: grid;
padding-top: 10px;
grid-template-columns: 1fr 1fr;
grid-gap: 0 10px;
}

View File

@@ -3,15 +3,17 @@ import { httpGet } from '../utils/request'
import { author, name } from '../../../package.json'
export default {
getVersionInfo() {
getVersionInfo(state, retryNum = 0) {
return new Promise((resolve, reject) => {
httpGet(`https://raw.githubusercontent.com/${author.name}/${name}/master/publish/version.json`, (err, resp, body) => {
httpGet(`https://raw.githubusercontent.com/${author.name}/${name}/master/publish/version.json`, {
timeout: 20000,
}, (err, resp, body) => {
if (err) {
return resolve({
return ++retryNum > 3 ? resolve({
version: '0.0.0',
desc: '<h3>版本信息获取失败</h3><ul><li>更新信息获取失败可能是无法访问Github导致的请手动检查更新</li><li>检查方法:去设置-关于洛雪音乐打开<strong>开源地址</strong>或<strong>网盘地址</strong>查看<strong>版本号</strong>与当前版本对比是否最新</li></ul>',
history: [],
})
}) : this.dispatch('getVersionInfo', retryNum).then(ver => resolve(ver))
}
resolve(body)
})

View File

@@ -22,6 +22,8 @@ const state = {
const dls = {}
const tryNum = {}
const filterFileName = /[\\/:*?#"<>|]/g
// getters
const getters = {
list: state => state.list || [],
@@ -83,7 +85,7 @@ const getUrl = (downloadInfo, isRefresh) => {
* @param {*} isEmbedPic
*/
const saveMeta = (downloadInfo, filePath, isEmbedPic) => {
if (downloadInfo.type === 'ape') return
if (downloadInfo.type === 'ape' || downloadInfo.type === 'flac') return
const promise = isEmbedPic
? downloadInfo.musicInfo.img
? Promise.resolve(downloadInfo.musicInfo.img)
@@ -125,7 +127,7 @@ const actions = {
url: null,
fileName: `${rootState.setting.download.fileName
.replace('歌名', musicInfo.name)
.replace('歌手', musicInfo.singer)}.${ext}`,
.replace('歌手', musicInfo.singer)}.${ext}`.replace(filterFileName, ''),
progress: {
downloaded: 0,
total: 0,

View File

@@ -1,41 +1,103 @@
import music from '../../utils/music'
const sources = []
const sourceList = {}
const sourceMaxPage = {}
for (const source of music.sources) {
const musicSearch = music[source.id].musicSearch
if (!musicSearch) continue
sources.push(source)
sourceList[source.id] = {
page: 1,
allPage: 0,
limit: 30,
total: 0,
list: [],
}
sourceMaxPage[source.id] = 0
}
sources.push({
id: 'all',
name: '聚合搜索',
})
// state
const state = {
sourceList,
list: [],
text: '',
page: 1,
limit: 30,
allPage: 1,
total: 0,
sourceMaxPage,
}
// getters
const getters = {
list: state => state.list || [],
limit: state => state.limit,
info: state => ({ page: state.page, text: state.text }),
listInfo: state => ({ allPage: state.allPage, total: state.total }),
sources: () => sources,
sourceList: state => state.sourceList || [],
searchText: state => state.text,
allList: state => ({ list: state.list, allPage: state.allPage, page: state.page, total: state.total, limit: state.limit, sourceMaxPage: state.sourceMaxPage }),
}
// actions
const actions = {
search({ commit, rootState }, { text, page, limit }) {
return music[rootState.setting.sourceId].musicSearch.search(text, page, limit)
.then(data => commit('setList', { list: data.list, allPage: data.allPage, total: data.total, text, page }))
if (rootState.setting.search.searchSource == 'all') {
let task = []
for (const source of sources) {
if (source.id == 'all') continue
task.push(music[source.id].musicSearch.search(text, page))
}
Promise.all(task).then(results => commit('setLists', { results, text, page }))
} else {
return music[rootState.setting.search.searchSource].musicSearch.search(text, page, limit)
.then(data => commit('setList', { text, page, ...data }))
}
},
}
// mitations
const mutations = {
setList(state, datas) {
state.list = datas.list
state.total = datas.total
state.allPage = datas.allPage
state.page = datas.page
let source = state.sourceList[datas.source]
source.list = datas.list
source.total = datas.total
source.allPage = datas.allPage
source.page = datas.page
source.limit = datas.limit
state.text = datas.text
},
setLists(state, { results, text, page }) {
let pages = []
let total = 0
let limit = 0
let list = []
for (const source of results) {
state.sourceMaxPage[source.source] = source.allPage
if (source.allPage < page) continue
list.push(...source.list)
pages.push(source.allPage)
total += source.total
limit += source.limit
}
list.sort((a, b) => b.name.charCodeAt(0) - a.name.charCodeAt(0))
state.allPage = Math.max(...pages)
state.total = total
state.limit = limit
state.page = page
state.text = text
state.list = list
},
clearList(state) {
for (const source of Object.keys(state.sourceList)) {
state.sourceList[source].list.length = 0
state.sourceList[source].page = 0
state.sourceList[source].allPage = 0
state.sourceList[source].total = 0
state.sourceMaxPage[source] = 0
}
state.list.length = 0
state.page = 0
state.allPage = 0

View File

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

View File

@@ -2,8 +2,9 @@ export default {
setTheme(state, val) {
state.setting.themeId = val
},
setSource(state, val) {
state.setting.sourceId = val
setSearchSource(state, { searchSource, tempSearchSource }) {
if (searchSource != null) state.setting.search.searchSource = searchSource
if (tempSearchSource != null) state.setting.search.tempSearchSource = tempSearchSource
},
setSetting(state, val) {
state.setting = val
@@ -17,6 +18,9 @@ export default {
if (sortId != null) state.setting.songList.sortId = sortId
if (source != null) state.setting.songList.source = source
},
setListScroll(state, scrollTop) {
state.setting.list.scroll.location = scrollTop
},
setNewVersion(state, val) {
// val.history.forEach(ver => {
// ver.desc = ver.desc.replace(/\n/g, '<br>')

View File

@@ -6,6 +6,7 @@ import { version } from '../../../package.json'
let electronStore = new Store()
const setting = updateSetting(electronStore.get('setting'))
electronStore.set('setting', setting)
process.versions.app = version
export default {
themes: [
@@ -44,6 +45,16 @@ export default {
name: '灰常美丽',
class: 'grey',
},
{
id: 7,
name: '月里嫦娥',
class: 'midAutumn',
},
{
id: 8,
name: '木叶之村',
class: 'dhHyrz',
},
],
version: {
version,

View File

@@ -43,7 +43,8 @@ export const b64DecodeUnicode = str => {
export const decodeName = str => str.replace(/&apos;/g, '\'')
export const scrollTo = (element, to, duration = 300, fn = function() {}) => {
const start = element.scrollTop || element.scrollY
if (!element) return
const start = element.scrollTop || element.scrollY || 0
const change = to - start
const increment = 10
if (!change) {
@@ -163,7 +164,7 @@ export const isChildren = (parent, children) => {
* @param {*} setting
*/
export const updateSetting = setting => {
const defaultVersion = '1.0.7'
const defaultVersion = '1.0.10'
const defaultSetting = {
version: defaultVersion,
player: {
@@ -174,6 +175,10 @@ export const updateSetting = setting => {
},
list: {
isShowAlbumName: true,
scroll: {
enable: true,
location: 0,
},
},
download: {
savePath: path.join(os.homedir(), 'Desktop'),
@@ -197,6 +202,19 @@ export const updateSetting = setting => {
odc: {
isAutoClearSearchInput: false,
},
search: {
searchSource: 'kw',
tempSearchSource: 'kw',
},
network: {
proxy: {
enable: false,
host: '',
port: '',
username: '',
password: '',
},
},
themeId: 0,
sourceId: 'kw',
apiSource: 'test',
@@ -205,7 +223,6 @@ export const updateSetting = setting => {
}
const overwriteSetting = {
version: defaultVersion,
sourceId: 'kw',
}
@@ -268,3 +285,21 @@ export const saveLrc = (filePath, lrc) => {
if (err) console.log(err)
})
}
/**
* 生成节流函数
* @param {*} fn
* @param {*} delay
*/
export const throttle = (fn, delay = 100) => {
let timer = null
let _args = null
return function(...args) {
_args = args
if (timer) return
timer = setTimeout(() => {
timer = null
fn.apply(this, _args)
}, delay)
}
}

View File

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

View File

@@ -2,19 +2,32 @@ import leaderboard from './leaderboard'
import api_source from '../api-source'
import musicInfo from './musicInfo'
import songList from './songList'
import { httpFetch } from '../../request'
import musicSearch from './musicSearch'
const bd = {
leaderboard,
songList,
musicSearch,
getMusicUrl(songInfo, type) {
return api_source('bd').getMusicUrl(songInfo, type)
},
getLyric(songInfo) {
return api_source('bd').getLyric(songInfo)
},
getPic(songInfo) {
return api_source('bd').getPic(songInfo)
const requestObj = this.getMusicInfo(songInfo)
requestObj.promise = requestObj.promise.then(info => info.pic_premium)
return requestObj
},
getLyric(songInfo) {
const requestObj = this.getMusicInfo(songInfo)
requestObj.promise = requestObj.promise.then(info => httpFetch(info.lrclink).promise.then(resp => resp.body))
return requestObj
},
// getLyric(songInfo) {
// return api_source('bd').getLyric(songInfo)
// },
// getPic(songInfo) {
// return api_source('bd').getPic(songInfo)
// },
getMusicInfo(songInfo) {
return musicInfo.getMusicInfo(songInfo.songmid)
},

View File

@@ -1,4 +1,4 @@
import { httpFatch } from '../../request'
import { httpFetch } from '../../request'
// import { formatPlayTime } from '../../index'
// import jshtmlencode from 'js-htmlencode'
@@ -66,7 +66,7 @@ export default {
requestObj: null,
getData(url) {
if (this.requestObj) this.requestObj.cancelHttp()
this.requestObj = httpFatch(url)
this.requestObj = httpFetch(url)
return this.requestObj.promise
},
filterData(rawList) {
@@ -85,7 +85,7 @@ export default {
size,
}
types.push({ type: 'flac', size })
_types['flac'] = {
_types.flac = {
size,
}
}
@@ -126,6 +126,7 @@ export default {
list,
limit: this.limit,
page: parseInt(info[3]),
source: 'bd',
}
})
},

View File

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

View File

@@ -0,0 +1,89 @@
// import '../../polyfill/array.find'
// import jshtmlencode from 'js-htmlencode'
import { httpFetch } from '../../request'
import { formatPlayTime } from '../../index'
// import { debug } from '../../utils/env'
// import { formatSinger } from './util'
let searchRequest
export default {
limit: 30,
total: 0,
page: 0,
allPage: 1,
musicSearch(str, page) {
if (searchRequest && searchRequest.cancelHttp) searchRequest.cancelHttp()
searchRequest = httpFetch(`http://tingapi.ting.baidu.com/v1/restserver/ting?from=android&version=5.6.5.6&method=baidu.ting.search.merge&format=json&query=${encodeURIComponent(str)}&page_no=${page}&page_size=${this.limit}&type=0&data_source=0&use_cluster=1`)
return searchRequest.promise.then(({ body }) => body)
},
handleResult(rawData) {
let ids = new Set()
const list = []
if (!rawData) return list
rawData.forEach(item => {
if (ids.has(item.song_id)) return
ids.add(item.song_id)
const types = []
const _types = {}
let size = null
let itemTypes = item.all_rate.split(',')
if (itemTypes.includes('128')) {
types.push({ type: '128k', size })
_types['128k'] = {
size,
}
}
if (itemTypes.includes('320')) {
types.push({ type: '320k', size })
_types['320k'] = {
size,
}
}
if (itemTypes.includes('flac')) {
types.push({ type: 'flac', size })
_types.flac = {
size,
}
}
// types.reverse()
list.push({
singer: item.author.replace(',', '、'),
name: item.title,
albumName: item.album_title,
albumId: item.album_id,
source: 'bd',
interval: formatPlayTime(parseInt(item.file_duration)),
songmid: item.song_id,
img: null,
lrc: null,
types,
_types,
typeUrl: {},
})
})
return list
},
search(str, page = 1, { limit } = {}) {
if (limit != null) this.limit = limit
return this.musicSearch(str, page).then(result => {
if (!result || result.error_code !== 22000) return this.search(str, page, { limit })
let list = this.handleResult(result.result.song_info.song_list)
if (list == null) return this.search(str, page, { limit })
this.total = result.result.song_info.total
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: 'bd',
})
})
},
}

View File

@@ -1,4 +1,4 @@
import { httpFatch } from '../../request'
import { httpFetch } from '../../request'
import { formatPlayTime, toMD5 } from '../../index'
import CryptoJS from 'crypto-js'
@@ -110,12 +110,13 @@ export default {
// 获取标签
getTags() {
if (this._requestObj_tags) this._requestObj_tags.cancelHttp()
this._requestObj_tags = httpFatch(this.getTagsUrl())
this._requestObj_tags = httpFetch(this.getTagsUrl())
return this._requestObj_tags.promise.then(({ body }) => {
if (body.error_code !== this.successCode) return this.getTags()
return {
hotTag: this.filterInfoHotTag(body.result.hot),
tags: this.filterTagInfo(body.result.tags),
source: 'bd',
}
})
},
@@ -123,6 +124,7 @@ export default {
return rawList.map(item => ({
name: item,
id: item,
source: 'bd',
}))
},
filterTagInfo(rawList) {
@@ -133,6 +135,7 @@ export default {
parent_name: type.first,
id: item,
name: item,
source: 'bd',
})),
}))
},
@@ -140,7 +143,7 @@ export default {
// 获取列表数据
getList(sortId, tagId, page) {
if (this._requestObj_list) this._requestObj_list.cancelHttp()
this._requestObj_list = httpFatch(
this._requestObj_list = httpFetch(
this.getListUrl(sortId, tagId, page)
)
return this._requestObj_list.promise.then(({ body }) => {
@@ -150,6 +153,7 @@ export default {
total: body.nums,
page,
limit: this.limit_list,
source: 'bd',
}
})
},
@@ -174,6 +178,7 @@ export default {
img: item.list_pic_large || item.list_pic,
grade: item.grade,
desc: item.desc || item.tag,
source: 'bd',
}))
},
@@ -182,7 +187,7 @@ export default {
if (this._requestObj_listDetail) {
this._requestObj_listDetail.cancelHttp()
}
this._requestObj_listDetail = httpFatch(this.getListDetailUrl(id, page))
this._requestObj_listDetail = httpFetch(this.getListDetailUrl(id, page))
return this._requestObj_listDetail.promise.then(({ body }) => {
if (body.error_code !== this.successCode) return this.getListDetail(id, page)
let listData = this.filterData(body.result.songlist)
@@ -191,6 +196,7 @@ export default {
page,
limit: this.limit_song,
total: body.result.song_num,
source: 'bd',
}
})
},
@@ -215,7 +221,7 @@ export default {
}
if (itemTypes.includes('flac')) {
types.push({ type: 'flac', size })
_types['flac'] = {
_types.flac = {
size,
}
}

View File

@@ -1,13 +1,14 @@
import { httpFatch } from '../../request'
import { httpFetch } from '../../request'
import { requestMsg } from '../../message'
import { headers, timeout } from '../options'
const api_test = {
getMusicUrl(songInfo, type) {
const requestObj = httpFatch(`http://test.tempmusic.tk/url/kg/${songInfo._types[type].hash}/${type}`, {
const requestObj = httpFetch(`http://ts.tempmusic.tk/url/kg/${songInfo._types[type].hash}/${type}`, {
method: 'get',
timeout,
headers,
family: 4,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body.code === 0 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail))
@@ -15,10 +16,11 @@ const api_test = {
return requestObj
},
getPic(songInfo) {
const requestObj = httpFatch(`http://test.tempmusic.tk/pic/kg/${songInfo.hash}`, {
const requestObj = httpFetch(`http://ts.tempmusic.tk/pic/kg/${songInfo.hash}`, {
method: 'get',
timeout,
headers,
family: 4,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body.code === 0 ? Promise.resolve(body.data) : Promise.reject(new Error(requestMsg.fail))
@@ -26,10 +28,11 @@ const api_test = {
return requestObj
},
getLyric(songInfo) {
const requestObj = httpFatch(`http://test.tempmusic.tk/lrc/kg/${songInfo.hash}`, {
const requestObj = httpFetch(`http://ts.tempmusic.tk/lrc/kg/${songInfo.hash}`, {
method: 'get',
timeout,
headers,
family: 4,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body.code === 0 ? Promise.resolve(body.data) : Promise.reject(new Error(requestMsg.fail))

View File

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

View File

@@ -159,6 +159,7 @@ export default {
list: listData,
limit,
page,
source: 'kg',
}
})
},

View File

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

View File

@@ -0,0 +1,93 @@
// import '../../polyfill/array.find'
// import jshtmlencode from 'js-htmlencode'
import { httpFetch } from '../../request'
import { formatPlayTime, sizeFormate } from '../../index'
// import { debug } from '../../utils/env'
// import { formatSinger } from './util'
let searchRequest
export default {
limit: 30,
total: 0,
page: 0,
allPage: 1,
musicSearch(str, page) {
if (searchRequest && searchRequest.cancelHttp) searchRequest.cancelHttp()
searchRequest = httpFetch(`http://ioscdn.kugou.com/api/v3/search/song?keyword=${encodeURIComponent(str)}&page=${page}&pagesize=${this.limit}&showtype=10&plat=2&version=7910&tag=1&correct=1&privilege=1&sver=5`)
return searchRequest.promise.then(({ body }) => body)
},
handleResult(rawData) {
// console.log(rawData)
let ids = new Set()
const list = []
rawData.forEach(item => {
if (ids.has(item.audio_id)) return
ids.add(item.audio_id)
const types = []
const _types = {}
if (item.filesize !== 0) {
let size = sizeFormate(item.filesize)
types.push({ type: '128k', size, hash: item.hash })
_types['128k'] = {
size,
hash: item.hash,
}
}
if (item['320filesize'] !== 0) {
let size = sizeFormate(item['320filesize'])
types.push({ type: '320k', size, hash: item['320hash'] })
_types['320k'] = {
size,
hash: item['320hash'],
}
}
if (item.sqfilesize !== 0) {
let size = sizeFormate(item.sqfilesize)
types.push({ type: 'flac', size, hash: item.sqhash })
_types.flac = {
size,
hash: item.sqhash,
}
}
list.push({
singer: item.singername,
name: item.songname,
albumName: item.album_name,
albumId: item.album_id,
songmid: item.audio_id,
source: 'kg',
interval: formatPlayTime(item.duration),
_interval: item.duration,
img: null,
lrc: null,
hash: item.hash,
types,
_types,
typeUrl: {},
})
})
return list
},
search(str, page = 1, { limit } = {}) {
if (limit != null) this.limit = limit
// http://newlyric.kuwo.cn/newlyric.lrc?62355680
return this.musicSearch(str, page).then(result => {
if (!result || result.errcode !== 0) return this.search(str, page, { limit })
let list = this.handleResult(result.data.info)
if (list == null) return this.search(str, page, { limit })
this.total = result.data.total
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: 'kg',
})
})
},
}

View File

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

View File

@@ -1,4 +1,4 @@
import { httpFatch } from '../../request'
import { httpFetch } from '../../request'
import { formatPlayTime, sizeFormate } from '../../index'
export default {
@@ -39,7 +39,7 @@ export default {
getInfoUrl(tagId) {
return tagId
? `http://www2.kugou.kugou.com/yueku/v9/special/getSpecial?is_smarty=1&cdn=cdn&t=5&c=${tagId}`
: `http://www2.kugou.kugou.com/yueku/v9/special/getSpecial?is_smarty=1&`
: 'http://www2.kugou.kugou.com/yueku/v9/special/getSpecial?is_smarty=1&'
},
getSongListUrl(sortId, tagId, page) {
if (tagId == null) tagId = ''
@@ -80,6 +80,7 @@ export default {
parent_name: tag.pname,
id: tag.id,
name: tag.name,
source: 'kg',
})),
})
}
@@ -88,7 +89,7 @@ export default {
getSongList(sortId, tagId, page) {
if (this._requestObj_list) this._requestObj_list.cancelHttp()
this._requestObj_list = httpFatch(
this._requestObj_list = httpFetch(
this.getSongListUrl(sortId, tagId, page)
)
return this._requestObj_list.promise.then(({ body }) => {
@@ -98,7 +99,7 @@ export default {
},
getSongListRecommend() {
if (this._requestObj_listRecommend) this._requestObj_listRecommend.cancelHttp()
this._requestObj_listRecommend = httpFatch(
this._requestObj_listRecommend = httpFetch(
'http://everydayrec.service.kugou.com/guess_special_recommend',
{
method: 'post',
@@ -133,12 +134,13 @@ export default {
img: item.img || item.imgurl,
grade: item.grade,
desc: item.intro,
source: 'kg',
}))
},
getListDetail(id, page) { // 获取歌曲列表内的音乐
if (this._requestObj_listDetail) this._requestObj_listDetail.cancelHttp()
this._requestObj_listDetail = httpFatch(this.getSongListDetailUrl(id))
this._requestObj_listDetail = httpFetch(this.getSongListDetailUrl(id))
return this._requestObj_listDetail.promise.then(({ body }) => {
let listData = body.match(this.regExps.listData)
if (listData) listData = this.filterData(JSON.parse(RegExp.$1))
@@ -147,6 +149,7 @@ export default {
page: 1,
limit: 10000,
total: listData.length,
source: 'kg',
}
})
},
@@ -208,13 +211,14 @@ export default {
// 获取列表信息
getListInfo(tagId) {
if (this._requestObj_listInfo) this._requestObj_listInfo.cancelHttp()
this._requestObj_listInfo = httpFatch(this.getInfoUrl(tagId))
this._requestObj_listInfo = httpFetch(this.getInfoUrl(tagId))
return this._requestObj_listInfo.promise.then(({ body }) => {
if (body.status !== 1) return this.getListInfo(tagId)
return {
limit: body.data.params.pagesize,
page: body.data.params.p,
total: body.data.params.total,
source: 'kg',
}
})
},
@@ -244,12 +248,13 @@ export default {
// 获取标签
getTags() {
if (this._requestObj_tags) this._requestObj_tags.cancelHttp()
this._requestObj_tags = httpFatch(this.getInfoUrl())
this._requestObj_tags = httpFetch(this.getInfoUrl())
return this._requestObj_tags.promise.then(({ body }) => {
if (body.status !== 1) return this.getTags()
return {
hotTag: this.filterInfoHotTag(body.data.hotTag),
tags: this.filterTagInfo(body.data.tagids),
source: 'kg',
}
})
},

View File

@@ -1,12 +1,13 @@
import { httpFatch } from '../../request'
import { httpFetch } from '../../request'
import { headers, timeout } from '../options'
const api_temp = {
getMusicUrl(songInfo, type) {
const requestObj = httpFatch(`http://temp.tempmusic.tk/url/kw/${songInfo.songmid}/${type}`, {
const requestObj = httpFetch(`http://tm.tempmusic.tk/url/kw/${songInfo.songmid}/${type}`, {
method: 'get',
headers,
timeout,
family: 4,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body.code === 0 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(body.msg))

View File

@@ -1,10 +1,10 @@
import { httpFatch } from '../../request'
import { httpFetch } from '../../request'
import { requestMsg } from '../../message'
import { headers, timeout } from '../options'
const api_test = {
// getMusicUrl(songInfo, type) {
// const requestObj = httpFatch(`http://45.32.53.128:3002/m/kw/u/${songInfo.songmid}/${type}`, {
// const requestObj = httpFetch(`http://45.32.53.128:3002/m/kw/u/${songInfo.songmid}/${type}`, {
// method: 'get',
// headers,
// timeout,
@@ -15,10 +15,11 @@ const api_test = {
// return requestObj
// },
getMusicUrl(songInfo, type) {
const requestObj = httpFatch(`http://test.tempmusic.tk/url/kw/${songInfo.songmid}/${type}`, {
const requestObj = httpFetch(`http://ts.tempmusic.tk/url/kw/${songInfo.songmid}/${type}`, {
method: 'get',
timeout,
headers,
family: 4,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body.code === 0 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail))

View File

@@ -119,27 +119,27 @@ export default {
size: null,
}
}
if (formats.indexOf('MP3192')) {
types.push({ type: '192k', size: null })
_types['192k'] = {
size: null,
}
}
// if (formats.indexOf('MP3192')) {
// types.push({ type: '192k', size: null })
// _types['192k'] = {
// size: null,
// }
// }
if (formats.indexOf('MP3H')) {
types.push({ type: '320k', size: null })
_types['320k'] = {
size: null,
}
}
if (formats.indexOf('AL')) {
types.push({ type: 'ape', size: null })
_types['ape'] = {
size: null,
}
}
// if (formats.indexOf('AL')) {
// types.push({ type: 'ape', size: null })
// _types.ape = {
// size: null,
// }
// }
if (formats.indexOf('ALFLAC')) {
types.push({ type: 'flac', size: null })
_types['flac'] = {
_types.flac = {
size: null,
}
}
@@ -187,6 +187,7 @@ export default {
list,
limit: this.limit,
page,
source: 'kw',
}
})
},

View File

@@ -1,4 +1,4 @@
import { httpFatch } from '../../request'
import { httpFetch } from '../../request'
export default {
formatTime(time) {
@@ -10,7 +10,7 @@ export default {
return `[ti:${songinfo.songName}]\n[ar:${songinfo.artist}]\n[al:${songinfo.album}]\n[by:]\n[offset:0]\n${lrclist ? lrclist.map(l => `[${this.formatTime(l.time)}]${l.lineLyric}\n`).join('') : '暂无歌词'}`
},
getLyric(songId) {
const requestObj = httpFatch(`http://m.kuwo.cn/newh5/singles/songinfoandlrc?musicId=${songId}`)
const requestObj = httpFetch(`http://m.kuwo.cn/newh5/singles/songinfoandlrc?musicId=${songId}`)
requestObj.promise = requestObj.promise.then(({ body }) => {
return this.transformLrc(body.data)
})

View File

@@ -66,12 +66,12 @@ export default {
size: info[3].toLocaleUpperCase(),
}
break
case 'ape':
types.push({ type: 'ape', size: info[3] })
_types.ape = {
size: info[3].toLocaleUpperCase(),
}
break
// case 'ape':
// types.push({ type: 'ape', size: info[3] })
// _types.ape = {
// size: info[3].toLocaleUpperCase(),
// }
// break
case 'mp3':
switch (info[1]) {
case '320':
@@ -80,12 +80,12 @@ export default {
size: info[3].toLocaleUpperCase(),
}
break
case '192':
types.push({ type: '192k', size: info[3] })
_types['192k'] = {
size: info[3].toLocaleUpperCase(),
}
break
// case '192':
// types.push({ type: '192k', size: info[3] })
// _types['192k'] = {
// size: info[3].toLocaleUpperCase(),
// }
// break
case '128':
types.push({ type: '128k', size: info[3] })
_types['128k'] = {
@@ -121,7 +121,7 @@ export default {
}
return result
},
search(str, page = 1, { limit }) {
search(str, page = 1, { limit } = {}) {
if (limit != null) this.limit = limit
// http://newlyric.kuwo.cn/newlyric.lrc?62355680
return this.musicSearch(str, page).then(result => {
@@ -138,6 +138,8 @@ export default {
list,
allPage: this.allPage,
total: this.total,
limit: this.limit,
source: 'kw',
})
})
},

View File

@@ -1,8 +1,8 @@
import { httpFatch } from '../../request'
import { httpFetch } from '../../request'
export default {
getPic({ songmid }) {
const requestObj = httpFatch(`http://artistpicserver.kuwo.cn/pic.web?corp=kuwo&type=rid_pic&pictype=500&size=500&rid=${songmid}`)
const requestObj = httpFetch(`http://artistpicserver.kuwo.cn/pic.web?corp=kuwo&type=rid_pic&pictype=500&size=500&rid=${songmid}`)
requestObj.promise = requestObj.promise.then(({ body }) => body)
return requestObj
},

View File

@@ -1,4 +1,4 @@
import { httpFatch } from '../../request'
import { httpFetch } from '../../request'
import { formatPlayTime, decodeName } from '../../index'
import { formatSinger } from './util'
@@ -40,7 +40,7 @@ export default {
// 获取标签
getTag() {
if (this._requestObj_tags) this._requestObj_tags.cancelHttp()
this._requestObj_tags = httpFatch(this.tagsUrl)
this._requestObj_tags = httpFetch(this.tagsUrl)
return this._requestObj_tags.promise.then(({ body }) => {
if (body.code !== this.successCode) return this.getTag()
return this.filterTagInfo(body.data)
@@ -49,7 +49,7 @@ export default {
// 获取标签
getHotTag() {
if (this._requestObj_hotTags) this._requestObj_hotTags.cancelHttp()
this._requestObj_hotTags = httpFatch(this.hotTagUrl)
this._requestObj_hotTags = httpFetch(this.hotTagUrl)
return this._requestObj_hotTags.promise.then(({ body }) => {
if (body.code !== this.successCode) return this.getHotTag()
return this.filterInfoHotTag(body.data[0].data)
@@ -59,6 +59,7 @@ export default {
return rawList.map(item => ({
id: `${item.id}-${item.digest}`,
name: item.name,
source: 'kw',
}))
},
filterTagInfo(rawList) {
@@ -69,6 +70,7 @@ export default {
parent_name: type.name,
id: `${item.id}-${item.digest}`,
name: item.name,
source: 'kw',
})),
}))
},
@@ -85,7 +87,7 @@ export default {
} else {
id = null
}
this._requestObj_list = httpFatch(this.getListUrl({ sortId, id, type, page }))
this._requestObj_list = httpFetch(this.getListUrl({ sortId, id, type, page }))
return this._requestObj_list.promise.then(({ body }) => {
if (!id || type == '10000') {
if (body.code !== this.successCode) return this.getListUrl({ sortId, id, type, page })
@@ -94,6 +96,7 @@ export default {
total: body.data.total,
page: body.data.pn,
limit: body.data.rn,
source: 'kw',
}
} else if (!body.length) {
return this.getListUrl({ sortId, id, type, page })
@@ -103,6 +106,7 @@ export default {
total: 1000,
page,
limit: 1000,
source: 'kw',
}
})
},
@@ -127,6 +131,7 @@ export default {
img: item.img,
grade: item.favorcnt / 10,
desc: item.desc,
source: 'kw',
}))
},
filterList2(rawData) {
@@ -152,7 +157,7 @@ export default {
if (this._requestObj_listDetail) {
this._requestObj_listDetail.cancelHttp()
}
this._requestObj_listDetail = httpFatch(this.getListDetailUrl(id, page))
this._requestObj_listDetail = httpFetch(this.getListDetailUrl(id, page))
return this._requestObj_listDetail.promise.then(({ body }) => {
if (body.result !== 'ok') return this.getListDetail(id, page)
return {
@@ -160,6 +165,7 @@ export default {
page,
limit: body.rn,
total: body.total,
source: 'kw',
}
})
},
@@ -183,7 +189,7 @@ export default {
}
if (formats.indexOf('ALFLAC')) {
types.push({ type: 'flac', size: null })
_types['flac'] = {
_types.flac = {
size: null,
}
}

View File

@@ -8,10 +8,7 @@ export default {
_musicTempSearchRequestObj: null,
_musicTempSearchPromiseCancelFn: null,
tempSearch(str) {
if (this._musicTempSearchRequestObj != null) {
cancelHttp(this._musicTempSearchRequestObj)
this._musicTempSearchPromiseCancelFn(new Error('取消http请求'))
}
this.cancelTempSearch()
return new Promise((resolve, reject) => {
this._musicTempSearchPromiseCancelFn = reject
this._musicTempSearchRequestObj = httpGet(`http://www.kuwo.cn/api/www/search/searchKey?key=${encodeURIComponent(str)}`, (err, resp, body) => {

View File

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

View File

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

View File

@@ -196,6 +196,7 @@ export default {
list: this.filterData(data.toplist.data.songInfoList),
limit: this.limit,
page: 1,
source: 'tx',
}
})
})

View File

@@ -1,4 +1,4 @@
import { httpFatch } from '../../request'
import { httpFetch } from '../../request'
import { b64DecodeUnicode } from '../../index'
export default {
@@ -6,7 +6,7 @@ export default {
matchLrc: /.+"lyric":"([\w=+/]*)".+/,
},
getLyric(songmid) {
const requestObj = httpFatch(`https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg?songmid=${songmid}&g_tk=2001461048&loginUin=0&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8&platform=yqq`, {
const requestObj = httpFetch(`https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg?songmid=${songmid}&g_tk=2001461048&loginUin=0&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8&platform=yqq`, {
headers: {
Referer: 'https://y.qq.com/portal/player.html',
},

View File

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

View File

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

View File

@@ -1,13 +1,14 @@
import { httpFatch } from '../../request'
import { httpFetch } from '../../request'
import { requestMsg } from '../../message'
import { headers, timeout } from '../options'
const api_test = {
getMusicUrl(songInfo, type) {
const requestObj = httpFatch(`http://test.tempmusic.tk/url/wy/${songInfo.songmid}/${type}`, {
const requestObj = httpFetch(`http://ts.tempmusic.tk/url/wy/${songInfo.songmid}/${type}`, {
method: 'get',
timeout,
headers,
family: 4,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body.code === 0 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail))
@@ -15,10 +16,11 @@ const api_test = {
return requestObj
},
getPic(songInfo) {
const requestObj = httpFatch(`http://test.tempmusic.tk/pic/wy/${songInfo.songmid}`, {
const requestObj = httpFetch(`http://ts.tempmusic.tk/pic/wy/${songInfo.songmid}`, {
method: 'get',
timeout,
headers,
family: 4,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body.code === 0 ? Promise.resolve(body.data) : Promise.reject(new Error(requestMsg.fail))
@@ -26,10 +28,11 @@ const api_test = {
return requestObj
},
getLyric(songInfo) {
const requestObj = httpFatch(`http://test.tempmusic.tk/lrc/wy/${songInfo.songmid}`, {
const requestObj = httpFetch(`http://ts.tempmusic.tk/lrc/wy/${songInfo.songmid}`, {
method: 'get',
timeout,
headers,
family: 4,
})
requestObj.promise = requestObj.promise.then(({ body }) => {
return body.code === 0 ? Promise.resolve(body.data) : Promise.reject(new Error(requestMsg.fail))

View File

@@ -98,7 +98,7 @@ export default {
case 999000:
size = null
types.push({ type: 'flac', size })
_types['flac'] = {
_types.flac = {
size,
}
case 320000:
@@ -107,13 +107,13 @@ export default {
_types['320k'] = {
size,
}
case 192000:
case 190000:
size = null
types.push({ type: '192k', size })
_types['192k'] = {
size,
}
// case 192000:
// case 190000:
// size = null
// types.push({ type: '192k', size })
// _types['192k'] = {
// size,
// }
// case '160000':
default:
@@ -155,6 +155,7 @@ export default {
list,
limit: this.limit,
page,
source: 'tx',
}
})
},

View File

@@ -5,9 +5,11 @@ import { requestMsg } from './message'
import { bHh } from './music/options'
// import fs from 'fs'
const headers = {
const defaultHeaders = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
}
// var proxyUrl = "http://" + user + ":" + password + "@" + host + ":" + port;
// var proxiedRequest = request.defaults({'proxy': proxyUrl});
/**
* promise 形式的请求方法
@@ -17,21 +19,22 @@ const headers = {
const buildHttpPromose = (url, options) => {
let requestObj
let cancelFn
const p = new Promise((resolve, reject) => {
let p = new Promise((resolve, reject) => {
cancelFn = reject
debugRequest && console.log(`\n---send request------${url}------------`)
requestObj = fatchData(url, options.method, options, (err, resp, body) => {
requestObj = fetchData(url, options.method, options, (err, resp, body) => {
// options.isShowProgress && window.api.hideProgress()
debugRequest && console.log(`\n---response------${url}------------`)
debugRequest && console.log(JSON.stringify(body))
requestObj = null
cancelFn = null
if (err) {
console.log(err.code)
// console.log('出错', err.code)
if (err.code === 'ETIMEDOUT' || err.code == 'ESOCKETTIMEDOUT') {
const { promise, cancelHttp } = httpFatch(url, options)
const { promise, cancelHttp } = httpFetch(url, options)
obj.cancelHttp = cancelHttp
promise.then()
promise.then(resp => resolve(resp)).catch(err => reject(err))
return
}
return reject(err)
}
@@ -42,11 +45,11 @@ const buildHttpPromose = (url, options) => {
promise: p,
cancelHttp() {
if (!requestObj) return
console.log('cancel')
cancelHttp(requestObj)
cancelFn(new Error(requestMsg.cancelRequest))
cancelHttp(requestObj)
requestObj = null
cancelFn = null
p = null
},
}
return obj
@@ -57,11 +60,11 @@ const buildHttpPromose = (url, options) => {
* @param {*} url
* @param {*} options
*/
export const httpFatch = (url, options = { method: 'get' }) => {
export const httpFetch = (url, options = { method: 'get' }) => {
const requestObj = buildHttpPromose(url, options)
requestObj.promise = requestObj.promise.catch(err => {
if (err.code === 'ETIMEDOUT' || err.code == 'ESOCKETTIMEDOUT') {
const { promise, cancelHttp } = httpFatch(url, options)
const { promise, cancelHttp } = httpFetch(url, options)
requestObj.cancelHttp()
requestObj.cancelHttp = cancelHttp
return promise
@@ -104,7 +107,7 @@ export const http = (url, options, cb) => {
if (options.method == null) options.method = 'get'
debugRequest && console.log(`\n---send request------${url}------------`)
return fatchData(url, options.method, options, (err, resp, body) => {
return fetchData(url, options.method, options, (err, resp, body) => {
// options.isShowProgress && window.api.hideProgress()
debugRequest && console.log(`\n---response------${url}------------`)
debugRequest && console.log(JSON.stringify(body))
@@ -133,7 +136,7 @@ export const httpGet = (url, options, callback) => {
// })
debugRequest && console.log(`\n---send request-------${url}------------`)
return fatchData(url, 'get', options, function(err, resp, body) {
return fetchData(url, 'get', options, function(err, resp, body) {
// options.isShowProgress && window.api.hideProgress()
debugRequest && console.log(`\n---response------${url}------------`)
debugRequest && console.log(JSON.stringify(body))
@@ -164,7 +167,7 @@ export const httpPost = (url, data, options, callback) => {
options.data = data
debugRequest && console.log(`\n---send request-------${url}------------`)
return fatchData(url, 'post', options, function(err, resp, body) {
return fetchData(url, 'post', options, function(err, resp, body) {
// options.isShowProgress && window.api.hideProgress()
debugRequest && console.log(`\n---response------${url}------------`)
debugRequest && console.log(JSON.stringify(body))
@@ -201,7 +204,7 @@ export const http_jsonp = (url, options, callback) => {
// })
debugRequest && console.log(`\n---send request-------${url}------------`)
return fatchData(url, 'get', options, function(err, resp, body) {
return fetchData(url, 'get', options, function(err, resp, body) {
// options.isShowProgress && window.api.hideProgress()
debugRequest && console.log(`\n---response------${url}------------`)
debugRequest && console.log(JSON.stringify(body))
@@ -215,25 +218,32 @@ export const http_jsonp = (url, options, callback) => {
})
}
const fatchData = (url, method, options, callback) => {
const getProxyInfo = () => window.globalObj.proxy.enable
? `http://${window.globalObj.proxy.username}:${window.globalObj.proxy.password}@${window.globalObj.proxy.host}:${window.globalObj.proxy.port};`
: undefined
const fetchData = (url, method, {
headers = {},
format = 'json',
timeout = 15000,
...options
}, callback) => {
// console.log(url, options)
console.log('---start---', url)
if (options.headers && options.headers[bHh]) {
if (headers[bHh]) {
let s = Buffer.from(bHh, 'hex').toString()
s = s.replace(s.substr(-1), '')
s = Buffer.from(s, 'base64').toString()
options.headers[s] = !!s
delete options.headers[bHh]
headers[s] = !s || parseInt(process.versions.app.split('.').map(n => n.length < 3 ? n.padStart(3, '0') : n).join(''))
delete headers[bHh]
}
return request(url, {
...options,
method,
headers: Object.assign({}, headers, options.headers || {}),
Origin: options.origin,
body: options.body,
form: options.form,
formData: options.formData,
timeout: options.timeout || 10000,
json: options.format === undefined || options.format === 'json',
headers: Object.assign({}, defaultHeaders, headers),
timeout,
proxy: getProxyInfo(),
json: format === 'json',
}, (err, resp, body) => {
if (err) return callback(err, null)
callback(null, resp, body)

View File

@@ -150,7 +150,7 @@ export default {
this.handleStartTask(index)
})
break
case 'pause':
case 'pause': {
let runs = []
this.selectdData.forEach(item => {
if (item.isComplate || item.status == this.downloadStatus.PAUSE) return
@@ -166,6 +166,7 @@ export default {
this.handlePauseTask(index)
})
break
}
case 'remove':
this.removeTaskMultiple(this.selectdData)
break

View File

@@ -117,7 +117,7 @@ export default {
},
handleAddDownloadMultiple(type) {
switch (this.source) {
case 'kg':
// case 'kg':
case 'wy':
type = '128k'
}

View File

@@ -14,7 +14,7 @@
th.nobreak(style="width: 20%;") 专辑
th.nobreak(style="width: 20%;") 操作
th.nobreak(style="width: 10%;") 时长
div.scroll(:class="$style.tbody")
div.scroll(:class="$style.tbody" @scroll="handleScroll" ref="dom_scrollContent")
table
tbody
tr(v-for='(item, index) in list' :key='item.songmid'
@@ -37,7 +37,7 @@
//- button.btn-success(type='button' v-if="(item._types['128k'] || item._types['192k'] || item._types['320k']) && userInfo" @click.stop='showListModal(index)')
td(style="width: 10%;") {{item.interval || '--/--'}}
div(:class="$style.noItem" v-else)
p 加载中...
p(v-text="list.length ? '加载中...' : '列表竟然是空的...'")
material-download-modal(:show="isShowDownload" :musicInfo="musicInfo" @select="handleAddDownload" @close="isShowDownload = false")
material-download-multiple-modal(:show="isShowDownloadMultiple" :list="selectdData" @select="handleAddDownloadMultiple" @close="isShowDownloadMultiple = false")
material-flow-btn(:show="isShowEditBtn" :add-btn="false" :play-btn="false" @btn-click="handleFlowBtnClick")
@@ -45,6 +45,7 @@
<script>
import { mapMutations, mapGetters, mapActions } from 'vuex'
import { throttle } from '../utils'
export default {
name: 'List',
data() {
@@ -59,6 +60,7 @@ export default {
isShowEditBtn: false,
isShowDownloadMultiple: false,
delayShow: false,
routeLeaveLocation: null,
}
},
computed: {
@@ -121,12 +123,33 @@ export default {
// this.handleSearch(this.text, this.page)
// }
// },
beforeRouteLeave(to, from, next) {
this.routeLeaveLocation = (this.list.length && this.$refs.dom_scrollContent.scrollTop) || 0
next()
},
created() {
this.handleScroll = throttle(e => {
if (this.routeLeaveLocation) {
this.setListScroll(this.routeLeaveLocation)
} else {
this.setListScroll(e.target.scrollTop)
}
}, 1000)
},
mounted() {
if (this.list.length > 150) {
setTimeout(() => this.delayShow = true, 200)
} else this.delayShow = true
setTimeout(() => {
this.delayShow = true
if (this.setting.list.scroll.enable && this.setting.list.scroll.location) {
this.$nextTick(() => this.$refs.dom_scrollContent.scrollTo(0, this.setting.list.scroll.location))
}
}, 200)
} else {
this.delayShow = true
}
},
methods: {
...mapMutations(['setListScroll']),
...mapMutations('list', ['defaultListRemove', 'defaultListRemoveMultiple']),
...mapActions('download', ['createDownload', 'createDownloadMultiple']),
...mapMutations('player', ['setList']),
@@ -152,7 +175,7 @@ export default {
},
handleListBtnClick(info) {
switch (info.action) {
case 'download':
case 'download': {
const minfo = this.list[info.index]
if ((this.isAPITemp && minfo.source != 'kw') || minfo.source == 'tx' || minfo.source == 'wy') return
this.musicInfo = minfo
@@ -160,6 +183,7 @@ export default {
this.isShowDownload = true
})
break
}
case 'play':
this.testPlay(info.index)
break
@@ -196,6 +220,9 @@ export default {
break
}
},
// handleScroll(e) {
// console.log(e.target.scrollTop)
// },
},
}
</script>
@@ -256,7 +283,7 @@ export default {
p {
font-size: 24px;
color: #ccc;
color: @color-theme_2-font-label;
}
}
@@ -269,6 +296,12 @@ each(@themes, {
}
}
}
.no-item {
p {
color: ~'@{color-@{value}-theme_2-font-label}';
}
}
}
})
</style>

View File

@@ -1,7 +1,9 @@
<template lang="pug">
div(:class="$style.search")
//- transition
div(v-if="list.length" :class="$style.list")
div(:class="$style.header")
material-tab(:class="$style.tab" :list="sources" align="left" item-key="id" item-name="name" v-model="searchSourceId")
div(v-if="listInfo.list.length" :class="$style.list")
div(:class="$style.thead")
table
thead
@@ -17,7 +19,7 @@
div.scroll(:class="$style.tbody" ref="dom_scrollContent")
table
tbody
tr(v-for='(item, index) in list' :key='item.songmid' @click="handleDoubleClick(index)")
tr(v-for='(item, index) in listInfo.list' :key='item.songmid' @click="handleDoubleClick(index)")
td.nobreak.center(style="width: 37px;" @click.stop)
material-checkbox(:id="index.toString()" v-model="selectdData" :value="item")
td.break(style="width: 25%;")
@@ -27,15 +29,18 @@
td.break(style="width: 20%;") {{item.singer}}
td.break(style="width: 25%;") {{item.albumName}}
td(style="width: 15%;")
material-list-buttons(:index="index" :remove-btn="false" @btn-click="handleListBtnClick")
material-list-buttons(:index="index" :remove-btn="false" :class="$style.listBtn"
:play-btn="item.source == 'kw' || (!isAPITemp && item.source != 'tx' && item.source != 'wy')"
:download-btn="item.source == 'kw' || (!isAPITemp && item.source != 'tx' && item.source != 'wy')"
@btn-click="handleListBtnClick")
td(style="width: 10%;") {{item.interval}}
div(:class="$style.pagination")
material-pagination(:count="listInfo.total" :limit="limit" :page="page" @btn-click="handleTogglePage")
material-pagination(:count="listInfo.total" :limit="listInfo.limit" :page="page" @btn-click="handleTogglePage")
div(v-else :class="$style.noitem")
p 搜我所想~~😉
material-download-modal(:show="isShowDownload" :musicInfo="musicInfo" @select="handleAddDownload" @close="isShowDownload = false")
material-download-multiple-modal(:show="isShowDownloadMultiple" :list="selectdData" @select="handleAddDownloadMultiple" @close="isShowDownloadMultiple = false")
material-flow-btn(:show="isShowEditBtn" :remove-btn="false" @btn-click="handleFlowBtnClick")
material-flow-btn(:show="isShowEditBtn && (searchSourceId == 'kw' || searchSourceId == 'all' || !isAPITemp)" :remove-btn="false" @btn-click="handleFlowBtnClick")
</template>
<script>
@@ -57,25 +62,22 @@ export default {
isIndeterminate: false,
isShowEditBtn: false,
isShowDownloadMultiple: false,
searchSourceId: null,
}
},
beforeRouteUpdate(to, from, next) {
if (to.query.text === undefined) return
if (to.query.text === '') {
this.clearList()
} else {
this.text = to.query.text
this.page = 1
this.handleSearch(this.text, this.page)
}
this.text = to.query.text
this.page = 1
this.handleSearch(this.text, this.page)
next()
},
mounted() {
// console.log('mounted')
this.searchSourceId = this.setting.search.searchSource
if (this.$route.query.text === undefined) {
let info = this.$store.getters['search/info']
this.text = info.text
this.page = info.page
this.text = this.$store.getters['search/searchText']
this.page = this.listInfo.page
} else if (this.$route.query.text === '') {
this.clearList()
} else {
@@ -89,30 +91,49 @@ export default {
const len = n.length
if (len) {
this.isSelectAll = true
this.isIndeterminate = len !== this.list.length
this.isIndeterminate = len !== this.listInfo.list.length
this.isShowEditBtn = true
} else {
this.isSelectAll = false
this.isShowEditBtn = false
}
},
list() {
'listInfo.list'() {
this.resetSelect()
},
searchSourceId(n) {
if (n === this.setting.search.searchSource) return
this.$nextTick(() => {
this.page = 1
this.handleSearch(this.text, this.page)
})
this.setSearchSource({
searchSource: n,
})
},
},
computed: {
...mapGetters(['userInfo']),
...mapGetters('search', ['list', 'limit', 'listInfo']),
...mapGetters(['userInfo', 'setting']),
...mapGetters('search', ['sourceList', 'allList', 'sources']),
...mapGetters('list', ['defaultList']),
listInfo() {
return this.setting.search.searchSource == 'all' ? this.allList : this.sourceList[this.setting.search.searchSource]
},
isAPITemp() {
return this.setting.apiSource == 'temp'
},
},
methods: {
...mapMutations(['setSearchSource']),
...mapActions('search', ['search']),
...mapActions('download', ['createDownload', 'createDownloadMultiple']),
...mapMutations('search', ['clearList', 'setPage']),
...mapMutations('list', ['defaultListAdd', 'defaultListAddMultiple']),
...mapMutations('player', ['setList']),
handleSearch(text, page) {
this.search({ text, page, limit: this.limit }).then(data => {
if (text === '') return this.clearList()
this.search({ text, page, limit: this.listInfo.limit }).then(data => {
this.page = page
this.$nextTick(() => {
scrollTo(this.$refs.dom_scrollContent, 0)
@@ -135,7 +156,7 @@ export default {
handleListBtnClick(info) {
switch (info.action) {
case 'download':
this.musicInfo = this.list[info.index]
this.musicInfo = this.listInfo.list[info.index]
this.$nextTick(() => {
this.isShowDownload = true
})
@@ -151,9 +172,10 @@ export default {
let targetSong
if (index == null) {
targetSong = this.selectdData[0]
this.defaultListAddMultiple(this.selectdData)
this.defaultListAddMultiple(this.filterList(this.selectdData))
} else {
targetSong = this.list[index]
if ((this.isAPITemp && this.listInfo.list[index].source != 'kw') || this.listInfo.list[index].source == 'tx' || this.listInfo.list[index].source == 'wy') return
targetSong = this.listInfo.list[index]
this.defaultListAdd(targetSong)
}
let targetIndex = this.defaultList.list.findIndex(
@@ -175,12 +197,12 @@ export default {
this.isShowDownload = false
},
handleAddDownloadMultiple(type) {
this.createDownloadMultiple({ list: [...this.selectdData], type })
this.createDownloadMultiple({ list: this.filterList(this.selectdData), type })
this.resetSelect()
this.isShowDownloadMultiple = false
},
handleSelectAllData(isSelect) {
this.selectdData = isSelect ? [...this.list] : []
this.selectdData = isSelect ? [...this.listInfo.list] : []
},
resetSelect() {
this.isSelectAll = false
@@ -196,11 +218,14 @@ export default {
this.resetSelect()
break
case 'add':
this.defaultListAddMultiple(this.selectdData)
this.defaultListAddMultiple(this.filterList(this.selectdData))
this.resetSelect()
break
}
},
filterList(list) {
return this.setting.apiSource == 'temp' ? list.filter(s => s.source == 'kw') : list.filter(s => s.source != 'tx' && s.source != 'wy')
},
},
}
</script>
@@ -211,6 +236,11 @@ export default {
.search {
overflow: hidden;
height: 100%;
display: flex;
flex-flow: column nowrap;
}
.header {
flex: none;
}
.list {
position: relative;
@@ -218,6 +248,8 @@ export default {
font-size: 14px;
display: flex;
flex-flow: column nowrap;
flex: auto;
overflow: hidden;
}
.thead {
flex: none;
@@ -238,6 +270,9 @@ export default {
}
}
}
.listBtn {
min-height: 24px;
}
.pagination {
text-align: center;
padding: 15px 0;
@@ -245,8 +280,9 @@ export default {
// transform: translateX(-50%);
}
.noitem {
flex: auto;
overflow: hidden;
position: relative;
height: 100%;
display: flex;
flex-flow: column nowrap;
justify-content: center;
@@ -254,7 +290,17 @@ export default {
p {
font-size: 24px;
color: #ccc;
color: @color-theme_2-font-label;
}
}
each(@themes, {
:global(#container.@{value}) {
.noitem {
p {
color: ~'@{color-@{value}-theme_2-font-label}';
}
}
}
})
</style>

View File

@@ -35,6 +35,15 @@ div.scroll(:class="$style.setting")
h3 任务栏播放进度条
div
material-checkbox(id="setting_player_showTaskProgess" v-model="current_setting.player.isShowTaskProgess" label="是否启用")
dt 列表设置
dd(title='是否恢复播放列表滚动条位置')
h3 恢复列表滚动位置仅对我的音乐分类有效
div
material-checkbox(id="setting_list_scroll_enable" v-model="current_setting.list.scroll.enable" label="是否启用")
//- dd(title='播放列表是否显示专辑栏')
h3 专辑栏
div
material-checkbox(id="setting_list_showalbum" v-model="current_setting.list.isShowAlbumName" label="是否显示专辑栏")
dt 下载设置
dd(title='下载歌曲保存的路径')
h3 下载路径
@@ -57,11 +66,18 @@ div.scroll(:class="$style.setting")
h3 歌词下载
div
material-checkbox(id="setting_download_isDownloadLrc" v-model="current_setting.download.isDownloadLrc" label="是否启用")
//- dt 列表设置
//- dd(title='播放列表是否显示专辑栏')
h3 专辑栏
dt 网络设置
dd
h3 代理设置歌曲下载暂不支持代理
div
material-checkbox(id="setting_list_showalbum" v-model="current_setting.list.isShowAlbumName" label="是否显示专辑栏")
p
material-checkbox(id="setting_network_proxy_enable" v-model="current_setting.network.proxy.enable" @change="handleProxyChange('enable')" label="是否启用")
p
material-input(:class="$style.gapLeft" v-model="current_setting.network.proxy.host" @change="handleProxyChange('host')" placeholder="主机")
material-input(:class="$style.gapLeft" v-model="current_setting.network.proxy.port" @change="handleProxyChange('port')" placeholder="端口")
p
material-input(:class="$style.gapLeft" v-model="current_setting.network.proxy.username" @change="handleProxyChange('username')" placeholder="用户名")
material-input(:class="$style.gapLeft" v-model="current_setting.network.proxy.password" @change="handleProxyChange('password')" type="password" placeholder="密码")
dt 强迫症设置
dd
h3 离开搜索界面时清空搜索框
@@ -118,7 +134,7 @@ div.scroll(:class="$style.setting")
| 支持作者哦~~🍻
p
span 如果你资金充裕还可以
material-btn(@click="handleOpenUrl('https://cdn.stsky.cn/qrc.png')" min title="土豪,你好 🙂") 打赏下作者
material-btn(@click="handleOpenUrl('https://cdn.stsky.cn/qrc.png')" min title="土豪,你好 🙂") 捐赠下作者
span 以帮我分担点服务器费用~
p.small
| 本软件仅用于学习交流使用禁止将本软件用于
@@ -162,6 +178,10 @@ export default {
},
list: {
isShowAlbumName: true,
scroll: {
enable: true,
location: 0,
},
},
download: {
savePath: '',
@@ -169,6 +189,15 @@ export default {
isDownloadLrc: false,
isEmbedPic: true,
},
network: {
proxy: {
enable: false,
host: '',
port: '',
username: '',
password: '',
},
},
odc: {
isAutoClearSearchInput: false,
},
@@ -416,6 +445,9 @@ export default {
clipboardWriteText(text) {
clipboardWriteText(text)
},
handleProxyChange(key) {
window.globalObj.proxy[key] = this.current_setting.network.proxy[key]
},
openRewardModal() {
},
@@ -479,7 +511,9 @@ export default {
.theme {
display: flex;
flex-flow: row wrap;
// padding: 0 15px;
margin-bottom: -20px;
li {
display: flex;
@@ -489,6 +523,7 @@ export default {
// color: @color-theme;
margin-right: 30px;
transition: color .3s ease;
margin-bottom: 20px;
&:last-child {
margin-right: 0;
@@ -509,6 +544,9 @@ export default {
width: 100%;
height: 100%;
border-radius: 4px;
background-position: center;
background-size: auto 100%;
background-repeat: no-repeat;
}
}
@@ -517,6 +555,7 @@ export default {
span {
&:after {
background-color: ~'@{color-@{value}-theme}';
background-image: ~'@{color-@{value}-theme-bgimg}';
}
}
}

View File

@@ -1,24 +1,24 @@
<template lang="pug">
div(:class="$style.container")
div(:class="$style.header")
material-tag-list(:class="$style.tagList" :list="tagList" v-model="tagInfo")
material-tab(:class="$style.tab" :list="sorts" item-key="id" item-name="name" v-model="sortId")
material-select(:class="$style.select" :list="sourceInfo.sources" item-key="id" item-name="name" v-model="source")
div(:class="$style.main")
transition(enter-active-class="animated-fast fadeIn" leave-active-class="animated-fast fadeOut")
div(:class="$style.songListDetail" v-show="isVisibleListDetail")
div(:class="$style.songListHeader")
div(:class="$style.songListHeaderLeft")
img(:src="selectListInfo.img")
span(:class="$style.playNum" v-if="selectListInfo.play_count") {{selectListInfo.play_count}}
div(:class="$style.songListHeaderMiddle")
h3(:title="selectListInfo.name") {{selectListInfo.name}}
p(:title="selectListInfo.desc") {{selectListInfo.desc}}
div(:class="$style.songListHeaderRight")
material-btn(:class="$style.closeDetailButton" @click="hideListDetail") 返回
material-song-list(v-model="selectdData" @action="handleSongListAction" :source="source" :page="listDetail.page" :limit="listDetail.limit" :total="listDetail.total" :list="listDetail.list")
transition(enter-active-class="animated-fast fadeIn" leave-active-class="animated-fast fadeOut")
div.scroll(:class="$style.songList" ref="dom_scrollContent" v-show="!isVisibleListDetail")
transition(enter-active-class="animated-fast fadeIn" leave-active-class="animated-fast fadeOut")
div(:class="$style.songListDetailContent" v-show="isVisibleListDetail")
div(:class="$style.songListHeader")
div(:class="$style.songListHeaderLeft")
img(:src="selectListInfo.img")
span(:class="$style.playNum" v-if="selectListInfo.play_count") {{selectListInfo.play_count}}
div(:class="$style.songListHeaderMiddle")
h3(:title="selectListInfo.name") {{selectListInfo.name}}
p(:title="selectListInfo.desc") {{listDetail.desc || selectListInfo.desc}}
div(:class="$style.songListHeaderRight")
material-btn(:class="$style.closeDetailButton" @click="hideListDetail") 返回
material-song-list(v-model="selectdData" @action="handleSongListAction" :source="source" :page="listDetail.page" :limit="listDetail.limit" :total="listDetail.total" :list="listDetail.list")
transition(enter-active-class="animated-fast fadeIn" leave-active-class="animated-fast fadeOut")
div(:class="$style.songListContent" v-show="!isVisibleListDetail")
div(:class="$style.header")
material-tag-list(:class="$style.tagList" :list="tagList" v-model="tagInfo")
material-tab(:class="$style.tab" :list="sorts" item-key="id" item-name="name" v-model="sortId")
material-select(:class="$style.select" :list="sourceInfo.sources" item-key="id" item-name="name" v-model="source")
div.scroll(:class="$style.songList" ref="dom_scrollContent")
ul
li(:class="$style.item" v-for="(item, index) in listData.list" @click="handleItemClick(index)")
div(:class="$style.left")
@@ -191,7 +191,7 @@ export default {
},
handleAddDownloadMultiple(type) {
switch (this.source) {
case 'kg':
// case 'kg':
case 'wy':
type = '128k'
}
@@ -269,14 +269,18 @@ export default {
width: 80px;
}
.main {
flex: auto;
.songListContent, .song-list-detail-content {
// flex: auto;
overflow: hidden;
}
.songListContent {
display: flex;
flex-flow: column nowrap;
// position: relative;
}
.song-list-header {
background-color: @color-theme_2;
display: flex;
flex-flow: row nowrap;
height: 60px;
@@ -326,7 +330,7 @@ export default {
padding-right: 15px;
}
.song-list-detail {
.song-list-detail-content {
position: absolute;
width: 100%;
height: 100%;
@@ -340,7 +344,6 @@ export default {
height: 100%;
overflow-y: auto;
padding: 0 15px;
background-color: #fff;
ul {
display: flex;
flex-flow: row wrap;