feat: 添加播放历史页面

This commit is contained in:
alger
2023-12-29 16:04:44 +08:00
parent 8da7fdabe5
commit 492164d008
10 changed files with 317 additions and 207 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
"version": "0.0.1", "version": "1.3.0",
"isProxy": false, "isProxy": false,
"author": "alger" "author": "alger"
} }
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "alger-music", "name": "alger-music",
"version": "1.2.0", "version": "1.3.0",
"description": "这是一个用于音乐播放的应用程序。", "description": "这是一个用于音乐播放的应用程序。",
"author": "Alger <algerkc@qq.com>", "author": "Alger <algerkc@qq.com>",
"main": "app.js", "main": "app.js",
+5
View File
@@ -7,6 +7,11 @@ export const getMusicUrl = (id: number) => {
return request.get<IPlayMusicUrl>("/song/url", { params: { id: id } }) return request.get<IPlayMusicUrl>("/song/url", { params: { id: id } })
} }
// 获取歌曲详情
export const getMusicDetail = (ids: Array<number>) => {
return request.get("/song/detail", { params: { ids: ids.join(",")}})
}
// 根据音乐Id获取音乐歌词 // 根据音乐Id获取音乐歌词
export const getMusicLrc = (id: number) => { export const getMusicLrc = (id: number) => {
return request.get<ILyric>("/lyric", { params: { id: id } }) return request.get<ILyric>("/lyric", { params: { id: id } })
+4
View File
@@ -45,6 +45,7 @@
import { useStore } from 'vuex' import { useStore } from 'vuex'
import type { SongResult } from '@/type/music' import type { SongResult } from '@/type/music'
import { getImgUrl } from '@/utils' import { getImgUrl } from '@/utils'
import { useMusicHistory } from '@/hooks/MusicHistoryHook'
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
item: SongResult item: SongResult
@@ -66,12 +67,15 @@ const isPlaying = computed(() => {
const emits = defineEmits(['play']) const emits = defineEmits(['play'])
const musicHistory = useMusicHistory()
// 播放音乐 设置音乐详情 打开音乐底栏 // 播放音乐 设置音乐详情 打开音乐底栏
const playMusicEvent = (item: any) => { const playMusicEvent = (item: any) => {
store.commit('setPlay', item) store.commit('setPlay', item)
store.commit('setIsPlay', true) store.commit('setIsPlay', true)
store.state.playListIndex = 0 store.state.playListIndex = 0
emits('play', item) emits('play', item)
musicHistory.addMusic(item)
} }
</script> </script>
+39
View File
@@ -0,0 +1,39 @@
// musicHistoryHooks
import { RemovableRef, useLocalStorage } from '@vueuse/core'
import type { SongResult } from '@/type/music'
export const useMusicHistory = () => {
const musicHistory = useLocalStorage<SongResult[]>('musicHistory', [])
const addMusic = (music: SongResult) => {
const index = musicHistory.value.findIndex((item) => item.id === music.id)
if (index !== -1) {
musicHistory.value[index].count =
(musicHistory.value[index].count || 0) + 1
musicHistory.value.unshift(musicHistory.value.splice(index, 1)[0])
} else {
musicHistory.value.unshift({ ...music, count: 1 })
}
}
const delMusic = (music: any) => {
const index = musicHistory.value.findIndex((item) => item.id === music.id)
if (index !== -1) {
musicHistory.value.splice(index, 1)
}
}
const musicList = ref(musicHistory.value)
watch(
() => musicHistory.value,
() => {
musicList.value = musicHistory.value
}
)
return {
musicHistory,
musicList,
addMusic,
delMusic,
}
}
+10
View File
@@ -39,6 +39,16 @@ const layoutRouter = [
}, },
component: () => import('@/views/mv/index.vue'), component: () => import('@/views/mv/index.vue'),
}, },
{
path: '/history',
name: 'history',
mate: {
title: '历史',
keepAlive: true,
icon: 'icon-a-TicketStar',
},
component: () => import('@/views/history/index.vue'),
},
{ {
path: '/user', path: '/user',
name: 'user', name: 'user',
+10 -9
View File
@@ -5,15 +5,16 @@ export interface IRecommendMusic {
} }
export interface SongResult { export interface SongResult {
id: number; id: number
type: number; type: number
name: string; name: string
copywriter?: any; copywriter?: any
picUrl: string; picUrl: string
canDislike: boolean; canDislike: boolean
trackNumberUpdateTime?: any; trackNumberUpdateTime?: any
song: Song; song: Song
alg: string; alg: string
count?: number
} }
interface Song { interface Song {
+45
View File
@@ -0,0 +1,45 @@
<template>
<div class="history-page">
<div class="title">播放历史</div>
<n-scrollbar :size="100">
<div class="history-list-content" :class="setAnimationClass('animate__bounceInLeft')">
<div class="history-item" v-for="(item, index) in musicList" :key="item.id"
:class="setAnimationClass('animate__bounceIn')" :style="setAnimationDelay(index, 30)">
<song-item class="history-item-content" :item="item" />
<div class="history-item-delete">
<i class="iconfont icon-close" @click="delMusic(item)"></i>
</div>
</div>
</div>
</n-scrollbar>
</div>
</template>
<script setup lang="ts">
import { useMusicHistory } from '@/hooks/MusicHistoryHook'
import { setAnimationClass, setAnimationDelay } from "@/utils";
const {delMusic, musicList} = useMusicHistory();
</script>
<style scoped lang="scss">
.history-page{
@apply h-full w-full pt-2;
.title{
@apply text-xl font-bold;
}
.history-list-content{
@apply px-4 mt-2;
.history-item{
@apply flex items-center justify-between;
&-content{
@apply flex-1;
}
&-delete{
@apply cursor-pointer rounded-full border-2 border-gray-400 w-8 h-8 flex justify-center items-center;
}
}
}
}
</style>
+1 -1
View File
@@ -97,7 +97,7 @@ watch(
<style lang="scss" scoped> <style lang="scss" scoped>
.list-page { .list-page {
@apply relative h-full w-full pt-4; @apply relative h-full w-full pt-2;
} }
.recommend { .recommend {
+14 -8
View File
@@ -72,19 +72,25 @@ const close = () => {
<style scoped lang="scss"> <style scoped lang="scss">
.mv-list { .mv-list {
@apply relative h-full w-full pt-4; @apply relative h-full w-full pt-2;
&-title {
@apply text-xl font-bold;
}
&-content { &-content {
@apply grid gap-6 pb-28 pr-3; @apply grid gap-6 pb-28 pr-3 mt-2;
grid-template-columns: repeat(auto-fill, minmax(13%, 1fr)); grid-template-columns: repeat(auto-fill, minmax(14%, 1fr));
} }
.mv-item { .mv-item {
@apply p-2 rounded-lg;
background-color: #454545;
&-img { &-img {
@apply rounded-xl overflow-hidden relative; @apply rounded-lg overflow-hidden relative;
&:hover img { &:hover img {
@apply hover:scale-110 transition-all duration-300 ease-in-out; @apply hover:scale-110 transition-all duration-300 ease-in-out object-top;
} }
&-img { &-img {
@@ -93,11 +99,11 @@ const close = () => {
.top { .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; @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; background-color: #0000009b;
opacity: 0; opacity: 0;
i { i {
font-size: 50px; font-size: 40px;
transition: all 0.5s ease-in-out; transition: all 0.5s ease-in-out;
opacity: 0; opacity: 0;
} }
@@ -107,7 +113,7 @@ const close = () => {
} }
&:hover i { &:hover i {
@apply transform scale-150 opacity-100; @apply transform scale-150 opacity-80;
} }
.play-count { .play-count {