mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-05-19 03:57:28 +08:00
✨ feat: 添加播放历史页面
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "0.0.1",
|
||||
"version": "1.3.0",
|
||||
"isProxy": false,
|
||||
"author": "alger"
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "alger-music",
|
||||
"version": "1.2.0",
|
||||
"version": "1.3.0",
|
||||
"description": "这是一个用于音乐播放的应用程序。",
|
||||
"author": "Alger <algerkc@qq.com>",
|
||||
"main": "app.js",
|
||||
|
||||
@@ -7,6 +7,11 @@ export const getMusicUrl = (id: number) => {
|
||||
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获取音乐歌词
|
||||
export const getMusicLrc = (id: number) => {
|
||||
return request.get<ILyric>("/lyric", { params: { id: id } })
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
import { useStore } from 'vuex'
|
||||
import type { SongResult } from '@/type/music'
|
||||
import { getImgUrl } from '@/utils'
|
||||
import { useMusicHistory } from '@/hooks/MusicHistoryHook'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
item: SongResult
|
||||
@@ -66,12 +67,15 @@ const isPlaying = computed(() => {
|
||||
|
||||
const emits = defineEmits(['play'])
|
||||
|
||||
const musicHistory = useMusicHistory()
|
||||
|
||||
// 播放音乐 设置音乐详情 打开音乐底栏
|
||||
const playMusicEvent = (item: any) => {
|
||||
store.commit('setPlay', item)
|
||||
store.commit('setIsPlay', true)
|
||||
store.state.playListIndex = 0
|
||||
emits('play', item)
|
||||
musicHistory.addMusic(item)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,16 @@ const layoutRouter = [
|
||||
},
|
||||
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',
|
||||
name: 'user',
|
||||
|
||||
+10
-9
@@ -5,15 +5,16 @@ export interface IRecommendMusic {
|
||||
}
|
||||
|
||||
export interface SongResult {
|
||||
id: number;
|
||||
type: number;
|
||||
name: string;
|
||||
copywriter?: any;
|
||||
picUrl: string;
|
||||
canDislike: boolean;
|
||||
trackNumberUpdateTime?: any;
|
||||
song: Song;
|
||||
alg: string;
|
||||
id: number
|
||||
type: number
|
||||
name: string
|
||||
copywriter?: any
|
||||
picUrl: string
|
||||
canDislike: boolean
|
||||
trackNumberUpdateTime?: any
|
||||
song: Song
|
||||
alg: string
|
||||
count?: number
|
||||
}
|
||||
|
||||
interface Song {
|
||||
|
||||
@@ -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>
|
||||
@@ -97,7 +97,7 @@ watch(
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.list-page {
|
||||
@apply relative h-full w-full pt-4;
|
||||
@apply relative h-full w-full pt-2;
|
||||
}
|
||||
|
||||
.recommend {
|
||||
|
||||
+14
-8
@@ -72,19 +72,25 @@ const close = () => {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.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 {
|
||||
@apply grid gap-6 pb-28 pr-3;
|
||||
grid-template-columns: repeat(auto-fill, minmax(13%, 1fr));
|
||||
@apply grid gap-6 pb-28 pr-3 mt-2;
|
||||
grid-template-columns: repeat(auto-fill, minmax(14%, 1fr));
|
||||
}
|
||||
|
||||
.mv-item {
|
||||
@apply p-2 rounded-lg;
|
||||
background-color: #454545;
|
||||
&-img {
|
||||
@apply rounded-xl overflow-hidden relative;
|
||||
@apply rounded-lg overflow-hidden relative;
|
||||
|
||||
&: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 {
|
||||
@@ -93,11 +99,11 @@ const close = () => {
|
||||
|
||||
.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;
|
||||
background-color: #0000009b;
|
||||
opacity: 0;
|
||||
|
||||
i {
|
||||
font-size: 50px;
|
||||
font-size: 40px;
|
||||
transition: all 0.5s ease-in-out;
|
||||
opacity: 0;
|
||||
}
|
||||
@@ -107,7 +113,7 @@ const close = () => {
|
||||
}
|
||||
|
||||
&:hover i {
|
||||
@apply transform scale-150 opacity-100;
|
||||
@apply transform scale-150 opacity-80;
|
||||
}
|
||||
|
||||
.play-count {
|
||||
|
||||
Reference in New Issue
Block a user