Files
oci-portal-dash/src/layouts/MobileTabBar.vue
T
2026-07-21 19:26:22 +08:00

66 lines
2.1 KiB
Vue

<script setup lang="ts">
import { computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { findNavItem, mobileMoreNames, mobileTabNames, navIcon } from './navItems'
/** 移动端底部导航:高频四项直达 + 「更多」唤起抽屉(设计稿 ①) */
const emit = defineEmits<{ more: [] }>()
const route = useRoute()
const router = useRouter()
const tabs = mobileTabNames.map((name) => {
const item = findNavItem(name)
return { ...item, icon: navIcon(item.iconPaths, 'h-[22px] w-[22px] flex-none') }
})
const moreIcon = navIcon(
'<circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/>',
'h-[22px] w-[22px] flex-none',
)
const activeName = computed(() => {
const current = String(route.name)
return tabs.find((t) => t.activeNames.includes(current))?.name ?? ''
})
/** 当前路由属「更多」内页面时高亮更多槽 */
const moreActive = computed(() => {
const current = String(route.name)
return mobileMoreNames.some((n) => findNavItem(n).activeNames.includes(current))
})
function go(name: string) {
if (name !== String(route.name)) void router.push({ name })
}
</script>
<template>
<nav
class="fixed inset-x-0 bottom-0 z-30 border-t border-line bg-bg px-1 pt-1.5"
style="padding-bottom: env(safe-area-inset-bottom)"
>
<div class="flex">
<button
v-for="t in tabs"
:key="t.name"
class="flex min-h-[52px] flex-1 cursor-pointer flex-col items-center justify-center gap-0.5 rounded-md pb-1"
:class="activeName === t.name ? 'text-accent' : 'text-ink-3'"
@click="go(t.name)"
>
<component :is="t.icon" />
<span class="text-[10px] font-medium">{{ t.label }}</span>
</button>
<button
class="flex min-h-[52px] flex-1 cursor-pointer flex-col items-center justify-center gap-0.5 rounded-md pb-1"
:class="moreActive ? 'text-accent' : 'text-ink-3'"
@click="emit('more')"
>
<component :is="moreIcon" />
<span class="text-[10px] font-medium">更多</span>
</button>
</div>
</nav>
</template>