Files
BYW-VoiceHub/app/app.vue
T
Henry_Du 4ce4649aaf
Build VoiceHub FPK / build-fpk (push) Failing after 56m5s
Build and Push Docker Image / build-and-push (push) Canceled after 1h9m35s
初次提交
2026-09-06 08:19:02 +08:00

235 lines
6.5 KiB
Vue

<template>
<div class="app" :data-theme="theme" :data-color-scheme="colorScheme">
<!-- 全局通知容器组件 -->
<LazyUINotificationContainer ref="notificationContainer" />
<!-- 全局音频播放器 - 使用isPlayerVisible控制显示/隐藏 -->
<LazyUIAudioPlayer
v-show="isPlayerVisible"
:song="currentSong"
:is-playlist-mode="isPlaylistMode"
@close="handlePlayerClose"
@ended="handlePlayerEnded"
/>
<main class="main-content">
<div :key="route.path" :data-route="pageViewRouteName" class="page-view">
<NuxtPage />
</div>
</main>
</div>
</template>
<script setup>
import { computed, onMounted, ref, watch } from 'vue'
// 导入通知容器组件和音频播放器
import { useAudioPlayer } from '~/composables/useAudioPlayer'
import { useAuth } from '~/composables/useAuth'
import { useRoute } from 'vue-router'
import { useTheme } from '~/composables/useTheme'
// 获取运行时配置
const config = useRuntimeConfig()
const route = useRoute()
const pageViewRouteName = computed(() => {
if (typeof route.name === 'string' && route.name) {
return route.name
}
return route.path.split('/').filter(Boolean).join('-') || 'index'
})
// 主题初始化
const { theme, isDark, init: initTheme } = useTheme()
const colorScheme = computed(() => 'custom')
// 通知容器引用
const notificationContainer = ref(null)
// 音频播放器
const audioPlayer = useAudioPlayer()
const currentSong = ref(null)
const isPlayerVisible = ref(false) // 控制播放器显示/隐藏
// 判断是否为播放列表模式
// 投稿页面、搜索预览等场景不是播放列表模式,不应该自动跳过
const isPlaylistMode = computed(() => {
const currentPath = route.path
// 投稿页面不是播放列表模式
if (currentPath.includes('/request') || currentPath.includes('/submit')) {
return false
}
// 其他页面默认为播放列表模式(如歌曲列表、播出排期等)
return true
})
// 监听路由变化,控制播放器显示/隐藏
watch(
() => route.path,
(newPath) => {
// 其他页面,如果有当前歌曲则显示播放器
if (currentSong.value) {
isPlayerVisible.value = true
}
},
{ immediate: true }
)
// 监听当前播放的歌曲
watch(
() => audioPlayer.getCurrentSong().value,
(newSong) => {
if (newSong) {
currentSong.value = newSong
// 显示播放器
isPlayerVisible.value = true
} else {
// 当没有歌曲时,不立即隐藏播放器,而是让动画完成
currentSong.value = null
}
},
{ immediate: true }
)
// 处理播放器关闭事件
const handlePlayerClose = () => {
// 延迟隐藏播放器,与AudioPlayer组件的动画时长同步
setTimeout(() => {
isPlayerVisible.value = false
}, 500)
}
// 处理播放结束事件
const handlePlayerEnded = () => {
// 不在这里处理播放结束逻辑
// 播放结束的逻辑已经在 useAudioPlayerControl.ts 的 onEnded 中处理
// 包括单曲循环、列表播放等模式
// 只有在播放模式为 'off' 时才需要隐藏播放器
const audioPlayerControl = useAudioPlayerControl()
if (audioPlayerControl.playMode.value === 'off') {
// 播放完成后停止播放器
audioPlayer.stopSong()
// 延迟隐藏播放器
setTimeout(() => {
isPlayerVisible.value = false
}, 500)
}
}
// 使用onMounted确保只在客户端初始化认证
let auth = null
let isAuthenticated = false
// 设置鸿蒙系统控制事件监听
const setupHarmonyOSListeners = () => {
if (typeof window === 'undefined') return
// 监听鸿蒙系统控制事件
const handleHarmonyOSPlay = () => {
const currentGlobalSong = audioPlayer.getCurrentSong().value
if (currentGlobalSong) {
// 如果有当前歌曲,恢复播放
audioPlayer.playSong(currentGlobalSong)
}
}
const handleHarmonyOSPause = () => {
audioPlayer.pauseSong()
}
const handleHarmonyOSStop = () => {
audioPlayer.stopSong()
}
const handleHarmonyOSNext = async () => {
try {
const success = await audioPlayer.playNext()
if (!success) {
console.log('没有下一首歌曲或切换失败,继续播放当前歌曲')
// 如果切换失败,不做任何操作,继续播放当前歌曲
}
} catch (error) {
console.error('切换下一首歌曲失败:', error)
// 切换失败时不停止播放,继续播放当前歌曲
}
}
const handleHarmonyOSPrevious = async () => {
try {
const success = await audioPlayer.playPrevious()
if (!success) {
console.log('没有上一首歌曲或切换失败,继续播放当前歌曲')
// 如果切换失败,不做任何操作,继续播放当前歌曲
}
} catch (error) {
console.error('切换上一首歌曲失败:', error)
// 切换失败时不停止播放,继续播放当前歌曲
}
}
// 使用Nuxt的事件总线监听鸿蒙控制事件
if (window.__NUXT__ && window.__NUXT__.$nuxt) {
const nuxtApp = window.__NUXT__.$nuxt
if (nuxtApp.$on) {
nuxtApp.$on('harmonyos-play', handleHarmonyOSPlay)
nuxtApp.$on('harmonyos-pause', handleHarmonyOSPause)
nuxtApp.$on('harmonyos-stop', handleHarmonyOSStop)
nuxtApp.$on('harmonyos-next', handleHarmonyOSNext)
nuxtApp.$on('harmonyos-previous', handleHarmonyOSPrevious)
}
}
// 备用方案:直接在window上监听自定义事件
window.addEventListener('harmonyos-play', handleHarmonyOSPlay)
window.addEventListener('harmonyos-pause', handleHarmonyOSPause)
window.addEventListener('harmonyos-stop', handleHarmonyOSStop)
window.addEventListener('harmonyos-next', handleHarmonyOSNext)
window.addEventListener('harmonyos-previous', handleHarmonyOSPrevious)
}
// 在组件挂载后初始化认证(只会在客户端执行)
onMounted(async () => {
initTheme()
auth = useAuth()
isAuthenticated = auth.isAuthenticated.value
// 初始化鸿蒙系统控制事件监听
setupHarmonyOSListeners()
})
// 使用计算属性确保安全地访问auth对象
const safeIsAuthenticated = computed(() => auth?.isAuthenticated?.value || false)
const handleLogout = () => {
if (auth) {
auth.logout()
}
}
</script>
<style>
/* 应用布局 */
.app {
display: flex;
flex-direction: column;
min-height: 100vh;
position: relative;
}
/* 主要内容 */
.main-content {
flex: 1;
padding: 0;
position: relative;
z-index: 1;
background: transparent;
}
/* 响应式调整 */
@media (max-width: 768px) {
.main-content {
padding: 0;
}
}
</style>