vite-zmusic/src/views/discover/Recommend.vue
2021-10-19 21:40:06 +08:00

447 lines
9.3 KiB
Vue

<template>
<div class="lmt-width">
<n-carousel
show-arrow
trigger="hover"
:autoplay="true"
style="margin: 0 auto; max-width: 800px"
>
<div
class="wp-carousel"
v-for="(b, idx) in banners"
:key="idx"
>
<img class="carousel-img" :src="b.imageUrl" />
<span class="title">{{ b.typeTitle }}</span>
</div>
</n-carousel>
<!-- 最新音乐 -->
<div>
<n-button
text
icon-placement="right"
size="large"
type="primary"
style="font-size: 1.3em; margin-top: 6px"
>
<template #icon>
<n-icon>
<ChevronForward />
</n-icon>
</template>
最新音乐
</n-button>
<n-grid
:x-gap="18"
:y-gap="8"
:cols="2"
style="margin: 6px 0"
>
<n-grid-item
v-for="(song, idx) in topSongs"
key="idx"
>
<div class="c2-list">
<div class="play-btn">
<img :src="song.album.blurPicUrl" />
<n-button
text
class="start-play-bg"
type="info"
>
<n-icon>
<PlayCircle @click="play(song.id)" />
</n-icon>
</n-button>
<n-button
text
class="start-play"
type="primary"
>
<n-icon>
<Play @click="play(song.id)" />
</n-icon>
</n-button>
</div>
<div class="title">
<span class="name">
{{ song.name }}
<span class="alias"
><template
v-for="(al, idx) in song.alias"
>
{{ al }}
</template></span
>
</span>
<span class="artist">
<ArtistsSpan :artists="song.artists" />
</span>
</div>
<span class="icon"></span>
</div>
</n-grid-item>
</n-grid>
</div>
<!-- 推荐MV -->
<div>
<!-- 标题 -->
<n-button
text
icon-placement="right"
size="large"
type="primary"
style="font-size: 1.3em; margin-top: 6px"
>
<template #icon>
<n-icon>
<ChevronForward />
</n-icon>
</template>
推荐MV
</n-button>
<!-- 列表 -->
<n-grid
:x-gap="18"
:y-gap="8"
:cols="4"
style="margin: 6px 0"
>
<n-grid-item
v-for="(mv, idx) in personalizedMV"
key="idx"
>
<div class="mv-c2-list">
<div class="play-mv">
<div>
<img :src="mv.picUrl" />
</div>
<n-button
text
class="start-play-bg"
type="info"
>
<n-icon>
<PlayCircle />
</n-icon>
</n-button>
<n-button
text
class="start-play"
type="primary"
>
<n-icon>
<Play />
</n-icon>
</n-button>
</div>
<div class="title">
<span class="name">
{{ mv.name }}
</span>
<span class="artist">{{
mv.artistName
}}</span>
</div>
</div>
</n-grid-item>
</n-grid>
</div>
<!-- 推荐歌单 -->
<div>
<n-button
text
icon-placement="right"
size="large"
type="primary"
style="font-size: 1.3em; margin-top: 6px"
>
<template #icon>
<n-icon>
<ChevronForward />
</n-icon>
</template>
推荐歌单
</n-button>
<n-grid
:x-gap="18"
:y-gap="8"
:cols="4"
style="margin: 6px 0"
>
<n-grid-item v-for="p in personalized">
<n-card
title
hoverable
content-style="padding: 2px 6px;"
>
<template #cover>
<img :src="p.picUrl" />
</template>
<span class="card-span">{{ p.name }}</span>
</n-card>
</n-grid-item>
</n-grid>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from "vue";
import { useStore } from "vuex";
import {
NCarousel,
NScrollbar,
NGrid,
NGridItem,
NCard,
NButton,
NIcon,
NImage,
} from "naive-ui";
// import {
// ChevronForward,
// PlayCircle,
// Play,
// } from "@vicons/ionicons5";
import PlayCircle from "@/assets/svgs/PlayCircle.svg";
import Play from "@/assets/svgs/Play_.svg";
import ChevronForward from "@/assets/svgs/ChevronForward.svg";
import {
getBanner,
getPersonalized,
getTopSong,
getPersonalizedMV,
} from "@/network/discover";
import pubsub from "pubsub-js";
import ArtistsSpan from "@/components/ArtistsSpan.vue";
// console.log("recommend 初始化");
const store = useStore();
const play = (id) => {
pubsub.publish("zp.play", { id, im: true });
};
//#region 轮播图片
let banners = ref([]);
banners.value = store.getters.cache('banners')
getBanner(0)
.then((res) => {
banners.value = res.data.banners;
store.commit("saveCaches", {
banners: { data: banners.value, time: Date.now() },
});
// console.log(banners.value);
})
.catch((err) => {
console.log("getBanner err", err);
});
//#endregion
//#region 最新音乐
let topSongs = ref([]);
// topSongs.value = store.getters.cache('topSongs')
if(store.getters.cache('topSongs'))
{
topSongs.value = store.getters.cache('topSongs')
console.log('载入Caches');
}
//最新音乐
getTopSong()
.then((res) => {
topSongs.value = res.data.data.filter((item, index) => {
return index < 10;
});
store.commit("saveCaches", {
topSongs: { data: topSongs.value, time: Date.now() },
});
// console.log(topSongs.value);
})
.catch((err) => {
console.log("getTopSong err", err);
});
function songAlias(alias) {
if (alias.length > 0) return "[" + alias.join(",") + "]";
}
function songArtists(artists) {
if (artists.length > 0) {
return artists
.map((a) => {
return a.name;
})
.join(" ");
}
}
//#endregion
//#region 推荐歌单
let personalized = ref([]);
personalized.value = store.getters.cache('personalized')
getPersonalized(8)
.then((res) => {
personalized.value = res.data.result;
store.commit("saveCaches", {
personalized: { data: personalized.value, time: Date.now() },
});
// console.log(personalized.value);
})
.catch((err) => {
console.log("getPersonalized err", err);
});
//#endregion
//#region 推荐MV
let personalizedMV = ref([]);
personalizedMV.value = store.getters.cache('personalizedMV')
getPersonalizedMV()
.then((res) => {
personalizedMV.value = res.data.result;
store.commit("saveCaches", {
personalizedMV: { data: personalizedMV.value, time: Date.now() },
});
// console.log(personalized.value);
})
.catch((err) => {
console.log("getPersonalizedMV err", err);
});
//#endregion
</script>
<style lang="less" scoped>
@import "@/assets/css/common.less";
.wp-carousel {
position: relative;
// width: 20em;
// font-size: 1vw;
.carousel-img {
width: 100%;
border-radius: 6px;
}
.title {
position: absolute;
color: #fff;
background-color: #5c18a0ff;
bottom: 0px;
right: 0;
padding: 2px 6px;
font-size: 0.9em;
border-top-left-radius: 6px;
border-bottom-right-radius: 6px;
}
}
.card-span {
.text-el-line2();
}
.mv-c2-list {
display: flex;
flex-direction: column;
position: relative;
border: 1px solid #eee;
border-radius: 6px;
.play-mv {
img {
width: 100%;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
}
button {
display: none;
}
.start-play-bg {
font-size: 38px;
position: absolute;
right: 0px;
bottom: 42px;
color: rgba(255, 255, 255, 0.8);
}
.start-play {
font-size: 25px;
position: absolute;
right: 5px;
bottom: 48px;
}
&:hover {
button {
display: block;
}
}
}
.title {
padding: 3px;
.name {
.text-el-line();
.alias {
font-size: 13px;
color: #888;
}
}
.artist {
font-size: 13px;
color: #666;
.text-el-line();
}
}
}
.c2-list {
display: flex;
align-items: center;
position: relative;
border-radius: 4px;
border: 1px solid #eee;
img {
width: 60px;
border-radius: 4px;
}
.start-play-bg {
font-size: 30px;
position: absolute;
left: 16px;
top: 16px;
color: rgba(255, 255, 255, 0.8);
}
.start-play {
font-size: 16px;
position: absolute;
left: 24px;
top: 23px;
}
.title {
padding-left: 8px;
display: flex;
flex-direction: column;
.name {
.text-el-line();
.alias {
font-size: 13px;
color: #888;
}
}
.artist {
font-size: 13px;
color: #666;
.text-el-line();
}
}
// .icon {
// }
}
</style>