升级到 vue3

This commit is contained in:
lyswhut
2021-12-03 22:11:11 +08:00
parent c6635e554a
commit 8059d9cd73
260 changed files with 14443 additions and 10979 deletions
+55 -726
View File
@@ -1,737 +1,51 @@
<template lang="pug">
#container(v-if="isProd && !isDT && !isLinux" :class="theme" @mouseenter="enableIgnoreMouseEvents" @mouseleave="dieableIgnoreMouseEvents")
#container
core-aside#left
#right
core-toolbar#toolbar
core-view#view
core-player#player
core-play-bar#player
core-icons
material-version-modal(v-show="version.showModal")
material-pact-modal(v-show="!setting.isAgreePact || globalObj.isShowPact")
material-sync-mode-modal(v-show="globalObj.sync.isShowSyncMode")
#container(v-else :class="theme")
core-aside#left
#right
core-toolbar#toolbar
core-view#view
core-player#player
core-icons
material-version-modal(v-show="version.showModal")
material-pact-modal(v-show="!setting.isAgreePact || globalObj.isShowPact")
material-sync-mode-modal(v-show="globalObj.sync.isShowSyncMode")
core-version-modal
core-pact-modal
core-sync-mode-modal
core-play-detail
</template>
<script>
import { mapMutations, mapGetters, mapActions } from 'vuex'
import { rendererOn, rendererSend, rendererInvoke, NAMES } from '../common/ipc'
import { isLinux } from '../common/utils'
import music from './utils/music'
import { throttle, openUrl, compareVer, getPlayList, parseUrlParams, saveSetting } from './utils'
import { base as eventBaseName, sync as eventSyncName } from './event/names'
import apiSourceInfo from './utils/music/api-source-info'
import { initListPosition, initListPrevSelectId } from '@renderer/utils/data'
window.ELECTRON_DISABLE_SECURITY_WARNINGS = process.env.ELECTRON_DISABLE_SECURITY_WARNINGS
const listThrottle = (fn, delay = 100) => {
let timer = null
let _data = {}
return function(data) {
Object.assign(_data, data)
if (timer) return
timer = setTimeout(() => {
timer = null
fn.call(this, _data)
_data = {}
}, delay)
}
}
import { useRefGetter, watch, onMounted } from '@renderer/utils/vueTools'
import useApp from '@renderer/core/useApp'
export default {
data() {
return {
isProd: process.env.NODE_ENV === 'production',
isDT: false,
isLinux,
globalObj: {
apiSource: null,
proxy: {},
isShowPact: false,
qualityList: {},
userApi: {
list: [],
status: false,
message: 'initing',
apis: {},
},
sync: {
enable: false,
isShowSyncMode: false,
deviceName: '',
},
},
updateTimeout: null,
envParams: {
nt: false,
},
}
},
computed: {
...mapGetters(['setting', 'theme', 'version', 'windowSizeActive']),
...mapGetters('list', ['defaultList', 'loveList', 'userList']),
...mapGetters('download', {
downloadList: 'list',
downloadStatus: 'downloadStatus',
}),
...mapGetters('search', {
searchHistoryList: 'historyList',
}),
},
created() {
this.saveMyList = listThrottle(data => {
rendererSend(NAMES.mainWindow.save_playlist, {
type: 'myList',
data,
})
}, 300)
this.saveDownloadList = throttle(n => {
rendererSend(NAMES.mainWindow.save_playlist, {
type: 'downloadList',
data: n,
})
}, 1000)
this.saveSearchHistoryList = throttle(n => {
rendererSend(NAMES.mainWindow.save_data, {
path: 'searchHistoryList',
data: n,
})
}, 500)
},
mounted() {
document.body.classList.add(this.isDT ? 'disableTransparent' : 'transparent')
window.eventHub.$emit(eventBaseName.bindKey)
this.init()
window.eventHub.$on(eventSyncName.handle_action_list, this.handleSyncAction)
window.eventHub.$on(eventSyncName.handle_sync_list, this.handleSyncList)
if (this.setting.sync.enable && this.setting.sync.port) {
rendererInvoke(NAMES.mainWindow.sync_enable, {
enable: this.setting.sync.enable,
port: this.setting.sync.port,
})
}
},
watch: {
setting: {
handler(n, o) {
saveSetting(n)
global.appSetting = n
},
deep: true,
},
defaultList: {
handler(n) {
this.saveMyList({ defaultList: n })
},
deep: true,
},
loveList: {
handler(n) {
this.saveMyList({ loveList: n })
},
deep: true,
},
userList: {
handler(n) {
this.saveMyList({ userList: n })
},
deep: true,
},
downloadList: {
handler(n) {
this.saveDownloadList(window.downloadListFull)
},
deep: true,
},
searchHistoryList(n) {
this.saveSearchHistoryList(n)
},
'globalObj.apiSource'(n, o) {
if (/^user_api/.test(n)) {
this.globalObj.qualityList = {}
this.globalObj.userApi.status = false
this.globalObj.userApi.message = 'initing'
} else {
this.globalObj.qualityList = music.supportQuality[n]
}
if (o === null) return
rendererInvoke(NAMES.mainWindow.set_user_api, n).catch(err => {
console.log(err)
let api = apiSourceInfo.find(api => !api.disabled)
if (api) this.globalObj.apiSource = api.id
})
if (n != this.setting.apiSource) {
this.setSetting(Object.assign({}, this.setting, {
apiSource: n,
}))
}
},
'globalObj.proxy.enable'(n, o) {
if (n != this.setting.network.proxy.enable) {
this.setSetting({
...this.setting,
network: {
...this.setting.network,
proxy: {
...this.setting.network.proxy,
enable: n,
},
},
setup() {
const theme = useRefGetter('theme')
const dom_root = document.getElementById('root')
watch(theme, (val) => {
dom_root.className = val
})
dom_root.className = theme.value
useApp()
onMounted(() => {
// 隐藏等待界面
/* inited.value = true
const dom_mask = document.getElementById('waiting-mask')
if (dom_mask) {
dom_mask.addEventListener('transitionend', () => {
dom_mask.parentNode.removeChild(dom_mask)
})
}
},
'windowSizeActive.fontSize'(n) {
document.documentElement.style.fontSize = n
},
'setting.isShowAnimation': {
handler(n) {
if (n) {
if (document.body.classList.contains('disableAnimation')) {
document.body.classList.remove('disableAnimation')
}
} else {
if (!document.body.classList.contains('disableAnimation')) {
document.body.classList.add('disableAnimation')
}
}
},
immediate: true,
},
},
methods: {
...mapActions(['getVersionInfo']),
...mapMutations(['setNewVersion', 'setVersionModalVisible', 'setDownloadProgress', 'setSetting', 'setDesktopLyricConfig']),
...mapMutations('list', {
list_initList: 'initList',
list_setList: 'setList',
list_listAdd: 'listAdd',
list_listMove: 'listMove',
list_listAddMultiple: 'listAddMultiple',
list_listMoveMultiple: 'listMoveMultiple',
list_listRemove: 'listRemove',
list_listRemoveMultiple: 'listRemoveMultiple',
list_listClear: 'listClear',
list_updateMusicInfo: 'updateMusicInfo',
list_createUserList: 'createUserList',
list_removeUserList: 'removeUserList',
list_setUserListName: 'setUserListName',
list_moveupUserList: 'moveupUserList',
list_movedownUserList: 'movedownUserList',
list_setMusicPosition: 'setMusicPosition',
list_setSyncListData: 'setSyncListData',
}),
...mapMutations('download', ['updateDownloadList']),
...mapMutations('search', {
setSearchHistoryList: 'setHistory',
}),
...mapMutations('player', {
setPlayList: 'setList',
}),
...mapActions('songList', ['getListDetailAll']),
init() {
document.documentElement.style.fontSize = this.windowSizeActive.fontSize
const asyncTask = []
asyncTask.push(rendererInvoke(NAMES.mainWindow.get_env_params).then(this.handleEnvParamsInit))
document.body.addEventListener('click', this.handleBodyClick, true)
rendererOn(NAMES.mainWindow.update_available, (e, info) => {
// this.showUpdateModal(true)
// console.log(info)
this.setVersionModalVisible({ isDownloading: true })
this.getVersionInfo().catch(() => ({
version: info.version,
desc: info.releaseNotes,
})).then(body => {
// console.log(body)
this.setNewVersion(body)
this.$nextTick(() => {
this.setVersionModalVisible({ isShow: true })
})
})
})
rendererOn(NAMES.mainWindow.update_error, (event, err) => {
// console.log(err)
this.clearUpdateTimeout()
this.setVersionModalVisible({ isError: true })
this.$nextTick(() => {
this.showUpdateModal()
})
})
rendererOn(NAMES.mainWindow.update_progress, (event, progress) => {
// console.log(progress)
this.setDownloadProgress(progress)
})
rendererOn(NAMES.mainWindow.update_downloaded, info => {
// console.log(info)
this.clearUpdateTimeout()
this.setVersionModalVisible({ isDownloaded: true })
this.$nextTick(() => {
this.showUpdateModal()
})
})
rendererOn(NAMES.mainWindow.update_not_available, (event, info) => {
this.clearUpdateTimeout()
this.setNewVersion({
version: info.version,
desc: info.releaseNotes,
})
this.setVersionModalVisible({ isLatestVer: true })
})
rendererOn(NAMES.mainWindow.set_config, (event, config) => {
// console.log(config)
// this.setDesktopLyricConfig(config)
// console.log('set_config', JSON.stringify(this.setting) === JSON.stringify(config))
this.setSetting(Object.assign({}, this.setting, config))
window.eventHub.$emit(eventBaseName.set_config, config)
})
// 更新超时定时器
this.updateTimeout = setTimeout(() => {
this.updateTimeout = null
this.setVersionModalVisible({ isTimeOut: true })
this.$nextTick(() => {
this.showUpdateModal()
})
}, 60 * 30 * 1000)
this.listenEvent()
asyncTask.push(this.initData())
asyncTask.push(this.initUserApi())
this.globalObj.sync.enable = this.setting.sync.enable
this.globalObj.apiSource = this.setting.apiSource
if (/^user_api/.test(this.setting.apiSource)) {
rendererInvoke(NAMES.mainWindow.set_user_api, this.setting.apiSource)
} else {
this.globalObj.qualityList = music.supportQuality[this.setting.apiSource]
}
this.globalObj.proxy = Object.assign({}, this.setting.network.proxy)
window.globalObj = this.globalObj
// 初始化音乐sdk
asyncTask.push(music.init())
Promise.all(asyncTask).then(() => {
this.handleInitEnvParamSearch()
this.handleInitEnvParamPlay()
})
},
enableIgnoreMouseEvents() {
if (this.isDT) return
rendererSend(NAMES.mainWindow.set_ignore_mouse_events, false)
// console.log('content enable')
},
dieableIgnoreMouseEvents() {
if (this.isDT) return
// console.log('content disable')
rendererSend(NAMES.mainWindow.set_ignore_mouse_events, true)
},
initData() { // 初始化数据
return Promise.all([
this.initMyList(), // 初始化播放列表
this.initSearchHistoryList(), // 初始化搜索历史列表
initListPosition(), // 列表位置记录
initListPrevSelectId(), // 上次选中的列表记录
])
// this.initDownloadList() // 初始化下载列表
},
initMyList() {
return getPlayList().then(({ defaultList, loveList, userList, downloadList }) => {
if (!defaultList) defaultList = this.defaultList
if (!loveList) loveList = this.loveList
if (userList) {
let needSave = false
const getListId = id => id.includes('.') ? getListId(id.substring(0, id.lastIndexOf('_'))) : id
userList.forEach(l => {
if (!l.id.includes('__') || l.source) return
let [source, id] = l.id.split('__')
id = getListId(id)
l.source = source
l.sourceListId = id
if (!needSave) needSave = true
})
if (needSave) this.saveMyList({ userList })
} else {
userList = this.userList
}
if (!defaultList.list) defaultList.list = []
if (!loveList.list) loveList.list = []
this.list_initList({ defaultList, loveList, userList })
this.initDownloadList(downloadList) // 初始化下载列表
this.initPlayInfo()
})
},
initDownloadList(downloadList) {
if (downloadList) {
downloadList = downloadList.filter(item => item && item.key && item.musicInfo)
for (const item of downloadList) {
if (item.name == null) {
item.name = `${item.musicInfo.name} - ${item.musicInfo.singer}`
item.songmid = item.musicInfo.songmid
}
if (item.status == this.downloadStatus.RUN || item.status == this.downloadStatus.WAITING) {
item.status = this.downloadStatus.PAUSE
item.statusText = '暂停下载'
}
}
this.updateDownloadList(downloadList)
}
},
initSearchHistoryList() {
rendererInvoke(NAMES.mainWindow.get_data, 'searchHistoryList').then(historyList => {
if (historyList == null) {
historyList = []
rendererSend(NAMES.mainWindow.save_data, { path: 'searchHistoryList', data: historyList })
} else {
this.setSearchHistoryList(historyList)
}
})
},
initPlayInfo() {
rendererInvoke(NAMES.mainWindow.get_data, 'playInfo').then(info => {
// console.log(info, window.allList)
window.restorePlayInfo = null
if (!info) return
if (info.index < 0) return
if (info.listId) {
if (info.listId == 'download') {
const list = this.downloadList
// console.log(list)
if (!list || !list[info.index]) return
info.list = list
} else {
const list = window.allList[info.listId]
// console.log(list)
if (!list || !list.list[info.index]) return
info.list = list.list
}
}
if (!info.list || !info.list[info.index]) return
window.restorePlayInfo = info
this.setPlayList({
list: {
list: info.list,
id: info.listId,
},
index: info.index,
})
})
},
initUserApi() {
return Promise.all([
rendererOn(NAMES.mainWindow.user_api_status, (event, { status, message, apiInfo }) => {
// console.log(apiInfo)
this.globalObj.userApi.status = status
this.globalObj.userApi.message = message
if (status) {
if (apiInfo.id === this.setting.apiSource) {
let apis = {}
let qualitys = {}
for (const [source, { actions, type, qualitys: sourceQualitys }] of Object.entries(apiInfo.sources)) {
if (type != 'music') continue
apis[source] = {}
for (const action of actions) {
switch (action) {
case 'musicUrl':
apis[source].getMusicUrl = (songInfo, type) => {
const requestKey = `request__${Math.random().toString().substring(2)}`
return {
canceleFn() {
rendererInvoke(NAMES.mainWindow.request_user_api_cancel, requestKey)
},
promise: rendererInvoke(NAMES.mainWindow.request_user_api, {
requestKey,
data: {
source: source,
action: 'musicUrl',
info: {
type,
musicInfo: songInfo,
},
},
}).then(res => {
// console.log(res)
if (!/^https?:/.test(res.data.url)) return Promise.reject(new Error('Get url failed'))
return { type, url: res.data.url }
}).catch(err => {
console.log(err.message)
return Promise.reject(err)
}),
}
}
break
default:
break
}
}
qualitys[source] = sourceQualitys
}
this.globalObj.qualityList = qualitys
this.globalObj.userApi.apis = apis
}
}
}),
rendererInvoke(NAMES.mainWindow.get_user_api_list).then(res => {
// console.log(res)
if (![...apiSourceInfo.map(s => s.id), ...res.map(s => s.id)].includes(this.setting.apiSource)) {
console.warn('reset api')
let api = apiSourceInfo.find(api => !api.disabled)
if (api) this.globalObj.apiSource = api.id
}
this.globalObj.userApi.list = res
}),
])
},
showUpdateModal() {
(this.version.newVersion && this.version.newVersion.history
? Promise.resolve(this.version.newVersion)
: this.getVersionInfo().then(body => {
this.setNewVersion(body)
return body
})
).catch(() => {
if (this.version.newVersion) return this.version.newVersion
this.setVersionModalVisible({ isUnknow: true })
let result = {
version: '0.0.0',
desc: null,
}
this.setNewVersion(result)
return result
}).then(result => {
if (result.version == '0.0.0') return this.setVersionModalVisible({ isUnknow: true, isShow: true })
if (compareVer(this.version.version, result.version) != -1) return this.setVersionModalVisible({ isLatestVer: true })
if (result.version === this.setting.ignoreVersion) return
// console.log(this.version)
this.$nextTick(() => {
this.setVersionModalVisible({ isShow: true })
})
})
},
clearUpdateTimeout() {
if (!this.updateTimeout) return
clearTimeout(this.updateTimeout)
this.updateTimeout = null
},
handleBodyClick(event) {
if (event.target.tagName != 'A') return
if (event.target.host == window.location.host) return
event.preventDefault()
if (/^https?:\/\//.test(event.target.href)) openUrl(event.target.href)
},
handleEnvParamsInit(envParams) {
this.envParams = envParams
this.isDT = this.envParams.dt
if (this.isDT) {
document.body.classList.remove('transparent')
document.body.classList.add('disableTransparent')
}
if (this.isProd && !this.isDT && !this.isLinux) {
document.body.addEventListener('mouseenter', this.dieableIgnoreMouseEvents)
document.body.addEventListener('mouseleave', this.enableIgnoreMouseEvents)
}
this.handleInitEnvParamSearch()
this.handleInitEnvParamPlay()
},
// 处理启动参数 search
handleInitEnvParamSearch() {
if (this.envParams.search == null) return
this.$router.push({
path: 'search',
query: {
text: this.envParams.search,
},
})
},
// 处理启动参数 play
handleInitEnvParamPlay() {
if (this.envParams.play == null || typeof this.envParams.play != 'string') return
// -play="source=kw&link=链接、ID"
// -play="source=myList&name=名字"
// -play="source=myList&name=名字&index=位置"
const params = parseUrlParams(this.envParams.play)
if (params.type != 'songList') return
this.handlePlaySongList(params)
},
handlePlaySongList(params) {
switch (params.source) {
case 'myList':
if (params.name != null) {
let targetList
const lists = Object.values(window.allList)
for (const list of lists) {
if (list.name === params.name) {
targetList = list
break
}
}
if (!targetList) return
this.setPlayList({
list: {
list: targetList.list,
id: targetList.id,
},
index: this.getListPlayIndex(targetList.list, params.index),
})
}
break
case 'kw':
case 'kg':
case 'tx':
case 'mg':
case 'wy':
this.playSongListDetail(params.source, params.link, params.index)
break
}
},
async playSongListDetail(source, link, playIndex) {
if (link == null) return
let list
try {
list = await this.getListDetailAll({ source, id: decodeURIComponent(link) })
} catch (err) {
console.log(err)
}
this.setPlayList({
list: {
list,
id: null,
},
index: this.getListPlayIndex(list, playIndex),
})
},
getListPlayIndex(list, index) {
if (index == null) {
index = 1
} else {
index = parseInt(index)
if (Number.isNaN(index)) {
index = 1
} else {
if (index < 1) index = 1
else if (index > list.length) index = list.length
}
}
return index - 1
},
listenEvent() {
window.eventHub.$on('key_escape_down', this.handle_key_esc_down)
},
unlistenEvent() {
window.eventHub.$off('key_escape_down', this.handle_key_esc_down)
},
handle_key_esc_down({ event }) {
if (event.repeat) return
if (event.target.tagName != 'INPUT' || event.target.classList.contains('ignore-esc')) return
event.target.value = ''
event.target.blur()
},
handleSyncAction({ action, data }) {
if (typeof data == 'object') data.isSync = true
// console.log(action, data)
switch (action) {
case 'set_list':
this.list_setList(data)
break
case 'list_add':
this.list_listAdd(data)
break
case 'list_move':
this.list_listMove(data)
break
case 'list_add_multiple':
this.list_listAddMultiple(data)
break
case 'list_move_multiple':
this.list_listMoveMultiple(data)
break
case 'list_remove':
this.list_listRemove(data)
break
case 'list_remove_multiple':
this.list_listRemoveMultiple(data)
break
case 'list_clear':
this.list_listClear(data)
break
case 'update_music_info':
this.list_updateMusicInfo(data)
break
case 'create_user_list':
this.list_createUserList(data)
break
case 'remove_user_list':
this.list_removeUserList(data)
break
case 'set_user_list_name':
this.list_setUserListName(data)
break
case 'moveup_user_list':
this.list_moveupUserList(data)
break
case 'movedown_user_list':
this.list_movedownUserList(data)
break
case 'set_music_position':
this.list_setMusicPosition(data)
break
default:
break
}
},
handleSyncList({ action, data }) {
switch (action) {
case 'getData':
global.eventHub.$emit(eventSyncName.send_sync_list, {
action: 'getData',
data: {
defaultList: this.defaultList,
loveList: this.loveList,
userList: this.userList,
},
})
break
case 'setData':
this.list_setSyncListData(data)
break
case 'selectMode':
this.globalObj.sync.deviceName = data.deviceName
this.globalObj.sync.isShowSyncMode = true
break
case 'closeSelectMode':
this.globalObj.sync.isShowSyncMode = false
break
}
},
},
beforeDestroy() {
this.clearUpdateTimeout()
this.unlistenEvent()
if (this.isProd) {
document.body.removeEventListener('mouseenter', this.dieableIgnoreMouseEvents)
document.body.removeEventListener('mouseleave', this.enableIgnoreMouseEvents)
}
document.body.removeEventListener('click', this.handleBodyClick)
window.eventHub.$emit(eventBaseName.unbindKey)
dom_mask.classList.add('hide')
} */
document.getElementById('root').style.display = 'block'
})
},
}
</script>
<style lang="less">
@import './assets/styles/index.less';
@import './assets/styles/layout.less';
@@ -745,6 +59,16 @@ body {
height: 100vh;
box-sizing: border-box;
}
#root {
height: 100%;
position: relative;
overflow: hidden;
color: @color-theme_2-font;
background: @color-theme-bgimg @color-theme-bgposition no-repeat;
background-size: @color-theme-bgsize;
transition: background-color @transition-theme;
background-color: @color-theme;
}
.disableAnimation * {
transition: none !important;
@@ -753,11 +77,22 @@ body {
.transparent {
padding: @shadow-app;
#container {
#waiting-mask {
border-radius: @radius-border;
left: @shadow-app;
right: @shadow-app;
top: @shadow-app;
bottom: @shadow-app;
}
#root {
box-shadow: 0 0 @shadow-app rgba(0, 0, 0, 0.5);
border-radius: @radius-border;
background-color: transparent;
}
#container {
border-radius: @radius-border;
background-color: transparent;
}
}
.disableTransparent {
background-color: #fff;
@@ -776,12 +111,6 @@ body {
position: relative;
display: flex;
height: 100%;
overflow: hidden;
color: @color-theme_2-font;
background: @color-theme-bgimg @color-theme-bgposition no-repeat;
background-size: @color-theme-bgsize;
transition: background-color @transition-theme;
background-color: @color-theme;
}
#left {
@@ -809,7 +138,7 @@ body {
}
each(@themes, {
#container.@{value} {
#root.@{value} {
color: ~'@{color-@{value}-theme_2-font}';
background-color: ~'@{color-@{value}-theme}';
background-image: ~'@{color-@{value}-theme-bgimg}';