v2.0.0
This commit is contained in:
@@ -1,37 +1,50 @@
|
||||
<template lang="pug">
|
||||
div(:class="$style.btns")
|
||||
button(type="button" v-if="playBtn" @contextmenu.capture.stop :aria-label="$t('list__play')" @click.stop="handleClick('play')")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 287.386 287.386' space='preserve' v-once)
|
||||
use(xlink:href='#icon-testPlay')
|
||||
button(type="button" v-if="listAddBtn" @contextmenu.capture.stop :aria-label="$t('list__add_to')" @click.stop="handleClick('listAdd')")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 42 42' space='preserve' v-once)
|
||||
use(xlink:href='#icon-addTo')
|
||||
button(type="button" v-if="downloadBtn && setting.download.enable" @contextmenu.capture.stop :aria-label="$t('list__download')" @click.stop="handleClick('download')")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 475.078 475.077' space='preserve' v-once)
|
||||
use(xlink:href='#icon-download')
|
||||
//- button(type="button" :aria-label="$t('list__add')" v-if="userInfo" @click.stop="handleClick('add')")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 42 42' space='preserve')
|
||||
use(xlink:href='#icon-addTo')
|
||||
button(type="button" v-if="startBtn" @contextmenu.capture.stop :aria-label="$t('list__start')" @click.stop="handleClick('start')")
|
||||
svg(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' v-once)
|
||||
use(xlink:href='#icon-play')
|
||||
button(type="button" v-if="pauseBtn" @contextmenu.capture.stop :aria-label="$t('list__pause')" @click.stop="handleClick('pause')")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 277.338 277.338' space='preserve' v-once)
|
||||
use(xlink:href='#icon-pause')
|
||||
button(type="button" v-if="fileBtn" @contextmenu.capture.stop :aria-label="$t('list__file')" @click.stop="handleClick('file')")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='-61 0 512 512' space='preserve' v-once)
|
||||
use(xlink:href='#icon-musicFile')
|
||||
button(type="button" v-if="searchBtn" @contextmenu.capture.stop :aria-label="$t('list__search')" @click.stop="handleClick('search')")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 30.239 30.239' space='preserve' v-once)
|
||||
use(xlink:href='#icon-search')
|
||||
button(type="button" v-if="removeBtn" :aria-label="$t('list__remove')" @click.stop="handleClick('remove')")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 212.982 212.982' space='preserve' v-once)
|
||||
use(xlink:href='#icon-delete')
|
||||
|
||||
<template>
|
||||
<div :class="$style.btns">
|
||||
<button v-if="playBtn" type="button" :aria-label="$t('list__play')" @contextmenu.capture.stop @click.stop="handleClick('play')">
|
||||
<svg v-once version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 287.386 287.386" space="preserve">
|
||||
<use xlink:href="#icon-testPlay" />
|
||||
</svg>
|
||||
</button>
|
||||
<button v-if="listAddBtn" type="button" :aria-label="$t('list__add_to')" @contextmenu.capture.stop @click.stop="handleClick('listAdd')">
|
||||
<svg v-once version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 42 42" space="preserve">
|
||||
<use xlink:href="#icon-addTo" />
|
||||
</svg>
|
||||
</button>
|
||||
<button v-if="downloadBtn && appSetting['download.enable']" type="button" :aria-label="$t('list__download')" @contextmenu.capture.stop @click.stop="handleClick('download')">
|
||||
<svg v-once version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 475.078 475.077" space="preserve">
|
||||
<use xlink:href="#icon-download" />
|
||||
</svg>
|
||||
</button>
|
||||
<button v-if="startBtn" type="button" :aria-label="$t('list__start')" @contextmenu.capture.stop @click.stop="handleClick('start')">
|
||||
<svg v-once 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" />
|
||||
</svg>
|
||||
</button>
|
||||
<button v-if="pauseBtn" type="button" :aria-label="$t('list__pause')" @contextmenu.capture.stop @click.stop="handleClick('pause')">
|
||||
<svg v-once version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 277.338 277.338" space="preserve">
|
||||
<use xlink:href="#icon-pause" />
|
||||
</svg>
|
||||
</button>
|
||||
<button v-if="fileBtn" type="button" :aria-label="$t('list__file')" @contextmenu.capture.stop @click.stop="handleClick('file')">
|
||||
<svg v-once version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="-61 0 512 512" space="preserve">
|
||||
<use xlink:href="#icon-musicFile" />
|
||||
</svg>
|
||||
</button>
|
||||
<button v-if="searchBtn" type="button" :aria-label="$t('list__search')" @contextmenu.capture.stop @click.stop="handleClick('search')">
|
||||
<svg v-once version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 30.239 30.239" space="preserve">
|
||||
<use xlink:href="#icon-search" />
|
||||
</svg>
|
||||
</button>
|
||||
<button v-if="removeBtn" type="button" :aria-label="$t('list__remove')" @click.stop="handleClick('remove')">
|
||||
<svg v-once version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 212.982 212.982" space="preserve">
|
||||
<use xlink:href="#icon-delete" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -72,8 +85,11 @@ export default {
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['setting']),
|
||||
emits: ['btn-click'],
|
||||
setup() {
|
||||
return {
|
||||
appSetting,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick(action) {
|
||||
@@ -97,7 +113,7 @@ export default {
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
padding: 4px 7px;
|
||||
color: @color-btn;
|
||||
color: var(--color-button-font);
|
||||
outline: none;
|
||||
transition: background-color 0.2s ease;
|
||||
line-height: 0;
|
||||
@@ -110,27 +126,12 @@ export default {
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: @color-theme_2-hover;
|
||||
background-color: var(--color-button-background-hover);
|
||||
}
|
||||
&:active {
|
||||
background-color: @color-theme_2-active;
|
||||
background-color: var(--color-button-background-active);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
each(@themes, {
|
||||
:global(#root.@{value}) {
|
||||
.btns {
|
||||
button {
|
||||
color: ~'@{color-@{value}-btn}';
|
||||
&:hover {
|
||||
background-color: ~'@{color-@{value}-theme_2-hover}';
|
||||
}
|
||||
&:active {
|
||||
background-color: ~'@{color-@{value}-theme_2-active}';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</style>
|
||||
|
||||
@@ -1,21 +1,31 @@
|
||||
<template lang="pug">
|
||||
teleport(:to="teleport")
|
||||
div(:class="$style.container" v-if="showModal")
|
||||
transition(enter-active-class="animated fadeIn" leave-active-class="animated fadeOut")
|
||||
div(:class="$style.modal" v-show="showContent" @click="bgClose && close()")
|
||||
transition(:enter-active-class="inClass" :leave-active-class="outClass" @after-enter="$emit('after-enter', $event)" @after-leave="handleAfterLeave")
|
||||
div(:class="$style.content" v-show="showContent" @click.stop :style="contentStyle")
|
||||
header(:class="$style.header")
|
||||
button(type="button" @click="close" v-if="closeBtn")
|
||||
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='100%' viewBox='0 0 212.982 212.982' space='preserve')
|
||||
use(xlink:href='#icon-delete')
|
||||
slot
|
||||
<template>
|
||||
<teleport :to="teleport">
|
||||
<div v-if="showModal" ref="dom_container" :class="$style.container">
|
||||
<transition enter-active-class="animated fadeIn" leave-active-class="animated fadeOut">
|
||||
<div v-show="showContent" :class="[$style.modal, {[$style.filter]: teleport == '#root'}]" @click="bgClose && close()">
|
||||
<transition :enter-active-class="inClass" :leave-active-class="outClass" @after-enter="$emit('after-enter', $event)" @after-leave="handleAfterLeave">
|
||||
<div v-show="showContent" :class="$style.content" :style="contentStyle" @click.stop>
|
||||
<header :class="$style.header">
|
||||
<button v-if="closeBtn" type="button" @click="close">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 212.982 212.982" space="preserve">
|
||||
<use xlink:href="#icon-delete" />
|
||||
</svg>
|
||||
</button>
|
||||
</header>
|
||||
<slot />
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</teleport>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getRandom } from '@renderer/utils'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { nextTick } from '@renderer/utils/vueTools'
|
||||
import { getRandom } from '@common/utils/common'
|
||||
import { nextTick } from '@common/utils/vueTools'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
show: {
|
||||
@@ -38,81 +48,125 @@ export default {
|
||||
type: String,
|
||||
default: '76%',
|
||||
},
|
||||
minWidth: {
|
||||
type: String,
|
||||
default: '280px',
|
||||
},
|
||||
maxHeight: {
|
||||
type: String,
|
||||
default: '80%',
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: 'auto',
|
||||
},
|
||||
},
|
||||
emits: ['after-enter', 'after-leave', 'close'],
|
||||
data() {
|
||||
return {
|
||||
animateIn: [
|
||||
'flipInX',
|
||||
'flipInY',
|
||||
'fadeIn',
|
||||
'bounceIn',
|
||||
'lightSpeedIn',
|
||||
'rotateInDownLeft',
|
||||
'rotateInDownRight',
|
||||
'rotateInUpLeft',
|
||||
'rotateInUpRight',
|
||||
'rollIn',
|
||||
'zoomIn',
|
||||
'zoomInDown',
|
||||
'zoomInLeft',
|
||||
'zoomInRight',
|
||||
'zoomInUp',
|
||||
'slideInDown',
|
||||
'slideInLeft',
|
||||
'slideInRight',
|
||||
'slideInUp',
|
||||
'jackInTheBox',
|
||||
],
|
||||
animateOut: [
|
||||
'flipOutX',
|
||||
'flipOutY',
|
||||
'fadeOut',
|
||||
'bounceOut',
|
||||
'lightSpeedOut',
|
||||
'rotateOutDownLeft',
|
||||
'rotateOutDownRight',
|
||||
'rotateOutUpLeft',
|
||||
'rotateOutUpRight',
|
||||
'rollOut',
|
||||
'zoomOut',
|
||||
'zoomOutDown',
|
||||
'zoomOutLeft',
|
||||
'zoomOutRight',
|
||||
'zoomOutUp',
|
||||
'slideOutDown',
|
||||
'slideOutLeft',
|
||||
'slideOutRight',
|
||||
'slideOutUp',
|
||||
// 'hinge',
|
||||
animates: [
|
||||
[['jackInTheBox', 'flipInX', 'flipInY', 'lightSpeedIn'], ['flipOutX', 'flipOutY', 'lightSpeedOut']],
|
||||
// [['jackInTheBox', 'lightSpeedIn'], ['lightSpeedOut']],
|
||||
[['rotateInDownLeft', 'rotateInDownRight', 'rotateInUpLeft', 'rotateInUpRight'], ['rotateOutDownLeft', 'rotateOutDownRight', 'rotateOutUpLeft', 'rotateOutUpRight']],
|
||||
[['jackInTheBox', 'zoomInDown', 'zoomInUp'], ['zoomOutDown', 'zoomOutUp']],
|
||||
[['slideInDown', 'slideInLeft', 'slideInRight', 'slideInUp'], ['slideOutDown', 'slideOutLeft', 'slideOutRight', 'slideOutUp']],
|
||||
|
||||
// ['flipInX', 'flipOutX'],
|
||||
// ['flipInY', 'flipOutY'],
|
||||
// ['lightSpeedIn', 'lightSpeedOut'],
|
||||
// ['rotateInDownLeft', 'rotateOutDownLeft'],
|
||||
// ['rotateInDownRight', 'rotateOutDownRight'],
|
||||
// ['rotateInUpLeft', 'rotateOutUpLeft'],
|
||||
// ['rotateInUpRight', 'rotateOutUpRight'],
|
||||
// // ['rollIn', 'rollOut'],
|
||||
// // ['zoomIn', 'zoomOut'],
|
||||
// ['zoomInDown', 'zoomOutDown'],
|
||||
// // ['zoomInLeft', 'zoomOutLeft'],
|
||||
// // ['zoomInRight', 'zoomOutRight'],
|
||||
// ['zoomInUp', 'zoomOutUp'],
|
||||
// ['slideInDown', 'slideOutDown'],
|
||||
// ['slideInLeft', 'slideOutLeft'],
|
||||
// ['slideInRight', 'slideOutRight'],
|
||||
// ['slideInUp', 'slideOutUp'],
|
||||
// // ['jackInTheBox', 'hinge'],
|
||||
],
|
||||
// animateIn: [
|
||||
// 'flipInX',
|
||||
// 'flipInY',
|
||||
// // 'fadeIn',
|
||||
// // 'bounceIn',
|
||||
// 'lightSpeedIn',
|
||||
// 'rotateInDownLeft',
|
||||
// 'rotateInDownRight',
|
||||
// 'rotateInUpLeft',
|
||||
// 'rotateInUpRight',
|
||||
// 'rollIn',
|
||||
// 'zoomIn',
|
||||
// 'zoomInDown',
|
||||
// 'zoomInLeft',
|
||||
// 'zoomInRight',
|
||||
// 'zoomInUp',
|
||||
// 'slideInDown',
|
||||
// 'slideInLeft',
|
||||
// 'slideInRight',
|
||||
// 'slideInUp',
|
||||
// 'jackInTheBox',
|
||||
// ],
|
||||
// animateOut: [
|
||||
// 'flipOutX',
|
||||
// 'flipOutY',
|
||||
// // 'fadeOut',
|
||||
// // 'bounceOut',
|
||||
// 'lightSpeedOut',
|
||||
// 'rotateOutDownLeft',
|
||||
// 'rotateOutDownRight',
|
||||
// 'rotateOutUpLeft',
|
||||
// 'rotateOutUpRight',
|
||||
// 'rollOut',
|
||||
// 'zoomOut',
|
||||
// 'zoomOutDown',
|
||||
// 'zoomOutLeft',
|
||||
// 'zoomOutRight',
|
||||
// 'zoomOutUp',
|
||||
// 'slideOutDown',
|
||||
// 'slideOutLeft',
|
||||
// 'slideOutRight',
|
||||
// 'slideOutUp',
|
||||
// 'hinge',
|
||||
// ],
|
||||
inClass: 'animated jackInTheBox',
|
||||
outClass: 'animated flipOutX',
|
||||
unwatchFn: null,
|
||||
outClass: 'animated slideOutRight',
|
||||
showModal: false,
|
||||
showContent: false,
|
||||
// ai: 0,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['setting']),
|
||||
contentStyle() {
|
||||
return {
|
||||
maxWidth: this.maxWidth,
|
||||
minWidth: this.minWidth,
|
||||
width: this.width,
|
||||
maxHeight: this.maxHeight,
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'setting.randomAnimate'(n) {
|
||||
n ? this.createWatch() : this.removeWatch()
|
||||
},
|
||||
show: {
|
||||
handler(val) {
|
||||
if (val) {
|
||||
// const dom = document.getElementById(this.teleport)
|
||||
// if (dom) {
|
||||
// // dom.t
|
||||
// }
|
||||
this.setRandomAnimation()
|
||||
this.showModal = true
|
||||
nextTick(() => {
|
||||
this.$refs.dom_container.parentNode.classList.add('show-modal')
|
||||
this.showContent = true
|
||||
})
|
||||
} else {
|
||||
this.$refs.dom_container?.parentNode.classList.remove('show-modal')
|
||||
this.showContent = false
|
||||
}
|
||||
},
|
||||
@@ -120,37 +174,24 @@ export default {
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.setting.randomAnimate) this.createWatch()
|
||||
this.setRandomAnimation()
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.removeWatch()
|
||||
this.$refs.dom_container?.parentNode.classList.remove('show-modal')
|
||||
},
|
||||
methods: {
|
||||
check(isShow) {
|
||||
if (isShow) {
|
||||
this.showModal = true
|
||||
nextTick(() => {
|
||||
this.showContent = true
|
||||
})
|
||||
} else {
|
||||
this.showContent = false
|
||||
setRandomAnimation() {
|
||||
if (appSetting['common.randomAnimate']) {
|
||||
const [animIn, animOut] = this.animates[getRandom(0, this.animates.length)]
|
||||
// const [animIn, animOut] = this.animates[this.ai]
|
||||
// if (++this.ai >= this.animates.length) this.ai = 0
|
||||
// console.log(animIn, animOut)
|
||||
// this.inClass = 'animated ' + animIn
|
||||
// this.outClass = 'animated ' + animOut
|
||||
this.inClass = 'animated ' + animIn[getRandom(0, animIn.length)]
|
||||
this.outClass = 'animated ' + animOut[getRandom(0, animOut.length)]
|
||||
}
|
||||
},
|
||||
createWatch() {
|
||||
this.removeWatch()
|
||||
this.unwatchFn = this.$watch('show', function(n) {
|
||||
if (!n) return
|
||||
this.inClass = 'animated ' + this.animateIn[getRandom(0, this.animateIn.length)]
|
||||
this.outClass = 'animated ' + this.animateOut[getRandom(0, this.animateOut.length)]
|
||||
})
|
||||
this.inClass = 'animated ' + this.animateIn[getRandom(0, this.animateIn.length)]
|
||||
this.outClass = 'animated ' + this.animateOut[getRandom(0, this.animateOut.length)]
|
||||
},
|
||||
removeWatch() {
|
||||
if (!this.unwatchFn) return
|
||||
this.unwatchFn()
|
||||
this.unwatchFn = null
|
||||
},
|
||||
close() {
|
||||
this.$emit('close')
|
||||
},
|
||||
@@ -178,34 +219,50 @@ export default {
|
||||
.modal {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, .3);
|
||||
// background-color: rgba(0, 0, 0, .2);
|
||||
// background-color: rgba(255, 255, 255, .6);
|
||||
// background-color: var(--color-primary-light-600-alpha-900);
|
||||
// backdrop-filter: blur(4px);
|
||||
// backdrop-filter: grayscale(70%);
|
||||
display: grid;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
// will-change: transform;
|
||||
|
||||
&.filter {
|
||||
backdrop-filter: grayscale(70%);
|
||||
}
|
||||
|
||||
// &:before {
|
||||
// .mixin-after;
|
||||
// position: absolute;
|
||||
// left: 0;
|
||||
// top: 0;
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
// background-color: var(--color-000);
|
||||
// opacity: .6;
|
||||
// }
|
||||
}
|
||||
|
||||
.content {
|
||||
position: relative;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 3px rgba(0, 0, 0, .3);
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 0 4px rgba(0, 0, 0, .25);
|
||||
overflow: hidden;
|
||||
max-height: 80%;
|
||||
// max-height: 80%;
|
||||
// max-width: 76%;
|
||||
min-width: 220px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
z-index: 100;
|
||||
|
||||
> * {
|
||||
background-color: @color-theme_2-background_2;
|
||||
}
|
||||
background-color: var(--color-content-background);
|
||||
}
|
||||
|
||||
.header {
|
||||
flex: none;
|
||||
background-color: @color-theme;
|
||||
background-color: var(--color-primary-light-100-alpha-100);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
@@ -216,7 +273,7 @@ export default {
|
||||
cursor: pointer;
|
||||
padding: 4px 7px;
|
||||
background-color: transparent;
|
||||
color: @color-theme-font-label;
|
||||
color: var(--color-primary-dark-500-alpha-500);
|
||||
outline: none;
|
||||
transition: background-color 0.2s ease;
|
||||
line-height: 0;
|
||||
@@ -226,41 +283,12 @@ export default {
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: @color-theme-hover;
|
||||
background-color: var(--color-primary-dark-100-alpha-600);
|
||||
}
|
||||
&:active {
|
||||
background-color: @color-theme_2-active;
|
||||
background-color: var(--color-primary-dark-200-alpha-600);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
each(@themes, {
|
||||
:global(#root.@{value}) {
|
||||
.modal {
|
||||
background-color: rgba(0, 0, 0, .3);
|
||||
}
|
||||
|
||||
.content {
|
||||
box-shadow: 0 0 3px rgba(0, 0, 0, .3);
|
||||
> * {
|
||||
background-color: ~'@{color-@{value}-theme_2-background_2}';
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
background-color: ~'@{color-@{value}-theme}';
|
||||
button {
|
||||
color: ~'@{color-@{value}-theme-font-label}';
|
||||
|
||||
&:hover {
|
||||
background-color: ~'@{color-@{value}-theme-hover}';
|
||||
}
|
||||
&:active {
|
||||
background-color: ~'@{color-@{value}-theme_2-active}';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,63 +1,114 @@
|
||||
<template lang="pug">
|
||||
div(:class="$style.songList")
|
||||
transition(enter-active-class="animated-fast fadeIn" leave-active-class="animated-fast fadeOut")
|
||||
div(:class="$style.list")
|
||||
div.thead(:class="$style.thead")
|
||||
table
|
||||
thead
|
||||
tr
|
||||
th.nobreak.center(:class="$style.th" :style="{ width: rowWidth.r1 }") #
|
||||
th.nobreak(:class="$style.th" :style="{ width: rowWidth.r2 }") {{$t('music_name')}}
|
||||
th.nobreak(:class="$style.th" :style="{ width: rowWidth.r3 }") {{$t('music_singer')}}
|
||||
th.nobreak(:class="$style.th" :style="{ width: rowWidth.r4 }") {{$t('music_album')}}
|
||||
th.nobreak(:class="$style.th" :style="{ width: rowWidth.r5 }") {{$t('music_time')}}
|
||||
th.nobreak(:class="$style.th" :style="{ width: rowWidth.r6 }") {{$t('action')}}
|
||||
div(:class="$style.content")
|
||||
div(v-show="list.length" :class="$style.content" ref="dom_listContent")
|
||||
base-virtualized-list(:list="list" key-name="songmid" ref="listRef" :item-height="listItemHeight"
|
||||
containerClass="scroll" contentClass="list" @contextmenu.capture="handleListRightClick")
|
||||
template(#default="{ item, index }")
|
||||
div.list-item(@click="handleListItemClick($event, index)" @contextmenu="handleListItemRightClick($event, index)"
|
||||
:class="[{ selected: rightClickSelectedIndex == index }, { active: selectedList.includes(item) }]")
|
||||
div.list-item-cell.nobreak.center(:style="{ width: rowWidth.r1 }" style="padding-left: 3px; padding-right: 3px;" :class="$style.noSelect" @click.stop) {{index + 1}}
|
||||
div.list-item-cell.auto(:style="{ width: rowWidth.r2 }" :aria-label="item.name + (item._types.flac32bit ? ` - ${$t('tag__lossless_24bit')}` : (item._types.ape || item._types.flac || item._types.wav) ? ` - ${$t('tag__lossless')}` : item._types['320k'] ? ` - ${$t('tag__high_quality')}` : '')")
|
||||
span.select {{item.name}}
|
||||
span.badge.badge-theme-success(:class="[$style.labelQuality, $style.noSelect]" v-if="item._types.flac32bit") {{$t('tag__lossless_24bit')}}
|
||||
span.badge.badge-theme-success(:class="[$style.labelQuality, $style.noSelect]" v-else-if="item._types.ape || item._types.flac || item._types.wav") {{$t('tag__lossless')}}
|
||||
span.badge.badge-theme-info(:class="[$style.labelQuality, $style.noSelect]" v-else-if="item._types['320k']") {{$t('tag__high_quality')}}
|
||||
div.list-item-cell(:style="{ width: rowWidth.r3 }" :aria-label="item.singer")
|
||||
span.select {{item.singer}}
|
||||
div.list-item-cell(:style="{ width: rowWidth.r4 }" :aria-label="item.albumName")
|
||||
span.select {{item.albumName}}
|
||||
div.list-item-cell(:style="{ width: rowWidth.r5 }")
|
||||
span(:class="[$style.time, $style.noSelect]") {{item.interval || '--/--'}}
|
||||
div.list-item-cell(:style="{ width: rowWidth.r6 }" style="padding-left: 0; padding-right: 0;")
|
||||
material-list-buttons(:index="index" :class="$style.btns"
|
||||
:remove-btn="false" @btn-click="handleListBtnClick"
|
||||
:download-btn="assertApiSupport(item.source)")
|
||||
template(#footer)
|
||||
div(:class="$style.pagination")
|
||||
material-pagination(:count="total" :limit="limit" :page="page" @btn-click="$emit('togglePage', $event)")
|
||||
transition(enter-active-class="animated-fast fadeIn" leave-active-class="animated-fast fadeOut")
|
||||
div(v-show="!list.length" :class="$style.noitem")
|
||||
p(v-html="noItem")
|
||||
//- material-flow-btn(:show="isShowEditBtn && assertApiSupport(source)" :remove-btn="false" @btn-click="handleFlowBtnClick")
|
||||
common-download-modal(v-model:show="isShowDownload" :musicInfo="selectedDownloadMusicInfo" teleport="#view")
|
||||
common-download-multiple-modal(v-model:show="isShowDownloadMultiple" :list="selectedList" @confirm="removeAllSelect" teleport="#view")
|
||||
common-list-add-modal(v-model:show="isShowListAdd" :musicInfo="selectedAddMusicInfo" teleport="#view")
|
||||
common-list-add-multiple-modal(v-model:show="isShowListAddMultiple" :musicList="selectedList" @confirm="removeAllSelect" teleport="#view")
|
||||
base-menu(:menus="menus" :location="menuLocation" item-name="name" :isShow="isShowItemMenu" @menu-click="handleMenuClick")
|
||||
<template>
|
||||
<div :class="$style.songList">
|
||||
<transition enter-active-class="animated-fast fadeIn" leave-active-class="animated-fast fadeOut">
|
||||
<div :class="$style.list">
|
||||
<div class="thead">
|
||||
<table>
|
||||
<thead>
|
||||
<tr v-if="actionButtonsVisible">
|
||||
<th class="num" style="width: 5%;">#</th>
|
||||
<th class="nobreak">{{ $t('music_name') }}</th>
|
||||
<th class="nobreak" style="width: 22%;">{{ $t('music_singer') }}</th>
|
||||
<th class="nobreak" style="width: 22%;">{{ $t('music_album') }}</th>
|
||||
<th class="nobreak" style="width: 9%;">{{ $t('music_time') }}</th>
|
||||
<th class="nobreak" style="width: 16%;">{{ $t('action') }}</th>
|
||||
</tr>
|
||||
<tr v-else>
|
||||
<th class="num" style="width: 5%;">#</th>
|
||||
<th class="nobreak">{{ $t('music_name') }}</th>
|
||||
<th class="nobreak" style="width: 24%;">{{ $t('music_singer') }}</th>
|
||||
<th class="nobreak" style="width: 27%;">{{ $t('music_album') }}</th>
|
||||
<th class="nobreak" style="width: 10%;">{{ $t('music_time') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
<div :class="$style.content">
|
||||
<div v-show="!noItem" ref="dom_listContent" :class="$style.content">
|
||||
<base-virtualized-list v-if="actionButtonsVisible" ref="listRef" :list="list" key-name="id" :item-height="listItemHeight" container-class="scroll" content-class="list" @contextmenu.capture="handleListRightClick">
|
||||
<template #default="{ item, index }">
|
||||
<div
|
||||
class="list-item" :class="[{ selected: rightClickSelectedIndex == index }, { active: selectedList.includes(item) }]"
|
||||
@click="handleListItemClick($event, index)" @contextmenu="handleListItemRightClick($event, index)"
|
||||
>
|
||||
<div class="list-item-cell no-select num" style="flex: 0 0 5%;" @click.stop>{{ index + 1 }}</div>
|
||||
<div class="list-item-cell auto name">
|
||||
<span class="select name" :aria-label="item.name">{{ item.name }}</span>
|
||||
<span v-if="item.meta._qualitys.flac24bit" class="no-select badge badge-theme-primary">{{ $t('tag__lossless_24bit') }}</span>
|
||||
<span v-else-if="item.meta._qualitys.ape || item.meta._qualitys.flac || item.meta._qualitys.wav" class="no-select badge badge-theme-primary">{{ $t('tag__lossless') }}</span>
|
||||
<span v-else-if="item.meta._qualitys['320k']" class="no-select badge badge-theme-secondary">{{ $t('tag__high_quality') }}</span>
|
||||
<span v-if="sourceTag" class="no-select badge badge-theme-tertiary">{{ item.source }}</span>
|
||||
</div>
|
||||
<div class="list-item-cell" style="flex: 0 0 22%;"><span class="select" :aria-label="item.singer">{{ item.singer }}</span></div>
|
||||
<div class="list-item-cell" style="flex: 0 0 22%;"><span class="select" :aria-label="item.meta.albumName">{{ item.meta.albumName }}</span></div>
|
||||
<div class="list-item-cell" style="flex: 0 0 9%;"><span class="no-select">{{ item.interval || '--/--' }}</span></div>
|
||||
<div class="list-item-cell" style="flex: 0 0 16%; padding-left: 0; padding-right: 0;">
|
||||
<material-list-buttons :index="index" :remove-btn="false" :download-btn="assertApiSupport(item.source)" :play-btn="checkApiSource ? assertApiSupport(item.source) : true" @btn-click="handleListBtnClick" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<div :class="$style.pagination">
|
||||
<material-pagination :count="total" :limit="limit" :page="page" @btn-click="$emit('togglePage', $event)" />
|
||||
</div>
|
||||
</template>
|
||||
</base-virtualized-list>
|
||||
<base-virtualized-list v-else ref="listRef" :list="list" key-name="id" :item-height="listItemHeight" container-class="scroll" content-class="list" @contextmenu.capture="handleListRightClick">
|
||||
<template #default="{ item, index }">
|
||||
<div
|
||||
class="list-item" :class="[{ selected: rightClickSelectedIndex == index }, { active: selectedList.includes(item) }]"
|
||||
@click="handleListItemClick($event, index)" @contextmenu="handleListItemRightClick($event, index)"
|
||||
>
|
||||
<div class="list-item-cell no-select num" style="flex: 0 0 5%;" @click.stop>{{ index + 1 }}</div>
|
||||
<div class="list-item-cell auto name">
|
||||
<span class="select name" :aria-label="item.name">{{ item.name }}</span>
|
||||
<span v-if="item.meta._qualitys.flac24bit" class="no-select badge badge-theme-primary">{{ $t('tag__lossless_24bit') }}</span>
|
||||
<span v-else-if="item.meta._qualitys.ape || item.meta._qualitys.flac || item.meta._qualitys.wav" class="no-select badge badge-theme-primary">{{ $t('tag__lossless') }}</span>
|
||||
<span v-else-if="item.meta._qualitys['320k']" class="no-select badge badge-theme-secondary">{{ $t('tag__high_quality') }}</span>
|
||||
<span v-if="sourceTag" class="no-select badge badge-theme-tertiary">{{ item.source }}</span>
|
||||
</div>
|
||||
<div class="list-item-cell" style="flex: 0 0 24%;"><span class="select" :aria-label="item.singer">{{ item.singer }}</span></div>
|
||||
<div class="list-item-cell" style="flex: 0 0 27%;"><span class="select" :aria-label="item.meta.albumName">{{ item.meta.albumName }}</span></div>
|
||||
<div class="list-item-cell" style="flex: 0 0 10%;"><span class="no-select">{{ item.interval || '--/--' }}</span></div>
|
||||
</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<div :class="$style.pagination">
|
||||
<material-pagination :count="total" :limit="limit" :page="page" @btn-click="$emit('togglePage', $event)" />
|
||||
</div>
|
||||
</template>
|
||||
</base-virtualized-list>
|
||||
</div>
|
||||
<transition enter-active-class="animated fadeIn" leave-active-class="animated fadeOut">
|
||||
<div v-show="noItem" :class="$style.noitem">
|
||||
<p v-text="noItem" />
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
<!-- <material-flow-btn :show="isShowEditBtn && assertApiSupport(source)" :remove-btn="false" @btn-click="handleFlowBtnClick" /> -->
|
||||
<!-- <common-download-modal v-model:show="isShowDownload" :music-info="selectedDownloadMusicInfo" teleport="#view" />
|
||||
<common-download-multiple-modal v-model:show="isShowDownloadMultiple" :list="selectedList" teleport="#view" @confirm="removeAllSelect" /> -->
|
||||
<common-list-add-modal v-model:show="isShowListAdd" :music-info="selectedAddMusicInfo" teleport="#view" />
|
||||
<common-list-add-multiple-modal v-model:show="isShowListAddMultiple" :music-list="selectedList" teleport="#view" @confirm="removeAllSelect" />
|
||||
<common-download-modal v-model:show="isShowDownload" :music-info="selectedDownloadMusicInfo" teleport="#view" />
|
||||
<common-download-multiple-modal v-model:show="isShowDownloadMultiple" :list="selectedList" teleport="#view" @confirm="removeAllSelect" />
|
||||
<base-menu v-model="isShowItemMenu" :menus="menus" :xy="menuLocation" item-name="name" @menu-click="handleMenuClick" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { clipboardWriteText, assertApiSupport } from '@renderer/utils'
|
||||
import { ref, useCssModule, useRefGetter } from '@renderer/utils/vueTools'
|
||||
import { clipboardWriteText } from '@common/utils/electron'
|
||||
import { assertApiSupport } from '@renderer/store/utils'
|
||||
import { ref } from '@common/utils/vueTools'
|
||||
import useList from './useList'
|
||||
import useMenu from './useMenu'
|
||||
import usePlay from './usePlay'
|
||||
import useMusicDownload from './useMusicDownload'
|
||||
import useMusicAdd from './useMusicAdd'
|
||||
import useMusicActions from './useMusicActions'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
export default {
|
||||
name: 'MaterialOnlineList',
|
||||
props: {
|
||||
@@ -79,33 +130,26 @@ export default {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
rowWidth: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
r1: '5%',
|
||||
r2: 'auto',
|
||||
r3: '22%',
|
||||
r4: '22%',
|
||||
r5: '8%',
|
||||
r6: '13%',
|
||||
}
|
||||
},
|
||||
sourceTag: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
noItem: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
checkApiSource: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
emits: ['show-menu', 'play-list', 'togglePage'],
|
||||
setup(props, { emit }) {
|
||||
const actionButtonsVisible = appSetting['list.actionButtonsVisible']
|
||||
const rightClickSelectedIndex = ref(-1)
|
||||
const dom_listContent = ref(null)
|
||||
const listRef = ref(null)
|
||||
|
||||
const styles = useCssModule()
|
||||
|
||||
const setting = useRefGetter('setting')
|
||||
|
||||
const {
|
||||
selectedList,
|
||||
listItemHeight,
|
||||
@@ -117,7 +161,7 @@ export default {
|
||||
handlePlayMusic,
|
||||
handlePlayMusicLater,
|
||||
doubleClickPlay,
|
||||
} = usePlay({ selectedList, props, removeAllSelect, setting, emit })
|
||||
} = usePlay({ selectedList, props, removeAllSelect, emit })
|
||||
|
||||
const {
|
||||
isShowListAdd,
|
||||
@@ -143,10 +187,9 @@ export default {
|
||||
menuLocation,
|
||||
isShowItemMenu,
|
||||
showMenu,
|
||||
hideMenu,
|
||||
menuClick,
|
||||
} = useMenu({
|
||||
listRef,
|
||||
props,
|
||||
assertApiSupport,
|
||||
emit,
|
||||
|
||||
@@ -176,10 +219,10 @@ export default {
|
||||
if (!event.target.classList.contains('select')) return
|
||||
event.stopImmediatePropagation()
|
||||
let classList = dom_listContent.value.classList
|
||||
classList.add(styles.copying)
|
||||
classList.add('copying')
|
||||
window.requestAnimationFrame(() => {
|
||||
let str = window.getSelection().toString()
|
||||
classList.remove(styles.copying)
|
||||
classList.remove('copying')
|
||||
str = str.split(/\n\n/).map(s => s.replace(/\n/g, ' ')).join('\n').trim()
|
||||
if (!str.length) return
|
||||
clipboardWriteText(str)
|
||||
@@ -220,7 +263,6 @@ export default {
|
||||
isShowItemMenu,
|
||||
menuLocation,
|
||||
handleMenuClick,
|
||||
hideMenu,
|
||||
|
||||
handleListRightClick,
|
||||
assertApiSupport,
|
||||
@@ -234,6 +276,7 @@ export default {
|
||||
selectedDownloadMusicInfo,
|
||||
|
||||
scrollToTop,
|
||||
actionButtonsVisible,
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -251,50 +294,23 @@ export default {
|
||||
}
|
||||
|
||||
.list {
|
||||
position: relative;
|
||||
font-size: 14px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
height: 100%;
|
||||
}
|
||||
.thead {
|
||||
flex: none;
|
||||
}
|
||||
.th:first-child {
|
||||
color: @color-theme_2-font-label;
|
||||
// padding-left: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: auto;
|
||||
min-height: 0;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&.copying {
|
||||
.no-select {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
:global(.list) {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
:global(.list-item-cell) {
|
||||
font-size: 12px !important;
|
||||
:global(.badge) {
|
||||
margin-left: 3px;
|
||||
}
|
||||
&:first-child {
|
||||
// padding-left: 10px;
|
||||
font-size: 11px !important;
|
||||
color: @color-theme_2-font-label !important;
|
||||
}
|
||||
}
|
||||
:global(.badge) {
|
||||
opacity: .85;
|
||||
}
|
||||
}
|
||||
.pagination {
|
||||
text-align: center;
|
||||
padding: 15px 0;
|
||||
@@ -311,30 +327,12 @@ export default {
|
||||
flex-flow: column nowrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
// background-color: var(--color-000);
|
||||
|
||||
p {
|
||||
font-size: 24px;
|
||||
color: @color-theme_2-font-label;
|
||||
color: var(--color-font-label);
|
||||
}
|
||||
}
|
||||
|
||||
each(@themes, {
|
||||
:global(#root.@{value}) {
|
||||
.th:first-child {
|
||||
color: ~'@{color-@{value}-theme_2-font-label}';
|
||||
}
|
||||
:global(.list) {
|
||||
:global(.list-item-cell) {
|
||||
&:first-child {
|
||||
color: ~'@{color-@{value}-theme_2-font-label}' !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.noitem {
|
||||
p {
|
||||
color: ~'@{color-@{value}-theme_2-font-label}';
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</style>
|
||||
|
||||
+26
-20
@@ -1,8 +1,11 @@
|
||||
import { computed, useRefGetter, watch, ref, onBeforeUnmount } from '@renderer/utils/vueTools'
|
||||
import { windowSizeList, isFullscreen } from '@renderer/core/share'
|
||||
import { computed, watch, ref, onBeforeUnmount } from '@common/utils/vueTools'
|
||||
import { isFullscreen } from '@renderer/store'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
import { getFontSizeWithScreen } from '@renderer/utils'
|
||||
|
||||
const useKeyEvent = ({ handleSelectAllData }) => {
|
||||
const useKeyEvent = ({ handleSelectAllData }: {
|
||||
handleSelectAllData: () => void
|
||||
}) => {
|
||||
const keyEvent = {
|
||||
isShiftDown: false,
|
||||
isModDown: false,
|
||||
@@ -20,8 +23,8 @@ const useKeyEvent = ({ handleSelectAllData }) => {
|
||||
const handle_key_mod_up = () => {
|
||||
if (keyEvent.isModDown) keyEvent.isModDown = false
|
||||
}
|
||||
const handle_key_mod_a_down = ({ event }) => {
|
||||
if (event.target.tagName == 'INPUT') return
|
||||
const handle_key_mod_a_down = ({ event }: LX.KeyDownEevent) => {
|
||||
if (!event || (event.target as HTMLElement).tagName == 'INPUT') return
|
||||
event.preventDefault()
|
||||
if (event.repeat) return
|
||||
keyEvent.isModDown = false
|
||||
@@ -29,28 +32,31 @@ const useKeyEvent = ({ handleSelectAllData }) => {
|
||||
}
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.eventHub.off('key_shift_down', handle_key_shift_down)
|
||||
window.eventHub.off('key_shift_up', handle_key_shift_up)
|
||||
window.eventHub.off('key_mod_down', handle_key_mod_down)
|
||||
window.eventHub.off('key_mod_up', handle_key_mod_up)
|
||||
window.eventHub.off('key_mod+a_down', handle_key_mod_a_down)
|
||||
window.key_event.off('key_shift_down', handle_key_shift_down)
|
||||
window.key_event.off('key_shift_up', handle_key_shift_up)
|
||||
window.key_event.off('key_mod_down', handle_key_mod_down)
|
||||
window.key_event.off('key_mod_up', handle_key_mod_up)
|
||||
window.key_event.off('key_mod+a_down', handle_key_mod_a_down)
|
||||
})
|
||||
window.eventHub.on('key_shift_down', handle_key_shift_down)
|
||||
window.eventHub.on('key_shift_up', handle_key_shift_up)
|
||||
window.eventHub.on('key_mod_down', handle_key_mod_down)
|
||||
window.eventHub.on('key_mod_up', handle_key_mod_up)
|
||||
window.eventHub.on('key_mod+a_down', handle_key_mod_a_down)
|
||||
window.key_event.on('key_shift_down', handle_key_shift_down)
|
||||
window.key_event.on('key_shift_up', handle_key_shift_up)
|
||||
window.key_event.on('key_mod_down', handle_key_mod_down)
|
||||
window.key_event.on('key_mod_up', handle_key_mod_up)
|
||||
window.key_event.on('key_mod+a_down', handle_key_mod_a_down)
|
||||
|
||||
return keyEvent
|
||||
}
|
||||
|
||||
|
||||
export default ({ props }) => {
|
||||
const selectedList = ref([])
|
||||
const setting = useRefGetter('setting')
|
||||
export default ({ props }: {
|
||||
props: {
|
||||
list: LX.Music.MusicInfoOnline[]
|
||||
}
|
||||
}) => {
|
||||
const selectedList = ref<LX.Music.MusicInfoOnline[]>([])
|
||||
let lastSelectIndex = -1
|
||||
const listItemHeight = computed(() => {
|
||||
return Math.ceil((isFullscreen.value ? getFontSizeWithScreen() : parseInt(windowSizeList.find(item => item.id == setting.value.windowSizeId).fontSize)) * 2.3)
|
||||
return Math.ceil((isFullscreen.value ? getFontSizeWithScreen() : appSetting['common.fontSize']) * 2.3)
|
||||
})
|
||||
|
||||
const removeAllSelect = () => {
|
||||
@@ -62,7 +68,7 @@ export default ({ props }) => {
|
||||
}
|
||||
const keyEvent = useKeyEvent({ handleSelectAllData })
|
||||
|
||||
const handleSelectData = clickIndex => {
|
||||
const handleSelectData = (clickIndex: number) => {
|
||||
if (keyEvent.isShiftDown) {
|
||||
if (selectedList.value.length) {
|
||||
removeAllSelect()
|
||||
@@ -1,8 +1,9 @@
|
||||
import { computed, ref, reactive, useI18n, useCssModule, nextTick } from '@renderer/utils/vueTools'
|
||||
import musicSdk from '@renderer/utils/music'
|
||||
import { computed, ref, reactive, nextTick } from '@common/utils/vueTools'
|
||||
import musicSdk from '@renderer/utils/musicSdk'
|
||||
import { useI18n } from '@renderer/plugins/i18n'
|
||||
|
||||
export default ({
|
||||
listRef,
|
||||
props,
|
||||
assertApiSupport,
|
||||
emit,
|
||||
|
||||
@@ -21,9 +22,8 @@ export default ({
|
||||
search: true,
|
||||
sourceDetail: true,
|
||||
})
|
||||
const { t } = useI18n()
|
||||
const styles = useCssModule()
|
||||
const menuLocation = ref({ x: 0, y: 0 })
|
||||
const t = useI18n()
|
||||
const menuLocation = reactive({ x: 0, y: 0 })
|
||||
const isShowItemMenu = ref(false)
|
||||
|
||||
const menus = computed(() => {
|
||||
@@ -66,17 +66,17 @@ export default ({
|
||||
// this.listMenu.itemMenuControl.play =
|
||||
// this.listMenu.itemMenuControl.playLater =
|
||||
itemMenuControl.download = assertApiSupport(musicInfo.source)
|
||||
let dom_container = event.target.closest('.' + styles.songList)
|
||||
const getOffsetValue = (target, x = 0, y = 0) => {
|
||||
if (target === dom_container) return { x, y }
|
||||
if (!target) return { x: 0, y: 0 }
|
||||
x += target.offsetLeft
|
||||
y += target.offsetTop
|
||||
return getOffsetValue(target.offsetParent, x, y)
|
||||
|
||||
if (props.checkApiSource) {
|
||||
itemMenuControl.playLater =
|
||||
itemMenuControl.play =
|
||||
itemMenuControl.download
|
||||
}
|
||||
let { x, y } = getOffsetValue(event.target)
|
||||
menuLocation.value.x = x + event.offsetX
|
||||
menuLocation.value.y = y + event.offsetY - listRef.value.getScrollTop()
|
||||
|
||||
menuLocation.x = event.pageX
|
||||
menuLocation.y = event.pageY
|
||||
|
||||
if (isShowItemMenu.value) return
|
||||
emit('show-menu')
|
||||
nextTick(() => {
|
||||
isShowItemMenu.value = true
|
||||
@@ -119,6 +119,5 @@ export default ({
|
||||
isShowItemMenu,
|
||||
showMenu,
|
||||
menuClick,
|
||||
hideMenu,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useRouter } from '@renderer/utils/vueTools'
|
||||
import musicSdk from '@renderer/utils/music'
|
||||
import { openUrl } from '@renderer/utils'
|
||||
import { useRouter } from '@common/utils/vueRouter'
|
||||
import musicSdk from '@renderer/utils/musicSdk'
|
||||
import { openUrl } from '@common/utils/electron'
|
||||
import { toOldMusicInfo } from '@renderer/utils'
|
||||
|
||||
|
||||
export default ({ props }) => {
|
||||
@@ -9,7 +10,7 @@ export default ({ props }) => {
|
||||
const handleSearch = index => {
|
||||
const info = props.list[index]
|
||||
router.push({
|
||||
path: 'search',
|
||||
path: '/search',
|
||||
query: {
|
||||
text: `${info.name} ${info.singer}`,
|
||||
},
|
||||
@@ -18,7 +19,7 @@ export default ({ props }) => {
|
||||
|
||||
const handleOpenMusicDetail = index => {
|
||||
const minfo = props.list[index]
|
||||
const url = musicSdk[minfo.source].getMusicDetailPageUrl(minfo)
|
||||
const url = musicSdk[minfo.source].getMusicDetailPageUrl(toOldMusicInfo(minfo))
|
||||
if (!url) return
|
||||
openUrl(url)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ref, nextTick } from '@renderer/utils/vueTools'
|
||||
import { ref, nextTick } from '@common/utils/vueTools'
|
||||
|
||||
export default ({ selectedList, props }) => {
|
||||
const isShowListAdd = ref(false)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ref, nextTick } from '@renderer/utils/vueTools'
|
||||
import { ref, nextTick } from '@common/utils/vueTools'
|
||||
|
||||
export default ({ selectedList, props }) => {
|
||||
const isShowDownload = ref(false)
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
import { useCommit } from '@renderer/utils/vueTools'
|
||||
import { defaultList } from '@renderer/core/share/list'
|
||||
import { getList } from '@renderer/core/share/utils'
|
||||
|
||||
export default ({ selectedList, props, removeAllSelect, setting, emit }) => {
|
||||
let clickTime = 0
|
||||
let clickIndex = -1
|
||||
|
||||
const listAddMultiple = useCommit('list', 'listAddMultiple')
|
||||
const listAdd = useCommit('list', 'listAdd')
|
||||
const setList = useCommit('player', 'setList')
|
||||
const setTempPlayList = useCommit('player', 'setTempPlayList')
|
||||
|
||||
const handlePlayMusic = (index, single) => {
|
||||
let targetSong = props.list[index]
|
||||
const defaultListMusics = getList(defaultList.id)
|
||||
if (selectedList.value.length && !single) {
|
||||
listAddMultiple({ id: defaultList.id, list: [...selectedList.value] })
|
||||
removeAllSelect()
|
||||
} else {
|
||||
listAdd({ id: defaultList.id, musicInfo: targetSong })
|
||||
}
|
||||
let targetIndex = defaultListMusics.findIndex(s => s.songmid === targetSong.songmid)
|
||||
if (targetIndex > -1) {
|
||||
setList({
|
||||
listId: defaultList.id,
|
||||
index: targetIndex,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const handlePlayMusicLater = (index, single) => {
|
||||
if (selectedList.value.length && !single) {
|
||||
setTempPlayList(selectedList.value.map(s => ({ listId: '__temp__', musicInfo: s })))
|
||||
removeAllSelect()
|
||||
} else {
|
||||
setTempPlayList([{ listId: '__temp__', musicInfo: props.list[index] }])
|
||||
}
|
||||
}
|
||||
|
||||
const doubleClickPlay = index => {
|
||||
if (
|
||||
window.performance.now() - clickTime > 400 ||
|
||||
clickIndex !== index
|
||||
) {
|
||||
clickTime = window.performance.now()
|
||||
clickIndex = index
|
||||
return
|
||||
}
|
||||
if (setting.value.list.isClickPlayList) {
|
||||
emit('play-list', index)
|
||||
} else {
|
||||
handlePlayMusic(index, true)
|
||||
}
|
||||
clickTime = 0
|
||||
clickIndex = -1
|
||||
}
|
||||
|
||||
return {
|
||||
handlePlayMusic,
|
||||
handlePlayMusicLater,
|
||||
doubleClickPlay,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// import { useCommit } from '@common/utils/vueTools'
|
||||
import { defaultList } from '@renderer/store/list/state'
|
||||
import { getListMusics, addListMusics } from '@renderer/store/list/action'
|
||||
import { addTempPlayList } from '@renderer/store/player/action'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
import { Ref } from '@common/utils/vueTools'
|
||||
import { playList } from '@renderer/core/player'
|
||||
|
||||
export default ({ selectedList, props, removeAllSelect, emit }: {
|
||||
selectedList: Ref<LX.Music.MusicInfoOnline[]>
|
||||
props: {
|
||||
list: LX.Music.MusicInfoOnline[]
|
||||
}
|
||||
removeAllSelect: () => void
|
||||
emit: (event: 'show-menu' | 'play-list' | 'togglePage', ...args: any[]) => void
|
||||
}) => {
|
||||
let clickTime = 0
|
||||
let clickIndex = -1
|
||||
|
||||
const handlePlayMusic = async(index: number, single: boolean) => {
|
||||
let targetSong = props.list[index]
|
||||
const defaultListMusics = await getListMusics(defaultList.id)
|
||||
if (selectedList.value.length && !single) {
|
||||
await addListMusics(defaultList.id, [...selectedList.value])
|
||||
removeAllSelect()
|
||||
} else {
|
||||
await addListMusics(defaultList.id, [targetSong])
|
||||
}
|
||||
let targetIndex = defaultListMusics.findIndex(s => s.id === targetSong.id)
|
||||
if (targetIndex > -1) {
|
||||
playList(defaultList.id, targetIndex)
|
||||
}
|
||||
}
|
||||
|
||||
const handlePlayMusicLater = (index: number, single: boolean) => {
|
||||
if (selectedList.value.length && !single) {
|
||||
addTempPlayList(selectedList.value.map(s => ({ listId: '__temp__', musicInfo: s })))
|
||||
removeAllSelect()
|
||||
} else {
|
||||
addTempPlayList([{ listId: '__temp__', musicInfo: props.list[index] }])
|
||||
}
|
||||
}
|
||||
|
||||
const doubleClickPlay = (index: number) => {
|
||||
if (
|
||||
window.performance.now() - clickTime > 400 ||
|
||||
clickIndex !== index
|
||||
) {
|
||||
clickTime = window.performance.now()
|
||||
clickIndex = index
|
||||
return
|
||||
}
|
||||
if (appSetting['list.isClickPlayList']) {
|
||||
emit('play-list', index)
|
||||
} else {
|
||||
void handlePlayMusic(index, true)
|
||||
}
|
||||
clickTime = 0
|
||||
clickIndex = -1
|
||||
}
|
||||
|
||||
return {
|
||||
handlePlayMusic,
|
||||
handlePlayMusicLater,
|
||||
doubleClickPlay,
|
||||
}
|
||||
}
|
||||
@@ -1,52 +1,56 @@
|
||||
<template>
|
||||
<div :class="$style.pagination" v-if="allPage > 1">
|
||||
<ul>
|
||||
<li v-if="page===1" :class="$style.disabled"><span>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 451.846 451.847" space="preserve">
|
||||
<use xlink:href="#icon-left"></use>
|
||||
</svg></span></li>
|
||||
<li v-else>
|
||||
<button type="button" @click="handleClick(page - 1)" :aria-label="$t('pagination__prev')">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 451.846 451.847" space="preserve">
|
||||
<use xlink:href="#icon-left"></use>
|
||||
</svg>
|
||||
</button>
|
||||
</li>
|
||||
<li v-if="allPage > btnLength && page > pageEvg+1" :class="$style.first">
|
||||
<button type="button" @click="handleClick(1)" :aria-label="$t('pagination__page', { num: 1 })">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 451.846 451.847" space="preserve">
|
||||
<use xlink:href="#icon-first"></use>
|
||||
</svg>
|
||||
</button>
|
||||
</li>
|
||||
<li v-for="(p, index) in pages" :key="index" :class="{[$style.active] : p == page}"><span v-if="p === page" v-text="page"></span>
|
||||
<button v-else type="button" @click="handleClick(p)" v-text="p" :aria-label="$t('pagination__page', { num: p })"></button>
|
||||
</li>
|
||||
<li v-if="allPage > btnLength && allPage - page > pageEvg" :class="$style.last">
|
||||
<button type="button" @click="handleClick(allPage)" :aria-label="$t('pagination__page', { num: allPage })">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 451.846 451.847" space="preserve">
|
||||
<use xlink:href="#icon-last"></use>
|
||||
</svg>
|
||||
</button>
|
||||
</li>
|
||||
<li v-if="page===allPage" :class="$style.disabled"><span>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 451.846 451.847" space="preserve">
|
||||
<use xlink:href="#icon-right"></use>
|
||||
</svg></span></li>
|
||||
<li v-else>
|
||||
<button type="button" @click="handleClick(page + 1)" :aria-label="$t('pagination__next')">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 451.846 451.847" space="preserve">
|
||||
<use xlink:href="#icon-right"></use>
|
||||
</svg>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div v-if="maxPage > 1" :class="$style.pagination">
|
||||
<ul>
|
||||
<li v-if="page == 1" :class="$style.disabled">
|
||||
<span>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 451.846 451.847" space="preserve">
|
||||
<use xlink:href="#icon-left" />
|
||||
</svg>
|
||||
</span>
|
||||
</li>
|
||||
<li v-else>
|
||||
<button type="button" :aria-label="$t('pagination__prev')" @click="handleClick(page - 1)">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 451.846 451.847" space="preserve">
|
||||
<use xlink:href="#icon-left" />
|
||||
</svg>
|
||||
</button>
|
||||
</li>
|
||||
<li v-if="maxPage > btnLength && page > pageEvg+1" :class="$style.first">
|
||||
<button type="button" :aria-label="$t('pagination__page', { num: 1 })" @click="handleClick(1)">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 451.846 451.847" space="preserve">
|
||||
<use xlink:href="#icon-first" />
|
||||
</svg>
|
||||
</button>
|
||||
</li>
|
||||
<li v-for="p in pages" :key="p" :class="{[$style.active] : p == page}">
|
||||
<span v-if="p === page" v-text="page" />
|
||||
<button v-else type="button" :aria-label="$t('pagination__page', { num: p })" @click="handleClick(p)" v-text="p" />
|
||||
</li>
|
||||
<li v-if="maxPage > btnLength && maxPage - page > pageEvg" :class="$style.last">
|
||||
<button type="button" :aria-label="$t('pagination__page', { num: maxPage })" @click="handleClick(maxPage)">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 451.846 451.847" space="preserve">
|
||||
<use xlink:href="#icon-last" />
|
||||
</svg>
|
||||
</button>
|
||||
</li>
|
||||
<li v-if="page == maxPage" :class="$style.disabled">
|
||||
<span>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 451.846 451.847" space="preserve">
|
||||
<use xlink:href="#icon-right" />
|
||||
</svg></span>
|
||||
</li>
|
||||
<li v-else>
|
||||
<button type="button" :aria-label="$t('pagination__next')" @click="handleClick(page + 1)">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 451.846 451.847" space="preserve">
|
||||
<use xlink:href="#icon-right" />
|
||||
</svg>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -66,61 +70,31 @@ export default {
|
||||
type: Number,
|
||||
default: 7,
|
||||
},
|
||||
maxPage: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageArr: [],
|
||||
}
|
||||
},
|
||||
emits: ['btn-click'],
|
||||
computed: {
|
||||
...mapGetters(['userInfo']),
|
||||
allPage() {
|
||||
return this.maxPage == null ? Math.ceil(this.count / this.limit) || 1 : this.maxPage
|
||||
maxPage() {
|
||||
return Math.ceil(this.count / this.limit) || 1
|
||||
},
|
||||
pageEvg() {
|
||||
return Math.floor(this.btnLength / 2)
|
||||
},
|
||||
pages() {
|
||||
if (this.allPage <= this.btnLength) return this.pageArr
|
||||
if (this.maxPage <= this.btnLength) return Array.from({ length: this.maxPage }, (_, i) => i + 1)
|
||||
let start =
|
||||
this.page - this.pageEvg > 1
|
||||
? this.allPage - this.page < this.pageEvg + 1
|
||||
? this.allPage - (this.btnLength - 1)
|
||||
? this.maxPage - this.page < this.pageEvg + 1
|
||||
? this.maxPage - (this.btnLength - 1)
|
||||
: this.page - this.pageEvg
|
||||
: 1
|
||||
let end =
|
||||
this.page + this.pageEvg <= this.btnLength
|
||||
? this.btnLength
|
||||
: this.page + this.pageEvg <= this.allPage
|
||||
? this.page + this.pageEvg
|
||||
: this.allPage
|
||||
// console.log(start-1);
|
||||
// console.log(end);
|
||||
// console.log(this.pageArr.slice(start-1, end-1));
|
||||
return this.pageArr.slice(start - 1, end)
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
allPage() {
|
||||
this.initPageArr()
|
||||
return Array.from({ length: this.btnLength }, (_, i) => start + i)
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
initPageArr() {
|
||||
this.pageArr = []
|
||||
for (let i = 1; i <= this.allPage; i++) this.pageArr.push(i)
|
||||
},
|
||||
handleClick(page) {
|
||||
this.$emit('btn-click', page)
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.initPageArr()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -130,7 +104,7 @@ export default {
|
||||
|
||||
.pagination {
|
||||
display: inline-block;
|
||||
background-color: @color-pagination-background;
|
||||
background-color: var(--color-button-background);
|
||||
// border-top-left-radius: 8px;
|
||||
border-radius: @radius-border;
|
||||
ul {
|
||||
@@ -140,7 +114,7 @@ export default {
|
||||
// border-radius: .3125rem;
|
||||
li {
|
||||
// margin-right: @padding;
|
||||
color: @color-theme;
|
||||
// color: var(--color-button-font);
|
||||
// border: .0625rem solid @theme_line;
|
||||
// border-radius: .3125rem;
|
||||
transition: 0.4s ease;
|
||||
@@ -156,12 +130,12 @@ export default {
|
||||
display: block;
|
||||
padding: 7px 12px;
|
||||
line-height: 1;
|
||||
color: @color-theme;
|
||||
color: var(--color-button-font);
|
||||
font-size: 13px;
|
||||
}
|
||||
&.active {
|
||||
span {
|
||||
background-color: @color-pagination-select;
|
||||
background-color: var(--color-button-background-selected);
|
||||
}
|
||||
}
|
||||
button {
|
||||
@@ -171,10 +145,10 @@ export default {
|
||||
outline: none;
|
||||
transition: background-color .3s ease;
|
||||
&:hover {
|
||||
background-color: @color-pagination-hover;
|
||||
background-color: var(--color-button-background-hover);
|
||||
}
|
||||
&:active {
|
||||
background-color: @color-pagination-active;
|
||||
background-color: var(--color-button-background-active);
|
||||
}
|
||||
}
|
||||
&.disabled {
|
||||
@@ -207,35 +181,4 @@ export default {
|
||||
}
|
||||
|
||||
|
||||
each(@themes, {
|
||||
:global(#root.@{value}) {
|
||||
|
||||
.pagination {
|
||||
background-color: ~'@{color-@{value}-pagination-background}';
|
||||
ul {
|
||||
li {
|
||||
color: ~'@{color-@{value}-theme}';
|
||||
span,
|
||||
button {
|
||||
color: ~'@{color-@{value}-theme}';
|
||||
}
|
||||
&.active {
|
||||
span {
|
||||
background-color: ~'@{color-@{value}-pagination-select}';
|
||||
}
|
||||
}
|
||||
button {
|
||||
&:hover {
|
||||
background-color: ~'@{color-@{value}-pagination-hover}';
|
||||
}
|
||||
&:active {
|
||||
background-color: ~'@{color-@{value}-pagination-active}';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,50 +1,57 @@
|
||||
<template>
|
||||
<div :class="$style.container">
|
||||
<div :class="[$style.search, {[$style.active]: focus}, {[$style.big]: big}, {[$style.small]: small}]">
|
||||
<div :class="$style.form">
|
||||
<input :placeholder="placeholder"
|
||||
v-model.trim="text"
|
||||
ref="dom_input"
|
||||
@focus="handleFocus"
|
||||
@blur="handleBlur"
|
||||
@input="$emit('update:modelValue', text)"
|
||||
@change="sendEvent('change')"
|
||||
@keyup.enter="handleSearch"
|
||||
@keyup.arrow-down.prevent="handleKeyDown"
|
||||
@keyup.arrow-up.prevent="handleKeyUp"
|
||||
@contextmenu="handleContextMenu" />
|
||||
<transition enter-active-class="animated zoomIn" leave-active-class="animated zoomOut">
|
||||
<button type="button" @click="handleClearList" v-show="text">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 24 24" space="preserve">
|
||||
<use xlink:href="#icon-window-close"></use>
|
||||
</svg>
|
||||
<div :class="$style.container">
|
||||
<div :class="[$style.search, {[$style.active]: focus}, {[$style.big]: big}, {[$style.small]: small}]">
|
||||
<div :class="$style.form">
|
||||
<input
|
||||
ref="dom_input"
|
||||
v-model.trim="text"
|
||||
:placeholder="placeholder"
|
||||
@focus="handleFocus"
|
||||
@blur="handleBlur"
|
||||
@input="$emit('update:modelValue', text)"
|
||||
@change="sendEvent('change')"
|
||||
@keyup.enter="handleSearch"
|
||||
@keyup.arrow-down.prevent="handleKeyDown"
|
||||
@keyup.arrow-up.prevent="handleKeyUp"
|
||||
@contextmenu="handleContextMenu"
|
||||
>
|
||||
<transition enter-active-class="animated zoomIn" leave-active-class="animated zoomOut">
|
||||
<button v-show="text" type="button" @click="handleClearList">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 24 24" space="preserve">
|
||||
<use xlink:href="#icon-window-close" />
|
||||
</svg>
|
||||
</button>
|
||||
</transition>
|
||||
<button type="button" @click="handleSearch">
|
||||
<slot>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 30.239 30.239" space="preserve">
|
||||
<use xlink:href="#icon-search" />
|
||||
</svg>
|
||||
</slot>
|
||||
</button>
|
||||
</transition>
|
||||
<button type="button" @click="handleSearch">
|
||||
<slot>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="100%" viewBox="0 0 30.239 30.239" space="preserve">
|
||||
<use xlink:href="#icon-search"></use>
|
||||
</svg>
|
||||
</slot>
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="list" :class="$style.list" :style="listStyle">
|
||||
<ul ref="dom_list">
|
||||
<li v-for="(item, index) in list"
|
||||
:key="item"
|
||||
:class="{[$style.select]: selectIndex === index }"
|
||||
@mouseenter="selectIndex = index"
|
||||
@click="handleTemplistClick(index)"
|
||||
><span>{{item}}</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div v-if="list" :class="$style.list" :style="listStyle">
|
||||
<ul ref="dom_list">
|
||||
<li
|
||||
v-for="(item, index) in list"
|
||||
:key="item"
|
||||
:class="{[$style.select]: selectIndex === index }"
|
||||
@mouseenter="selectIndex = index"
|
||||
@click="handleTemplistClick(index)"
|
||||
>
|
||||
<span>{{ item }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { clipboardReadText } from '@renderer/utils'
|
||||
import { common as eventCommonNames } from '@common/hotKey'
|
||||
import { clipboardReadText } from '@common/utils/electron'
|
||||
import { HOTKEY_COMMON } from '@common/hotKey'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
placeholder: {
|
||||
@@ -53,6 +60,9 @@ export default {
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
},
|
||||
},
|
||||
visibleList: {
|
||||
type: Boolean,
|
||||
@@ -99,7 +109,7 @@ export default {
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.$store.getters.setting.search.isFocusSearchBox) this.handleFocusInput()
|
||||
if (appSetting['search.isFocusSearchBox']) this.handleFocusInput()
|
||||
this.handleRegisterEvent('on')
|
||||
},
|
||||
beforeUnmount() {
|
||||
@@ -107,9 +117,9 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
handleRegisterEvent(action) {
|
||||
let eventHub = window.eventHub
|
||||
let eventHub = window.key_event
|
||||
let name = action == 'on' ? 'on' : 'off'
|
||||
eventHub[name](eventCommonNames.focusSearchInput.action, this.handleFocusInput)
|
||||
eventHub[name](HOTKEY_COMMON.focusSearchInput.action, this.handleFocusInput)
|
||||
},
|
||||
handleFocusInput() {
|
||||
this.$refs.dom_input.focus()
|
||||
@@ -162,7 +172,7 @@ export default {
|
||||
str = str.replace(/\t|\r\n|\n|\r/g, ' ')
|
||||
str = str.replace(/\s+/g, ' ')
|
||||
let dom_input = this.$refs.dom_input
|
||||
this.text = `${this.text.substring(0, dom_input.selectionStart)}${str}${this.text.substring(dom_input.selectionEnd, this.text.length)}`
|
||||
this.text = this.text.substring(0, dom_input.selectionStart) + str + this.text.substring(dom_input.selectionEnd, this.text.length)
|
||||
this.$emit('update:modelValue', this.text)
|
||||
},
|
||||
handleClearList() {
|
||||
@@ -189,10 +199,10 @@ export default {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
border-radius: @form-radius;
|
||||
transition: box-shadow .4s ease, background-color @transition-theme;
|
||||
transition: box-shadow .4s ease, background-color @transition-normal;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
background-color: @color-search-form-background;
|
||||
background-color: var(--color-primary-light-600-alpha-100);
|
||||
|
||||
&.active {
|
||||
box-shadow: 0 1px 5px 0 rgba(0,0,0,.2);
|
||||
@@ -216,8 +226,8 @@ export default {
|
||||
border-top-left-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
background-color: transparent;
|
||||
// border-bottom: 2px solid @color-theme;
|
||||
// border-color: @color-theme;
|
||||
// border-bottom: 2px solid var(--color-primary);
|
||||
// border-color: var(--color-primary);
|
||||
border: none;
|
||||
|
||||
outline: none;
|
||||
@@ -227,7 +237,7 @@ export default {
|
||||
font-size: 13.5px;
|
||||
line-height: @height-toolbar * 0.52 + 5px;
|
||||
&::placeholder {
|
||||
color: @color-btn;
|
||||
color: var(--color-button-font);
|
||||
}
|
||||
}
|
||||
button {
|
||||
@@ -239,7 +249,7 @@ export default {
|
||||
cursor: pointer;
|
||||
height: 100%;
|
||||
padding: 6px 7px;
|
||||
color: @color-btn;
|
||||
color: var(--color-button-font);
|
||||
transition: background-color .2s ease;
|
||||
|
||||
&:last-child {
|
||||
@@ -248,10 +258,10 @@ export default {
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: @color-theme-hover;
|
||||
background-color: var(--color-button-background-hover);
|
||||
}
|
||||
&:active {
|
||||
background-color: @color-theme-active;
|
||||
background-color: var(--color-button-background-active);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -272,7 +282,7 @@ export default {
|
||||
}
|
||||
|
||||
&.select {
|
||||
background-color: @color-search-list-hover;
|
||||
background-color: var(--color-primary-dark-100-alpha-700);
|
||||
}
|
||||
&:last-child {
|
||||
border-bottom-left-radius: 3px;
|
||||
@@ -295,41 +305,5 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
each(@themes, {
|
||||
:global(#root.@{value}) {
|
||||
|
||||
.search {
|
||||
background-color: ~'@{color-@{value}-search-form-background}';
|
||||
&.active {
|
||||
box-shadow: 0 1px 5px 0 rgba(0,0,0,.2);
|
||||
}
|
||||
|
||||
.form {
|
||||
input {
|
||||
&::placeholder {
|
||||
color: ~'@{color-@{value}-btn}';
|
||||
}
|
||||
}
|
||||
button {
|
||||
color: ~'@{color-@{value}-btn}';
|
||||
|
||||
&:hover {
|
||||
background-color: ~'@{color-@{value}-theme-hover}';
|
||||
}
|
||||
&:active {
|
||||
background-color: ~'@{color-@{value}-theme-active}';
|
||||
}
|
||||
}
|
||||
}
|
||||
.list {
|
||||
li {
|
||||
&.select {
|
||||
background-color: ~'@{color-@{value}-search-list-hover}';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<div :class="$style.container" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="less" module>
|
||||
@import '@renderer/assets/styles/layout.less';
|
||||
|
||||
.container {
|
||||
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user