Files
chazhi/src/tabbar/index.vue
2025-08-12 14:26:38 +08:00

166 lines
5.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
// 'i-carbon-code',
import { customTabbarList as _tabBarList, customTabbarEnable, nativeTabbarNeedHide, tabbarCacheEnable } from './config'
import { tabbarStore } from './store'
// #ifdef MP-WEIXIN
// 将自定义节点设置成虚拟的去掉自定义组件包裹层更加接近Vue组件的表现能更好的使用flex属性
defineOptions({
virtualHost: true,
})
// #endif
// TODO 1/2: 中间的鼓包tabbarItem的开关
const BULGE_ENABLE = false
function handleClickBulge() {
uni.showToast({
title: '点击了中间的鼓包tabbarItem',
icon: 'none',
})
}
/** tabbarList 里面的 path 从 pages.config.ts 得到 */
const tabbarList = _tabBarList.map(item => ({ ...item, path: `/${item.pagePath}` }))
if (BULGE_ENABLE) {
if (tabbarList.length % 2 === 1) {
console.error('tabbar 数量必须是偶数,否则样式很奇怪!!')
}
tabbarList.splice(tabbarList.length / 2, 0, {
isBulge: true,
} as any)
}
function handleClick(index: number) {
// 点击原来的不做操作
if (index === tabbarStore.curIdx) {
return
}
if (tabbarList[index].isBulge) {
handleClickBulge()
return
}
const url = tabbarList[index].path
tabbarStore.setCurIdx(index)
if (tabbarCacheEnable) {
uni.switchTab({ url })
}
else {
uni.navigateTo({ url })
}
}
onLoad(() => {
// 解决原生 tabBar 未隐藏导致有2个 tabBar 的问题
nativeTabbarNeedHide
&& uni.hideTabBar({
fail(err) {
console.log('hideTabBar fail: ', err)
},
success(res) {
// console.log('hideTabBar success: ', res)
},
})
})
const activeColor = '#1890ff'
const inactiveColor = '#666'
function getColorByIndex(index: number) {
return tabbarStore.curIdx === index ? activeColor : inactiveColor
}
function getImageByIndex(index: number, item: { iconActive?: string, icon: string }) {
if (!item.iconActive) {
console.warn('image 模式下,需要配置 iconActive (高亮时的图片),否则无法切换高亮图片')
return item.icon
}
return tabbarStore.curIdx === index ? item.iconActive : item.icon
}
</script>
<template>
<view v-if="customTabbarEnable" class="h-50px pb-safe">
<view class="border-and-fixed bg-white" @touchmove.stop.prevent>
<view class="h-50px flex items-center">
<view
v-for="(item, index) in tabbarList" :key="index"
class="flex flex-1 flex-col items-center justify-center"
:style="{ color: getColorByIndex(index) }"
@click="handleClick(index)"
>
<view v-if="item.isBulge" class="relative">
<!-- 中间一个鼓包tabbarItem的处理 -->
<view class="bulge">
<!-- TODO 2/2: 通常是一个图片或者icon点击触发业务逻辑 -->
<!-- 常见的是扫描按钮发布按钮更多按钮等 -->
<image class="mt-6rpx h-200rpx w-200rpx" src="/static/tabbar/scan.png" />
</view>
</view>
<view v-else class="relative px-3 text-center">
<template v-if="item.iconType === 'uniUi'">
<uni-icons :type="item.icon" size="20" :color="getColorByIndex(index)" />
</template>
<template v-if="item.iconType === 'uiLib'">
<!-- TODO: 以下内容请根据选择的UI库自行替换 -->
<!-- <wd-icon name="home" /> (https://wot-design-uni.cn/component/icon.html) -->
<!-- <uv-icon name="home" /> (https://www.uvui.cn/components/icon.html) -->
<!-- <sar-icon name="image" /> (https://sard.wzt.zone/sard-uniapp-docs/components/icon)(sar没有home图标^_^) -->
<wd-icon :name="item.icon" size="20" />
</template>
<template v-if="item.iconType === 'unocss' || item.iconType === 'iconfont'">
<view :class="item.icon" class="text-20px" />
</template>
<template v-if="item.iconType === 'image'">
<image :src="getImageByIndex(index, item)" mode="scaleToFill" class="h-20px w-20px" />
</template>
<view class="mt-2px text-12px">
{{ item.text }}
</view>
<!-- 角标显示 -->
<view v-if="item.badge">
<template v-if="item.badge === 'dot'">
<view class="absolute right-0 top-0 h-2 w-2 rounded-full bg-#f56c6c" />
</template>
<template v-else>
<view class="absolute right-0 top-0 h-4 w-4 center rounded-full bg-#f56c6c text-center text-xs text-white">
{{ item.badge }}
</view>
</template>
</view>
</view>
</view>
</view>
<view class="pb-safe" />
</view>
</view>
</template>
<style scoped lang="scss">
.border-and-fixed {
position: fixed;
bottom: 0;
left: 0;
right: 0;
border-top: 1px solid #eee;
box-sizing: border-box;
}
// 中间鼓包的样式
.bulge {
position: absolute;
top: -20px;
left: 50%;
transform-origin: top center;
transform: translateX(-50%) scale(0.5) translateY(-33%);
display: flex;
justify-content: center;
align-items: center;
width: 250rpx;
height: 250rpx;
border-radius: 50%;
background-color: #fff;
box-shadow: inset 0 0 0 1px #fefefe;
&:active {
// opacity: 0.8;
}
}
</style>