feat: 歌单支持拖动排序
This commit is contained in:
1 parent
38e1b098d2
commit
55381df4f6
8 files changed
+117
-29
No files matched your search
+4
-4
@@ -135,9 +135,9 @@ provide('rootDirectory', rootDirectory)
|
||||
: view.title
|
||||
}}
|
||||
</span>
|
||||
<div class="tab-point" :style="{ backgroundColor: view.color }"></div>
|
||||
<div class="tab-control">
|
||||
<n-icon class="tag-control-icon icon" @click="view.switchShow()" v-if="view.allowCopy">
|
||||
<div class="tab-point" :style="{ backgroundColor: view.color }"></div>
|
||||
<n-icon class="tag-control-icon icon" @click="view.switchShow()">
|
||||
<EyeOutline v-show="view.visible" class="icon-inner" />
|
||||
<EyeOffOutline v-show="!view.visible" class="icon-inner" />
|
||||
</n-icon>
|
||||
@@ -148,7 +148,7 @@ provide('rootDirectory', rootDirectory)
|
||||
view.currentFiles,
|
||||
index + 1
|
||||
)
|
||||
">
|
||||
" v-if="view.allowCopy">
|
||||
<CopyOutline />
|
||||
</n-icon>
|
||||
<n-icon class="tag-control-icon icon" @click="deleteView(index)">
|
||||
@@ -241,7 +241,7 @@ $tag-width: 170px;
|
||||
height: 5px;
|
||||
aspect-ratio: 1;
|
||||
border-radius: 66px;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.tab-control {
|
||||
|
||||
@@ -12,6 +12,13 @@ import VirtualDirectory, { VirtualFile } from '@/class/VirtualDirectory'
|
||||
import config from '@/config'
|
||||
import useDataBus from '@/hooks/useDataBus'
|
||||
|
||||
const props = defineProps({
|
||||
disable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
const dataBus = useDataBus()
|
||||
|
||||
const { uploadSizeLimit } = config
|
||||
@@ -57,8 +64,16 @@ const removeDirectory = async (files: File[]) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
const check = (event: DragEvent) => [
|
||||
...(event.dataTransfer?.files ?? []),
|
||||
...(dataBus.get('dragData_vFiles') ?? []),
|
||||
...(dataBus.get('dragData_vDirectory') ?? [])
|
||||
].length !== 0
|
||||
|
||||
const handleDragOver = async (event: DragEvent) => {
|
||||
if (props.disable || check(event) === false) {
|
||||
return
|
||||
}
|
||||
event.preventDefault()
|
||||
if (showMask.value === 1) {
|
||||
return
|
||||
@@ -71,6 +86,9 @@ const handleDragLeave = async () => {
|
||||
}
|
||||
|
||||
const handleDrop = async (event: DragEvent) => {
|
||||
if (props.disable || check(event) === false) {
|
||||
return
|
||||
}
|
||||
showMask.value = 0
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
|
||||
@@ -17,6 +17,10 @@ export default function useDataBus() {
|
||||
const value = dataStorage[key];
|
||||
dataStorage[key] = undefined;
|
||||
return value;
|
||||
},
|
||||
get(key: string | number) {
|
||||
const value = dataStorage[key];
|
||||
return value;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -2,10 +2,15 @@ import { createApp, Reactive } from "vue";
|
||||
import aplayerListNew from "../src/aplayerListNew.vue";
|
||||
import apType from "../types/ap";
|
||||
|
||||
type aplayerMiaoOption = {
|
||||
onDragItemStart?: () => void,
|
||||
onDragItemEnd?: () => void,
|
||||
}
|
||||
|
||||
/**
|
||||
* 对aplayer进行一些自定义的风格优化
|
||||
*/
|
||||
const useAplayerMiao = (ap: Reactive<apType>) => {
|
||||
const useAplayerMiao = (ap: Reactive<apType>, options?: aplayerMiaoOption) => {
|
||||
const container = ap.container as HTMLDivElement;
|
||||
|
||||
// 隐藏旧版歌单
|
||||
@@ -30,7 +35,7 @@ const useAplayerMiao = (ap: Reactive<apType>) => {
|
||||
});
|
||||
|
||||
container.appendChild(new_list_dom);
|
||||
const app = createApp(aplayerListNew, { ap });
|
||||
const app = createApp(aplayerListNew, { ap, ...(options ?? {}) });
|
||||
app.mount(new_list_dom);
|
||||
|
||||
ap.on("destroy", () => {
|
||||
|
||||
@@ -45,6 +45,8 @@ const handleDropVFiles = (files: VirtualFile[]) => {
|
||||
|
||||
const aplayer = ref<any>(null);
|
||||
|
||||
const disableDropReceiver = ref(false)
|
||||
|
||||
let ap: apType
|
||||
let vueApp: any
|
||||
|
||||
@@ -59,7 +61,14 @@ onMounted(() => {
|
||||
theme: "#60e8a2"
|
||||
}
|
||||
ap = reactive<apType>(new APlayer(aplayerOption))
|
||||
vueApp = useAplayerMiao(ap)
|
||||
vueApp = useAplayerMiao(ap, {
|
||||
onDragItemStart: () => {
|
||||
disableDropReceiver.value = true
|
||||
},
|
||||
onDragItemEnd: () => {
|
||||
disableDropReceiver.value = false
|
||||
},
|
||||
})
|
||||
ap.on('listremove', (...args: any) => {
|
||||
const {index} = args[0] as {index: number}
|
||||
const _name = ap.list.audios[index].name
|
||||
|
||||
@@ -1,33 +1,43 @@
|
||||
<template>
|
||||
<ol :style="{ maxHeight: ap.options.listMaxHeight }" :key="refreshKey">
|
||||
<li v-for="(audio, index) in ap.list.audios" :class="activeAudioIndex == index ? 'aplayer-list-light' : ''"
|
||||
class="aplayer-list-new" @click="switchAudio(index)" :key="audio.id">
|
||||
<span class="aplayer-list-cur" :style="{ backgroundColor: apTheme }"></span>
|
||||
<span class="aplayer-list-index">{{ index + 1 }}</span>
|
||||
<span class="aplayer-list-title">{{ audio.name }}</span>
|
||||
<span class="aplayer-list-author" v-show="audio.artist">{{ audio.artist }}</span>
|
||||
<div class="aplayer-list-control">
|
||||
<div class="aplayer-list-control-btn" @click.stop="listAudioUp(index)">
|
||||
<ChevronUpOutline class="aplayer-list-control-btn-svg" />
|
||||
</div>
|
||||
<div class="aplayer-list-control-btn" @click.stop="listAudioDown(index)">
|
||||
<ChevronDownOutline class="aplayer-list-control-btn-svg" />
|
||||
</div>
|
||||
<div class="aplayer-list-control-btn" @click.stop="listAudioRemove(index)">
|
||||
<CloseOutline class="aplayer-list-control-btn-svg" />
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<ol :style="{ maxHeight: ap.options.listMaxHeight }" :key="refreshKey" >
|
||||
<VueDraggable v-model="ap.list.audios" @start="onDragStart" @end="onDragEnd" item-key="id" handle=".aplayer-list-control-btn-reorder">
|
||||
<!-- <template #item="{ element, index }"> -->
|
||||
<li v-for="(element, index) in ap.list.audios" :class="activeAudioIndex == index ? 'aplayer-list-light' : ''"
|
||||
class="aplayer-list-new" @click="switchAudio(index)" :key="element.id">
|
||||
<span class="aplayer-list-cur" :style="{ backgroundColor: apTheme }"></span>
|
||||
<span class="aplayer-list-index">{{ index + 1 }}</span>
|
||||
<span class="aplayer-list-title">{{ element.name }}</span>
|
||||
<span class="aplayer-list-author" v-show="element.artist">{{ element.artist }}</span>
|
||||
<div class="aplayer-list-control">
|
||||
<div class="aplayer-list-control-btn" @click.stop="listAudioUp(index)" v-if="false">
|
||||
<ChevronUpOutline class="aplayer-list-control-btn-svg" />
|
||||
</div>
|
||||
<div class="aplayer-list-control-btn" @click.stop="listAudioDown(index)" v-if="false">
|
||||
<ChevronDownOutline class="aplayer-list-control-btn-svg" />
|
||||
</div>
|
||||
<div class="aplayer-list-control-btn" @click.stop="listAudioRemove(index)">
|
||||
<CloseOutline class="aplayer-list-control-btn-svg" />
|
||||
</div>
|
||||
<div class="aplayer-list-control-btn aplayer-list-control-btn-reorder">
|
||||
<ReorderFourOutline class="aplayer-list-control-btn-svg" />
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<!-- </template> -->
|
||||
</VueDraggable>
|
||||
</ol>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { ChevronUpOutline, ChevronDownOutline, CloseOutline } from '@vicons/ionicons5';
|
||||
import { ChevronUpOutline, ChevronDownOutline, CloseOutline, ReorderFourOutline } from '@vicons/ionicons5';
|
||||
import { VueDraggable } from 'vue-draggable-plus'
|
||||
import apType, { audioType } from '../types/ap';
|
||||
|
||||
const props = defineProps<{
|
||||
ap: apType
|
||||
onDragItemStart: () => void,
|
||||
onDragItemEnd: () => void
|
||||
}>()
|
||||
|
||||
const refreshKey = ref(Math.random())
|
||||
@@ -97,7 +107,21 @@ const listAudioDown = (index: number) => {
|
||||
const listAudioRemove = (index: number) => {
|
||||
props.ap.list.remove(index)
|
||||
}
|
||||
|
||||
const {onDragStart, onDragEnd} = (() => {
|
||||
let curr: audioType
|
||||
return {
|
||||
onDragStart: () => {
|
||||
curr = props.ap.list.audios[props.ap.list.index]
|
||||
},
|
||||
onDragEnd: () => {
|
||||
listRefreshIndex(curr)
|
||||
}
|
||||
}
|
||||
})()
|
||||
// const onDragEnd = (_e: any) => {
|
||||
// const curr = props.ap.list.audios[props.ap.list.index]
|
||||
// listRefreshIndex(curr)
|
||||
// }
|
||||
|
||||
onMounted(() => {
|
||||
console.log(props.ap)
|
||||
@@ -105,6 +129,12 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.aplayer-list-new {
|
||||
height: fit-content !important;
|
||||
.aplayer-list-cur {
|
||||
height: calc( 100% - 8px ) !important;
|
||||
}
|
||||
}
|
||||
.aplayer-list-control {
|
||||
float: right;
|
||||
height: 32px;
|
||||
@@ -136,4 +166,4 @@ onMounted(() => {
|
||||
.aplayer .aplayer-list-new svg path {
|
||||
fill: #ffffff00;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
Reference in new issue
Block a user