Files
digital-psychology/apps/user-h5/src/components/TabBar.vue
T
jackyu66gitandCursor 53eb4577b3 feat: 按测测功能重构 H5 首页与各子页,并修正顶栏「+」添加档案菜单
对齐测测交互:首页「+」支持邀请填档案/添加档案/邀请合盘;各 Tab 与工具页按同一视觉与功能标准落地;本地对照截图目录显式忽略。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-05 14:32:35 +08:00

125 lines
2.9 KiB
Vue

<template>
<nav class="tabbar" aria-label="主导航">
<router-link
v-for="item in items"
:key="item.to"
:to="item.to"
class="item"
:class="{ ask: item.ask, on: isActive(item.key) }"
>
<span class="ni" aria-hidden="true">{{ item.icon }}</span>
<span class="lb">{{ item.label }}</span>
</router-link>
</nav>
</template>
<script setup lang="ts">
import { useRoute } from 'vue-router'
const route = useRoute()
const items = [
{ key: 'home', to: '/', icon: '⌂', label: '首页' },
{ key: 'explore', to: '/explore', icon: '◆', label: '探索' },
{ key: 'ask', to: '/ask', icon: '问', label: '问答', ask: true },
{ key: 'companion', to: '/companion', icon: '♡', label: '陪伴' },
{ key: 'mine', to: '/mine', icon: '◍', label: '我的' },
] as const
function activeKey(): string {
const p = route.path
if (p.startsWith('/ask')) return 'ask'
if (p.startsWith('/companion')) return 'companion'
if (
p.startsWith('/mine') ||
p.startsWith('/profile') ||
p.startsWith('/membership') ||
p.startsWith('/reports')
) {
return 'mine'
}
if (
p.startsWith('/explore') ||
p.startsWith('/relation') ||
p.startsWith('/scales') ||
p.startsWith('/portrait') ||
p.startsWith('/star') ||
p.startsWith('/synastry') ||
p.startsWith('/rhythm') ||
p.startsWith('/cards') ||
p.startsWith('/growth-plan') ||
p.startsWith('/share')
) {
return 'explore'
}
if (p === '/') return 'home'
return 'home'
}
function isActive(key: string): boolean {
return activeKey() === key
}
</script>
<style scoped>
.tabbar {
position: fixed;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 100%;
max-width: var(--yxg-max-w);
background: rgba(255, 255, 255, 0.96);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
display: flex;
justify-content: space-around;
padding: 6px 0 calc(10px + env(safe-area-inset-bottom, 0));
border-top: 1px solid var(--color-border);
z-index: 100;
box-shadow: var(--shadow-nav);
}
.item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
font-size: 10px;
color: var(--color-text-secondary);
padding: 2px 0;
letter-spacing: 0.02em;
transition: color var(--duration-fast) ease;
}
.item.on {
color: var(--color-primary);
font-weight: 600;
}
.ni {
font-size: 17px;
line-height: 1.2;
}
.lb {
line-height: 1.2;
}
.item.ask .ni {
width: 44px;
height: 44px;
border-radius: 50%;
background: linear-gradient(135deg, #ff7a6e, var(--color-primary));
color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 15px;
font-weight: 700;
margin-top: -14px;
box-shadow: 0 6px 16px rgba(229, 77, 66, 0.38);
}
.item.ask.on {
color: var(--color-primary);
}
.item.ask.on .ni {
box-shadow: 0 8px 20px rgba(229, 77, 66, 0.45);
}
</style>