175 lines
3.3 KiB
Vue
175 lines
3.3 KiB
Vue
<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>
|