feat: add merged venue navigation

This commit is contained in:
gqt
2026-06-08 21:42:32 +08:00
parent 845385c3b9
commit 4c20371c6d
13 changed files with 245 additions and 8 deletions
+112
View File
@@ -0,0 +1,112 @@
<template>
<view class="venue-tabbar-wrap">
<view class="venue-tabbar-spacer" />
<view class="venue-tabbar">
<view
v-for="item in items"
:key="item.key"
class="venue-tabbar__item"
:class="{ active: item.key === active }"
@tap="go(item)"
>
<image
class="venue-tabbar__icon"
:src="item.key === active ? item.activeIcon : item.icon"
mode="aspectFit"
/>
<text class="venue-tabbar__label">{{ item.label }}</text>
</view>
</view>
</view>
</template>
<script setup>
import { computed } from 'vue'
import { setStoredVenue } from '@/utils/venue'
const props = defineProps({
venue: {
type: String,
required: true,
validator: (value) => ['ice', 'comprehensive'].includes(value)
},
active: {
type: String,
required: true,
validator: (value) => ['home', 'courses', 'bookings', 'profile'].includes(value)
}
})
const tabDefinitions = [
{ key: 'home', label: '首页', icon: 'home', path: 'home' },
{ key: 'courses', label: '课程', icon: 'course', path: 'courses' },
{ key: 'bookings', label: '预约', icon: 'booking', path: 'bookings' },
{ key: 'profile', label: '我的', icon: 'mine', path: 'profile' }
]
const items = computed(() => {
return tabDefinitions.map((item) => ({
...item,
icon: `/static/${props.venue}/tab/${item.icon}.png`,
activeIcon: `/static/${props.venue}/tab/${item.icon}-active.png`,
url: `/pages/${props.venue}/${item.path}/index`
}))
})
const go = (item) => {
setStoredVenue(props.venue)
if (item.key === props.active) return
uni.reLaunch({ url: item.url })
}
</script>
<style lang="scss" scoped>
.venue-tabbar-spacer {
height: calc(124rpx + env(safe-area-inset-bottom));
}
.venue-tabbar {
position: fixed;
right: 0;
bottom: 0;
left: 0;
z-index: 1000;
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
padding: 10rpx 0 calc(10rpx + env(safe-area-inset-bottom));
border-top: 1rpx solid $border-color;
background: rgba(255, 255, 255, 0.98);
box-shadow: 0 -8rpx 24rpx rgba(15, 23, 42, 0.06);
}
.venue-tabbar__item {
min-width: 0;
height: 104rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 6rpx;
color: $text-color-light;
font-size: 22rpx;
font-weight: 700;
line-height: 1;
}
.venue-tabbar__item.active {
color: $text-color-main;
}
.venue-tabbar__icon {
width: 46rpx;
height: 46rpx;
}
.venue-tabbar__label {
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>