Merge branch 'dev' into 黑色主题
commit
7b7711d410
14
FAQ.md
14
FAQ.md
|
@ -45,15 +45,22 @@
|
|||
对于分享出来的歌单,若打开失败,可尝试先在浏览器中打开后,再从浏览器地址栏复制URL地址到软件打开;<br>
|
||||
或者如果你知道歌单 id 也可以直接输入歌单 id 打开。<br>
|
||||
|
||||
## Windows 7 下界面异常(界面显示不完整)
|
||||
## 界面异常(界面显示不完整)
|
||||
|
||||
### Windows 7 下界面异常
|
||||
|
||||
由于软件默认使用了透明窗口,根据Electron官方文档的[说明](https://electronjs.org/docs/api/frameless-window#%E5%B1%80%E9%99%90%E6%80%A7):
|
||||
> 在 windows 操作系统上, 当 DWM 被禁用时, 透明窗口将无法工作。
|
||||
|
||||
因此,当 win7 没有使用**AERO**主题时界面将会显示异常,开启AERO的方法请自行百度:`win7开启aero效果`(开启后可看到任务栏变透明)。<br>
|
||||
从`0.14.0`版本起不再强制要求开启透明效果,若你实在不想开启(若非电脑配置太低,墙裂建议开启!),可通过添加运行参数`-nt`来运行程序即可,例如:`.\lx-music-desktop.exe -nt`,添加方法可自行百度“给快捷方式加参数”,该参数的作用是用来控制程序是否使用非透明窗口运行。
|
||||
从`0.14.0`版本起不再强制要求开启透明效果,若你实在不想开启(若非电脑配置太低,墙裂建议开启!),可通过添加运行参数`-dt`来运行程序即可,例如:`.\lx-music-desktop.exe -dt`,添加方法可自行百度“给快捷方式加参数”,该参数的作用是用来控制程序是否使用非透明窗口运行。
|
||||
|
||||
对于一些完全无法正常显示界面、开启了AERO后问题仍未解决的情况,请阅读下面的 **软件启动后,界面无法显示** 解决
|
||||
对于一些完全无法正常显示界面、开启了AERO后问题仍未解决的情况,请阅读下面的 **软件启动后,界面无法显示** 解决。
|
||||
|
||||
### Linux 下界面异常
|
||||
|
||||
根据Electron里issue的[解决方案](https://github.com/electron/electron/issues/2170#issuecomment-736223269),<br>
|
||||
若你遇到透明问题可尝试添加启动参数 `-dha` 来禁用硬件加速,例如:`.\lx-music-desktop.exe -dha`。
|
||||
|
||||
## 软件启动后,界面无法显示
|
||||
|
||||
|
@ -66,6 +73,7 @@
|
|||
若还是不行可尝试以下操作:
|
||||
|
||||
- 更新显卡驱动
|
||||
- 添加启动参数`-dha`运行(添加的方法请自行百度“给快捷方式加参数”)
|
||||
- 尝试将绿色版的软件放在**桌面**或**我的文档**运行
|
||||
|
||||
## 安装版安装失败,提示安装程序并未成功地运行完成
|
||||
|
|
|
@ -81,7 +81,8 @@ npm run pack:linux
|
|||
目前软件已支持的启动参数如下:
|
||||
|
||||
- `-search` 启动软件时自动在搜索框搜索指定的内容,例如:`-search="突然的自我 - 伍佰"`
|
||||
- `-nt` 以非透明模式启动,对于未开启AERO效果的win7系统可加此参数启动以确保界面正常显示
|
||||
- `-dha` 禁用硬件加速启动(Disable Hardware Acceleration),窗口显示有问题时可以尝试添加此参数启动
|
||||
- `-dt` 以非透明模式启动(Disable Transparent),对于未开启AERO效果的win7系统可加此参数启动以确保界面正常显示,原来的`-nt`参数已重命名为`-dt`
|
||||
|
||||
### 常见问题
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
30
package.json
30
package.json
|
@ -165,24 +165,24 @@
|
|||
"@babel/plugin-transform-modules-umd": "^7.12.1",
|
||||
"@babel/plugin-transform-runtime": "^7.12.10",
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@babel/preset-env": "^7.12.10",
|
||||
"@babel/preset-env": "^7.12.11",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^8.2.2",
|
||||
"babel-minify-webpack-plugin": "^0.3.1",
|
||||
"babel-preset-minify": "^0.5.1",
|
||||
"cfonts": "^2.9.0",
|
||||
"cfonts": "^2.9.1",
|
||||
"chalk": "^4.1.0",
|
||||
"changelog-parser": "^2.8.0",
|
||||
"copy-webpack-plugin": "^6.4.0",
|
||||
"core-js": "^3.8.1",
|
||||
"core-js": "^3.8.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^4.3.0",
|
||||
"del": "^6.0.0",
|
||||
"electron": "^9.4.0",
|
||||
"electron-builder": "^22.9.1",
|
||||
"electron-debug": "^3.1.0",
|
||||
"electron-debug": "^3.2.0",
|
||||
"electron-devtools-installer": "^3.1.1",
|
||||
"eslint": "^7.15.0",
|
||||
"eslint": "^7.17.0",
|
||||
"eslint-config-standard": "^14.1.1",
|
||||
"eslint-formatter-friendly": "^7.0.0",
|
||||
"eslint-loader": "^4.0.2",
|
||||
|
@ -193,10 +193,10 @@
|
|||
"eslint-plugin-standard": "^4.1.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"friendly-errors-webpack-plugin": "^1.7.0",
|
||||
"html-webpack-plugin": "^4.5.0",
|
||||
"html-webpack-plugin": "^4.5.1",
|
||||
"less": "^3.12.2",
|
||||
"less-loader": "^7.1.0",
|
||||
"markdown-it": "^12.0.3",
|
||||
"less-loader": "^7.2.1",
|
||||
"markdown-it": "^12.0.4",
|
||||
"mini-css-extract-plugin": "^0.12.0",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.4",
|
||||
"postcss-loader": "^4.1.0",
|
||||
|
@ -211,29 +211,29 @@
|
|||
"stylus-loader": "^4.3.1",
|
||||
"terser-webpack-plugin": "^4.2.3",
|
||||
"url-loader": "^4.1.1",
|
||||
"vue-loader": "^15.9.5",
|
||||
"vue-loader": "^15.9.6",
|
||||
"vue-template-compiler": "^2.6.12",
|
||||
"webpack": "^4.44.2",
|
||||
"webpack-cli": "^3.3.12",
|
||||
"webpack-dev-server": "^3.11.0",
|
||||
"webpack-dev-server": "^3.11.1",
|
||||
"webpack-hot-middleware": "^2.25.0",
|
||||
"webpack-merge": "^5.6.1"
|
||||
"webpack-merge": "^5.7.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"crypto-js": "^4.0.0",
|
||||
"dnscache": "^1.0.2",
|
||||
"electron-log": "^4.3.0",
|
||||
"electron-log": "^4.3.1",
|
||||
"electron-store": "^6.0.1",
|
||||
"electron-updater": "^4.3.5",
|
||||
"iconv-lite": "^0.6.2",
|
||||
"image-size": "^0.9.3",
|
||||
"js-htmlencode": "^0.3.0",
|
||||
"lrc-file-parser": "^1.0.5",
|
||||
"needle": "^2.5.2",
|
||||
"node-id3": "^0.1.19",
|
||||
"needle": "^2.6.0",
|
||||
"node-id3": "^0.2.2",
|
||||
"request": "^2.88.2",
|
||||
"vue": "^2.6.12",
|
||||
"vue-i18n": "^8.22.2",
|
||||
"vue-i18n": "^8.22.3",
|
||||
"vue-router": "^3.4.9",
|
||||
"vuex": "^3.6.0",
|
||||
"vuex-router-sync": "^5.0.0"
|
||||
|
|
|
@ -1,8 +1,20 @@
|
|||
### 新增
|
||||
|
||||
- 我的列表右键菜单新增列表排序功能,可调整单曲、多选后的歌曲的顺序。注意:多选排序还将会按照选中歌曲时的顺序排序
|
||||
- 添加鼠标提示的自动关闭功能,鼠标长时间(目前是10秒)不动时鼠标提示将会自动关闭
|
||||
- 添加鼠标指向歌曲封面的提示(对于进度条左边的歌曲封面,你可能不知道的操作->右击在“我的列表”定位当前播放的歌曲)
|
||||
- 隐藏播放详情页按钮添加快速隐藏详情页提示(你可能不知道的操作->在播放详情页内的任意非窗口可拖动区域右键双击可以快速隐藏详情页)
|
||||
- 添加桌面歌词字体、透明度调整按钮微调提示(你可能不知道的操作->对于字体、透明度可右击微调)
|
||||
- 我的列表右键菜单添加搜索当前歌曲功能
|
||||
- 新增`-dha`参数,添加此启动参数将禁用硬件加速启动(Disable Hardware Acceleration),窗口显示有问题时可以尝试添加此参数启动,Linux系统的界面显示有问题时可尝试添加此参数启动,若不行可尝试添加`-dt`参数启动
|
||||
- 新增播放自动换源功能~
|
||||
|
||||
### 变更
|
||||
|
||||
- `-nt`参数更名为`-dt`(Disable Transparent),目前原来的`-nt`参数仍然可用,但将在后续的版本中移除
|
||||
|
||||
### 修复
|
||||
|
||||
- 修复恢复上次播放的歌曲时在随机播放模式下不把恢复播放的歌曲放入已播放队列的问题(该问题会导致随机模式下会导致未播放完整个列表前就会再次随机到该歌曲,以及无法通过上一曲切回该歌曲)
|
||||
- 修复音乐嵌入的封面在 Mac 系统无法显示的问题
|
||||
- 修复`-dt`(原来的`-nt`)启动参数不真正生效的问题
|
||||
|
|
|
@ -24,14 +24,20 @@ app.on('second-instance', (event, argv, cwd) => {
|
|||
|
||||
const isDev = global.isDev = process.env.NODE_ENV !== 'production'
|
||||
require('./env')
|
||||
// console.log(global.envParams.cmdParams)
|
||||
|
||||
// Is disable hardware acceleration
|
||||
if (global.envParams.cmdParams.dha) app.disableHardwareAcceleration()
|
||||
if (global.envParams.cmdParams.dt == null && global.envParams.cmdParams.nt != null) global.envParams.cmdParams.dt = global.envParams.cmdParams.nt
|
||||
// https://github.com/electron/electron/issues/22691
|
||||
app.commandLine.appendSwitch('wm-window-animations-disabled')
|
||||
|
||||
|
||||
const { navigationUrlWhiteList } = require('../common/config')
|
||||
const { getWindowSizeInfo } = require('./utils')
|
||||
const { isMac, isLinux, initSetting, initHotKey } = require('../common/utils')
|
||||
|
||||
|
||||
// https://github.com/electron/electron/issues/22691
|
||||
app.commandLine.appendSwitch('wm-window-animations-disabled')
|
||||
|
||||
// https://github.com/electron/electron/issues/18397
|
||||
// 开发模式下为true时 多次引入native模块会导致渲染进程卡死
|
||||
// https://github.com/electron/electron/issues/22791
|
||||
|
@ -95,7 +101,7 @@ function createWindow() {
|
|||
useContentSize: true,
|
||||
width: windowSizeInfo.width,
|
||||
frame: false,
|
||||
transparent: !global.envParams.nt,
|
||||
transparent: !global.envParams.cmdParams.dt,
|
||||
enableRemoteModule: false,
|
||||
// icon: path.join(global.__static, isWin ? 'icons/256x256.ico' : 'icons/512x512.png'),
|
||||
resizable: false,
|
||||
|
@ -124,6 +130,7 @@ global.appHotKey = {
|
|||
}
|
||||
|
||||
function init() {
|
||||
console.log('init')
|
||||
const info = initSetting()
|
||||
global.appSetting = info.setting
|
||||
global.appSettingVersion = info.version
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template lang="pug">
|
||||
#container(v-if="isProd && !isNt && !isLinux" :class="theme" @mouseenter="enableIgnoreMouseEvents" @mouseleave="dieableIgnoreMouseEvents")
|
||||
#container(v-if="isProd && !isDT && !isLinux" :class="theme" @mouseenter="enableIgnoreMouseEvents" @mouseleave="dieableIgnoreMouseEvents")
|
||||
core-aside#left
|
||||
#right
|
||||
core-toolbar#toolbar
|
||||
|
@ -41,7 +41,7 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
isProd: process.env.NODE_ENV === 'production',
|
||||
isNt: false,
|
||||
isDT: false,
|
||||
isLinux,
|
||||
globalObj: {
|
||||
apiSource: 'test',
|
||||
|
@ -102,7 +102,7 @@ export default {
|
|||
}, 500)
|
||||
},
|
||||
mounted() {
|
||||
document.body.classList.add(this.isNt ? 'noTransparent' : 'transparent')
|
||||
document.body.classList.add(this.isDT ? 'disableTransparent' : 'transparent')
|
||||
window.eventHub.$emit(eventBaseName.bindKey)
|
||||
this.init()
|
||||
},
|
||||
|
@ -254,12 +254,12 @@ export default {
|
|||
music.init()
|
||||
},
|
||||
enableIgnoreMouseEvents() {
|
||||
if (this.isNt) return
|
||||
if (this.isDT) return
|
||||
rendererSend(NAMES.mainWindow.set_ignore_mouse_events, false)
|
||||
// console.log('content enable')
|
||||
},
|
||||
dieableIgnoreMouseEvents() {
|
||||
if (this.isNt) return
|
||||
if (this.isDT) return
|
||||
// console.log('content disable')
|
||||
rendererSend(NAMES.mainWindow.set_ignore_mouse_events, true)
|
||||
},
|
||||
|
@ -380,12 +380,12 @@ export default {
|
|||
},
|
||||
handleEnvParamsInit(envParams) {
|
||||
this.envParams = envParams
|
||||
this.isNt = this.envParams.nt
|
||||
if (this.isNt) {
|
||||
this.isDT = this.envParams.dt
|
||||
if (this.isDT) {
|
||||
document.body.classList.remove('transparent')
|
||||
document.body.classList.add('noTransparent')
|
||||
document.body.classList.add('disableTransparent')
|
||||
}
|
||||
if (this.isProd && !this.isNt && !this.isLinux) {
|
||||
if (this.isProd && !this.isDT && !this.isLinux) {
|
||||
document.body.addEventListener('mouseenter', this.dieableIgnoreMouseEvents)
|
||||
document.body.addEventListener('mouseleave', this.enableIgnoreMouseEvents)
|
||||
}
|
||||
|
@ -455,8 +455,13 @@ body {
|
|||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
.noTransparent {
|
||||
.disableTransparent {
|
||||
background-color: #fff;
|
||||
|
||||
#right {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#container {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template lang="pug">
|
||||
div(:class="$style.player")
|
||||
div(:class="$style.left" @contextmenu="handleToMusicLocation" @click="showPlayerDetail")
|
||||
div(:class="$style.left" @contextmenu="handleToMusicLocation" @click="showPlayerDetail" :tips="$t('core.player.pic_tip')")
|
||||
img(v-if="musicInfo.img" :src="musicInfo.img" @error="imgError")
|
||||
svg(v-else version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='102%' width='100%' viewBox='0 0 60 60' space='preserve')
|
||||
use(:xlink:href='`#${$style.iconPic}`')
|
||||
|
@ -92,6 +92,7 @@ import { mapGetters, mapActions, mapMutations } from 'vuex'
|
|||
import { requestMsg } from '../../utils/message'
|
||||
import { isMac } from '../../../common/utils'
|
||||
import { player as eventPlayerNames } from '../../../common/hotKey'
|
||||
import musicSdk from '@renderer/utils/music'
|
||||
import path from 'path'
|
||||
|
||||
let audio
|
||||
|
@ -469,7 +470,7 @@ export default {
|
|||
},
|
||||
async play() {
|
||||
console.log('play', this.playIndex)
|
||||
this.checkDelayNextTimeout()
|
||||
this.clearDelayNextTimeout()
|
||||
let targetSong = this.targetSong = this.list[this.playIndex]
|
||||
if (this.setting.player.togglePlayMethod == 'random') this.setPlayedList(targetSong)
|
||||
this.retryNum = 0
|
||||
|
@ -506,7 +507,7 @@ export default {
|
|||
album: this.musicInfo.album,
|
||||
})
|
||||
},
|
||||
checkDelayNextTimeout() {
|
||||
clearDelayNextTimeout() {
|
||||
// console.log(this.delayNextTimeout)
|
||||
if (this.delayNextTimeout) {
|
||||
clearTimeout(this.delayNextTimeout)
|
||||
|
@ -514,7 +515,7 @@ export default {
|
|||
}
|
||||
},
|
||||
addDelayNextTimeout() {
|
||||
this.checkDelayNextTimeout()
|
||||
this.clearDelayNextTimeout()
|
||||
this.delayNextTimeout = setTimeout(() => {
|
||||
this.delayNextTimeout = null
|
||||
this.handleNext()
|
||||
|
@ -694,20 +695,39 @@ export default {
|
|||
if (highQuality && songInfo._types['320k'] && list && list.includes('320k')) type = '320k'
|
||||
return type
|
||||
},
|
||||
setUrl(targetSong, isRefresh, isRetryed = false) {
|
||||
setUrl(targetSong, isRefresh, isRetryed = false, retryedSource = [], originMusic = null) {
|
||||
if (!retryedSource.includes(targetSong.source)) retryedSource.push(targetSong.source)
|
||||
|
||||
let type = this.getPlayType(this.setting.player.highQuality, targetSong)
|
||||
this.musicInfo.url = targetSong.typeUrl[type]
|
||||
this.status = this.statusText = this.$t('core.player.geting_url')
|
||||
|
||||
return this.getUrl({ musicInfo: targetSong, type, isRefresh }).then(() => {
|
||||
return this.getUrl({ musicInfo: targetSong, originMusic, type, isRefresh }).then(() => {
|
||||
audio.src = this.musicInfo.url = targetSong.typeUrl[type]
|
||||
}).catch(err => {
|
||||
// console.log('err', err.message)
|
||||
if (err.message == requestMsg.cancelRequest) return
|
||||
if (!isRetryed) return this.setUrl(targetSong, isRefresh, true)
|
||||
this.status = this.statusText = err.message
|
||||
this.addDelayNextTimeout()
|
||||
return Promise.reject(err)
|
||||
if (!isRetryed) return this.setUrl(targetSong, isRefresh, true, retryedSource, originMusic)
|
||||
if (!originMusic) originMusic = targetSong
|
||||
|
||||
this.status = this.statusText = 'Try toggle source...'
|
||||
|
||||
return (originMusic.otherSource && originMusic.otherSource.length ? Promise.resolve(originMusic.otherSource) : musicSdk.findMusic(originMusic)).then(res => {
|
||||
this.updateMusicInfo({ id: this.listId, index: this.playIndex, data: { otherSource: res } })
|
||||
return res
|
||||
}).then(otherSource => {
|
||||
console.log('find otherSource', otherSource)
|
||||
if (otherSource.length) {
|
||||
for (const item of otherSource) {
|
||||
if (retryedSource.includes(item.source)) continue
|
||||
console.log('try toggle to: ', item.source, item.name, item.singer, item.interval)
|
||||
return this.setUrl(item, isRefresh, false, retryedSource, originMusic)
|
||||
}
|
||||
}
|
||||
this.status = this.statusText = err.message
|
||||
this.addDelayNextTimeout()
|
||||
return Promise.reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
setImg(targetSong) {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
"buffering": "Buffering...",
|
||||
"geting_url": "Getting music link...",
|
||||
"lyric_error": "Failed to get lyrics",
|
||||
"hide_detail": "Hide detail page",
|
||||
"hide_detail": "Hide detail page (Right-click in the view to quickly hide the details page)",
|
||||
"name": "Name: ",
|
||||
"singer": "Artist: ",
|
||||
"album": "Album: ",
|
||||
|
@ -28,6 +28,7 @@
|
|||
"play_toggle_mode_list": "Play in order",
|
||||
"play_toggle_mode_single_loop": "Single Loop",
|
||||
"play_toggle_mode_off": "Disable",
|
||||
"pic_tip": "Right click to locate the currently playing song in \"My List\"",
|
||||
|
||||
"comment_show": "Song comments",
|
||||
"comment_hot_loading": "Hot comments are loading",
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
"lock": "Lock Lyrics",
|
||||
"unlock": "Unlock Lyrics",
|
||||
"theme": "Theme Color",
|
||||
"font_increase": "Increase font size",
|
||||
"font_decrease": "Reduce font size",
|
||||
"opactiy_increase": "Decrease Transparency",
|
||||
"opactiy_decrease": "Increase Transparency",
|
||||
"font_increase": "Increase font size (Right click to fine-tune)",
|
||||
"font_decrease": "Reduce font size (Right click to fine-tune)",
|
||||
"opactiy_increase": "Decrease Transparency (Right click to fine-tune)",
|
||||
"opactiy_decrease": "Increase Transparency (Right click to fine-tune)",
|
||||
"lrc_active_zoom_on": "Zoom the currently playing lyrics",
|
||||
"lrc_active_zoom_off": "Unzoom the currently playing lyrics",
|
||||
"win_top_on": "Top lyrics interface",
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
"list_move_to": "Move to ...",
|
||||
"list_sort": "Adjust position",
|
||||
"list_download": "Download",
|
||||
"list_search": "Search",
|
||||
"list_remove": "Remove",
|
||||
"list_source_detail": "Song Page",
|
||||
"default_list": "Recently Played",
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
"buffering": "缓冲中...",
|
||||
"geting_url": "歌曲链接获取中...",
|
||||
"lyric_error": "歌词获取失败",
|
||||
"hide_detail": "隐藏详情页",
|
||||
"hide_detail": "隐藏详情页(界面内右键双击可快速隐藏详情页)",
|
||||
"name": "歌曲名:",
|
||||
"singer": "艺术家:",
|
||||
"album": "专辑名:",
|
||||
|
@ -28,6 +28,7 @@
|
|||
"play_toggle_mode_list": "顺序播放",
|
||||
"play_toggle_mode_single_loop": "单曲循环",
|
||||
"play_toggle_mode_off": "禁用",
|
||||
"pic_tip": "右击在“我的列表”定位当前播放的歌曲",
|
||||
|
||||
"comment_show": "歌曲评论",
|
||||
"comment_hot_loading": "热门评论加载中",
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
"lock": "锁定歌词",
|
||||
"unlock": "解锁歌词",
|
||||
"theme": "主题配色",
|
||||
"font_increase": "增加字体大小",
|
||||
"font_decrease": "减小字体大小",
|
||||
"opactiy_increase": "减小透明度",
|
||||
"opactiy_decrease": "增加透明度",
|
||||
"font_increase": "增加字体大小(右击可微调)",
|
||||
"font_decrease": "减小字体大小(右击可微调)",
|
||||
"opactiy_increase": "减小透明度(右击可微调)",
|
||||
"opactiy_decrease": "增加透明度(右击可微调)",
|
||||
"lrc_active_zoom_on": "缩放当前播放的歌词",
|
||||
"lrc_active_zoom_off": "取消缩放当前播放的歌词",
|
||||
"win_top_on": "置顶歌词界面",
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
"list_move_to": "移动到...",
|
||||
"list_sort": "调整位置",
|
||||
"list_download": "下载",
|
||||
"list_search": "搜索",
|
||||
"list_remove": "删除",
|
||||
"default_list": "试听列表",
|
||||
"love_list": "收藏",
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
"buffering": "緩衝中...",
|
||||
"geting_url": "歌曲鏈接獲取中...",
|
||||
"lyric_error": "歌詞獲取失敗",
|
||||
"hide_detail": "隱藏詳情頁",
|
||||
"hide_detail": "隱藏詳情頁(界面內右鍵雙擊可快速隱藏詳情頁)",
|
||||
"name": "歌曲名:",
|
||||
"singer": "藝術家:",
|
||||
"album": "專輯名:",
|
||||
|
@ -28,6 +28,7 @@
|
|||
"play_toggle_mode_list": "順序播放",
|
||||
"play_toggle_mode_single_loop": "單曲循環",
|
||||
"play_toggle_mode_off": "禁用",
|
||||
"pic_tip": "右擊在“我的列表”定位當前播放的歌曲",
|
||||
|
||||
"comment_show": "歌曲評論",
|
||||
"comment_hot_loading": "熱門評論加載中",
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
"lock": "鎖定歌詞",
|
||||
"unlock": "解鎖歌詞",
|
||||
"theme": "主題配色",
|
||||
"font_increase": "增加字體大小",
|
||||
"font_decrease": "減小字體大小",
|
||||
"opactiy_increase": "減小透明度",
|
||||
"opactiy_decrease": "增加透明度",
|
||||
"font_increase": "增加字體大小(右擊可微調)",
|
||||
"font_decrease": "減小字體大小(右擊可微調)",
|
||||
"opactiy_increase": "減小透明度(右擊可微調)",
|
||||
"opactiy_decrease": "增加透明度(右擊可微調)",
|
||||
"lrc_active_zoom_on": "縮放當前播放的歌詞",
|
||||
"lrc_active_zoom_off": "取消縮放當前播放的歌詞",
|
||||
"win_top_on": "置頂歌詞界面",
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
"list_move_to": "移動到...",
|
||||
"list_sort": "調整位置",
|
||||
"list_download": "下載",
|
||||
"list_search": "搜索",
|
||||
"list_remove": "刪除",
|
||||
"list_source_detail": "歌曲詳情頁",
|
||||
"default_list": "試聽列表",
|
||||
|
|
|
@ -2,7 +2,21 @@ import Tips from './Tips.vue'
|
|||
import Vue from 'vue'
|
||||
|
||||
const TipsConstructor = Vue.extend(Tips)
|
||||
export default ({ position, message } = {}) => {
|
||||
|
||||
const addAutoCloseTimer = (instance, time) => {
|
||||
if (!time) return
|
||||
if (instance.autoCloseTimer) clearTimeout(instance.autoCloseTimer)
|
||||
instance.autoCloseTimer = setTimeout(() => {
|
||||
instance.cancel()
|
||||
}, time)
|
||||
}
|
||||
const clearAutoCloseTimer = instance => {
|
||||
if (!instance.autoCloseTimer) return
|
||||
clearTimeout(instance.autoCloseTimer)
|
||||
instance.autoCloseTimer = null
|
||||
}
|
||||
|
||||
export default ({ position, message, autoCloseTime } = {}) => {
|
||||
if (!position) return
|
||||
let instance = new TipsConstructor().$mount(document.createElement('div'))
|
||||
|
||||
|
@ -17,14 +31,19 @@ export default ({ position, message } = {}) => {
|
|||
document.body.appendChild(instance.$el)
|
||||
|
||||
instance.cancel = () => {
|
||||
instance.$emit('beforeClose', instance)
|
||||
clearAutoCloseTimer(instance)
|
||||
instance.visible = false
|
||||
instance = null
|
||||
}
|
||||
|
||||
instance.setTips = tips => {
|
||||
addAutoCloseTimer(instance, autoCloseTime)
|
||||
instance.message = tips
|
||||
}
|
||||
|
||||
addAutoCloseTimer(instance, autoCloseTime)
|
||||
|
||||
return instance
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ export default {
|
|||
transform: 'translate(0, 0)',
|
||||
cancel: null,
|
||||
setTips: null,
|
||||
aotoCloseTimer: null,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -26,9 +27,13 @@ export default {
|
|||
})
|
||||
},
|
||||
},
|
||||
beforeDestroy() {
|
||||
const el = this.$el
|
||||
el.parentNode.removeChild(el)
|
||||
},
|
||||
methods: {
|
||||
afterLeave(el, done) {
|
||||
el.parentNode.removeChild(el)
|
||||
this.$destroy()
|
||||
},
|
||||
handleGetOffsetXY(left, top) {
|
||||
const tipsWidth = this.$refs.dom_tips.clientWidth
|
||||
|
|
|
@ -19,18 +19,22 @@ const showTips = debounce(event => {
|
|||
prevTips = msg
|
||||
instance = tips({
|
||||
message: msg,
|
||||
autoCloseTime: 10000,
|
||||
position: {
|
||||
top: event.y + 12,
|
||||
left: event.x + 8,
|
||||
},
|
||||
})
|
||||
instance.$on('beforeClose', closeInstance => {
|
||||
if (instance !== closeInstance) return
|
||||
prevTips = null
|
||||
instance = null
|
||||
})
|
||||
}, 400)
|
||||
|
||||
const hideTips = () => {
|
||||
if (!instance) return
|
||||
instance.cancel()
|
||||
prevTips = null
|
||||
instance = null
|
||||
}
|
||||
|
||||
const setTips = tips => {
|
||||
|
@ -39,7 +43,7 @@ const setTips = tips => {
|
|||
}
|
||||
|
||||
const updateTips = event => {
|
||||
if (!instance) return
|
||||
if (!instance) return showTips(event)
|
||||
setTimeout(() => {
|
||||
let msg = getTips(event.target)
|
||||
if (!msg || prevTips === msg) return
|
||||
|
|
|
@ -28,7 +28,7 @@ const getters = {
|
|||
|
||||
// actions
|
||||
const actions = {
|
||||
getUrl({ commit, state }, { musicInfo, type, isRefresh }) {
|
||||
getUrl({ commit, state }, { musicInfo, originMusic, type, isRefresh }) {
|
||||
if (!musicInfo._types[type]) {
|
||||
// 兼容旧版酷我源搜索列表过滤128k音质的bug
|
||||
if (!(musicInfo.source == 'kw' && type == '128k')) return Promise.reject(new Error('该歌曲没有可播放的音频'))
|
||||
|
@ -39,6 +39,7 @@ const actions = {
|
|||
if (musicInfo.typeUrl[type] && !isRefresh) return Promise.resolve()
|
||||
urlRequest = music[musicInfo.source].getMusicUrl(musicInfo, type)
|
||||
return urlRequest.promise.then(result => {
|
||||
if (originMusic) commit('setUrl', { musicInfo: originMusic, url: result.url, type })
|
||||
commit('setUrl', { musicInfo, url: result.url, type })
|
||||
urlRequest = null
|
||||
}).catch(err => {
|
||||
|
|
|
@ -56,4 +56,64 @@ export default {
|
|||
}
|
||||
},
|
||||
supportQuality,
|
||||
|
||||
async findMusic(musicInfo) {
|
||||
const tasks = []
|
||||
for (const source of sources.sources) {
|
||||
if (!sources[source.id].musicSearch || source.id === musicInfo.source || source.id === 'xm') continue
|
||||
|
||||
tasks.push(sources[source.id].musicSearch.search(`${musicInfo.name} ${musicInfo.singer || ''} ${musicInfo.albumName || ''}`.trim(), 1, { limit: 5 }).then(res => {
|
||||
for (const item of res.list) {
|
||||
if (
|
||||
(
|
||||
item.singer === musicInfo.singer &&
|
||||
(item.name === musicInfo.name || item.interval === musicInfo.interval)
|
||||
) ||
|
||||
(
|
||||
item.interval === musicInfo.interval && item.name === musicInfo.name &&
|
||||
(item.singer.includes(musicInfo.singer) || musicInfo.singer.includes(item.singer))
|
||||
)
|
||||
) {
|
||||
return item
|
||||
}
|
||||
}
|
||||
return null
|
||||
}).catch(_ => null))
|
||||
}
|
||||
const result = (await Promise.all(tasks)).filter(s => s)
|
||||
const newResult = []
|
||||
if (result.length) {
|
||||
for (let i = result.length - 1; i > -1; i--) {
|
||||
const item = result[i]
|
||||
if (item.singer === musicInfo.singer && item.name === musicInfo.name && item.interval === musicInfo.interval) {
|
||||
newResult.push(item)
|
||||
result.splice(i, 1)
|
||||
}
|
||||
}
|
||||
for (let i = result.length - 1; i > -1; i--) {
|
||||
const item = result[i]
|
||||
if (item.singer === musicInfo.singer && item.interval === musicInfo.interval) {
|
||||
newResult.push(item)
|
||||
result.splice(i, 1)
|
||||
}
|
||||
}
|
||||
for (let i = result.length - 1; i > -1; i--) {
|
||||
const item = result[i]
|
||||
if (item.name === musicInfo.name && item.singer === musicInfo.singer && item.albumName === musicInfo.albumName) {
|
||||
newResult.push(item)
|
||||
result.splice(i, 1)
|
||||
}
|
||||
}
|
||||
for (let i = result.length - 1; i > -1; i--) {
|
||||
const item = result[i]
|
||||
if (item.singer === musicInfo.singer && item.name === musicInfo.name) {
|
||||
newResult.push(item)
|
||||
result.splice(i, 1)
|
||||
}
|
||||
}
|
||||
newResult.push(...result)
|
||||
}
|
||||
// console.log(newResult)
|
||||
return newResult
|
||||
},
|
||||
}
|
||||
|
|
|
@ -144,6 +144,7 @@ export default {
|
|||
img: null,
|
||||
lrc: null,
|
||||
hash: item.HASH,
|
||||
otherSource: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
|
|
|
@ -60,6 +60,7 @@ export default {
|
|||
_interval: item.duration,
|
||||
img: null,
|
||||
lrc: null,
|
||||
otherSource: null,
|
||||
hash: item.hash,
|
||||
types,
|
||||
_types,
|
||||
|
|
|
@ -517,6 +517,7 @@ export default {
|
|||
img: null,
|
||||
lrc: null,
|
||||
hash: item.audio_info.hash,
|
||||
otherSource: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
|
|
|
@ -142,6 +142,7 @@ export default {
|
|||
interval: formatPlayTime(parseInt(item.song_duration)),
|
||||
img: item.pic,
|
||||
lrc: null,
|
||||
otherSource: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
|
|
|
@ -115,6 +115,7 @@ export default {
|
|||
albumName: info.ALBUM ? decodeName(info.ALBUM) : '',
|
||||
lrc: null,
|
||||
img: null,
|
||||
otherSource: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
|
|
|
@ -237,6 +237,7 @@ export default {
|
|||
interval: formatPlayTime(parseInt(item.duration)),
|
||||
img: null,
|
||||
lrc: null,
|
||||
otherSource: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
|
|
|
@ -144,6 +144,7 @@ export default {
|
|||
img: item.albumImgs && item.albumImgs.length ? item.albumImgs[0].img : null,
|
||||
lrc: null,
|
||||
lrcUrl: item.lrcUrl,
|
||||
otherSource: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
|
|
|
@ -36,7 +36,7 @@ export default {
|
|||
return arr.join('、')
|
||||
},
|
||||
handleResult(rawData) {
|
||||
console.log(rawData)
|
||||
// console.log(rawData)
|
||||
let ids = new Set()
|
||||
const list = []
|
||||
rawData.forEach(item => {
|
||||
|
@ -89,6 +89,7 @@ export default {
|
|||
img: item.imgItems && item.imgItems.length ? item.imgItems[0].img : null,
|
||||
lrc: null,
|
||||
lrcUrl: item.lyricUrl,
|
||||
otherSource: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
|
|
|
@ -141,6 +141,7 @@ export default {
|
|||
img: item.albumImgs && item.albumImgs.length ? item.albumImgs[0].img : null,
|
||||
lrc: null,
|
||||
lrcUrl: item.lrcUrl,
|
||||
otherSource: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
|
|
|
@ -167,6 +167,7 @@ export default {
|
|||
? `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,
|
||||
otherSource: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
|
|
|
@ -78,6 +78,7 @@ export default {
|
|||
? `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,
|
||||
otherSource: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
|
|
|
@ -281,6 +281,7 @@ export default {
|
|||
? `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,
|
||||
otherSource: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
|
|
|
@ -60,6 +60,7 @@ export default {
|
|||
songmid: item.id,
|
||||
img: item.al.picUrl,
|
||||
lrc: null,
|
||||
otherSource: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
|
|
|
@ -161,6 +161,7 @@ export default {
|
|||
songmid: item.id,
|
||||
img: item.al.picUrl,
|
||||
lrc: null,
|
||||
otherSource: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
|
|
|
@ -127,6 +127,7 @@ export default {
|
|||
songStringId: songData.songStringId,
|
||||
lrc: null,
|
||||
lrcUrl: songData.lyricInfo && songData.lyricInfo.lyricFile,
|
||||
otherSource: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
|
|
|
@ -79,6 +79,7 @@ export default {
|
|||
songStringId: songData.songStringId,
|
||||
lrc: null,
|
||||
lrcUrl: songData.lyricInfo && songData.lyricInfo.lyricFile,
|
||||
otherSource: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
|
|
|
@ -142,6 +142,7 @@ export default {
|
|||
img: songData.albumLogo || songData.albumLogoS,
|
||||
lrc: null,
|
||||
lrcUrl: songData.lyricInfo && songData.lyricInfo.lyricFile,
|
||||
otherSource: null,
|
||||
types,
|
||||
_types,
|
||||
typeUrl: {},
|
||||
|
|
|
@ -127,6 +127,7 @@ export default {
|
|||
moveTo: true,
|
||||
sort: true,
|
||||
download: true,
|
||||
search: true,
|
||||
remove: true,
|
||||
sourceDetail: true,
|
||||
},
|
||||
|
@ -222,6 +223,21 @@ export default {
|
|||
action: 'download',
|
||||
disabled: !this.listMenu.itemMenuControl.download,
|
||||
},
|
||||
{
|
||||
name: this.$t('view.list.list_add_to'),
|
||||
action: 'addTo',
|
||||
disabled: !this.listMenu.itemMenuControl.addTo,
|
||||
},
|
||||
{
|
||||
name: this.$t('view.list.list_move_to'),
|
||||
action: 'moveTo',
|
||||
disabled: !this.listMenu.itemMenuControl.moveTo,
|
||||
},
|
||||
{
|
||||
name: this.$t('view.list.list_sort'),
|
||||
action: 'sort',
|
||||
disabled: !this.listMenu.itemMenuControl.sort,
|
||||
},
|
||||
{
|
||||
name: this.$t('view.list.list_copy_name'),
|
||||
action: 'copyName',
|
||||
|
@ -233,19 +249,9 @@ export default {
|
|||
disabled: !this.listMenu.itemMenuControl.sourceDetail,
|
||||
},
|
||||
{
|
||||
name: this.$t('view.list.list_sort'),
|
||||
action: 'sort',
|
||||
disabled: !this.listMenu.itemMenuControl.sort,
|
||||
},
|
||||
{
|
||||
name: this.$t('view.list.list_add_to'),
|
||||
action: 'addTo',
|
||||
disabled: !this.listMenu.itemMenuControl.addTo,
|
||||
},
|
||||
{
|
||||
name: this.$t('view.list.list_move_to'),
|
||||
action: 'moveTo',
|
||||
disabled: !this.listMenu.itemMenuControl.moveTo,
|
||||
name: this.$t('view.list.list_search'),
|
||||
action: 'search',
|
||||
disabled: !this.listMenu.itemMenuControl.search,
|
||||
},
|
||||
{
|
||||
name: this.$t('view.list.list_remove'),
|
||||
|
@ -653,6 +659,7 @@ export default {
|
|||
return assertApiSupport(source)
|
||||
},
|
||||
handleContainerClick(event) {
|
||||
if (!this.$refs.dom_lists) return
|
||||
let isFocusList = event.target == this.$refs.dom_lists || this.$refs.dom_lists.contains(event.target)
|
||||
this.focusTarget = isFocusList ? 'list' : 'listDetail'
|
||||
},
|
||||
|
@ -838,6 +845,10 @@ export default {
|
|||
// })
|
||||
// }
|
||||
break
|
||||
case 'search':
|
||||
minfo = this.list[index]
|
||||
this.handleSearch(minfo)
|
||||
break
|
||||
case 'remove':
|
||||
if (this.selectdListDetailData.length) {
|
||||
this.listRemoveMultiple({ id: this.listId, list: this.selectdListDetailData })
|
||||
|
@ -899,6 +910,14 @@ export default {
|
|||
this.removeAllSelectListDetail()
|
||||
this.isShowListSortModal = false
|
||||
},
|
||||
handleSearch(musicInfo) {
|
||||
this.$router.push({
|
||||
path: 'search',
|
||||
query: {
|
||||
text: `${musicInfo.name} ${musicInfo.singer}`,
|
||||
},
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue