From 0d97c592e1d97c6c188e1793b9727f82eb95adcc Mon Sep 17 00:00:00 2001 From: log1997 <2694233102@qq.com> Date: Thu, 4 Dec 2025 17:38:52 +0800 Subject: [PATCH] =?UTF-8?q?feat(layout):=20=E9=87=8D=E6=9E=84=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E5=B8=83=E5=B1=80=E4=B8=8E=E9=9F=B3=E4=B9=90=E6=92=AD?= =?UTF-8?q?=E6=94=BE=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将 PlayMusic 组件迁移至 layout/RightButton 并重构成通用右下角按钮组件, 提取音乐播放逻辑到独立 hook `usePlayMusic`,优化模态框提示逻辑并统一滚动行为。 --- src/App.vue | 66 +------------- src/components.d.ts | 1 - src/components/ToTop/index.vue | 4 +- .../RightButton}/index.vue | 82 ++---------------- src/layout/RightButton/usePlayMusic.ts | 85 +++++++++++++++++++ src/layout/index.vue | 22 +++-- src/layout/useMounted.ts | 65 ++++++++++++++ 7 files changed, 171 insertions(+), 154 deletions(-) rename src/{components/PlayMusic => layout/RightButton}/index.vue (50%) create mode 100644 src/layout/RightButton/usePlayMusic.ts create mode 100644 src/layout/useMounted.ts diff --git a/src/App.vue b/src/App.vue index 96991db..c7b1087 100644 --- a/src/App.vue +++ b/src/App.vue @@ -3,7 +3,7 @@ import { storeToRefs } from 'pinia' import { onMounted, provide, ref } from 'vue' import { useI18n } from 'vue-i18n' import { loadingKey, loadingState } from '@/components/Loading' -import PlayMusic from '@/components/PlayMusic/index.vue' +// import PlayMusic from '@/components/PlayMusic/index.vue' import useStore from '@/store' import { themeChange } from '@/utils' @@ -14,74 +14,10 @@ const prizeConfig = useStore().prizeConfig const system = useStore().system const { getTheme: localTheme } = storeToRefs(globalConfig) const { getPrizeConfig: prizeList } = storeToRefs(prizeConfig) - -const tipDialog = ref() -// 设置当前奖列表 -function setCurrentPrize() { - if (prizeList.value.length <= 0) { - return - } - for (let i = 0; i < prizeList.value.length; i++) { - if (!prizeList.value[i].isUsed) { - prizeConfig.setCurrentPrize(prizeList.value[i]) - - break - } - } -} -// 判断是否手机端访问 -function judgeMobile() { - const ua = navigator.userAgent - const isAndroid = ua.includes('Android') || ua.includes('Adr') - const isIOS = !!ua.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) - - system.setIsMobile(isAndroid || isIOS) - - return isAndroid || isIOS -} -// 判断是否chrome或者edge访问 -function judgeChromeOrEdge() { - const ua = navigator.userAgent - const isChrome = ua.includes('Chrome') - const isEdge = ua.includes('Edg') - - system.setIsChrome(isChrome) - - return isChrome || isEdge -} -onMounted(() => { - themeChange(localTheme.value.name) - setCurrentPrize() - if (judgeMobile() || !judgeChromeOrEdge()) { - tipDialog.value.showModal() - } -}) - - - - {{ t('dialog.titleTip') }} - - - {{ t('dialog.dialogPCWeb') }} - - - {{ t('dialog.dialogLatestBrowser') }} - - - - - - {{ t('button.confirm') }} - - - - - - diff --git a/src/components.d.ts b/src/components.d.ts index df513c9..86e9d91 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -16,7 +16,6 @@ declare module 'vue' { ImageSync: typeof import('./components/ImageSync/index.vue')['default'] Loading: typeof import('./components/Loading/index.vue')['default'] PageHeader: typeof import('./components/PageHeader/index.vue')['default'] - PlayMusic: typeof import('./components/PlayMusic/index.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] SvgIcon: typeof import('./components/SvgIcon/index.vue')['default'] diff --git a/src/components/ToTop/index.vue b/src/components/ToTop/index.vue index 9f1efa4..0a9e133 100644 --- a/src/components/ToTop/index.vue +++ b/src/components/ToTop/index.vue @@ -1,10 +1,10 @@ - + diff --git a/src/components/PlayMusic/index.vue b/src/layout/RightButton/index.vue similarity index 50% rename from src/components/PlayMusic/index.vue rename to src/layout/RightButton/index.vue index b85d020..24ae249 100644 --- a/src/components/PlayMusic/index.vue +++ b/src/layout/RightButton/index.vue @@ -1,97 +1,25 @@ diff --git a/src/layout/RightButton/usePlayMusic.ts b/src/layout/RightButton/usePlayMusic.ts new file mode 100644 index 0000000..47700b0 --- /dev/null +++ b/src/layout/RightButton/usePlayMusic.ts @@ -0,0 +1,85 @@ +import localforage from 'localforage' +import { storeToRefs } from 'pinia' +import { onMounted, onUnmounted, ref, watch } from 'vue' +import useStore from '@/store' + +export function usePlayMusic() { + const audioDbStore = localforage.createInstance({ + name: 'audioStore', + }) + + const globalConfig = useStore().globalConfig + const { getMusicList: localMusicList, getCurrentMusic: currentMusic } = storeToRefs(globalConfig) + const audio = ref(new Audio()) + + async function play(item: any) { + if (!item) { + return + } + // if (!audio.value.paused && !skip) { + // audio.value.pause() + + // return + // } + let audioUrl = '' + if (!item.url) { + return + } + if (item.url === 'Storage') { + audioUrl = await audioDbStore.getItem(item.name) as string + } + else { + audioUrl = item.url + } + audio.value.pause() + audio.value.src = audioUrl + audio.value.play() + } + function playMusic(item: any, skip = false) { + if (!item) { + return + } + if (!currentMusic.value.paused && !skip) { + globalConfig.setCurrentMusic(item, true) + + return + } + globalConfig.setCurrentMusic(item, false) + } + function nextPlay() { + // 播放下一首 + if (localMusicList.value.length >= 1) { + let index = localMusicList.value.findIndex((item: any) => item.name === currentMusic.value.item.name) + index++ + if (index >= localMusicList.value.length) { + index = 0 + } + globalConfig.setCurrentMusic(localMusicList.value[index], false) + } + } + // 监听播放成后开始下一首 + function onPlayEnd() { + audio.value.addEventListener('ended', nextPlay) + } + onMounted(() => { + globalConfig.setCurrentMusic(localMusicList.value[0], true) + onPlayEnd() + // 不使用空格控制audio + }) + onUnmounted(() => { + audio.value.removeEventListener('ended', nextPlay) + }) + watch(currentMusic, (val: any) => { + if (!val.paused && audio.value) { + play(val.item) + } + else { + audio.value.pause() + } + }, { deep: true }) + return { + currentMusic, + playMusic, + nextPlay, + } +} diff --git a/src/layout/index.vue b/src/layout/index.vue index 10cc77e..e24439f 100644 --- a/src/layout/index.vue +++ b/src/layout/index.vue @@ -1,32 +1,36 @@ - - + + diff --git a/src/layout/useMounted.ts b/src/layout/useMounted.ts new file mode 100644 index 0000000..00307a9 --- /dev/null +++ b/src/layout/useMounted.ts @@ -0,0 +1,65 @@ +import type { Ref } from 'vue' +import { storeToRefs } from 'pinia' +import { onMounted, provide, ref } from 'vue' +import { useI18n } from 'vue-i18n' +import { loadingKey, loadingState } from '@/components/Loading' +import useStore from '@/store' +import { themeChange } from '@/utils' + +export function useMounted(tipDialog: Ref) { + provide(loadingKey, loadingState) + const globalConfig = useStore().globalConfig + const prizeConfig = useStore().prizeConfig + const system = useStore().system + const { getTheme: localTheme } = storeToRefs(globalConfig) + const { getPrizeConfig: prizeList } = storeToRefs(prizeConfig) + const tipDesc = ref('') + const { t } = useI18n() + // 设置当前奖列表 + function setCurrentPrize() { + if (prizeList.value.length <= 0) { + return + } + for (let i = 0; i < prizeList.value.length; i++) { + if (!prizeList.value[i].isUsed) { + prizeConfig.setCurrentPrize(prizeList.value[i]) + + break + } + } + } + // 判断是否手机端访问 + function judgeMobile() { + const ua = navigator.userAgent + const isAndroid = ua.includes('Android') || ua.includes('Adr') + const isIOS = !!ua.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) + + system.setIsMobile(isAndroid || isIOS) + + return isAndroid || isIOS + } + // 判断是否chrome或者edge访问 + function judgeChromeOrEdge() { + const ua = navigator.userAgent + const isChrome = ua.includes('Chrome') + const isEdge = ua.includes('Edg') + + system.setIsChrome(isChrome) + + return isChrome || isEdge + } + onMounted(() => { + themeChange(localTheme.value.name) + setCurrentPrize() + if (judgeMobile()) { + tipDialog.value.showDialog() + tipDesc.value = t('dialog.dialogPCWeb') + } + else if (!judgeChromeOrEdge()) { + tipDialog.value.showDialog() + tipDesc.value = t('dialog.dialogLatestBrowser') + } + }) + + return { tipDesc } +}
- {{ t('dialog.dialogPCWeb') }} -
- {{ t('dialog.dialogLatestBrowser') }} -