对齐测测交互:首页「+」支持邀请填档案/添加档案/邀请合盘;各 Tab 与工具页按同一视觉与功能标准落地;本地对照截图目录显式忽略。 Co-authored-by: Cursor <cursoragent@cursor.com>
125 lines
2.9 KiB
Vue
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>
|