volunteer-4/src/components/bar/CustomTabBar.vue

175 lines
3.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<!-- TabBar占位块 - 与TabBar高度一致 -->
<view
v-if="showPlaceholder"
class="tabbar-placeholder"
:style="{ height: `${tabbarTotalHeight}px` }"
></view>
<!-- TabBar组件 -->
<view class="custom-tabbar pb-safe">
<view class="tabbar-content">
<view
class="tabbar-item"
v-for="item in tabbarList"
:key="item.id"
:class="[item.centerItem ? 'center-item' : '']"
@click="changeItem(item)"
>
<view class="item-top">
<image
class="w-full h-full object-contain item-icon"
:src="currentPage == item.id ? item.selectIcon : item.icon"
></image>
</view>
<view class="item-bottom" :class="[currentPage == item.id ? 'item-active' : '']">
<text>{{ item.text }}</text>
</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { TabesItem } from '@/service/app/types'
import { tabbarList } from '@/hooks/useTabbarList'
import { ref, computed, onMounted } from 'vue'
import { useUserStore } from '@/store'
defineProps({
currentPage: {
type: Number,
default: 0,
},
//
showPlaceholder: {
type: Boolean,
default: true,
},
})
//
const safeAreaBottom = ref(0)
const userStore = useUserStore()
// TabBar (TabBar + )
const tabbarTotalHeight = computed(() => {
// 100rpx转为px不同设备可能有差异
const tabbarHeight = uni.upx2px(100)
return tabbarHeight + safeAreaBottom.value
})
const changeItem = (item: TabesItem) => {
if (item.navigatorItem) {
// 唯独ai有这个情况
if (item.path === '/aiService-sub/index/index' && !userStore.isLoginFlag) {
uni.navigateTo({
url: item.path,
})
} else {
uni.navigateTo({
url: '/aiService-sub/index/newAi',
})
}
} else {
uni.switchTab({
url: item.path,
})
}
}
onMounted(() => {
uni.hideTabBar()
// 获取系统信息以计算安全区域
uni.getSystemInfo({
success: (res) => {
if (res.safeAreaInsets) {
safeAreaBottom.value = res.safeAreaInsets.bottom || 0
}
},
})
})
// 暴露高度信息给父组件
defineExpose({
tabbarTotalHeight,
})
</script>
<style scoped>
.custom-tabbar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: #ffffff;
border-top: 1px solid #f5f5f5;
z-index: 999;
}
.tabbar-content {
display: flex;
height: 100rpx;
padding: 0 20rpx;
position: relative;
}
.tabbar-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
padding: 10rpx 0;
}
.item-top {
display: flex;
align-items: center;
justify-content: center;
}
.item-bottom {
font-size: 20rpx;
margin-top: 6rpx;
color: #999;
}
.item-active {
color: #3370ff;
}
.center-item {
position: relative;
}
.item-icon {
width: 48rpx;
height: 48rpx;
}
.center-item .item-icon {
width: 98rpx;
height: 98rpx;
}
.center-item .item-bottom {
position: absolute;
bottom: 5rpx;
}
/* 占位块样式 */
.tabbar-placeholder {
width: 100%;
box-sizing: border-box;
}
/* 安全区域适配 */
.pb-safe {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
</style>