|
|
<template> |
|
|
<div |
|
|
class="app-tabbar" |
|
|
v-show="!shouldHideTabbar" |
|
|
> |
|
|
<div class="tabbar-content"> |
|
|
<router-link |
|
|
v-for="tab in tabs" |
|
|
:key="tab.name" |
|
|
:to="tab.path" |
|
|
class="tab-item" |
|
|
:class="{ active: currentRoute === tab.name }" |
|
|
@click="handleTabClick(tab)" |
|
|
> |
|
|
<i :class="tab.icon" class="tab-icon"></i> |
|
|
<span class="tab-label">{{ tab.label }}</span> |
|
|
</router-link> |
|
|
</div> |
|
|
</div> |
|
|
</template> |
|
|
|
|
|
<script setup> |
|
|
import { computed } from 'vue' |
|
|
import { useRoute } from 'vue-router' |
|
|
|
|
|
const route = useRoute() |
|
|
|
|
|
const tabs = [ |
|
|
{ |
|
|
name: 'Home', |
|
|
path: '/home', |
|
|
label: '首页', |
|
|
icon: 'fas fa-home' |
|
|
}, |
|
|
{ |
|
|
name: 'Favorites', |
|
|
path: '/favorites', |
|
|
label: '我喜欢', |
|
|
icon: 'fas fa-heart' |
|
|
}, |
|
|
{ |
|
|
name: 'Playlists', |
|
|
path: '/playlists', |
|
|
label: '歌单', |
|
|
icon: 'fas fa-music' |
|
|
}, |
|
|
{ |
|
|
name: 'PlayQueue', |
|
|
path: '/play-queue', |
|
|
label: '播放列表', |
|
|
icon: 'fas fa-list' |
|
|
} |
|
|
] |
|
|
|
|
|
const currentRoute = computed(() => route.name) |
|
|
|
|
|
|
|
|
const shouldHideTabbar = computed(() => { |
|
|
return route.meta?.fullScreen || false |
|
|
}) |
|
|
|
|
|
const handleTabClick = (tab) => { |
|
|
|
|
|
if (navigator.vibrate) { |
|
|
navigator.vibrate(10) |
|
|
} |
|
|
} |
|
|
</script> |
|
|
|
|
|
<style scoped> |
|
|
.app-tabbar { |
|
|
position: fixed; |
|
|
bottom: 0; |
|
|
left: 0; |
|
|
right: 0; |
|
|
background: var(--bg-card); |
|
|
backdrop-filter: blur(20px); |
|
|
border-top: 1px solid var(--border-strong); |
|
|
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1); |
|
|
z-index: 1000; |
|
|
} |
|
|
|
|
|
|
|
|
@supports (-webkit-touch-callout: none) { |
|
|
@media all and (display-mode: standalone) { |
|
|
.app-tabbar { |
|
|
padding-bottom: 20px; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
.tabbar-content { |
|
|
display: flex; |
|
|
height: var(--tabbar-height); |
|
|
max-width: 480px; |
|
|
margin: 0 auto; |
|
|
} |
|
|
|
|
|
.tab-item { |
|
|
flex: 1; |
|
|
display: flex; |
|
|
flex-direction: column; |
|
|
align-items: center; |
|
|
justify-content: center; |
|
|
text-decoration: none; |
|
|
color: var(--text-disabled); |
|
|
transition: var(--transition-fast); |
|
|
min-height: var(--touch-target); |
|
|
position: relative; |
|
|
padding: 4px; |
|
|
} |
|
|
|
|
|
.tab-item:hover, |
|
|
.tab-item.active { |
|
|
color: var(--primary-color); |
|
|
} |
|
|
|
|
|
.tab-item.active::after { |
|
|
content: ''; |
|
|
position: absolute; |
|
|
bottom: -1px; |
|
|
left: 50%; |
|
|
transform: translateX(-50%); |
|
|
width: 24px; |
|
|
height: 2px; |
|
|
background: var(--primary-color); |
|
|
border-radius: 1px; |
|
|
|
|
|
box-shadow: 0 -1px 4px var(--glow-color); |
|
|
opacity: 0.9; |
|
|
} |
|
|
|
|
|
.tab-icon { |
|
|
font-size: 20px; |
|
|
margin-bottom: 2px; |
|
|
} |
|
|
|
|
|
.tab-label { |
|
|
font-size: 10px; |
|
|
font-weight: 500; |
|
|
line-height: 1; |
|
|
} |
|
|
|
|
|
|
|
|
@media (max-width: 320px) { |
|
|
.tab-label { |
|
|
font-size: 9px; |
|
|
} |
|
|
|
|
|
.tab-icon { |
|
|
font-size: 18px; |
|
|
} |
|
|
|
|
|
.app-tabbar { |
|
|
border-top: 1px solid var(--border-strong); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@media (min-width: 1024px) { |
|
|
.app-tabbar { |
|
|
display: none; |
|
|
} |
|
|
} |
|
|
</style> |