升级到 vue3
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<material-modal :show="show" :bg-close="bgClose" @close="handleClose">
|
||||
<main :class="$style.main">
|
||||
<h2>{{ info.name }}<br/>{{ info.singer }}</h2>
|
||||
<base-btn :class="$style.btn" :key="type.type" @click="handleClick(type.type)" v-for="type in types"
|
||||
>{{getTypeName(type.type)}} {{ type.type.toUpperCase() }}{{ type.size && ` - ${type.size.toUpperCase()}` }}</base-btn>
|
||||
</main>
|
||||
</material-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex'
|
||||
import { qualityList } from '@renderer/core/share'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
musicInfo: {
|
||||
type: Object,
|
||||
},
|
||||
bgClose: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
emits: ['update:show'],
|
||||
setup() {
|
||||
return {
|
||||
qualityList,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
info() {
|
||||
return this.musicInfo || {}
|
||||
},
|
||||
sourceQualityList() {
|
||||
return this.qualityList[this.musicInfo.source] || []
|
||||
},
|
||||
types() {
|
||||
return this.info?.types?.filter(type => this.checkSource(type.type)) || []
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions('download', ['createDownload']),
|
||||
handleClick(type) {
|
||||
this.createDownload({ musicInfo: this.musicInfo, type })
|
||||
this.handleClose()
|
||||
},
|
||||
handleClose() {
|
||||
this.$emit('update:show', false)
|
||||
},
|
||||
getTypeName(type) {
|
||||
switch (type) {
|
||||
case 'flac':
|
||||
case 'ape':
|
||||
case 'wav':
|
||||
return this.$t('download__lossless')
|
||||
case '320k':
|
||||
return this.$t('download__high_quality')
|
||||
case '192k':
|
||||
case '128k':
|
||||
return this.$t('download__normal')
|
||||
}
|
||||
},
|
||||
checkSource(type) {
|
||||
return this.sourceQualityList.includes(type)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="less" module>
|
||||
@import '@renderer/assets/styles/layout.less';
|
||||
|
||||
.main {
|
||||
padding: 15px;
|
||||
max-width: 300px;
|
||||
min-width: 200px;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
justify-content: center;
|
||||
h2 {
|
||||
font-size: 13px;
|
||||
color: @color-theme_2-font;
|
||||
line-height: 1.3;
|
||||
text-align: center;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: block;
|
||||
margin-bottom: 15px;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
each(@themes, {
|
||||
:global(#root.@{value}) {
|
||||
.main {
|
||||
h2 {
|
||||
color: ~'@{color-@{value}-theme_2-font}';
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<material-modal :show="show" :bg-close="bgClose" @close="handleClose">
|
||||
<main :class="$style.main">
|
||||
<h2>{{$t('download__multiple_tip', { len: list.length })}}<br/>{{$t('download__multiple_tip2')}}</h2>
|
||||
<base-btn :class="$style.btn" @click="handleClick('128k')">{{$t('download__normal')}} - 128K</base-btn>
|
||||
<base-btn :class="$style.btn" @click="handleClick('320k')">{{$t('download__high_quality')}} - 320K</base-btn>
|
||||
<base-btn :class="$style.btn" @click="handleClick('flac')">{{$t('download__lossless')}} - FLAC</base-btn>
|
||||
</main>
|
||||
</material-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
bgClose: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
},
|
||||
},
|
||||
},
|
||||
emits: ['update:show', 'confirm'],
|
||||
methods: {
|
||||
...mapActions('download', ['createDownloadMultiple']),
|
||||
handleClick(type) {
|
||||
this.createDownloadMultiple({ list: [...this.list], type })
|
||||
this.handleClose()
|
||||
this.$emit('confirm')
|
||||
},
|
||||
handleClose() {
|
||||
this.$emit('update:show', false)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="less" module>
|
||||
@import '@renderer/assets/styles/layout.less';
|
||||
|
||||
.main {
|
||||
padding: 15px;
|
||||
max-width: 300px;
|
||||
min-width: 200px;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
justify-content: center;
|
||||
h2 {
|
||||
font-size: 13px;
|
||||
color: @color-theme_2-font;
|
||||
line-height: 1.3;
|
||||
text-align: center;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: block;
|
||||
margin-bottom: 15px;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
each(@themes, {
|
||||
:global(#root.@{value}) {
|
||||
.main {
|
||||
h2 {
|
||||
color: ~'@{color-@{value}-theme_2-font}';
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,214 @@
|
||||
<template>
|
||||
<material-modal :show="show" :bg-close="bgClose" @close="handleClose">
|
||||
<main :class="$style.main">
|
||||
<h2>{{$t('list_add__' + (isMove ? 'title_first_move' : 'title_first_add'))}} <span :class="$style.name">{{this.musicInfo && `${musicInfo.name}`}}</span> {{$t('list_add__title_last')}}</h2>
|
||||
<div class="scroll" :class="$style.btnContent">
|
||||
<base-btn :class="$style.btn" :tips="$t('list_add__btn_title', { name: item.name })" :key="item.id" :disabled="item.isExist" @click="handleClick(index)" v-for="(item, index) in lists">{{item.name}}</base-btn>
|
||||
<base-btn :class="[$style.btn, $style.newList, isEditing ? $style.editing : null]" @click="handleEditing($event)" :tips="$t('lists__new_list_btn')">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" viewBox="0 0 42 42" space="preserve">
|
||||
<use xlink:href="#icon-addTo"></use>
|
||||
</svg>
|
||||
<input class="key-bind" :class="$style.newListInput" :value="newListName" type="text" :placeholder="$t('lists__new_list_input')" @keyup.enter="handleSaveList($event)" @blur="handleSaveList($event)"/>
|
||||
</base-btn>
|
||||
<span :class="$style.btn" :key="i" v-for="i in spaceNum"></span>
|
||||
</div>
|
||||
</main>
|
||||
</material-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
import { computed } from '@renderer/utils/vueTools'
|
||||
import { defaultList, loveList, userLists } from '@renderer/core/share/list'
|
||||
import { getList } from '@renderer/core/share/utils'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
musicInfo: {
|
||||
type: Object,
|
||||
},
|
||||
bgClose: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
excludeListId: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
},
|
||||
},
|
||||
listName: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
fromListId: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
isMove: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
emits: ['update:show'],
|
||||
setup(props) {
|
||||
const lists = computed(() => {
|
||||
if (!props.musicInfo) return []
|
||||
const targetMid = props.musicInfo.songmid
|
||||
return [
|
||||
defaultList,
|
||||
loveList,
|
||||
...userLists,
|
||||
].filter(l => !props.excludeListId.includes(l.id)).map(l => ({ ...l, isExist: getList(l.id).some(s => s.songmid == targetMid) }))
|
||||
})
|
||||
return {
|
||||
lists,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isEditing: false,
|
||||
newListName: '',
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
spaceNum() {
|
||||
return this.lists.length < 2 ? 0 : (3 - this.lists.length % 3 - 1)
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapMutations('list', ['listAdd', 'listMove', 'createUserList']),
|
||||
handleClick(index) {
|
||||
this.isMove
|
||||
? this.listMove({ fromId: this.fromListId, toId: this.lists[index].id, musicInfo: this.musicInfo })
|
||||
: this.listAdd({ id: this.lists[index].id, musicInfo: this.musicInfo })
|
||||
this.$nextTick(() => {
|
||||
this.handleClose()
|
||||
})
|
||||
},
|
||||
handleClose() {
|
||||
this.$emit('update:show', false)
|
||||
},
|
||||
handleEditing(event) {
|
||||
if (this.isEditing) return
|
||||
if (!this.newListName) this.newListName = this.listName
|
||||
this.isEditing = true
|
||||
this.$nextTick(() => event.currentTarget.querySelector('.' + this.$style.newListInput).focus())
|
||||
},
|
||||
handleSaveList(event) {
|
||||
let name = event.target.value
|
||||
this.newListName = event.target.value = ''
|
||||
this.isEditing = false
|
||||
if (!name) return
|
||||
this.createUserList({ name })
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="less" module>
|
||||
@import '@renderer/assets/styles/layout.less';
|
||||
|
||||
.main {
|
||||
// padding: 15px 0;
|
||||
max-width: 530px;
|
||||
min-width: 200px;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
justify-content: center;
|
||||
min-height: 0;
|
||||
// max-height: 100%;
|
||||
// overflow: hidden;
|
||||
h2 {
|
||||
font-size: 13px;
|
||||
color: @color-theme_2-font;
|
||||
line-height: 1.3;
|
||||
text-align: center;
|
||||
padding: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
color: @color-theme;
|
||||
}
|
||||
|
||||
.btn-content {
|
||||
flex: auto;
|
||||
max-height: 100%;
|
||||
padding-right: 15px;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.btn {
|
||||
box-sizing: border-box;
|
||||
margin-left: 15px;
|
||||
margin-bottom: 15px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
padding: 0 10px !important;
|
||||
width: 150px;
|
||||
.mixin-ellipsis-1;
|
||||
}
|
||||
|
||||
.newList {
|
||||
border: 1px dashed @color-theme-hover;
|
||||
background-color: @color-theme_2-background_2;
|
||||
color: @color-theme-hover;
|
||||
opacity: .7;
|
||||
|
||||
svg {
|
||||
height: 18px;
|
||||
margin-top: 9px;
|
||||
}
|
||||
|
||||
&.editing {
|
||||
opacity: 1;
|
||||
|
||||
svg {
|
||||
display: none;
|
||||
}
|
||||
.newListInput {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
.newListInput {
|
||||
width: 100%;
|
||||
height: 34px;
|
||||
border: none;
|
||||
padding: 0;
|
||||
line-height: 34px;
|
||||
background: none;
|
||||
outline: none;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
font-family: inherit;
|
||||
display: none;
|
||||
}
|
||||
|
||||
each(@themes, {
|
||||
:global(#root.@{value}) {
|
||||
.main {
|
||||
h2 {
|
||||
color: ~'@{color-@{value}-theme_2-font}';
|
||||
}
|
||||
}
|
||||
.name {
|
||||
color: ~'@{color-@{value}-theme}';
|
||||
}
|
||||
.newList {
|
||||
border-color: ~'@{color-@{value}-theme-hover}';
|
||||
color: ~'@{color-@{value}-theme-hover}';
|
||||
background-color: ~'@{color-@{value}-theme_2-background_2}';
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,209 @@
|
||||
<template>
|
||||
<material-modal :show="show" :bg-close="bgClose" @close="handleClose">
|
||||
<main :class="$style.main">
|
||||
<h2>{{$t('list_add__multiple_' + (isMove ? 'title_move' : 'title_add'), { num: musicList.length })}}</h2>
|
||||
<div class="scroll" :class="$style.btnContent">
|
||||
<base-btn :class="$style.btn" :tips="$t('list_add__multiple_btn_title', { name: item.name })" :key="item.id" @click="handleClick(index)" v-for="(item, index) in lists">{{item.name}}</base-btn>
|
||||
<base-btn :class="[$style.btn, $style.newList, isEditing ? $style.editing : null]" @click="handleEditing($event)" :tips="$t('lists__new_list_btn')">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" viewBox="0 0 42 42" space="preserve">
|
||||
<use xlink:href="#icon-addTo"></use>
|
||||
</svg>
|
||||
<input class="key-bind" :class="$style.newListInput" :value="newListName" type="text" :placeholder="$t('lists__new_list_input')" @keyup.enter="handleSaveList($event)" @blur="handleSaveList($event)"/>
|
||||
</base-btn>
|
||||
<span :class="$style.btn" :key="i" v-for="i in spaceNum"></span>
|
||||
</div>
|
||||
</main>
|
||||
</material-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
import { computed } from '@renderer/utils/vueTools'
|
||||
import { defaultList, loveList, userLists } from '@renderer/core/share/list'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
musicList: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
},
|
||||
},
|
||||
bgClose: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
excludeListId: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
},
|
||||
},
|
||||
listName: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
fromListId: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
isMove: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
emits: ['update:show', 'confirm'],
|
||||
setup(props) {
|
||||
const lists = computed(() => {
|
||||
return [
|
||||
defaultList,
|
||||
loveList,
|
||||
...userLists,
|
||||
].filter(l => !props.excludeListId.includes(l.id))
|
||||
})
|
||||
return {
|
||||
lists,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isEditing: false,
|
||||
newListName: '',
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
spaceNum() {
|
||||
return this.lists.length < 2 ? 0 : (3 - this.lists.length % 3 - 1)
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapMutations('list', ['listAddMultiple', 'listMoveMultiple', 'createUserList']),
|
||||
handleClick(index) {
|
||||
this.isMove
|
||||
? this.listMoveMultiple({ fromId: this.fromListId, toId: this.lists[index].id, list: this.musicList })
|
||||
: this.listAddMultiple({ id: this.lists[index].id, list: this.musicList })
|
||||
this.$nextTick(() => {
|
||||
this.handleClose()
|
||||
this.$emit('confirm')
|
||||
})
|
||||
},
|
||||
handleClose() {
|
||||
this.$emit('update:show', false)
|
||||
},
|
||||
handleEditing(event) {
|
||||
if (this.isEditing) return
|
||||
if (!this.newListName) this.newListName = this.listName
|
||||
this.isEditing = true
|
||||
this.$nextTick(() => event.currentTarget.querySelector('.' + this.$style.newListInput).focus())
|
||||
},
|
||||
handleSaveList(event) {
|
||||
let name = event.target.value
|
||||
this.newListName = event.target.value = ''
|
||||
this.isEditing = false
|
||||
if (!name) return
|
||||
this.createUserList({ name })
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="less" module>
|
||||
@import '@renderer/assets/styles/layout.less';
|
||||
|
||||
.main {
|
||||
// padding: 15px 0;
|
||||
max-width: 530px;
|
||||
min-width: 200px;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
justify-content: center;
|
||||
min-height: 0;
|
||||
// max-height: 100%;
|
||||
// overflow: hidden;
|
||||
h2 {
|
||||
font-size: 13px;
|
||||
color: @color-theme_2-font;
|
||||
line-height: 1.3;
|
||||
text-align: center;
|
||||
padding: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-content {
|
||||
flex: auto;
|
||||
max-height: 100%;
|
||||
padding-right: 15px;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.btn {
|
||||
box-sizing: border-box;
|
||||
margin-left: 15px;
|
||||
margin-bottom: 15px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
padding: 0 10px !important;
|
||||
width: 150px;
|
||||
.mixin-ellipsis-1;
|
||||
}
|
||||
|
||||
.newList {
|
||||
border: 1px dashed @color-theme-hover;
|
||||
background-color: @color-theme_2-background_2;
|
||||
color: @color-theme-hover;
|
||||
opacity: .7;
|
||||
|
||||
svg {
|
||||
height: 18px;
|
||||
margin-top: 9px;
|
||||
}
|
||||
|
||||
&.editing {
|
||||
opacity: 1;
|
||||
|
||||
svg {
|
||||
display: none;
|
||||
}
|
||||
.newListInput {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
.newListInput {
|
||||
width: 100%;
|
||||
height: 34px;
|
||||
border: none;
|
||||
padding: 0;
|
||||
line-height: 34px;
|
||||
background: none;
|
||||
outline: none;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
font-family: inherit;
|
||||
display: none;
|
||||
}
|
||||
|
||||
each(@themes, {
|
||||
:global(#root.@{value}) {
|
||||
.main {
|
||||
h2 {
|
||||
color: ~'@{color-@{value}-theme_2-font}';
|
||||
}
|
||||
}
|
||||
.newList {
|
||||
border-color: ~'@{color-@{value}-theme-hover}';
|
||||
color: ~'@{color-@{value}-theme-hover}';
|
||||
background-color: ~'@{color-@{value}-theme_2-background_2}';
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<div :class="[$style.progress, className]">
|
||||
<div :class="[$style.progressBar, $style.progressBar2, {[$style.barTransition]: isActiveTransition}]" @transitionend="handleTransitionEnd" :style="{ transform: `scaleX(${progress || 0})` }"></div>
|
||||
<div v-show="dragging" :class="[$style.progressBar, $style.progressBar3]" :style="{ transform: `scaleX(${dragProgress || 0})` }"></div>
|
||||
</div>
|
||||
<div :class="$style.progressMask" @mousedown="handleMsDown" ref="dom_progress"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, onBeforeUnmount } from '@renderer/utils/vueTools'
|
||||
import { player as eventPlayerNames } from '@renderer/event/names'
|
||||
import { playProgress } from '@renderer/core/share/playProgress'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
className: String,
|
||||
progress: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
isActiveTransition: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
handleTransitionEnd: {
|
||||
type: Function,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const msEvent = {
|
||||
isMsDown: false,
|
||||
msDownX: 0,
|
||||
msDownProgress: 0,
|
||||
}
|
||||
const dom_progress = ref(null)
|
||||
const dragging = ref(false)
|
||||
const dragProgress = ref(0)
|
||||
|
||||
const handleMsDown = event => {
|
||||
msEvent.isMsDown = true
|
||||
msEvent.msDownX = event.clientX
|
||||
|
||||
let val = event.offsetX / dom_progress.value.clientWidth
|
||||
if (val < 0) val = 0
|
||||
if (val > 1) val = 1
|
||||
|
||||
dragProgress.value = msEvent.msDownProgress = val
|
||||
}
|
||||
const handleMsUp = () => {
|
||||
if (msEvent.isMsDown) setProgress(dragProgress.value * playProgress.maxPlayTime)
|
||||
msEvent.isMsDown = false
|
||||
dragging.value = false
|
||||
}
|
||||
const handleMsMove = event => {
|
||||
if (!msEvent.isMsDown) return
|
||||
if (!dragging.value) dragging.value = true
|
||||
|
||||
let progress = msEvent.msDownProgress + (event.clientX - msEvent.msDownX) / dom_progress.value.clientWidth
|
||||
if (progress > 1) progress = 1
|
||||
else if (progress < 0) progress = 0
|
||||
dragProgress.value = progress
|
||||
}
|
||||
|
||||
document.addEventListener('mousemove', handleMsMove)
|
||||
document.addEventListener('mouseup', handleMsUp)
|
||||
onBeforeUnmount(() => {
|
||||
document.removeEventListener('mousemove', handleMsMove)
|
||||
document.removeEventListener('mouseup', handleMsUp)
|
||||
})
|
||||
|
||||
const setProgress = num => {
|
||||
window.eventHub.emit(eventPlayerNames.setProgress, num)
|
||||
}
|
||||
|
||||
// const handleSetProgress = event => {
|
||||
// // setProgress(event.offsetX / dom_progress.value.clientWidth * playProgress.maxPlayTime)
|
||||
// }
|
||||
|
||||
return {
|
||||
dom_progress,
|
||||
// handleSetProgress,
|
||||
dragging,
|
||||
dragProgress,
|
||||
handleMsDown,
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" module>
|
||||
@import '@renderer/assets/styles/layout.less';
|
||||
|
||||
.progress {
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
// overflow: hidden;
|
||||
transition: @transition-theme;
|
||||
transition-property: background-color;
|
||||
background-color: @color-player-progress;
|
||||
// background-color: #f5f5f5;
|
||||
position: relative;
|
||||
border-radius: 20px;
|
||||
}
|
||||
.progress-mask {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
.progress-bar {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform-origin: 0;
|
||||
border-radius: 20px;
|
||||
}
|
||||
.progress-bar1 {
|
||||
background-color: @color-player-progress-bar1;
|
||||
}
|
||||
|
||||
.progress-bar2 {
|
||||
background-color: @color-player-progress-bar2;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.3);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.progress-bar3 {
|
||||
background-color: @color-player-progress-bar2;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.3);
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.bar-transition {
|
||||
transition-property: transform;
|
||||
transition-timing-function: ease-out;
|
||||
transition-duration: 0.2s;
|
||||
}
|
||||
|
||||
each(@themes, {
|
||||
:global(#root.@{value}) {
|
||||
.progress {
|
||||
background-color: ~'@{color-@{value}-player-progress}';
|
||||
}
|
||||
.progress-bar1 {
|
||||
background-color: ~'@{color-@{value}-player-progress-bar1}';
|
||||
}
|
||||
.progress-bar2 {
|
||||
background-color: ~'@{color-@{value}-player-progress-bar2}';
|
||||
}
|
||||
.progress-bar3 {
|
||||
background-color: ~'@{color-@{value}-player-progress-bar2}';
|
||||
}
|
||||
}
|
||||
})
|
||||
</style>
|
||||
@@ -0,0 +1,144 @@
|
||||
<template>
|
||||
<div :class="[$style.volumeContent, className]">
|
||||
<div :class="[$style.volume, {[$style.muted]: setting.player.isMute} ]">
|
||||
<div :class="$style.volumeBar" ref="dom_volumeBar" :style="{ transform: `scaleX(${volume || 0})` }"></div>
|
||||
</div>
|
||||
<div :class="$style.volumeMask" @mousedown="handleVolumeMsDown" :tips="`${$t('player__volume')}${parseInt(volume * 100)}%`"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, onBeforeUnmount } from '@renderer/utils/vueTools'
|
||||
// import { player as eventPlayerNames } from '@renderer/event/names'
|
||||
import { volume, isMute, setVolume, setMute } from '@renderer/core/share/volume'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
className: {
|
||||
type: String,
|
||||
},
|
||||
setting: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const volumeEvent = {
|
||||
isMsDown: false,
|
||||
msDownX: 0,
|
||||
msDownVolume: 0,
|
||||
}
|
||||
const dom_volumeBar = ref(null)
|
||||
|
||||
const handleVolumeMsDown = event => {
|
||||
volumeEvent.isMsDown = true
|
||||
volumeEvent.msDownX = event.clientX
|
||||
|
||||
let val = event.offsetX / 80
|
||||
if (val < 0) val = 0
|
||||
if (val > 1) val = 1
|
||||
|
||||
setVolume(volumeEvent.msDownVolume = val)
|
||||
|
||||
if (isMute.value) setMute(false)
|
||||
}
|
||||
const handleVolumeMsUp = () => {
|
||||
volumeEvent.isMsDown = false
|
||||
}
|
||||
const handleVolumeMsMove = event => {
|
||||
if (!volumeEvent.isMsDown) return
|
||||
let volume = volumeEvent.msDownVolume + (event.clientX - volumeEvent.msDownX) / dom_volumeBar.value.clientWidth
|
||||
if (volume > 1) volume = 1
|
||||
else if (volume < 0) volume = 0
|
||||
setVolume(volume)
|
||||
}
|
||||
|
||||
document.addEventListener('mousemove', handleVolumeMsMove)
|
||||
document.addEventListener('mouseup', handleVolumeMsUp)
|
||||
onBeforeUnmount(() => {
|
||||
document.removeEventListener('mousemove', handleVolumeMsMove)
|
||||
document.removeEventListener('mouseup', handleVolumeMsUp)
|
||||
})
|
||||
|
||||
return {
|
||||
handleVolumeMsDown,
|
||||
dom_volumeBar,
|
||||
volume,
|
||||
isMute,
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" module>
|
||||
@import '@renderer/assets/styles/layout.less';
|
||||
|
||||
.volume-content {
|
||||
flex: none;
|
||||
position: relative;
|
||||
width: 80px;
|
||||
margin-right: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
opacity: .5;
|
||||
transition: opacity @transition-theme;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.volume {
|
||||
// cursor: pointer;
|
||||
width: 100%;
|
||||
height: 0.25em;
|
||||
border-radius: 10px;
|
||||
// overflow: hidden;
|
||||
transition: @transition-theme;
|
||||
transition-property: background-color, opacity;
|
||||
background-color: @color-player-progress-bar1;
|
||||
// background-color: #f5f5f5;
|
||||
position: relative;
|
||||
border-radius: @radius-progress-border;
|
||||
}
|
||||
|
||||
.muted {
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.volume-bar {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
transform: scaleX(0);
|
||||
transform-origin: 0;
|
||||
transition-property: transform;
|
||||
transition-timing-function: ease;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: @radius-progress-border;
|
||||
transition-duration: 0.2s;
|
||||
background-color: @color-btn;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.volume-mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
each(@themes, {
|
||||
:global(#root.@{value}) {
|
||||
.volume {
|
||||
background-color: ~'@{color-@{value}-player-progress-bar1}';
|
||||
}
|
||||
|
||||
.volume-bar {
|
||||
background-color: ~'@{color-@{value}-btn}';
|
||||
}
|
||||
}
|
||||
})
|
||||
</style>
|
||||
Reference in New Issue
Block a user