mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-23 15:47:23 +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',
|
||||
|
||||
+197
-196
@@ -1,196 +1,197 @@
|
||||
export interface IRecommendMusic {
|
||||
code: number;
|
||||
category: number;
|
||||
result: SongResult[];
|
||||
}
|
||||
|
||||
export interface SongResult {
|
||||
id: number;
|
||||
type: number;
|
||||
name: string;
|
||||
copywriter?: any;
|
||||
picUrl: string;
|
||||
canDislike: boolean;
|
||||
trackNumberUpdateTime?: any;
|
||||
song: Song;
|
||||
alg: string;
|
||||
}
|
||||
|
||||
interface Song {
|
||||
name: string;
|
||||
id: number;
|
||||
position: number;
|
||||
alias: string[];
|
||||
status: number;
|
||||
fee: number;
|
||||
copyrightId: number;
|
||||
disc: string;
|
||||
no: number;
|
||||
artists: Artist[];
|
||||
album: Album;
|
||||
starred: boolean;
|
||||
popularity: number;
|
||||
score: number;
|
||||
starredNum: number;
|
||||
duration: number;
|
||||
playedNum: number;
|
||||
dayPlays: number;
|
||||
hearTime: number;
|
||||
ringtone: string;
|
||||
crbt?: any;
|
||||
audition?: any;
|
||||
copyFrom: string;
|
||||
commentThreadId: string;
|
||||
rtUrl?: any;
|
||||
ftype: number;
|
||||
rtUrls: any[];
|
||||
copyright: number;
|
||||
transName?: any;
|
||||
sign?: any;
|
||||
mark: number;
|
||||
originCoverType: number;
|
||||
originSongSimpleData?: any;
|
||||
single: number;
|
||||
noCopyrightRcmd?: any;
|
||||
rtype: number;
|
||||
rurl?: any;
|
||||
mvid: number;
|
||||
bMusic: BMusic;
|
||||
mp3Url?: any;
|
||||
hMusic: BMusic;
|
||||
mMusic: BMusic;
|
||||
lMusic: BMusic;
|
||||
exclusive: boolean;
|
||||
privilege: Privilege;
|
||||
}
|
||||
|
||||
interface Privilege {
|
||||
id: number;
|
||||
fee: number;
|
||||
payed: number;
|
||||
st: number;
|
||||
pl: number;
|
||||
dl: number;
|
||||
sp: number;
|
||||
cp: number;
|
||||
subp: number;
|
||||
cs: boolean;
|
||||
maxbr: number;
|
||||
fl: number;
|
||||
toast: boolean;
|
||||
flag: number;
|
||||
preSell: boolean;
|
||||
playMaxbr: number;
|
||||
downloadMaxbr: number;
|
||||
rscl?: any;
|
||||
freeTrialPrivilege: FreeTrialPrivilege;
|
||||
chargeInfoList: ChargeInfoList[];
|
||||
}
|
||||
|
||||
interface ChargeInfoList {
|
||||
rate: number;
|
||||
chargeUrl?: any;
|
||||
chargeMessage?: any;
|
||||
chargeType: number;
|
||||
}
|
||||
|
||||
interface FreeTrialPrivilege {
|
||||
resConsumable: boolean;
|
||||
userConsumable: boolean;
|
||||
}
|
||||
|
||||
interface BMusic {
|
||||
name?: any;
|
||||
id: number;
|
||||
size: number;
|
||||
extension: string;
|
||||
sr: number;
|
||||
dfsId: number;
|
||||
bitrate: number;
|
||||
playTime: number;
|
||||
volumeDelta: number;
|
||||
}
|
||||
|
||||
interface Album {
|
||||
name: string;
|
||||
id: number;
|
||||
type: string;
|
||||
size: number;
|
||||
picId: number;
|
||||
blurPicUrl: string;
|
||||
companyId: number;
|
||||
pic: number;
|
||||
picUrl: string;
|
||||
publishTime: number;
|
||||
description: string;
|
||||
tags: string;
|
||||
company: string;
|
||||
briefDesc: string;
|
||||
artist: Artist;
|
||||
songs: any[];
|
||||
alias: string[];
|
||||
status: number;
|
||||
copyrightId: number;
|
||||
commentThreadId: string;
|
||||
artists: Artist[];
|
||||
subType: string;
|
||||
transName?: any;
|
||||
onSale: boolean;
|
||||
mark: number;
|
||||
picId_str: string;
|
||||
}
|
||||
|
||||
interface Artist {
|
||||
name: string;
|
||||
id: number;
|
||||
picId: number;
|
||||
img1v1Id: number;
|
||||
briefDesc: string;
|
||||
picUrl: string;
|
||||
img1v1Url: string;
|
||||
albumSize: number;
|
||||
alias: any[];
|
||||
trans: string;
|
||||
musicSize: number;
|
||||
topicPerson: number;
|
||||
}
|
||||
|
||||
export interface IPlayMusicUrl {
|
||||
data: Datum[];
|
||||
code: number;
|
||||
}
|
||||
|
||||
interface Datum {
|
||||
id: number;
|
||||
url: string;
|
||||
br: number;
|
||||
size: number;
|
||||
md5: string;
|
||||
code: number;
|
||||
expi: number;
|
||||
type: string;
|
||||
gain: number;
|
||||
fee: number;
|
||||
uf?: any;
|
||||
payed: number;
|
||||
flag: number;
|
||||
canExtend: boolean;
|
||||
freeTrialInfo?: any;
|
||||
level: string;
|
||||
encodeType: string;
|
||||
freeTrialPrivilege: FreeTrialPrivilege;
|
||||
freeTimeTrialPrivilege: FreeTimeTrialPrivilege;
|
||||
urlSource: number;
|
||||
}
|
||||
|
||||
interface FreeTimeTrialPrivilege {
|
||||
resConsumable: boolean;
|
||||
userConsumable: boolean;
|
||||
type: number;
|
||||
remainTime: number;
|
||||
}
|
||||
|
||||
interface FreeTrialPrivilege {
|
||||
resConsumable: boolean;
|
||||
userConsumable: boolean;
|
||||
}
|
||||
export interface IRecommendMusic {
|
||||
code: number;
|
||||
category: number;
|
||||
result: SongResult[];
|
||||
}
|
||||
|
||||
export interface SongResult {
|
||||
id: number
|
||||
type: number
|
||||
name: string
|
||||
copywriter?: any
|
||||
picUrl: string
|
||||
canDislike: boolean
|
||||
trackNumberUpdateTime?: any
|
||||
song: Song
|
||||
alg: string
|
||||
count?: number
|
||||
}
|
||||
|
||||
interface Song {
|
||||
name: string;
|
||||
id: number;
|
||||
position: number;
|
||||
alias: string[];
|
||||
status: number;
|
||||
fee: number;
|
||||
copyrightId: number;
|
||||
disc: string;
|
||||
no: number;
|
||||
artists: Artist[];
|
||||
album: Album;
|
||||
starred: boolean;
|
||||
popularity: number;
|
||||
score: number;
|
||||
starredNum: number;
|
||||
duration: number;
|
||||
playedNum: number;
|
||||
dayPlays: number;
|
||||
hearTime: number;
|
||||
ringtone: string;
|
||||
crbt?: any;
|
||||
audition?: any;
|
||||
copyFrom: string;
|
||||
commentThreadId: string;
|
||||
rtUrl?: any;
|
||||
ftype: number;
|
||||
rtUrls: any[];
|
||||
copyright: number;
|
||||
transName?: any;
|
||||
sign?: any;
|
||||
mark: number;
|
||||
originCoverType: number;
|
||||
originSongSimpleData?: any;
|
||||
single: number;
|
||||
noCopyrightRcmd?: any;
|
||||
rtype: number;
|
||||
rurl?: any;
|
||||
mvid: number;
|
||||
bMusic: BMusic;
|
||||
mp3Url?: any;
|
||||
hMusic: BMusic;
|
||||
mMusic: BMusic;
|
||||
lMusic: BMusic;
|
||||
exclusive: boolean;
|
||||
privilege: Privilege;
|
||||
}
|
||||
|
||||
interface Privilege {
|
||||
id: number;
|
||||
fee: number;
|
||||
payed: number;
|
||||
st: number;
|
||||
pl: number;
|
||||
dl: number;
|
||||
sp: number;
|
||||
cp: number;
|
||||
subp: number;
|
||||
cs: boolean;
|
||||
maxbr: number;
|
||||
fl: number;
|
||||
toast: boolean;
|
||||
flag: number;
|
||||
preSell: boolean;
|
||||
playMaxbr: number;
|
||||
downloadMaxbr: number;
|
||||
rscl?: any;
|
||||
freeTrialPrivilege: FreeTrialPrivilege;
|
||||
chargeInfoList: ChargeInfoList[];
|
||||
}
|
||||
|
||||
interface ChargeInfoList {
|
||||
rate: number;
|
||||
chargeUrl?: any;
|
||||
chargeMessage?: any;
|
||||
chargeType: number;
|
||||
}
|
||||
|
||||
interface FreeTrialPrivilege {
|
||||
resConsumable: boolean;
|
||||
userConsumable: boolean;
|
||||
}
|
||||
|
||||
interface BMusic {
|
||||
name?: any;
|
||||
id: number;
|
||||
size: number;
|
||||
extension: string;
|
||||
sr: number;
|
||||
dfsId: number;
|
||||
bitrate: number;
|
||||
playTime: number;
|
||||
volumeDelta: number;
|
||||
}
|
||||
|
||||
interface Album {
|
||||
name: string;
|
||||
id: number;
|
||||
type: string;
|
||||
size: number;
|
||||
picId: number;
|
||||
blurPicUrl: string;
|
||||
companyId: number;
|
||||
pic: number;
|
||||
picUrl: string;
|
||||
publishTime: number;
|
||||
description: string;
|
||||
tags: string;
|
||||
company: string;
|
||||
briefDesc: string;
|
||||
artist: Artist;
|
||||
songs: any[];
|
||||
alias: string[];
|
||||
status: number;
|
||||
copyrightId: number;
|
||||
commentThreadId: string;
|
||||
artists: Artist[];
|
||||
subType: string;
|
||||
transName?: any;
|
||||
onSale: boolean;
|
||||
mark: number;
|
||||
picId_str: string;
|
||||
}
|
||||
|
||||
interface Artist {
|
||||
name: string;
|
||||
id: number;
|
||||
picId: number;
|
||||
img1v1Id: number;
|
||||
briefDesc: string;
|
||||
picUrl: string;
|
||||
img1v1Url: string;
|
||||
albumSize: number;
|
||||
alias: any[];
|
||||
trans: string;
|
||||
musicSize: number;
|
||||
topicPerson: number;
|
||||
}
|
||||
|
||||
export interface IPlayMusicUrl {
|
||||
data: Datum[];
|
||||
code: number;
|
||||
}
|
||||
|
||||
interface Datum {
|
||||
id: number;
|
||||
url: string;
|
||||
br: number;
|
||||
size: number;
|
||||
md5: string;
|
||||
code: number;
|
||||
expi: number;
|
||||
type: string;
|
||||
gain: number;
|
||||
fee: number;
|
||||
uf?: any;
|
||||
payed: number;
|
||||
flag: number;
|
||||
canExtend: boolean;
|
||||
freeTrialInfo?: any;
|
||||
level: string;
|
||||
encodeType: string;
|
||||
freeTrialPrivilege: FreeTrialPrivilege;
|
||||
freeTimeTrialPrivilege: FreeTimeTrialPrivilege;
|
||||
urlSource: number;
|
||||
}
|
||||
|
||||
interface FreeTimeTrialPrivilege {
|
||||
resConsumable: boolean;
|
||||
userConsumable: boolean;
|
||||
type: number;
|
||||
remainTime: number;
|
||||
}
|
||||
|
||||
interface FreeTrialPrivilege {
|
||||
resConsumable: boolean;
|
||||
userConsumable: boolean;
|
||||
}
|
||||
|
||||
@@ -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