fix: 修复歌单顺序错误的问题
This commit is contained in:
1 parent
483a573f06
commit
e876c117c6
3 files changed
+81
-81
No files matched your search
@@ -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,
|
||||||
@@ -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,24 +1,17 @@
|
|||||||
<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"
|
|
||||||
v-if="isEditing"
|
|
||||||
@click="
|
|
||||||
clickDeleteCount !== 2
|
clickDeleteCount !== 2
|
||||||
? clickDeleteCount++
|
? clickDeleteCount++
|
||||||
: emit('deleteSelf')
|
: emit('deleteSelf')
|
||||||
@@ -36,9 +29,7 @@
|
|||||||
</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,6 +184,7 @@ $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;
|
||||||
@@ -206,17 +192,21 @@ $ig: linear-gradient(90deg, #a1ee5e 0%, #00e3ae 100%);
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-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,23 +215,27 @@ $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;
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
Reference in new issue
Block a user