mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-05 07:20:50 +08:00
用户界面 可以打开歌单了 添加听歌排行
This commit is contained in:
@@ -9,3 +9,9 @@ export function getUserDetail(uid: number) {
|
||||
export function getUserPlaylist(uid: number) {
|
||||
return request.get("/user/playlist", { params: { uid } });
|
||||
}
|
||||
|
||||
// 播放历史
|
||||
// /user/record?uid=32953014&type=1
|
||||
export function getUserRecord(uid: number, type: number = 0) {
|
||||
return request.get("/user/record", { params: { uid, type } });
|
||||
}
|
||||
|
||||
@@ -11,10 +11,13 @@
|
||||
<n-layout class="main-content bg-black" :native-scrollbar="false">
|
||||
<n-message-provider>
|
||||
<router-view class="main-page" v-slot="{ Component }">
|
||||
<keep-alive>
|
||||
<!-- <keep-alive>
|
||||
<component :is="Component" v-if="$route.meta.keepAlive" />
|
||||
</keep-alive>
|
||||
<component :is="Component" v-if="!$route.meta.keepAlive" />
|
||||
<component :is="Component" v-if="!$route.meta.keepAlive" /> -->
|
||||
<keep-alive>
|
||||
<component :is="Component"/>
|
||||
</keep-alive>
|
||||
</router-view>
|
||||
</n-message-provider>
|
||||
</n-layout>
|
||||
|
||||
@@ -23,6 +23,26 @@ const RecommendSinger = defineAsyncComponent(() => import("@/components/Recommen
|
||||
const PlaylistType = defineAsyncComponent(() => import("@/components/PlaylistType.vue"));
|
||||
const RecommendSonglist = defineAsyncComponent(() => import("@/components/RecommendSonglist.vue"));
|
||||
const RecommendAlbum = defineAsyncComponent(() => import("@/components/RecommendAlbum.vue"));
|
||||
/*
|
||||
异步组件的定义方式
|
||||
const asyncComponents = defineAsyncComponent({
|
||||
// 异步组件的路径
|
||||
loader: () => import("@/components/RecommendSinger.vue"),
|
||||
// 异步组件的占位
|
||||
loadingComponent:aaa,
|
||||
// 异步组件的错误
|
||||
errorComponent:bbb,
|
||||
// 在显示loading组件之前,等待多长时间
|
||||
delay:1000,
|
||||
// 监听错误
|
||||
// error 错误信息 retry 再次请求 attempts 当前重试次数
|
||||
onError:(err,retry,attempts)=>{
|
||||
console.log("错误")
|
||||
}
|
||||
})
|
||||
*/
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ const formatDetail = computed(() => (detail: any) => {
|
||||
v-for="(item, index) in listDetail?.playlist.tracks"
|
||||
:key="item.id"
|
||||
:class="setAnimationClass('animate__bounceInUp')"
|
||||
:style="setAnimationDelay(index, 100)"
|
||||
:style="setAnimationDelay(index, 50)"
|
||||
>
|
||||
<SongItem :item="formatDetail(item)" />
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
<script lang="ts" setup>
|
||||
import { useStore } from "vuex";
|
||||
import { useRouter } from "vue-router";
|
||||
import { getUserDetail, getUserPlaylist } from "@/api/user";
|
||||
import { getUserDetail, getUserPlaylist, getUserRecord } from "@/api/user";
|
||||
import type { IUserDetail } from "@/type/user";
|
||||
import { ref } from "vue";
|
||||
import { computed, ref } from "vue";
|
||||
import { setAnimationClass, setAnimationDelay } from "@/utils";
|
||||
import MPop from "@/components/common/MPop.vue";
|
||||
import { getListDetail } from '@/api/list'
|
||||
import SongItem from "@/components/common/SongItem.vue";
|
||||
|
||||
|
||||
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
@@ -13,6 +16,7 @@ const router = useRouter()
|
||||
|
||||
const userDetail = ref<IUserDetail>()
|
||||
const playList = ref<any[]>([])
|
||||
const recordList = ref()
|
||||
const user = store.state.user
|
||||
|
||||
const loadPage = async () => {
|
||||
@@ -27,14 +31,55 @@ const loadPage = async () => {
|
||||
const { data: playlistData } = await getUserPlaylist(user.userId)
|
||||
playList.value = playlistData.playlist
|
||||
|
||||
const { data: recordData } = await getUserRecord(user.userId)
|
||||
recordList.value = recordData.allData
|
||||
|
||||
|
||||
}
|
||||
loadPage()
|
||||
|
||||
|
||||
const isShowList = ref(false)
|
||||
const list = ref()
|
||||
// 展示歌单
|
||||
const showPlaylist = async (id: number) => {
|
||||
const { data } = await getListDetail(id)
|
||||
isShowList.value = true
|
||||
list.value = data.playlist
|
||||
}
|
||||
|
||||
// 格式化歌曲列表项
|
||||
const formatDetail = computed(() => (detail: any) => {
|
||||
let song = {
|
||||
artists: detail.ar,
|
||||
name: detail.al.name,
|
||||
id: detail.al.id,
|
||||
}
|
||||
|
||||
detail.song = song
|
||||
detail.picUrl = detail.al.picUrl
|
||||
return detail
|
||||
})
|
||||
|
||||
const musicFullClass = computed(() => {
|
||||
if (isShowList.value) {
|
||||
return setAnimationClass('animate__fadeInUp')
|
||||
} else {
|
||||
return setAnimationClass('animate__fadeOutDown')
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="user-page" :class="setAnimationClass('animate__fadeInLeft')">
|
||||
<div class="left" v-if="userDetail" :style="{ backgroundImage: `url(${user.backgroundUrl})` }">
|
||||
<div class="user-page" @click.stop="isShowList = false">
|
||||
<div
|
||||
class="left"
|
||||
v-if="userDetail"
|
||||
:class="setAnimationClass('animate__fadeInLeft')"
|
||||
:style="{ backgroundImage: `url(${user.backgroundUrl})` }"
|
||||
>
|
||||
<div class="page">
|
||||
<div class="user-name">{{ user.nickname }}</div>
|
||||
<div class="user-info">
|
||||
@@ -58,7 +103,12 @@ loadPage()
|
||||
|
||||
<div class="play-list" :class="setAnimationClass('animate__fadeInLeft')">
|
||||
<div class="play-list-title">创建的歌单</div>
|
||||
<div class="play-list-item" v-for="(item,index) in playList" :key="index">
|
||||
<div
|
||||
class="play-list-item"
|
||||
v-for="(item,index) in playList"
|
||||
:key="index"
|
||||
@click="showPlaylist(item.id)"
|
||||
>
|
||||
<img class="play-list-item-img" :src="item.coverImgUrl" />
|
||||
<div class="play-list-item-info">
|
||||
<div class="play-list-item-name">{{ item.name }}</div>
|
||||
@@ -68,46 +118,92 @@ loadPage()
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right" :class="setAnimationClass('animate__fadeInRight')">
|
||||
<n-layout class="record-list" :native-scrollbar="false">
|
||||
<div class="title">听歌排行</div>
|
||||
<div
|
||||
class="record-item"
|
||||
v-for="(item, index) in recordList"
|
||||
:key="item.song.id"
|
||||
:class="setAnimationClass('animate__bounceInUp')"
|
||||
:style="setAnimationDelay(index, 50)"
|
||||
>
|
||||
<SongItem class="song-item" :item="formatDetail(item.song)" />
|
||||
<div class="play-count">{{ item.playCount }}次</div>
|
||||
</div>
|
||||
</n-layout>
|
||||
</div>
|
||||
|
||||
<!-- <MPop :show-pop="true">
|
||||
<div>aaaaaaaaaaaaaaaaaa</div>
|
||||
</MPop> -->
|
||||
<div class="music-page" v-show="isShowList" :class="musicFullClass">
|
||||
<i class="iconfont icon-icon_error music-close" @click="isShowList = false"></i>
|
||||
<div class="music-title">{{ list?.name }}</div>
|
||||
<!-- 歌单歌曲列表 -->
|
||||
<n-layout class="music-list" :native-scrollbar="false">
|
||||
<div
|
||||
v-for="(item, index) in list?.tracks"
|
||||
:key="item.id"
|
||||
:class="setAnimationClass('animate__bounceInUp')"
|
||||
:style="setAnimationDelay(index, 100)"
|
||||
>
|
||||
<SongItem :item="formatDetail(item)" />
|
||||
</div>
|
||||
</n-layout>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.user-page {
|
||||
@apply flex;
|
||||
}
|
||||
.left {
|
||||
max-width: 600px;
|
||||
background-color: #0d0d0d;
|
||||
background-size: 100%;
|
||||
@apply flex-1 rounded-2xl overflow-hidden relative bg-no-repeat;
|
||||
.page {
|
||||
@apply p-4 w-full z-10;
|
||||
background-color: #0d0d0d66;
|
||||
}
|
||||
.user-name {
|
||||
@apply text-xl text-white font-bold opacity-70 mb-4;
|
||||
}
|
||||
|
||||
.left {
|
||||
max-width: 600px;
|
||||
background-color: #0d0d0d;
|
||||
background-size: 100%;
|
||||
@apply bg-no-repeat;
|
||||
|
||||
@apply flex-1 rounded-2xl mt-4 overflow-hidden relative;
|
||||
.page {
|
||||
@apply p-4 w-full z-10;
|
||||
background-color: #0d0d0d66;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
@apply text-xl text-white font-bold opacity-70 mb-4;
|
||||
}
|
||||
|
||||
.uesr-signature {
|
||||
@apply text-white opacity-70 mt-4;
|
||||
}
|
||||
.user-info {
|
||||
@apply flex items-center;
|
||||
&-list {
|
||||
@apply flex justify-around w-2/5 text-center opacity-70;
|
||||
.label {
|
||||
@apply text-xl text-white font-bold;
|
||||
.uesr-signature {
|
||||
@apply text-white opacity-70 mt-4;
|
||||
}
|
||||
.user-info {
|
||||
@apply flex items-center;
|
||||
&-list {
|
||||
@apply flex justify-around w-2/5 text-center opacity-70;
|
||||
.label {
|
||||
@apply text-xl text-white font-bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
@apply flex-1 ml-4;
|
||||
.record-list {
|
||||
height: 750px;
|
||||
background-color: #0d0d0d;
|
||||
@apply rounded-2xl;
|
||||
.record-item {
|
||||
@apply flex items-center px-4;
|
||||
}
|
||||
|
||||
.song-item {
|
||||
@apply flex-1;
|
||||
}
|
||||
|
||||
.play-count {
|
||||
@apply text-white opacity-70 ml-4;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
@apply text-xl text-white font-bold opacity-70 m-4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.play-list {
|
||||
@@ -131,4 +227,29 @@ loadPage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.music {
|
||||
&-page {
|
||||
width: 100%;
|
||||
height: 734px;
|
||||
position: absolute;
|
||||
background-color: #000000f0;
|
||||
top: 100px;
|
||||
left: 0;
|
||||
border-radius: 30px 30px 0 0;
|
||||
animation-duration: 300ms;
|
||||
}
|
||||
&-title {
|
||||
@apply text-lg font-bold text-white p-4;
|
||||
}
|
||||
|
||||
&-close {
|
||||
@apply absolute top-4 right-4 cursor-pointer text-white text-3xl;
|
||||
}
|
||||
|
||||
&-list {
|
||||
height: 594px;
|
||||
background-color: #00000000;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user