mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-14 14:50:50 +08:00
168 lines
4.4 KiB
Vue
168 lines
4.4 KiB
Vue
<script lang="ts" setup>
|
|
import { useRoute } from 'vue-router';
|
|
|
|
import { getListByCat, getListDetail, getRecommendList } from '@/api/list';
|
|
import MusicList from '@/components/MusicList.vue';
|
|
import type { IRecommendItem } from '@/type/list';
|
|
import type { IListDetail } from '@/type/listDetail';
|
|
import { formatNumber, getImgUrl, setAnimationClass, setAnimationDelay } from '@/utils';
|
|
|
|
defineOptions({
|
|
name: 'List',
|
|
});
|
|
|
|
const recommendList = ref();
|
|
const showMusic = ref(false);
|
|
|
|
const recommendItem = ref<IRecommendItem | null>();
|
|
const listDetail = ref<IListDetail | null>();
|
|
const listLoading = ref(true);
|
|
const selectRecommendItem = async (item: IRecommendItem) => {
|
|
listLoading.value = true;
|
|
recommendItem.value = null;
|
|
listDetail.value = null;
|
|
showMusic.value = true;
|
|
recommendItem.value = item;
|
|
const { data } = await getListDetail(item.id);
|
|
listDetail.value = data;
|
|
listLoading.value = false;
|
|
};
|
|
|
|
const route = useRoute();
|
|
const listTitle = ref(route.query.type || '歌单列表');
|
|
|
|
const loading = ref(false);
|
|
const loadList = async (type: string) => {
|
|
loading.value = true;
|
|
const params = {
|
|
cat: type || '',
|
|
limit: 30,
|
|
offset: 0,
|
|
};
|
|
const { data } = await getListByCat(params);
|
|
recommendList.value = data.playlists;
|
|
loading.value = false;
|
|
};
|
|
|
|
if (route.query.type) {
|
|
loadList(route.query.type as string);
|
|
} else {
|
|
getRecommendList().then((res: { data: { result: any } }) => {
|
|
recommendList.value = res.data.result;
|
|
});
|
|
}
|
|
|
|
watch(
|
|
() => route.query,
|
|
async (newParams) => {
|
|
if (newParams.type) {
|
|
recommendList.value = null;
|
|
listTitle.value = newParams.type || '歌单列表';
|
|
loadList(newParams.type as string);
|
|
}
|
|
},
|
|
);
|
|
</script>
|
|
|
|
<template>
|
|
<div class="list-page">
|
|
<div class="recommend-title" :class="setAnimationClass('animate__bounceInLeft')">{{ listTitle }}</div>
|
|
<!-- 歌单列表 -->
|
|
<n-scrollbar class="recommend" :size="100" @click="showMusic = false">
|
|
<div v-loading="loading" class="recommend-list">
|
|
<div
|
|
v-for="(item, index) in recommendList"
|
|
:key="item.id"
|
|
class="recommend-item"
|
|
:class="setAnimationClass('animate__bounceIn')"
|
|
:style="setAnimationDelay(index, 30)"
|
|
@click.stop="selectRecommendItem(item)"
|
|
>
|
|
<div class="recommend-item-img">
|
|
<n-image
|
|
class="recommend-item-img-img"
|
|
:src="getImgUrl(item.picUrl || item.coverImgUrl, '200y200')"
|
|
width="200"
|
|
height="200"
|
|
lazy
|
|
preview-disabled
|
|
/>
|
|
<div class="top">
|
|
<div class="play-count">{{ formatNumber(item.playCount) }}</div>
|
|
<i class="iconfont icon-videofill"></i>
|
|
</div>
|
|
</div>
|
|
<div class="recommend-item-title">{{ item.name }}</div>
|
|
</div>
|
|
</div>
|
|
</n-scrollbar>
|
|
<music-list
|
|
v-model:show="showMusic"
|
|
v-model:loading="listLoading"
|
|
:name="recommendItem?.name || ''"
|
|
:song-list="listDetail?.playlist.tracks || []"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
.list-page {
|
|
@apply relative h-full w-full px-4;
|
|
}
|
|
|
|
.recommend {
|
|
@apply w-full h-full bg-none;
|
|
&-title {
|
|
@apply text-lg font-bold text-white pb-4;
|
|
}
|
|
|
|
&-list {
|
|
@apply grid gap-6 pb-28;
|
|
grid-template-columns: repeat(auto-fill, minmax(13%, 1fr));
|
|
}
|
|
&-item {
|
|
&-img {
|
|
@apply rounded-xl overflow-hidden relative;
|
|
&:hover img {
|
|
@apply hover:scale-110 transition-all duration-300 ease-in-out;
|
|
}
|
|
&-img {
|
|
@apply h-full w-full rounded-xl overflow-hidden;
|
|
}
|
|
.top {
|
|
@apply absolute w-full h-full top-0 left-0 flex justify-center items-center transition-all duration-300 ease-in-out cursor-pointer;
|
|
background-color: #00000088;
|
|
opacity: 0;
|
|
i {
|
|
font-size: 50px;
|
|
transition: all 0.5s ease-in-out;
|
|
opacity: 0;
|
|
}
|
|
&:hover {
|
|
@apply opacity-100;
|
|
}
|
|
&:hover i {
|
|
@apply transform scale-150 opacity-100;
|
|
}
|
|
|
|
.play-count {
|
|
position: absolute;
|
|
top: 10px;
|
|
left: 10px;
|
|
font-size: 14px;
|
|
}
|
|
}
|
|
}
|
|
&-title {
|
|
@apply p-2 text-sm text-white truncate;
|
|
}
|
|
}
|
|
}
|
|
|
|
.mobile {
|
|
.recommend-list {
|
|
grid-template-columns: repeat(auto-fill, minmax(25%, 1fr));
|
|
}
|
|
}
|
|
</style>
|