feat: 优化样式,添加播放列表

This commit is contained in:
alger
2023-12-27 14:39:52 +08:00
parent 4dde40ac60
commit 70139e3ca4
6 changed files with 119 additions and 48 deletions
+52 -16
View File
@@ -1,18 +1,18 @@
<template> <template>
<div class="recommend-music-list-item"> <div class="song-item" :class="{'song-mini': mini}">
<n-image <n-image
:src="getImgUrl( item.picUrl, '40y40')" :src="getImgUrl( item.picUrl, '40y40')"
class="recommend-music-list-item-img" class="song-item-img"
lazy lazy
preview-disabled preview-disabled
/> />
<div class="recommend-music-list-item-content"> <div class="song-item-content">
<div class="recommend-music-list-item-content-title"> <div class="song-item-content-title">
<n-ellipsis class="text-ellipsis" line-clamp="1">{{ <n-ellipsis class="text-ellipsis" line-clamp="1">{{
item.name item.name
}}</n-ellipsis> }}</n-ellipsis>
</div> </div>
<div class="recommend-music-list-item-content-name"> <div class="song-item-content-name">
<n-ellipsis class="text-ellipsis" line-clamp="1"> <n-ellipsis class="text-ellipsis" line-clamp="1">
<span <span
v-for="(artists, artistsindex) in item.song.artists" v-for="(artists, artistsindex) in item.song.artists"
@@ -25,12 +25,12 @@
</n-ellipsis> </n-ellipsis>
</div> </div>
</div> </div>
<div class="recommend-music-list-item-operating"> <div class="song-item-operating">
<div class="recommend-music-list-item-operating-like"> <div class="song-item-operating-like">
<i class="iconfont icon-likefill"></i> <i class="iconfont icon-likefill"></i>
</div> </div>
<div <div
class="recommend-music-list-item-operating-play bg-black" class="song-item-operating-play bg-black"
:class="isPlaying ? 'bg-green-600' : ''" :class="isPlaying ? 'bg-green-600' : ''"
@click="playMusicEvent(item)" @click="playMusicEvent(item)"
> >
@@ -44,14 +44,13 @@
<script lang="ts" setup> <script lang="ts" setup>
import { useStore } from 'vuex' import { useStore } from 'vuex'
import type { SongResult } from '@/type/music' import type { SongResult } from '@/type/music'
import { computed } from 'vue'
import { getImgUrl } from '@/utils' import { getImgUrl } from '@/utils'
const props = defineProps({ const props = withDefaults(defineProps<{
item: { item: SongResult
type: Object, mini?: boolean
required: true, }>(), {
}, mini: false
}) })
const store = useStore() const store = useStore()
@@ -77,10 +76,16 @@ const playMusicEvent = (item: any) => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
// 配置文字不可选中
.text-ellipsis { .text-ellipsis {
width: 100%; width: 100%;
} }
.recommend-music-list-item { .song-item {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
@apply rounded-3xl p-3 flex items-center hover:bg-gray-800 transition; @apply rounded-3xl p-3 flex items-center hover:bg-gray-800 transition;
&-img { &-img {
@apply w-12 h-12 rounded-2xl mr-4; @apply w-12 h-12 rounded-2xl mr-4;
@@ -96,7 +101,7 @@ const playMusicEvent = (item: any) => {
} }
} }
&-operating { &-operating {
@apply flex items-center pl-4 rounded-full border border-gray-700; @apply flex items-center pl-4 rounded-full border border-gray-700 ml-4;
background-color: #0d0d0d; background-color: #0d0d0d;
.iconfont { .iconfont {
@apply text-xl; @apply text-xl;
@@ -113,4 +118,35 @@ const playMusicEvent = (item: any) => {
} }
} }
} }
.song-mini{
@apply p-2 rounded-2xl;
.song-item{
@apply p-0;
&-img{
@apply w-10 h-10 mr-2;
}
&-content{
@apply flex-1;
&-title{
@apply text-sm;
}
&-name{
@apply text-xs;
}
}
&-operating{
@apply pl-2;
.iconfont{
@apply text-base;
}
&-like{
@apply mr-1;
}
&-play{
@apply w-8 h-8;
}
}
}
}
</style> </style>
+2 -3
View File
@@ -4,7 +4,7 @@
<div class="app-menu"> <div class="app-menu">
<div class="app-menu-header"> <div class="app-menu-header">
<div class="app-menu-logo"> <div class="app-menu-logo">
<img src="@/assets/logo.png" class="w-9 h-9 mt-2" alt="logo" /> <img src="/icon.png" class="w-9 h-9" alt="logo" />
</div> </div>
</div> </div>
<div class="app-menu-list"> <div class="app-menu-list">
@@ -24,7 +24,6 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, onMounted, ref, watch } from "@vue/runtime-core";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
const props = defineProps({ const props = defineProps({
isText: { isText: {
@@ -67,7 +66,7 @@ const iconStyle = (index: any) => {
<style lang="scss" scoped> <style lang="scss" scoped>
.app-menu { .app-menu {
@apply flex-col items-center justify-center p-6; @apply flex-col items-center justify-center px-6;
max-width: 100px; max-width: 100px;
} }
.app-menu-item-link, .app-menu-item-link,
+16 -6
View File
@@ -6,7 +6,7 @@
:drawer-style="{ backgroundColor: 'transparent' }" :drawer-style="{ backgroundColor: 'transparent' }"
> >
<div id="drawer-target"> <div id="drawer-target">
<div class="drawer-back" :style="{backgroundImage:`url(${getImgUrl(playMusic?.picUrl, '300y300')})`}"></div> <div class="drawer-back" :class="{'paused': !isPlaying}" :style="{backgroundImage:`url(${getImgUrl(playMusic?.picUrl, '300y300')})`}"></div>
<div class="music-img"> <div class="music-img">
<n-image <n-image
ref="PicImgRef" ref="PicImgRef"
@@ -26,7 +26,7 @@
</div> </div>
<n-layout <n-layout
class="music-lrc" class="music-lrc"
style="height: 550px" style="height: 55vh"
ref="lrcSider" ref="lrcSider"
:native-scrollbar="false" :native-scrollbar="false"
@mouseover="mouseOverLayout" @mouseover="mouseOverLayout"
@@ -43,9 +43,10 @@
</template> </template>
</n-layout> </n-layout>
<!-- 时间矫正 --> <!-- 时间矫正 -->
<div class="music-content-time"></div> <div class="music-content-time">
<n-button @click="reduceCorrectionTime(0.2)">-0.2</n-button> <n-button @click="reduceCorrectionTime(0.2)">-</n-button>
<n-button @click="addCorrectionTime(0.2)">+0.2</n-button> <n-button @click="addCorrectionTime(0.2)">+</n-button>
</div>
</div> </div>
</div> </div>
</n-drawer> </n-drawer>
@@ -54,7 +55,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { SongResult } from '@/type/music' import type { SongResult } from '@/type/music'
import { getImgUrl } from '@/utils' import { getImgUrl } from '@/utils'
import { computed, ref } from 'vue'
import { useStore } from 'vuex' import { useStore } from 'vuex'
import { import {
lrcArray, lrcArray,
@@ -83,6 +83,7 @@ const emit = defineEmits(['update:musicFull'])
// 播放的音乐信息 // 播放的音乐信息
const playMusic = computed(() => store.state.playMusic as SongResult) const playMusic = computed(() => store.state.playMusic as SongResult)
const isPlaying = computed(() => store.state.play as boolean)
// 获取歌词滚动dom // 获取歌词滚动dom
const lrcSider = ref<any>(null) const lrcSider = ref<any>(null)
const isMouse = ref(false) const isMouse = ref(false)
@@ -128,6 +129,10 @@ defineExpose({
animation: round 20s linear infinite; animation: round 20s linear infinite;
} }
.drawer-back.paused {
animation-play-state: paused;
}
#drawer-target { #drawer-target {
@apply top-0 left-0 absolute w-full h-full overflow-hidden rounded px-24 pt-24 pb-48 flex items-center; @apply top-0 left-0 absolute w-full h-full overflow-hidden rounded px-24 pt-24 pb-48 flex items-center;
backdrop-filter: blur(20px); backdrop-filter: blur(20px);
@@ -156,6 +161,11 @@ defineExpose({
} }
} }
.music-content-time{
display: none;
@apply flex justify-center items-center;
}
.music-lrc { .music-lrc {
background-color: inherit; background-color: inherit;
width: 500px; width: 500px;
+44 -17
View File
@@ -56,24 +56,42 @@
></n-slider> ></n-slider>
</div> </div>
<div class="audio-button"> <div class="audio-button">
<n-tooltip trigger="hover"> <!-- <n-tooltip trigger="hover" :z-index="9999999">
<template #trigger> <template #trigger>
<i class="iconfont icon-likefill"></i> <i class="iconfont icon-likefill"></i>
</template> </template>
喜欢 喜欢
</n-tooltip> </n-tooltip> -->
<!-- <n-tooltip trigger="hover"> <!-- <n-tooltip trigger="hover" :z-index="9999999">
<template #trigger> <template #trigger>
<i class="iconfont icon-Play" @click="parsingMusic"></i> <i class="iconfont icon-Play" @click="parsingMusic"></i>
</template> </template>
解析播放 解析播放
</n-tooltip> --> </n-tooltip> -->
<n-tooltip trigger="hover"> <!-- <n-tooltip trigger="hover" :z-index="9999999">
<template #trigger> <template #trigger>
<i class="iconfont icon-full" @click="setMusicFull"></i> <i class="iconfont icon-full" @click="setMusicFull"></i>
</template> </template>
歌词 歌词
</n-tooltip> </n-tooltip> -->
<n-popover trigger="click" :z-index="99999999" content-class="music-play" raw :show-arrow="false" :delay="200">
<template #trigger>
<n-tooltip trigger="manual" :z-index="9999999">
<template #trigger>
<i class="iconfont icon-list"></i>
</template>
播放列表
</n-tooltip>
</template>
<div class="music-play-list">
<div class="music-play-list-back"></div>
<n-scrollbar>
<div class="music-play-list-content">
<song-item v-for="(item, index) in playList" :key="item.id" :item="item" mini></song-item>
</div>
</n-scrollbar>
</div>
</n-popover>
</div> </div>
<!-- 播放音乐 --> <!-- 播放音乐 -->
@@ -83,7 +101,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { SongResult } from '@/type/music' import type { SongResult } from '@/type/music'
import { secondToMinute, getImgUrl } from '@/utils' import { secondToMinute, getImgUrl } from '@/utils'
import { computed, onMounted, ref, watch } from 'vue'
import { useStore } from 'vuex' import { useStore } from 'vuex'
import { setAnimationClass } from '@/utils' import { setAnimationClass } from '@/utils'
import { import {
@@ -92,6 +109,7 @@ import {
allTime allTime
} from '@/hooks/MusicHook' } from '@/hooks/MusicHook'
import MusicFull from './MusicFull.vue' import MusicFull from './MusicFull.vue'
import SongItem from '@/components/common/SongItem.vue'
const store = useStore() const store = useStore()
@@ -100,6 +118,8 @@ const playMusic = computed(() => store.state.playMusic as SongResult)
// 是否播放 // 是否播放
const play = computed(() => store.state.play as boolean) const play = computed(() => store.state.play as boolean)
const playList = computed(() => store.state.playList as SongResult[])
const audio = { const audio = {
value: document.querySelector('#MusicAudio') as HTMLAudioElement value: document.querySelector('#MusicAudio') as HTMLAudioElement
} }
@@ -248,13 +268,6 @@ const setMusicFull = () => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.musicPage-enter-active {
animation: fadeInUp 0.4s ease-in-out;
}
.musicPage-leave-active {
animation: fadeOutDown 0.4s ease-in-out;
}
.text-ellipsis { .text-ellipsis {
width: 100%; width: 100%;
@@ -262,11 +275,10 @@ const setMusicFull = () => {
.music-play-bar { .music-play-bar {
@apply h-20 w-full absolute bottom-0 left-0 flex items-center rounded-t-2xl overflow-hidden box-border px-6 py-2; @apply h-20 w-full absolute bottom-0 left-0 flex items-center rounded-t-2xl overflow-hidden box-border px-6 py-2;
z-index: 99999999; z-index: 9999;
backdrop-filter: blur(20px); backdrop-filter: blur(20px);
background-color: rgba(0, 0, 0, 0.747); box-shadow: 0px 0px 8px 0px rgba(203, 203, 203, 0.238);
background-color: rgba(0, 0, 0, 0.747); .music-content {
.music-content {
width: 140px; width: 140px;
@apply ml-4; @apply ml-4;
@@ -332,4 +344,19 @@ const setMusicFull = () => {
@apply text-2xl hover:text-green-500 transition cursor-pointer m-4; @apply text-2xl hover:text-green-500 transition cursor-pointer m-4;
} }
} }
.music-play{
&-list{
height: 50vh;
@apply relative rounded-3xl overflow-hidden;
&-back{
backdrop-filter: blur(20px);
@apply absolute top-0 left-0 w-full h-full bg-gray-800 bg-opacity-75;
}
&-content{
padding: 10px;
}
}
}
</style> </style>
+4 -5
View File
@@ -2,7 +2,7 @@
<div class="search-box flex"> <div class="search-box flex">
<div class="search-box-input flex-1"> <div class="search-box-input flex-1">
<n-input <n-input
size="large" size="medium"
round round
v-model:value="searchValue" v-model:value="searchValue"
:placeholder="hotSearchKeyword" :placeholder="hotSearchKeyword"
@@ -21,14 +21,14 @@
<n-avatar <n-avatar
class="ml-2 cursor-pointer" class="ml-2 cursor-pointer"
circle circle
size="large" size="medium"
:src="getImgUrl(store.state.user.avatarUrl)" :src="getImgUrl(store.state.user.avatarUrl)"
v-if="store.state.user" v-if="store.state.user"
/> />
<n-avatar <n-avatar
class="ml-2 cursor-pointer" class="ml-2 cursor-pointer"
circle circle
size="large" size="medium"
src="https://picsum.photos/200/300?random=1" src="https://picsum.photos/200/300?random=1"
@click="toLogin()" @click="toLogin()"
v-else v-else
@@ -40,7 +40,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import { getSearchKeyword, getHotSearch } from '@/api/home'; import { getSearchKeyword, getHotSearch } from '@/api/home';
import { getUserDetail, logout } from '@/api/login'; import { getUserDetail, logout } from '@/api/login';
import { onMounted, ref } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import request from '@/utils/request_mt' import request from '@/utils/request_mt'
@@ -157,7 +156,7 @@ const selectItem = async (key: any) => {
<style lang="scss" scoped> <style lang="scss" scoped>
.user-box { .user-box {
@apply ml-6 flex text-lg justify-center items-center rounded-full pl-3 border border-gray-600; @apply ml-4 flex text-lg justify-center items-center rounded-full pl-3 border border-gray-600;
background: #1a1a1a; background: #1a1a1a;
} }
+1 -1
View File
@@ -51,7 +51,7 @@ const drag = (event: HTMLElement) => {
<style scoped lang="scss"> <style scoped lang="scss">
#title-bar { #title-bar {
-webkit-app-region: drag; -webkit-app-region: drag;
@apply flex justify-between text-white px-6 py-3 select-none relative; @apply flex justify-between text-white px-6 py-2 select-none relative;
z-index: 9999999; z-index: 9999999;
} }