From 9431faf932a18abd93d68fa751531d5f175d6af0 Mon Sep 17 00:00:00 2001 From: alger Date: Sat, 22 Mar 2025 13:45:23 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20=E4=BC=98=E5=8C=96=E7=A7=BB?= =?UTF-8?q?=E5=8A=A8=E7=AB=AF=E5=92=8C=E7=BD=91=E9=A1=B5=E7=AB=AF=E6=95=88?= =?UTF-8?q?=E6=9E=9C=E5=92=8C=E4=BD=93=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat: #82 --- src/renderer/components/MusicList.vue | 1 + src/renderer/components/home/TopBanner.vue | 92 ++-- src/renderer/layout/AppLayout.vue | 16 +- src/renderer/layout/components/AppMenu.vue | 2 +- .../layout/components/MobilePlayBar.vue | 505 ++++++++++++++++++ src/renderer/layout/components/MusicFull.vue | 26 +- src/renderer/layout/components/PlayBar.vue | 2 +- src/renderer/store/modules/settings.ts | 3 +- src/renderer/utils/index.ts | 23 +- src/renderer/views/set/index.vue | 5 +- 10 files changed, 616 insertions(+), 59 deletions(-) create mode 100644 src/renderer/layout/components/MobilePlayBar.vue diff --git a/src/renderer/components/MusicList.vue b/src/renderer/components/MusicList.vue index ef8a834..92559c5 100644 --- a/src/renderer/components/MusicList.vue +++ b/src/renderer/components/MusicList.vue @@ -439,6 +439,7 @@ onUnmounted(() => { .music-content { @apply flex-col; + width: 100vw !important; } .music-info { diff --git a/src/renderer/components/home/TopBanner.vue b/src/renderer/components/home/TopBanner.vue index be390fe..4992c97 100644 --- a/src/renderer/components/home/TopBanner.vue +++ b/src/renderer/components/home/TopBanner.vue @@ -11,7 +11,7 @@ >
- {{ t('comp.userPlayList.title', { name: userStore.user?.nickname }) }} + {{ t('comp.userPlayList.title', { name: userStore.user?.nickname }) }}
{{ item.name }}
-
{{ t('common.songCount', { count: item.trackCount }) }}
+
+ {{ t('common.songCount', { count: item.trackCount }) }} +
@@ -96,7 +98,9 @@ {{ t('common.songCount', { count: item.musicSize }) }}
-
{{ item.name }}
+
+ {{ item.name }} +
@@ -141,7 +145,13 @@ import { IDayRecommend } from '@/type/day_recommend'; import { Playlist } from '@/type/list'; import type { IListDetail } from '@/type/listDetail'; import type { IHotSinger } from '@/type/singer'; -import { getImgUrl, setAnimationClass, setAnimationDelay, setBackgroundImg } from '@/utils'; +import { + getImgUrl, + isMobile, + setAnimationClass, + setAnimationDelay, + setBackgroundImg +} from '@/utils'; const userStore = useUserStore(); @@ -168,15 +178,18 @@ const playlistDetail = ref(null); * @returns 样式字符串 */ const getCarouselItemStyle = ( - index: number, - delayStep: number, - totalItems: number = 5, + index: number, + delayStep: number, + totalItems: number = 5, maxWidth?: number ) => { + if (isMobile.value) { + return 'width: 30%;'; + } const animationDelay = setAnimationDelay(index, delayStep); const width = `calc((100% / ${totalItems}) - 16px)`; const maxWidthStyle = maxWidth ? `max-width: ${maxWidth}px;` : ''; - + return `${animationDelay}; width: ${width}; ${maxWidthStyle}`; }; @@ -186,11 +199,14 @@ const getCarouselItemStyle = ( * @returns 样式字符串 */ const getCarouselItemStyleForPlaylist = (playlistCount: number) => { + if (isMobile.value) { + return 'width: 100%;'; + } const animationDelay = setAnimationDelay(1, 100); let width = ''; let maxWidth = ''; - - switch(playlistCount) { + + switch (playlistCount) { case 1: width = 'calc(100% / 4 - 16px)'; maxWidth = 'max-width: 180px;'; @@ -207,7 +223,7 @@ const getCarouselItemStyleForPlaylist = (playlistCount: number) => { width = 'calc(100% / 1 - 16px)'; maxWidth = 'max-width: 656px;'; } - + return `${animationDelay}; width: ${width}; ${maxWidth}`; }; @@ -281,7 +297,7 @@ watchEffect(() => { }); const getPlaylistGridClass = (length: number) => { - switch(length) { + switch (length) { case 1: return 'one-column'; case 2: @@ -305,42 +321,42 @@ const getPlaylistGridClass = (length: number) => { @apply flex-1 h-full rounded-3xl p-5 flex flex-col justify-between overflow-hidden relative; cursor: pointer; transition: transform 0.3s ease; - + &:hover { transform: translateY(-5px); } - + &-bg { @apply bg-gray-900 dark:bg-gray-800 bg-no-repeat bg-cover bg-center rounded-3xl absolute w-full h-full top-0 left-0 z-0; filter: brightness(60%); } - + &-info { @apply flex flex-col p-2; &-name { @apply text-gray-100 dark:text-gray-100; } } - + &-count { @apply text-gray-100 dark:text-gray-100; } - + &-play { &-overlay { @apply absolute inset-0 bg-gradient-to-t from-black/70 via-transparent to-black/20 z-20 opacity-0 transition-all duration-300 flex items-center justify-center; backdrop-filter: blur(1px); - + .recommend-singer-item:hover & { opacity: 1; } } - + &-btn { @apply w-20 h-20 bg-transparent flex justify-center items-center text-white; transform: translateY(50px) scale(0.8); transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); - + .recommend-singer-item:hover & { transform: translateY(0) scale(1); } @@ -385,7 +401,7 @@ const getPlaylistGridClass = (length: number) => { &-item { @apply rounded-2xl overflow-hidden flex flex-col; height: 176px; - + &-img { @apply relative cursor-pointer transition-all duration-300; height: 0; @@ -394,12 +410,12 @@ const getPlaylistGridClass = (length: number) => { border-radius: 12px; overflow: hidden; &:hover { - transform: translateY(-5px); - box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15); - .user-play-item-overlay { - opacity: 1; + transform: translateY(-5px); + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15); + .user-play-item-overlay { + opacity: 1; + } } - } img { @apply absolute inset-0 w-full h-full object-cover; @@ -424,22 +440,24 @@ const getPlaylistGridClass = (length: number) => { @apply flex items-center justify-center; transform: scale(0.8); transition: transform 0.3s ease; - + .user-play-item:hover & { transform: scale(1); } } } } -.mobile .recommend-singer { - &-list { - height: 180px; - @apply ml-4; - } - &-item { - @apply p-4 rounded-xl; - &-bg { - @apply rounded-xl; +.mobile { + .recommend-singer { + &-list { + height: 180px; + @apply ml-4; + } + &-item { + @apply p-2 rounded-xl; + &-bg { + @apply rounded-xl; + } } } } diff --git a/src/renderer/layout/AppLayout.vue b/src/renderer/layout/AppLayout.vue index ecdbce8..1bd46ad 100644 --- a/src/renderer/layout/AppLayout.vue +++ b/src/renderer/layout/AppLayout.vue @@ -25,7 +25,16 @@
- + + + + + + +
+ +
+ +
+ + {{ playMusic.name }} + + + + {{ artists.name }}{{ artistsindex < artistList.length - 1 ? ' / ' : '' }} + + +
+
+ + +
+
+ +
+ + +
+
+ + + +
+
+
+
+ + + + + + + + + diff --git a/src/renderer/layout/components/MusicFull.vue b/src/renderer/layout/components/MusicFull.vue index cf772a8..c563c16 100644 --- a/src/renderer/layout/components/MusicFull.vue +++ b/src/renderer/layout/components/MusicFull.vue @@ -11,7 +11,7 @@
@@ -70,7 +70,7 @@ class="music-lrc" :style="{ height: config.hidePlayBar ? '85vh' : '65vh', - width: config.hideCover ? '50vw' : '500px' + width: isMobile ? '100vw' : config.hideCover ? '50vw' : '500px' }" :native-scrollbar="false" @mouseover="mouseOverLayout" @@ -142,6 +142,7 @@ import { textColors, useLyricProgress } from '@/hooks/MusicHook'; +import { usePlayerStore } from '@/store'; import { useSettingsStore } from '@/store/modules/settings'; import { getImgUrl, isMobile } from '@/utils'; import { animateGradient, getHoverBackgroundColor, getTextColors } from '@/utils/linearColor'; @@ -432,6 +433,13 @@ const handleScroll = () => { showStickyHeader.value = scrollTop > 100; }; +const playerStore = usePlayerStore(); + +const closeMusicFull = () => { + isVisible.value = false; + playerStore.setMusicFull(false); +}; + // 添加滚动监听 onMounted(() => { if (lrcSider.value?.$el) { @@ -648,12 +656,17 @@ defineExpose({ span { padding-right: 0px !important; } - } + .hover-text { + &:hover { + background-color: transparent; + } + } .music-lrc-text { @apply text-xl text-center; } .music-content { @apply h-[calc(100vh-120px)]; + width: 100vw !important; } } } @@ -664,8 +677,9 @@ defineExpose({ // 添加全局字体样式 :root { - --current-font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, - 'Helvetica Neue', Arial, sans-serif; + --current-font-family: + system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, + sans-serif; } #drawer-target { @@ -687,7 +701,7 @@ defineExpose({ } .control-btn { - @apply w-9 h-9 flex items-center justify-center rounded cursor-pointer transition-all duration-300; + @apply w-9 h-9 flex items-center justify-center rounded cursor-pointer transition-all duration-300 z-[9999]; background: rgba(142, 142, 142, 0.192); backdrop-filter: blur(12px); diff --git a/src/renderer/layout/components/PlayBar.vue b/src/renderer/layout/components/PlayBar.vue index 1258e80..72e6522 100644 --- a/src/renderer/layout/components/PlayBar.vue +++ b/src/renderer/layout/components/PlayBar.vue @@ -567,7 +567,7 @@ const isEQVisible = ref(false); .mobile { .music-play-bar { - @apply px-4 bottom-[70px] transition-all duration-300; + @apply px-4 bottom-[56px] transition-all duration-300; } .music-time { display: none; diff --git a/src/renderer/store/modules/settings.ts b/src/renderer/store/modules/settings.ts index 00133ac..0db08f5 100644 --- a/src/renderer/store/modules/settings.ts +++ b/src/renderer/store/modules/settings.ts @@ -37,11 +37,10 @@ export const useSettingsStore = defineStore('settings', () => { if (isElectron) { window.electron.ipcRenderer.send('set-store-value', 'set', cloneDeep(mergedData)); - console.log('mergedData', mergedData); - setData.value = cloneDeep(mergedData); } else { localStorage.setItem('appSettings', JSON.stringify(cloneDeep(mergedData))); } + setData.value = cloneDeep(mergedData); }; const toggleTheme = () => { diff --git a/src/renderer/utils/index.ts b/src/renderer/utils/index.ts index 8b0028e..0a21f62 100644 --- a/src/renderer/utils/index.ts +++ b/src/renderer/utils/index.ts @@ -1,3 +1,4 @@ +import { useWindowSize } from '@vueuse/core'; import { computed } from 'vue'; import { useSettingsStore } from '@/store/modules/settings'; @@ -73,16 +74,26 @@ export const getImgUrl = (url: string | undefined, size: string = '') => { }; export const isMobile = computed(() => { - const flag = navigator.userAgent.match( + const { width } = useWindowSize(); + const userAgentFlag = navigator.userAgent.match( /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i ); - const settingsStore = useSettingsStore(); - settingsStore.isMobile = !!flag; + const isMobileWidth = width.value < 500; + const isMobileDevice = !!userAgentFlag || isMobileWidth; - // 给html标签 添加mobile - if (flag) document.documentElement.classList.add('mobile'); - return !!flag; + const settingsStore = useSettingsStore(); + settingsStore.isMobile = isMobileDevice; + + // 给html标签 添加或移除mobile类 + if (isMobileDevice) { + document.documentElement.classList.add('mobile'); + } else { + document.documentElement.classList.add('pc'); + document.documentElement.classList.remove('mobile'); + } + + return isMobileDevice; }); export const isElectron = (window as any).electron !== undefined; diff --git a/src/renderer/views/set/index.vue b/src/renderer/views/set/index.vue index 7461bea..607109e 100644 --- a/src/renderer/views/set/index.vue +++ b/src/renderer/views/set/index.vue @@ -1,7 +1,7 @@