155 lines
2.9 KiB
Vue
155 lines
2.9 KiB
Vue
<template>
|
|
<AudioPlayer
|
|
v-if="isHostVisible"
|
|
controlled
|
|
:visible="visible"
|
|
:audio="currentAudio"
|
|
:playing="playing"
|
|
:loading="loading"
|
|
:playback-error="error"
|
|
:current-time="currentTime"
|
|
:duration-value="duration"
|
|
:closable="closable"
|
|
:expandable="expandable"
|
|
:avoid-bottom-nav="avoidBottomNav"
|
|
:mode="currentDisplayMode"
|
|
@toggle="handleToggle"
|
|
@collapse="handleCollapse"
|
|
@stop="handleStop"
|
|
@close="player.close"
|
|
@seek="player.seekToPercent"
|
|
@expand="handleExpand"
|
|
@update:visible="handleVisibleChange"
|
|
/>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed, onMounted, onUnmounted, watch } from 'vue'
|
|
import { onShow } from '@dcloudio/uni-app'
|
|
import AudioPlayer, {
|
|
type AudioDisplayMode
|
|
} from '@/components/audio/AudioPlayer.vue'
|
|
import { useGlobalAudioPlayer } from '@/composables/useGlobalAudioPlayer'
|
|
|
|
const props = withDefaults(defineProps<{
|
|
avoidBottomNav?: boolean
|
|
displayMode?: AudioDisplayMode
|
|
closable?: boolean
|
|
expandable?: boolean
|
|
}>(), {
|
|
avoidBottomNav: true,
|
|
displayMode: 'mini',
|
|
closable: true,
|
|
expandable: true
|
|
})
|
|
|
|
const player = useGlobalAudioPlayer()
|
|
const {
|
|
currentAudio,
|
|
currentSource,
|
|
visible,
|
|
playing,
|
|
loading,
|
|
error,
|
|
currentTime,
|
|
duration,
|
|
displayMode: currentDisplayMode,
|
|
activeHostId,
|
|
hasAudio
|
|
} = player
|
|
const hostId = player.registerHost()
|
|
const isHostVisible = computed(() => (
|
|
visible.value
|
|
&& hasAudio.value
|
|
&& activeHostId.value === hostId
|
|
))
|
|
|
|
const handleToggle = () => {
|
|
if (playing.value) {
|
|
player.pause()
|
|
return
|
|
}
|
|
|
|
void player.resume()
|
|
}
|
|
|
|
const applyHostDisplayMode = () => {
|
|
if (!hasAudio.value) {
|
|
return
|
|
}
|
|
|
|
if (currentDisplayMode.value !== props.displayMode) {
|
|
player.setDisplayMode(props.displayMode)
|
|
}
|
|
}
|
|
|
|
const isCurrentH5Route = (route: string) => {
|
|
if (typeof window === 'undefined') return false
|
|
|
|
return window.location.hash.replace(/^#/, '') === route
|
|
}
|
|
|
|
const handleStop = () => {
|
|
player.stop()
|
|
}
|
|
|
|
const handleCollapse = () => {
|
|
player.collapse(props.displayMode === 'floating' ? 'floating' : 'mini')
|
|
}
|
|
|
|
const handleVisibleChange = (visible: boolean) => {
|
|
if (!visible && hasAudio.value) {
|
|
player.collapse(props.displayMode === 'floating' ? 'floating' : 'mini')
|
|
}
|
|
}
|
|
|
|
const handleExpand = () => {
|
|
if (!props.expandable) return
|
|
|
|
if (currentDisplayMode.value === 'floating') {
|
|
player.setDisplayMode('mini')
|
|
return
|
|
}
|
|
|
|
player.setDisplayMode('expanded')
|
|
|
|
const route = currentSource.value?.detailRoute
|
|
if (!route) {
|
|
return
|
|
}
|
|
|
|
if (isCurrentH5Route(route)) {
|
|
return
|
|
}
|
|
|
|
uni.navigateTo({
|
|
url: route
|
|
})
|
|
}
|
|
|
|
onMounted(() => {
|
|
player.activateHost(hostId)
|
|
applyHostDisplayMode()
|
|
})
|
|
|
|
onShow(() => {
|
|
player.activateHost(hostId)
|
|
applyHostDisplayMode()
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
player.unregisterHost(hostId)
|
|
})
|
|
|
|
watch(
|
|
() => props.displayMode,
|
|
() => {
|
|
applyHostDisplayMode()
|
|
}
|
|
)
|
|
|
|
watch(hasAudio, () => {
|
|
applyHostDisplayMode()
|
|
})
|
|
</script>
|