162 lines
4.7 KiB
Vue
162 lines
4.7 KiB
Vue
<script setup lang="ts">
|
|
import { computed } from 'vue'
|
|
import { useRoute, useRouter } from 'vue-router'
|
|
|
|
const route = useRoute()
|
|
const router = useRouter()
|
|
|
|
const currentTab = computed(() => {
|
|
const path = route.path
|
|
if (path.startsWith('/assessment')) return 'assessment'
|
|
if (path.startsWith('/tcm-assessment')) return 'tcm'
|
|
if (path.startsWith('/profile')) return 'profile'
|
|
return 'home'
|
|
})
|
|
|
|
function navigate(target: string) {
|
|
if (target === 'home' && route.path !== '/dashboard') {
|
|
router.replace('/dashboard')
|
|
} else if (target === 'assessment' && route.path !== '/assessment') {
|
|
router.replace('/assessment')
|
|
} else if (target === 'tcm' && route.path !== '/tcm-assessment') {
|
|
router.replace('/tcm-assessment')
|
|
} else if (target === 'profile' && route.path !== '/profile') {
|
|
router.replace('/profile')
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<nav class="app-tab-bar" aria-label="主导航">
|
|
<button type="button"
|
|
class="tab-item"
|
|
:class="{ active: currentTab === 'home' }"
|
|
:aria-current="currentTab === 'home' ? 'page' : undefined"
|
|
@click="navigate('home')"
|
|
>
|
|
<div class="tab-icon">
|
|
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
|
|
<polyline points="9 22 9 12 15 12 15 22" />
|
|
</svg>
|
|
</div>
|
|
<span class="tab-label">首页</span>
|
|
</button>
|
|
|
|
<button type="button"
|
|
class="tab-item"
|
|
:class="{ active: currentTab === 'tcm' }"
|
|
:aria-current="currentTab === 'tcm' ? 'page' : undefined"
|
|
@click="navigate('tcm')"
|
|
>
|
|
<div class="tab-icon">
|
|
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<circle cx="12" cy="12" r="9" />
|
|
<path d="M12 3c-4 4-4 8 0 9s4 5 0 9" />
|
|
<circle cx="9" cy="8" r="1" fill="currentColor" stroke="none" />
|
|
<circle cx="15" cy="16" r="1" fill="currentColor" stroke="none" />
|
|
</svg>
|
|
</div>
|
|
<span class="tab-label">中医四诊</span>
|
|
</button>
|
|
|
|
<button type="button"
|
|
class="tab-item"
|
|
:class="{ active: currentTab === 'assessment' }"
|
|
:aria-current="currentTab === 'assessment' ? 'page' : undefined"
|
|
@click="navigate('assessment')"
|
|
>
|
|
<div class="tab-icon">
|
|
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
|
<polyline points="14 2 14 8 20 8" />
|
|
<path d="M9 13h6" />
|
|
<path d="M9 17h6" />
|
|
<polyline points="10 9 12 11 14 9" />
|
|
</svg>
|
|
</div>
|
|
<span class="tab-label">健康评估</span>
|
|
</button>
|
|
|
|
<button type="button"
|
|
class="tab-item"
|
|
:class="{ active: currentTab === 'profile' }"
|
|
:aria-current="currentTab === 'profile' ? 'page' : undefined"
|
|
@click="navigate('profile')"
|
|
>
|
|
<div class="tab-icon">
|
|
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
|
|
<circle cx="12" cy="7" r="4" />
|
|
</svg>
|
|
</div>
|
|
<span class="tab-label">我的</span>
|
|
</button>
|
|
</nav>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.app-tab-bar {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
width: 100%;
|
|
max-width: 480px;
|
|
min-height: 56px;
|
|
height: calc(56px + env(safe-area-inset-bottom, 0px));
|
|
box-sizing: border-box;
|
|
background: rgba(255, 255, 255, 0.98);
|
|
backdrop-filter: blur(12px);
|
|
-webkit-backdrop-filter: blur(12px);
|
|
border-top: 1px solid rgba(18, 63, 55, 0.08);
|
|
display: flex;
|
|
justify-content: space-around;
|
|
align-items: flex-start;
|
|
padding-top: 6px;
|
|
padding-bottom: env(safe-area-inset-bottom, 0px);
|
|
z-index: 999;
|
|
box-shadow: 0 -4px 16px rgba(18, 63, 55, 0.04);
|
|
}
|
|
|
|
.tab-item {
|
|
border: 0;
|
|
background: transparent;
|
|
font: inherit;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex: 1;
|
|
height: 44px;
|
|
color: #7d8e87;
|
|
cursor: pointer;
|
|
transition: color 0.2s ease;
|
|
user-select: none;
|
|
}
|
|
|
|
.tab-icon {
|
|
width: 22px;
|
|
height: 22px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.tab-label {
|
|
font-size: 11px;
|
|
font-weight: 500;
|
|
letter-spacing: 0.02em;
|
|
margin-top: 2px;
|
|
line-height: 1.2;
|
|
}
|
|
|
|
.tab-item.active {
|
|
color: #0c5045;
|
|
}
|
|
|
|
.tab-item.active .tab-label {
|
|
font-weight: 700;
|
|
}
|
|
</style>
|