mirror of
https://github.com/imsyy/SPlayer.git
synced 2025-11-25 19:37:35 +08:00
feat: 播放列表重构 & fix: 修复一些样式问题
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "splayer",
|
"name": "splayer",
|
||||||
"version": "1.1.2",
|
"version": "1.1.3",
|
||||||
"author": "imsyy",
|
"author": "imsyy",
|
||||||
"home": "https://imsyy.top",
|
"home": "https://imsyy.top",
|
||||||
"github": "https://github.com/imsyy/SPlayer",
|
"github": "https://github.com/imsyy/SPlayer",
|
||||||
|
|||||||
15
src/App.vue
15
src/App.vue
@@ -10,7 +10,12 @@
|
|||||||
:native-scrollbar="false"
|
:native-scrollbar="false"
|
||||||
embedded
|
embedded
|
||||||
>
|
>
|
||||||
<main ref="mainContent" class="main">
|
<main
|
||||||
|
ref="mainContent"
|
||||||
|
class="main"
|
||||||
|
id="main"
|
||||||
|
:class="[music.showPlayList ? 'playlist' : null]"
|
||||||
|
>
|
||||||
<n-back-top
|
<n-back-top
|
||||||
:bottom="music.getPlaylists[0] && music.showPlayBar ? 100 : 40"
|
:bottom="music.getPlaylists[0] && music.showPlayBar ? 100 : 40"
|
||||||
style="transition: all 0.3s"
|
style="transition: all 0.3s"
|
||||||
@@ -223,6 +228,14 @@ onMounted(() => {
|
|||||||
.main {
|
.main {
|
||||||
max-width: 1400px;
|
max-width: 1400px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
div:nth-of-type(2) {
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
&.playlist {
|
||||||
|
div:nth-of-type(2) {
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,12 @@
|
|||||||
<img
|
<img
|
||||||
class="musicPackage"
|
class="musicPackage"
|
||||||
v-if="commentData.user.vipRights?.redVipAnnualCount > 0"
|
v-if="commentData.user.vipRights?.redVipAnnualCount > 0"
|
||||||
:src="commentData.user.vipRights.musicPackage.iconUrl"
|
:src="
|
||||||
|
commentData.user.vipRights.musicPackage.iconUrl.replace(
|
||||||
|
/^http:/,
|
||||||
|
'https:'
|
||||||
|
)
|
||||||
|
"
|
||||||
alt="redVipAnnualCount"
|
alt="redVipAnnualCount"
|
||||||
title="网易音乐人"
|
title="网易音乐人"
|
||||||
/>
|
/>
|
||||||
@@ -25,7 +30,12 @@
|
|||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
v-if="commentData.user.vipRights.associator"
|
v-if="commentData.user.vipRights.associator"
|
||||||
:src="commentData.user.vipRights.associator.iconUrl"
|
:src="
|
||||||
|
commentData.user.vipRights.associator.iconUrl.replace(
|
||||||
|
/^http:/,
|
||||||
|
'https:'
|
||||||
|
)
|
||||||
|
"
|
||||||
alt="associator"
|
alt="associator"
|
||||||
title="黑胶会员"
|
title="黑胶会员"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,178 +0,0 @@
|
|||||||
<template>
|
|
||||||
<CollapseTransition easing="ease-in-out">
|
|
||||||
<n-card
|
|
||||||
title="播放列表"
|
|
||||||
closable
|
|
||||||
class="playlistModel"
|
|
||||||
v-show="music.showPlayList && music.getPlaylists.length"
|
|
||||||
:header-style="{
|
|
||||||
padding: '12px 16px',
|
|
||||||
fontSize: '16px',
|
|
||||||
backgroundColor: 'var(--n-border-color)',
|
|
||||||
borderRadius: '8px',
|
|
||||||
}"
|
|
||||||
:content-style="{
|
|
||||||
padding: '0',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
}"
|
|
||||||
@close="music.showPlayList = false"
|
|
||||||
@click.stop
|
|
||||||
>
|
|
||||||
<n-scrollbar>
|
|
||||||
<n-card
|
|
||||||
hoverable
|
|
||||||
:class="
|
|
||||||
index == music.persistData.playSongIndex ? 'songs play' : 'songs'
|
|
||||||
"
|
|
||||||
:id="'playlist' + index"
|
|
||||||
:content-style="{
|
|
||||||
padding: '8px',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
}"
|
|
||||||
v-for="(item, index) in music.getPlaylists"
|
|
||||||
:key="item"
|
|
||||||
@click="changeIndex(index)"
|
|
||||||
>
|
|
||||||
<div class="left">
|
|
||||||
<div class="num">{{ index + 1 }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="right">
|
|
||||||
<div class="name text-hidden">{{ item.name }}</div>
|
|
||||||
<AllArtists class="text-hidden" :artistsData="item.artist" />
|
|
||||||
<n-icon
|
|
||||||
class="remove"
|
|
||||||
size="18"
|
|
||||||
:component="DeleteFour"
|
|
||||||
@click.stop="music.removeSong(index)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</n-card>
|
|
||||||
</n-scrollbar>
|
|
||||||
</n-card>
|
|
||||||
</CollapseTransition>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { musicStore } from "@/store";
|
|
||||||
import { DeleteFour } from "@icon-park/vue-next";
|
|
||||||
import AllArtists from "./AllArtists.vue";
|
|
||||||
import CollapseTransition from "@ivanv/vue-collapse-transition/src/CollapseTransition.vue";
|
|
||||||
|
|
||||||
const music = musicStore();
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
// 点击外部区域关闭播放列表
|
|
||||||
document.addEventListener("click", () => {
|
|
||||||
music.showPlayList = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 改变播放索引
|
|
||||||
const changeIndex = (index) => {
|
|
||||||
music.persistData.playSongIndex = index;
|
|
||||||
music.setPlayState(true);
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.playlistModel {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 76px;
|
|
||||||
min-width: 300px;
|
|
||||||
right: 0;
|
|
||||||
border-radius: 8px;
|
|
||||||
border-top: none;
|
|
||||||
box-shadow: var(--n-box-shadow);
|
|
||||||
:deep(.n-card__content) {
|
|
||||||
.n-scrollbar {
|
|
||||||
max-height: 70vh;
|
|
||||||
.n-scrollbar-content {
|
|
||||||
padding: 12px;
|
|
||||||
.songs {
|
|
||||||
border-radius: 8px;
|
|
||||||
cursor: pointer;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
transition: all 0.3s;
|
|
||||||
&:nth-last-of-type(1) {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
&:active {
|
|
||||||
transform: scale(0.98);
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
.n-card__content {
|
|
||||||
.right {
|
|
||||||
.remove {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.play {
|
|
||||||
background-color: $mainSecondaryColor;
|
|
||||||
border-color: $mainColor;
|
|
||||||
a,
|
|
||||||
span,
|
|
||||||
div,
|
|
||||||
.n-icon {
|
|
||||||
color: $mainColor;
|
|
||||||
}
|
|
||||||
.right {
|
|
||||||
.remove {
|
|
||||||
color: $mainColor;
|
|
||||||
&:hover {
|
|
||||||
background-color: var(--n-action-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.left {
|
|
||||||
width: 30px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
margin-right: 12px;
|
|
||||||
}
|
|
||||||
.right {
|
|
||||||
flex: 1;
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: center;
|
|
||||||
padding-right: 42px;
|
|
||||||
.name {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
.artists {
|
|
||||||
opacity: 0.8;
|
|
||||||
font-size: 13px;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
.remove {
|
|
||||||
position: absolute;
|
|
||||||
border-radius: 8px;
|
|
||||||
right: 0;
|
|
||||||
opacity: 0;
|
|
||||||
transition: all 0.3s;
|
|
||||||
color: #999;
|
|
||||||
padding: 6px;
|
|
||||||
&:hover {
|
|
||||||
color: $mainColor;
|
|
||||||
background-color: var(--n-border-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.n-scrollbar-rail {
|
|
||||||
width: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
223
src/components/DataModel/PlayListDrawer.vue
Normal file
223
src/components/DataModel/PlayListDrawer.vue
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
<template>
|
||||||
|
<n-drawer
|
||||||
|
class="playlist-drawer"
|
||||||
|
v-model:show="playListShow"
|
||||||
|
:z-index="2000"
|
||||||
|
:width="400"
|
||||||
|
:trap-focus="false"
|
||||||
|
:block-scroll="false"
|
||||||
|
placement="right"
|
||||||
|
to="#main"
|
||||||
|
@after-leave="music.showPlayList = false"
|
||||||
|
@mask-click="music.showPlayList = false"
|
||||||
|
>
|
||||||
|
<n-drawer-content title="播放列表" :native-scrollbar="false" closable>
|
||||||
|
<n-card
|
||||||
|
hoverable
|
||||||
|
:class="
|
||||||
|
index === music.persistData.playSongIndex ? 'songs play' : 'songs'
|
||||||
|
"
|
||||||
|
:id="'playlist' + index"
|
||||||
|
:content-style="{
|
||||||
|
padding: '8px',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
}"
|
||||||
|
v-for="(item, index) in music.getPlaylists"
|
||||||
|
:key="item"
|
||||||
|
@click="changeIndex(index)"
|
||||||
|
>
|
||||||
|
<div class="left">
|
||||||
|
<div v-if="index !== music.persistData.playSongIndex" class="num">
|
||||||
|
{{ index + 1 }}
|
||||||
|
</div>
|
||||||
|
<div v-else class="bar">
|
||||||
|
<div
|
||||||
|
v-for="item in 3"
|
||||||
|
:key="item"
|
||||||
|
class="line"
|
||||||
|
:style="{
|
||||||
|
animationDelay: `0.${item * item}s`,
|
||||||
|
animationPlayState: music.getPlayState ? 'running' : 'paused',
|
||||||
|
height: `${Math.floor(Math.random() * 7) + 10}px`,
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
<div class="name text-hidden">{{ item.name }}</div>
|
||||||
|
<AllArtists class="text-hidden" :artistsData="item.artist" />
|
||||||
|
<n-icon
|
||||||
|
class="remove"
|
||||||
|
size="18"
|
||||||
|
:component="DeleteFour"
|
||||||
|
@click.stop="music.removeSong(index)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</n-card>
|
||||||
|
</n-drawer-content>
|
||||||
|
</n-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { musicStore } from "@/store";
|
||||||
|
import { DeleteFour } from "@icon-park/vue-next";
|
||||||
|
import AllArtists from "@/components/DataList/AllArtists.vue";
|
||||||
|
|
||||||
|
const music = musicStore();
|
||||||
|
|
||||||
|
// 播放列表显隐
|
||||||
|
const playListShow = ref(false);
|
||||||
|
|
||||||
|
// 改变播放索引
|
||||||
|
const changeIndex = (index) => {
|
||||||
|
music.persistData.playSongIndex = index;
|
||||||
|
music.setPlayState(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听播放列表显隐
|
||||||
|
const timeOut = ref(null);
|
||||||
|
watch(
|
||||||
|
() => music.showPlayList,
|
||||||
|
(val) => {
|
||||||
|
playListShow.value = val;
|
||||||
|
nextTick(() => {
|
||||||
|
if (val && music.getPlaylists[0]) {
|
||||||
|
const el = document.getElementById(
|
||||||
|
`playlist${music.persistData.playSongIndex}`
|
||||||
|
);
|
||||||
|
if (el) {
|
||||||
|
timeOut.value = setTimeout(() => {
|
||||||
|
el.scrollIntoView({
|
||||||
|
behavior: "smooth",
|
||||||
|
block: "center",
|
||||||
|
});
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clearTimeout(timeOut.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
playListShow.value = music.showPlayList;
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
clearTimeout(timeOut.value);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.playlist-drawer {
|
||||||
|
.songs {
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
&:nth-last-of-type(1) {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
.n-card__content {
|
||||||
|
.right {
|
||||||
|
.remove {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.play {
|
||||||
|
background-color: $mainSecondaryColor;
|
||||||
|
border-color: $mainColor;
|
||||||
|
a,
|
||||||
|
span,
|
||||||
|
div,
|
||||||
|
.n-icon {
|
||||||
|
color: $mainColor;
|
||||||
|
}
|
||||||
|
:deep(span) {
|
||||||
|
color: $mainColor;
|
||||||
|
}
|
||||||
|
.right {
|
||||||
|
.remove {
|
||||||
|
color: $mainColor;
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--n-action-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.left {
|
||||||
|
width: 30px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-right: 12px;
|
||||||
|
.bar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
align-items: flex-end;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
.line {
|
||||||
|
width: 3px;
|
||||||
|
height: 16px;
|
||||||
|
background-color: $mainColor;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
animation: lineMove 1s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
@keyframes lineMove {
|
||||||
|
0% {
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.right {
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: center;
|
||||||
|
padding-right: 42px;
|
||||||
|
.name {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.artists {
|
||||||
|
opacity: 0.8;
|
||||||
|
font-size: 13px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.remove {
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 8px;
|
||||||
|
right: 0;
|
||||||
|
opacity: 0;
|
||||||
|
transition: all 0.3s;
|
||||||
|
color: #999;
|
||||||
|
padding: 6px;
|
||||||
|
&:hover {
|
||||||
|
color: $mainColor;
|
||||||
|
background-color: var(--n-border-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -18,11 +18,7 @@
|
|||||||
>
|
>
|
||||||
<router-link class="link" to="/discover">发现</router-link>
|
<router-link class="link" to="/discover">发现</router-link>
|
||||||
</n-dropdown>
|
</n-dropdown>
|
||||||
<n-dropdown
|
<n-dropdown trigger="hover" :options="userOptions" @select="menuSelect">
|
||||||
trigger="hover"
|
|
||||||
:options="userOptions"
|
|
||||||
@select="menuSelect"
|
|
||||||
>
|
|
||||||
<router-link class="link" to="/user">我的</router-link>
|
<router-link class="link" to="/user">我的</router-link>
|
||||||
</n-dropdown>
|
</n-dropdown>
|
||||||
</div>
|
</div>
|
||||||
@@ -44,7 +40,8 @@
|
|||||||
size="small"
|
size="small"
|
||||||
:src="
|
:src="
|
||||||
user.getUserData.avatarUrl
|
user.getUserData.avatarUrl
|
||||||
? user.getUserData.avatarUrl
|
? user.getUserData.avatarUrl.replace(/^http:/, 'https:') +
|
||||||
|
'?param=60y60'
|
||||||
: '/images/ico/user-filling.svg'
|
: '/images/ico/user-filling.svg'
|
||||||
"
|
"
|
||||||
:img-props="{ class: 'avatarImg' }"
|
:img-props="{ class: 'avatarImg' }"
|
||||||
@@ -109,7 +106,8 @@ const userDataRender = () => {
|
|||||||
round: true,
|
round: true,
|
||||||
style: "margin-right: 12px",
|
style: "margin-right: 12px",
|
||||||
src: user.userLogin
|
src: user.userLogin
|
||||||
? user.getUserData.avatarUrl
|
? user.getUserData.avatarUrl.replace(/^http:/, "https:") +
|
||||||
|
"?param=60y60"
|
||||||
: "/images/ico/user-filling.svg",
|
: "/images/ico/user-filling.svg",
|
||||||
fallbackSrc: "/images/ico/user-filling.svg",
|
fallbackSrc: "/images/ico/user-filling.svg",
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ const lrcAllLeave = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 全屏切换
|
// 全屏切换
|
||||||
|
const timeOut = ref(null);
|
||||||
const screenfullIcon = shallowRef(FullscreenRound);
|
const screenfullIcon = shallowRef(FullscreenRound);
|
||||||
const screenfullChange = () => {
|
const screenfullChange = () => {
|
||||||
if (screenfull.isEnabled) {
|
if (screenfull.isEnabled) {
|
||||||
@@ -189,7 +190,7 @@ const screenfullChange = () => {
|
|||||||
? FullscreenRound
|
? FullscreenRound
|
||||||
: FullscreenExitRound;
|
: FullscreenExitRound;
|
||||||
// 延迟一段时间执行列表滚动
|
// 延迟一段时间执行列表滚动
|
||||||
setTimeout(() => {
|
timeOut.value = setTimeout(() => {
|
||||||
lrcMouseStatus.value = false;
|
lrcMouseStatus.value = false;
|
||||||
lyricsScroll(music.getPlaySongLyricIndex);
|
lyricsScroll(music.getPlaySongLyricIndex);
|
||||||
}, 500);
|
}, 500);
|
||||||
@@ -248,6 +249,10 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
clearTimeout(timeOut.value);
|
||||||
|
});
|
||||||
|
|
||||||
// 监听页面是否打开
|
// 监听页面是否打开
|
||||||
watch(
|
watch(
|
||||||
() => music.showBigPlayer,
|
() => music.showBigPlayer,
|
||||||
@@ -256,6 +261,7 @@ watch(
|
|||||||
console.log("开启播放器", music.getPlaySongLyricIndex);
|
console.log("开启播放器", music.getPlaySongLyricIndex);
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
lyricsScroll(music.getPlaySongLyricIndex);
|
lyricsScroll(music.getPlaySongLyricIndex);
|
||||||
|
music.showPlayList = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,11 @@
|
|||||||
<div
|
<div
|
||||||
class="countdown"
|
class="countdown"
|
||||||
:style="{ animationPlayState: music.getPlayState ? 'running' : 'paused' }"
|
:style="{ animationPlayState: music.getPlayState ? 'running' : 'paused' }"
|
||||||
v-if="remainingPoint <= 2 && totalDuration > 3"
|
v-if="
|
||||||
|
remainingPoint <= 2 &&
|
||||||
|
totalDuration > 3 &&
|
||||||
|
music.getPlaySongLyric.lrc[0]
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<span class="point" :class="remainingPoint > 2 ? 'hidden' : null">●</span>
|
<span class="point" :class="remainingPoint > 2 ? 'hidden' : null">●</span>
|
||||||
<span class="point" :class="remainingPoint > 1 ? 'hidden' : null">●</span>
|
<span class="point" :class="remainingPoint > 1 ? 'hidden' : null">●</span>
|
||||||
@@ -30,9 +34,11 @@ const totalDuration = ref(
|
|||||||
watch(
|
watch(
|
||||||
() => music.getPlaySongTime.currentTime,
|
() => music.getPlaySongTime.currentTime,
|
||||||
(val) => {
|
(val) => {
|
||||||
const remainingTime = totalDuration.value - val - 0.5;
|
if (music.getPlaySongLyric.lrc[0]) {
|
||||||
const progress = 1 - remainingTime / totalDuration.value;
|
const remainingTime = totalDuration.value - val - 0.5;
|
||||||
remainingPoint.value = Number(Math.floor(3 * progress));
|
const progress = 1 - remainingTime / totalDuration.value;
|
||||||
|
remainingPoint.value = Number(Math.floor(3 * progress));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -40,10 +46,12 @@ watch(
|
|||||||
watch(
|
watch(
|
||||||
() => music.getPlaySongLyric?.lrc,
|
() => music.getPlaySongLyric?.lrc,
|
||||||
(val) => {
|
(val) => {
|
||||||
totalDuration.value = music.getPlaySongLyric.hasYrc
|
if (music.getPlaySongLyric.lrc[0]) {
|
||||||
? music.getPlaySongLyric?.yrc[0].time
|
totalDuration.value = music.getPlaySongLyric.hasYrc
|
||||||
: val[0].time;
|
? music.getPlaySongLyric?.yrc[0].time
|
||||||
remainingPoint.value = 0;
|
: val[0].time;
|
||||||
|
remainingPoint.value = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -168,10 +168,8 @@
|
|||||||
@click="music.setPlaySongMode()"
|
@click="music.setPlaySongMode()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="playlist">
|
<div :class="music.showPlayList ? 'playlist open' : 'playlist'">
|
||||||
<PlayList />
|
|
||||||
<n-icon
|
<n-icon
|
||||||
class="next"
|
|
||||||
size="30"
|
size="30"
|
||||||
:component="PlaylistPlayRound"
|
:component="PlaylistPlayRound"
|
||||||
@click.stop="music.showPlayList = !music.showPlayList"
|
@click.stop="music.showPlayList = !music.showPlayList"
|
||||||
@@ -215,7 +213,11 @@
|
|||||||
:src="music.getPlaySongLink"
|
:src="music.getPlaySongLink"
|
||||||
></audio>
|
></audio>
|
||||||
</n-card>
|
</n-card>
|
||||||
|
<!-- 播放列表 -->
|
||||||
|
<PlayListDrawer ref="PlayListDrawerRef" />
|
||||||
|
<!-- 添加到歌单 -->
|
||||||
<AddPlaylist ref="addPlayListRef" />
|
<AddPlaylist ref="addPlayListRef" />
|
||||||
|
<!-- 播放器 -->
|
||||||
<BigPlayer />
|
<BigPlayer />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -249,8 +251,8 @@ import { storeToRefs } from "pinia";
|
|||||||
import { musicStore, settingStore } from "@/store";
|
import { musicStore, settingStore } from "@/store";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import AddPlaylist from "@/components/DataModel/AddPlaylist.vue";
|
import AddPlaylist from "@/components/DataModel/AddPlaylist.vue";
|
||||||
|
import PlayListDrawer from "@/components/DataModel/PlayListDrawer.vue";
|
||||||
import AllArtists from "@/components/DataList/AllArtists.vue";
|
import AllArtists from "@/components/DataList/AllArtists.vue";
|
||||||
import PlayList from "@/components/DataList/PlayList.vue";
|
|
||||||
import BigPlayer from "./BigPlayer.vue";
|
import BigPlayer from "./BigPlayer.vue";
|
||||||
import debounce from "@/utils/debounce";
|
import debounce from "@/utils/debounce";
|
||||||
|
|
||||||
@@ -259,6 +261,7 @@ const setting = settingStore();
|
|||||||
const music = musicStore();
|
const music = musicStore();
|
||||||
const { persistData } = storeToRefs(music);
|
const { persistData } = storeToRefs(music);
|
||||||
const addPlayListRef = ref(null);
|
const addPlayListRef = ref(null);
|
||||||
|
const PlayListDrawerRef = ref(null);
|
||||||
|
|
||||||
// 重试次数
|
// 重试次数
|
||||||
const testNumber = ref(0);
|
const testNumber = ref(0);
|
||||||
@@ -562,7 +565,7 @@ watch(
|
|||||||
bottom: -90px;
|
bottom: -90px;
|
||||||
left: 0;
|
left: 0;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
z-index: 2;
|
z-index: 2004;
|
||||||
&.show {
|
&.show {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
@@ -606,23 +609,6 @@ watch(
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
max-width: 1400px;
|
max-width: 1400px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
@media (max-width: 620px) {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
.data {
|
|
||||||
.time {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.control {
|
|
||||||
margin-left: auto;
|
|
||||||
.prev,
|
|
||||||
.next {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.data {
|
.data {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -794,6 +780,12 @@ watch(
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
&.open {
|
||||||
|
.n-icon {
|
||||||
|
background-color: $mainColor;
|
||||||
|
color: var(--n-color-embedded);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.volume {
|
.volume {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -810,6 +802,26 @@ watch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@media (max-width: 620px) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
.data {
|
||||||
|
.time {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.control {
|
||||||
|
margin-left: auto;
|
||||||
|
.prev,
|
||||||
|
.next {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.play-state {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -328,6 +328,14 @@ watch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 监听播放列表显隐
|
||||||
|
watch(
|
||||||
|
() => music.showPlayList,
|
||||||
|
(val) => {
|
||||||
|
if (val) inputActive.value = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@@ -339,11 +347,17 @@ watch(
|
|||||||
.input {
|
.input {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
|
@media (max-width: 450px) {
|
||||||
|
width: 40px;
|
||||||
|
}
|
||||||
&.focus {
|
&.focus {
|
||||||
width: 280px;
|
width: 280px;
|
||||||
:deep(input) {
|
:deep(input) {
|
||||||
color: $mainColor;
|
color: $mainColor;
|
||||||
}
|
}
|
||||||
|
@media (max-width: 450px) {
|
||||||
|
width: 60vw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.list {
|
.list {
|
||||||
@@ -353,10 +367,34 @@ watch(
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
width: 280px;
|
width: 280px;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
|
|
||||||
|
@media (max-width: 450px) {
|
||||||
|
padding-top: 12px;
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
top: 58px;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
border-radius: 0 0 8px 8px;
|
||||||
|
&::after {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
content: "收起";
|
||||||
|
padding: 4px 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
background-color: #efefef;
|
||||||
|
border-radius: 0 0 0 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
:deep(.n-scrollbar) {
|
:deep(.n-scrollbar) {
|
||||||
max-height: 80vh;
|
max-height: 80vh;
|
||||||
|
@media (max-width: 450px) {
|
||||||
|
max-height: calc(100vh - 130px);
|
||||||
|
min-height: calc(100vh - 130px);
|
||||||
|
}
|
||||||
.n-scrollbar-rail {
|
.n-scrollbar-rail {
|
||||||
width: 0;
|
width: 4px;
|
||||||
}
|
}
|
||||||
.n-scrollbar-content {
|
.n-scrollbar-content {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
|
|||||||
@@ -47,21 +47,7 @@ body,
|
|||||||
}
|
}
|
||||||
.n-card-header {
|
.n-card-header {
|
||||||
.n-card-header__main {
|
.n-card-header__main {
|
||||||
// font-weight: bold;
|
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
// position: relative;
|
|
||||||
// padding-left: 6px;
|
|
||||||
// display: flex;
|
|
||||||
// align-items: center;
|
|
||||||
// &::before {
|
|
||||||
// content: "";
|
|
||||||
// position: absolute;
|
|
||||||
// left: -4px;
|
|
||||||
// width: 4px;
|
|
||||||
// height: 80%;
|
|
||||||
// border-radius: 4px;
|
|
||||||
// background-color: $mainColor;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.n-card__content {
|
.n-card__content {
|
||||||
@@ -73,10 +59,13 @@ body,
|
|||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.n-modal-body-wrapper {
|
.n-modal-container {
|
||||||
.n-modal-mask {
|
z-index: 2006 !important;
|
||||||
-webkit-backdrop-filter: blur(16px);
|
.n-modal-body-wrapper {
|
||||||
backdrop-filter: blur(16px);
|
.n-modal-mask {
|
||||||
|
-webkit-backdrop-filter: blur(16px);
|
||||||
|
backdrop-filter: blur(16px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +101,18 @@ body,
|
|||||||
border-radius: 8px !important;
|
border-radius: 8px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Drawer
|
||||||
|
.n-drawer-container {
|
||||||
|
.n-drawer {
|
||||||
|
border-radius: 8px 0 0 8px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
@media (max-width: 450px) {
|
||||||
|
width: 100% !important;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 文本超出隐藏
|
// 文本超出隐藏
|
||||||
.text-hidden {
|
.text-hidden {
|
||||||
display: -webkit-box !important;
|
display: -webkit-box !important;
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ watch(
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
$setSiteTitle("全局设置");
|
$setSiteTitle("全局设置");
|
||||||
|
if ($mainContent) $mainContent.scrollIntoView({ behavior: "smooth" });
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
round
|
round
|
||||||
:src="
|
:src="
|
||||||
user.getUserData.avatarUrl
|
user.getUserData.avatarUrl
|
||||||
? user.getUserData.avatarUrl
|
? user.getUserData.avatarUrl.replace(/^http:/, 'https:')
|
||||||
: '/images/ico/user-filling.svg'
|
: '/images/ico/user-filling.svg'
|
||||||
"
|
"
|
||||||
fallback-src="/images/ico/user-filling.svg"
|
fallback-src="/images/ico/user-filling.svg"
|
||||||
|
|||||||
Reference in New Issue
Block a user