mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-24 16:27:23 +08:00
✨ feat: 完善播放列表问题 修复 滚动
This commit is contained in:
@@ -68,7 +68,7 @@ const menus = store.state.menus;
|
|||||||
height: 100vh;
|
height: 100vh;
|
||||||
&-content {
|
&-content {
|
||||||
@apply rounded-2xl pb-28 box-border;
|
@apply rounded-2xl pb-28 box-border;
|
||||||
height: calc(100vh - 60px);
|
height: 100vh;
|
||||||
}
|
}
|
||||||
&-page {
|
&-page {
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
|
|||||||
@@ -82,11 +82,10 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { SongResult } from '@/type/music'
|
import type { SongResult } from '@/type/music'
|
||||||
import { secondToMinute, getImgUrl, getIsMc } from '@/utils'
|
import { secondToMinute, getImgUrl } from '@/utils'
|
||||||
import { computed, onMounted, ref, watch } from 'vue'
|
import { computed, onMounted, ref, watch } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { setAnimationClass } from '@/utils'
|
import { setAnimationClass } from '@/utils'
|
||||||
import { getParsingMusicUrl } from '@/api/music'
|
|
||||||
import {
|
import {
|
||||||
loadLrc,
|
loadLrc,
|
||||||
nowTime,
|
nowTime,
|
||||||
|
|||||||
@@ -46,10 +46,18 @@ const mutations = {
|
|||||||
state.playList = playList
|
state.playList = playList
|
||||||
},
|
},
|
||||||
async nextPlay(state: State) {
|
async nextPlay(state: State) {
|
||||||
|
if (state.playList.length === 0) {
|
||||||
|
state.play = true
|
||||||
|
return
|
||||||
|
}
|
||||||
state.playListIndex = (state.playListIndex + 1) % state.playList.length
|
state.playListIndex = (state.playListIndex + 1) % state.playList.length
|
||||||
await updatePlayMusic(state)
|
await updatePlayMusic(state)
|
||||||
},
|
},
|
||||||
async prevPlay(state: State) {
|
async prevPlay(state: State) {
|
||||||
|
if (state.playList.length === 0) {
|
||||||
|
state.play = true
|
||||||
|
return
|
||||||
|
}
|
||||||
state.playListIndex =
|
state.playListIndex =
|
||||||
(state.playListIndex - 1 + state.playList.length) % state.playList.length
|
(state.playListIndex - 1 + state.playList.length) % state.playList.length
|
||||||
await updatePlayMusic(state)
|
await updatePlayMusic(state)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
:class="setAnimationClass('animate__bounceInRight')"
|
:class="setAnimationClass('animate__bounceInRight')"
|
||||||
:style="setAnimationDelay(index, 50)"
|
:style="setAnimationDelay(index, 50)"
|
||||||
>
|
>
|
||||||
<SongItem :item="item" />
|
<SongItem :item="item" @play="handlePlay"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
@@ -52,10 +52,9 @@ import type { IHotSearch } from "@/type/search";
|
|||||||
import { getHotSearch } from "@/api/home";
|
import { getHotSearch } from "@/api/home";
|
||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
import { setAnimationClass, setAnimationDelay } from "@/utils";
|
import { setAnimationClass, setAnimationDelay } from "@/utils";
|
||||||
import type { ISearchDetail } from "@/type/search";
|
|
||||||
import { onMounted, ref, watch } from "vue";
|
import { onMounted, ref, watch } from "vue";
|
||||||
import SongItem from "@/components/common/SongItem.vue";
|
import SongItem from "@/components/common/SongItem.vue";
|
||||||
|
import { useStore } from "vuex";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -85,10 +84,8 @@ const clickHotKeyword = (keyword: string) => {
|
|||||||
// isHotSearchList.value = false;
|
// isHotSearchList.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const loadSearch = async (keyword: any) => {
|
const loadSearch = async (keyword: any) => {
|
||||||
|
hotKeyword.value = keyword;
|
||||||
searchDetail.value = undefined;
|
searchDetail.value = undefined;
|
||||||
if (!keyword) return;
|
if (!keyword) return;
|
||||||
const { data } = await getSearch(keyword);
|
const { data } = await getSearch(keyword);
|
||||||
@@ -112,6 +109,14 @@ watch(
|
|||||||
loadSearch(newParams.keyword);
|
loadSearch(newParams.keyword);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const store = useStore()
|
||||||
|
|
||||||
|
const handlePlay = (item: any) => {
|
||||||
|
const tracks = searchDetail.value?.result.songs || []
|
||||||
|
const musicIndex = (tracks.findIndex((music: any) => music.id == item.id) || 0)
|
||||||
|
store.commit('setPlayList', tracks.slice(musicIndex))
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
+39
-32
@@ -9,6 +9,7 @@ import { getListDetail } from '@/api/list'
|
|||||||
import SongItem from "@/components/common/SongItem.vue";
|
import SongItem from "@/components/common/SongItem.vue";
|
||||||
import MusicList from "@/components/MusicList.vue";
|
import MusicList from "@/components/MusicList.vue";
|
||||||
import type { Playlist } from '@/type/listDetail';
|
import type { Playlist } from '@/type/listDetail';
|
||||||
|
import PlayBottom from "@/components/common/PlayBottom.vue";
|
||||||
|
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
@@ -99,40 +100,46 @@ const handlePlay = (item: any) => {
|
|||||||
|
|
||||||
<div class="play-list" :class="setAnimationClass('animate__fadeInLeft')">
|
<div class="play-list" :class="setAnimationClass('animate__fadeInLeft')">
|
||||||
<div class="play-list-title">创建的歌单</div>
|
<div class="play-list-title">创建的歌单</div>
|
||||||
<div
|
<n-scrollbar>
|
||||||
class="play-list-item"
|
<div
|
||||||
v-for="(item,index) in playList"
|
class="play-list-item"
|
||||||
:key="index"
|
v-for="(item,index) in playList"
|
||||||
@click="showPlaylist(item.id)"
|
:key="index"
|
||||||
>
|
@click="showPlaylist(item.id)"
|
||||||
<n-image
|
>
|
||||||
:src="getImgUrl( item.coverImgUrl, '')"
|
<n-image
|
||||||
class="play-list-item-img"
|
:src="getImgUrl( item.coverImgUrl, '')"
|
||||||
lazy
|
class="play-list-item-img"
|
||||||
preview-disabled
|
lazy
|
||||||
/>
|
preview-disabled
|
||||||
<div class="play-list-item-info">
|
/>
|
||||||
<div class="play-list-item-name">{{ item.name }}</div>
|
<div class="play-list-item-info">
|
||||||
<div class="play-list-item-count">{{ item.trackCount }}首,播放{{ item.playCount }}次</div>
|
<div class="play-list-item-name">{{ item.name }}</div>
|
||||||
|
<div class="play-list-item-count">{{ item.trackCount }}首,播放{{ item.playCount }}次</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<PlayBottom/>
|
||||||
|
</n-scrollbar>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right" :class="setAnimationClass('animate__fadeInRight')">
|
<div class="right" :class="setAnimationClass('animate__fadeInRight')">
|
||||||
<n-layout class="record-list" :native-scrollbar="false">
|
<div class="title">听歌排行</div>
|
||||||
<div class="title">听歌排行</div>
|
<div class="record-list">
|
||||||
<div
|
<n-scrollbar>
|
||||||
class="record-item"
|
<div
|
||||||
v-for="(item, index) in recordList"
|
class="record-item"
|
||||||
:key="item.song.id"
|
v-for="(item, index) in recordList"
|
||||||
:class="setAnimationClass('animate__bounceInUp')"
|
:key="item.song.id"
|
||||||
:style="setAnimationDelay(index, 50)"
|
:class="setAnimationClass('animate__bounceInUp')"
|
||||||
>
|
:style="setAnimationDelay(index, 50)"
|
||||||
<SongItem class="song-item" :item="formatDetail(item.song)" @play="handlePlay"/>
|
>
|
||||||
<div class="play-count">{{ item.playCount }}次</div>
|
<SongItem class="song-item" :item="formatDetail(item.song)" @play="handlePlay"/>
|
||||||
</div>
|
<div class="play-count">{{ item.playCount }}次</div>
|
||||||
</n-layout>
|
</div>
|
||||||
|
<PlayBottom/>
|
||||||
|
</n-scrollbar>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MusicList v-if="list" v-model:show="isShowList" :music-list="list" />
|
<MusicList v-if="list" v-model:show="isShowList" :music-list="list" />
|
||||||
</div>
|
</div>
|
||||||
@@ -152,9 +159,9 @@ const handlePlay = (item: any) => {
|
|||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
background-color: #0d0d0d;
|
background-color: #0d0d0d;
|
||||||
background-size: 100%;
|
background-size: 100%;
|
||||||
@apply flex-1 rounded-2xl overflow-hidden relative bg-no-repeat;
|
@apply flex-1 rounded-2xl overflow-hidden relative bg-no-repeat h-full;
|
||||||
.page {
|
.page {
|
||||||
@apply p-4 w-full z-10;
|
@apply p-4 w-full z-10 flex flex-col h-full;
|
||||||
background-color: #0d0d0d66;
|
background-color: #0d0d0d66;
|
||||||
}
|
}
|
||||||
.user-name {
|
.user-name {
|
||||||
@@ -199,7 +206,7 @@ const handlePlay = (item: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.play-list {
|
.play-list {
|
||||||
@apply mt-4 py-4 px-2 rounded-xl;
|
@apply mt-4 py-4 px-2 rounded-xl flex-1 overflow-hidden;
|
||||||
background-color: #000000;
|
background-color: #000000;
|
||||||
&-title {
|
&-title {
|
||||||
@apply text-lg text-white opacity-70;
|
@apply text-lg text-white opacity-70;
|
||||||
|
|||||||
Reference in New Issue
Block a user