fix: 修复歌单顺序错误的问题

This commit is contained in:
539943419 committed 2024-10-01 00:15:11 +08:00
1 parent 483a573f06
commit e876c117c6
3 files changed
+95 -95

No files matched your search

+23 -25
View File
@@ -2,20 +2,11 @@
<miao-drop-handler @on-virtual-files="handleDropVFiles"> <miao-drop-handler @on-virtual-files="handleDropVFiles">
<miao-alert-tip-provider ref="miaoMessageRef"> <miao-alert-tip-provider ref="miaoMessageRef">
<div class="miaoMusic-container"> <div class="miaoMusic-container">
<miao-music-main <miao-music-main v-if="ap" :ap="ap" v-model:data="data" :updateLocalData="updateLocalData"
v-if="ap"
:ap="ap"
v-model:data="data"
:updateLocalData="updateLocalData"
@new-collection="saveCurrPlayList"></miao-music-main> @new-collection="saveCurrPlayList"></miao-music-main>
<miao-mask <miao-mask :show="isAPlayerListShow" style="z-index: 5" @click="() => ap?.list.hide()"></miao-mask>
:show="isAPlayerListShow"
style="z-index: 5"
@click="() => ap?.list.hide()"></miao-mask>
<div ref="aplayer" style="z-index: 10" /> <div ref="aplayer" style="z-index: 10" />
<miao-mask <miao-mask :show="isSavingCollection" @click="isSavingCollection = false"></miao-mask>
:show="isSavingCollection"
@click="isSavingCollection = false"></miao-mask>
</div> </div>
</miao-alert-tip-provider> </miao-alert-tip-provider>
</miao-drop-handler> </miao-drop-handler>
@@ -69,12 +60,12 @@ const props = defineProps<{
view: VirtualPage view: VirtualPage
}>() }>()
const data = ref<collectionType[]>([]) const data = ref<collectionType[]>()
watch( watch(
data, data,
() => { (_v, oldV) => {
updateLocalData() updateLocalData(oldV !== undefined)
}, },
{ {
deep: true deep: true
@@ -113,13 +104,13 @@ const handleDropVFiles = (files: VirtualFile[]) => {
const saveCurrPlayList = () => { const saveCurrPlayList = () => {
if (ap.value) { if (ap.value) {
data.value.unshift({ data.value?.unshift({
id: Math.random(), id: Math.random(),
name: `新建歌单-${new Date()}`, name: `新建歌单-${new Date()}`,
intro: 'none', intro: 'none',
createTime: new Date(), createTime: new Date(),
coverUrl: '', coverUrl: '',
audios: cloneDeep(ap.value.list.audios) audios: cloneDeep(ap.value.list.audios).map((v, i) => ({ ...v, index: i }))
}) })
miaoMessageRef.value?.alertTip('已创建新的歌单', { miaoMessageRef.value?.alertTip('已创建新的歌单', {
timeout: 1000, timeout: 1000,
@@ -139,8 +130,8 @@ const initAPlayerMiao = () => {
} }
ap.value = reactive<apType>(new APlayer(aplayerOption)) ap.value = reactive<apType>(new APlayer(aplayerOption))
vueApp = useAplayerMiao(ap.value, { vueApp = useAplayerMiao(ap.value, {
onDragItemStart: () => {}, onDragItemStart: () => { },
onDragItemEnd: () => {}, onDragItemEnd: () => { },
onPlayVideo: (element) => { onPlayVideo: (element) => {
pluginCenter.usePlugin( pluginCenter.usePlugin(
'miaoVideoPlayer', 'miaoVideoPlayer',
@@ -171,16 +162,22 @@ const initAPlayerMiao = () => {
}) })
} }
const updateLocalData = debounce(() => { const updateLocalData = debounce((log?: boolean) => {
console.log('update') log && miaoMessageRef.value?.alertTip(`保存设置成功`, {
type: 'success',
timeout: 999,
})
localForage.setItem('miaoMusic-storage-musicCollections', toRaw(data.value)) localForage.setItem('miaoMusic-storage-musicCollections', toRaw(data.value))
}, 1000, { }, 1000, {
'leading': false, 'leading': false,
'trailing': true 'trailing': true
}) })
const getLocalData = async () => { const getLocalData = async () => {
data.value = const _data =
(await localForage.getItem('miaoMusic-storage-musicCollections')) ?? [] (await localForage.getItem('miaoMusic-storage-musicCollections') as collectionType[]) ?? []
_data.forEach(v => v.audios.sort((a, b) => a.index - b.index))
data.value = _data
console.log('data ==>', toRaw(data.value))
} }
onBeforeMount(async () => { onBeforeMount(async () => {
await getLocalData() await getLocalData()
@@ -213,6 +210,7 @@ onUnmounted(() => {
position: absolute; position: absolute;
bottom: 10px; bottom: 10px;
width: -webkit-fill-available; width: -webkit-fill-available;
.aplayer-icon-order, .aplayer-icon-order,
.aplayer-icon-loop { .aplayer-icon-loop {
display: none !important; display: none !important;
@@ -1,27 +1,20 @@
<template> <template>
<div class="collection-info-container"> <div class="collection-info-container">
<div class="collection-info-container-top"> <div class="collection-info-container-top">
<div <div class="collection-info-container-top-exit" @click="emit('exit')">
class="collection-info-container-top-exit"
@click="emit('exit')">
<ArrowBackOutline></ArrowBackOutline> <ArrowBackOutline></ArrowBackOutline>
</div> </div>
<div class="collection-info-container-top-title"> <div class="collection-info-container-top-title">
<span :tooltip="false" v-if="!isEditing"> <span :tooltip="false" v-if="!isEditing">
{{ collection.name }} {{ collection.name }}
</span> </span>
<n-input <n-input v-if="isEditing" v-model:value="collection.name"></n-input>
v-if="isEditing"
v-model:value="collection.name"></n-input>
</div> </div>
<div <div class="collection-info-container-top-delete" v-if="isEditing" @click="
class="collection-info-container-top-delete" clickDeleteCount !== 2
v-if="isEditing" ? clickDeleteCount++
@click=" : emit('deleteSelf')
clickDeleteCount !== 2
? clickDeleteCount++
: emit('deleteSelf')
"> ">
<TrashOutline></TrashOutline> <TrashOutline></TrashOutline>
<span> <span>
@@ -29,16 +22,14 @@
clickDeleteCount === 0 clickDeleteCount === 0
? `删除` ? `删除`
: clickDeleteCount === 1 : clickDeleteCount === 1
? '确认删除' ? '确认删除'
: '再次确认' : '再次确认'
}} }}
</span> </span>
</div> </div>
</div> </div>
<div class="collection-info-container-controller"> <div class="collection-info-container-controller">
<div <div class="collection-info-container-controller-play" @click="emit('playAll', collection)">
class="collection-info-container-controller-play"
@click="emit('playAll', collection)">
<div class="collection-info-container-controller-play-icon"> <div class="collection-info-container-controller-play-icon">
<CaretForwardOutline></CaretForwardOutline> <CaretForwardOutline></CaretForwardOutline>
</div> </div>
@@ -47,58 +38,39 @@
</div> </div>
</div> </div>
<div class="collection-info-container-controller-right"> <div class="collection-info-container-controller-right">
<div <div class="collection-info-container-controller-edit" @click="isEditing = !isEditing">
class="collection-info-container-controller-edit" <component :is="isEditing ? CheckmarkOutline : CreateOutline
@click="isEditing = !isEditing">
<component
:is="
isEditing ? CheckmarkOutline : CreateOutline
"></component> "></component>
</div> </div>
</div> </div>
</div> </div>
<NScrollbar> <NScrollbar>
<div class="collection-info-container-audioList"> <div class="collection-info-container-audioList">
<VueDraggable <VueDraggable v-model="collection.audios" :animation="150"
v-model="collection.audios" handle=".collection-info-container-audioList-item-controller-item-drag" ghostClass="iSDragging"
:animation="150" @end="updateAudiosIndex">
handle=".collection-info-container-audioList-item-controller-item-drag" <div v-for="(audio, index) in collection.audios" class="collection-info-container-audioList-item">
ghostClass="iSDragging"> <div class="collection-info-container-audioList-item-index">
<div
v-for="(audio, index) in collection.audios"
class="collection-info-container-audioList-item">
<div
class="collection-info-container-audioList-item-index">
<div>{{ index + 1 }}</div> <div>{{ index + 1 }}</div>
</div> </div>
<div <div class="collection-info-container-audioList-item-info">
class="collection-info-container-audioList-item-info"> <div v-if="!isEditing" class="collection-info-container-audioList-item-info-name">
<div
v-if="!isEditing"
class="collection-info-container-audioList-item-info-name">
<NEllipsis :tooltip="false"> <NEllipsis :tooltip="false">
{{ audio.name }} {{ audio.name }}
</NEllipsis> </NEllipsis>
</div> </div>
<n-input <n-input v-model:value="audio.name" v-if="isEditing"></n-input>
v-model:value="audio.name"
v-if="isEditing"></n-input>
</div> </div>
<div <div class="collection-info-container-audioList-item-controller">
class="collection-info-container-audioList-item-controller"> <PlayOutline class="collection-info-container-audioList-item-controller-item"
<PlayOutline v-if="!isEditing" @click="
class="collection-info-container-audioList-item-controller-item"
v-if="!isEditing"
@click="
emit('playAll', collection, index) emit('playAll', collection, index)
"></PlayOutline> "></PlayOutline>
<TrashOutline <TrashOutline class="collection-info-container-audioList-item-controller-item"
class="collection-info-container-audioList-item-controller-item" v-if="isEditing" @click="handleDelete(index)"></TrashOutline>
v-if="isEditing" <ReorderFourOutline v-if="isEditing"
@click="handleDelete(index)"></TrashOutline> class="collection-info-container-audioList-item-controller-item collection-info-container-audioList-item-controller-item-drag">
<ReorderFourOutline </ReorderFourOutline>
v-if="isEditing"
class="collection-info-container-audioList-item-controller-item collection-info-container-audioList-item-controller-item-drag"></ReorderFourOutline>
</div> </div>
</div> </div>
</VueDraggable> </VueDraggable>
@@ -135,6 +107,10 @@ const handleDelete = (index: number) => {
props.collection.audios.splice(index, 1) props.collection.audios.splice(index, 1)
} }
const updateAudiosIndex = () => {
props.collection.audios = props.collection.audios.map((v, i) => ({ ...v, index: i }))
}
const emit = defineEmits<{ const emit = defineEmits<{
exit: [] exit: []
deleteSelf: [] deleteSelf: []
@@ -144,6 +120,7 @@ const emit = defineEmits<{
<style lang="scss" scoped> <style lang="scss" scoped>
$ig: linear-gradient(90deg, #a1ee5e 0%, #00e3ae 100%); $ig: linear-gradient(90deg, #a1ee5e 0%, #00e3ae 100%);
.collection-info-container { .collection-info-container {
width: 100%; width: 100%;
height: 100%; height: 100%;
@@ -153,12 +130,14 @@ $ig: linear-gradient(90deg, #a1ee5e 0%, #00e3ae 100%);
left: 0; left: 0;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
&-top { &-top {
height: 70px; height: 70px;
padding: 0 15px; padding: 0 15px;
background: $ig; background: $ig;
display: flex; display: flex;
align-items: center; align-items: center;
&-exit { &-exit {
width: 30px; width: 30px;
aspect-ratio: 1; aspect-ratio: 1;
@@ -167,30 +146,36 @@ $ig: linear-gradient(90deg, #a1ee5e 0%, #00e3ae 100%);
justify-content: center; justify-content: center;
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
svg { svg {
width: 25px; width: 25px;
aspect-ratio: 1; aspect-ratio: 1;
transition: width 0.25s ease; transition: width 0.25s ease;
} }
&:hover { &:hover {
svg { svg {
width: 30px; width: 30px;
} }
} }
} }
&-title { &-title {
display: flex; display: flex;
margin-left: 10px; margin-left: 10px;
&-confirm { &-confirm {
margin-left: 10px; margin-left: 10px;
width: 32px; width: 32px;
// color: #ffffff; // color: #ffffff;
} }
span { span {
user-select: none; user-select: none;
font-size: larger; font-size: larger;
} }
} }
&-delete { &-delete {
display: flex; display: flex;
height: 25px; height: 25px;
@@ -199,24 +184,29 @@ $ig: linear-gradient(90deg, #a1ee5e 0%, #00e3ae 100%);
color: red; color: red;
user-select: none; user-select: none;
cursor: pointer; cursor: pointer;
& > span {
&>span {
position: relative; position: relative;
top: 3px; top: 3px;
margin-left: 3px; margin-left: 3px;
} }
} }
} }
&-controller { &-controller {
height: 50px; height: 50px;
padding: 0 15px; padding: 0 15px;
display: flex; display: flex;
align-items: center; align-items: center;
&-play { &-play {
display: flex; display: flex;
align-items: center; align-items: center;
& > div {
&>div {
cursor: pointer; cursor: pointer;
} }
&-icon { &-icon {
height: 30px; height: 30px;
width: 45px; width: 45px;
@@ -225,24 +215,28 @@ $ig: linear-gradient(90deg, #a1ee5e 0%, #00e3ae 100%);
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
svg { svg {
width: 30px; width: 30px;
height: 25px; height: 25px;
color: aliceblue; color: aliceblue;
} }
} }
&-text { &-text {
user-select: none; user-select: none;
margin-left: 10px; margin-left: 10px;
font-size: larger; font-size: larger;
} }
} }
&-right { &-right {
flex: 1; flex: 1;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
& > div {
&>div {
margin: 0 10px; margin: 0 10px;
cursor: pointer; cursor: pointer;
height: 25px; height: 25px;
@@ -251,38 +245,46 @@ $ig: linear-gradient(90deg, #a1ee5e 0%, #00e3ae 100%);
} }
} }
} }
&-audioList { &-audioList {
flex: 1; flex: 1;
color: #002911; color: #002911;
padding-bottom: 88px; padding-bottom: 88px;
&-item { &-item {
// padding: 0 20px; // padding: 0 20px;
padding-right: 7px; padding-right: 7px;
display: flex; display: flex;
height: 70px; height: 70px;
align-items: center; align-items: center;
&-index { &-index {
width: 50px; width: 50px;
user-select: none; user-select: none;
font-size: 24px; font-size: 24px;
text-align: right; text-align: right;
& > div {
&>div {
margin: auto; margin: auto;
width: fit-content; width: fit-content;
} }
} }
&-info { &-info {
flex: 1; flex: 1;
display: flex; display: flex;
user-select: none; user-select: none;
overflow: hidden; overflow: hidden;
&-name { &-name {
overflow: hidden; overflow: hidden;
} }
} }
&-controller { &-controller {
display: flex; display: flex;
align-items: center; align-items: center;
&-item { &-item {
width: 30px; width: 30px;
cursor: pointer; cursor: pointer;
+10 -10
View File
@@ -1,14 +1,14 @@
import type { audioType } from './ap' import type { audioType } from "./ap";
export type collectionItemType = {} & audioType export type collectionItemType = {} & audioType;
export type collectionType = { export type collectionType = {
id: number id: number;
name: string name: string;
intro: string intro: string;
createTime: Date createTime: Date;
coverUrl?: string coverUrl?: string;
audios: collectionItemType[] audios: collectionItemType[];
} };
export default collectionType export default collectionType;