8.21提交

This commit is contained in:
zoujiandong
2025-08-21 17:45:03 +08:00
parent bbd3169335
commit f8003ca7a6
40 changed files with 5558 additions and 30 deletions
+367
View File
@@ -0,0 +1,367 @@
<template>
<view class="custom-tabbar">
<view
class="tabbar-item"
v-for="(item, index) in tabList"
:key="index"
@click="switchTab(index, item)"
:class="{ active: currentTab === index }"
>
<!-- 图标容器 -->
<view class="icon-container">
<!-- <uni-icons
:type="currentTab === index ? item.activeIcon : item.icon"
:size="currentTab === index ? 28 : 24"
:color="currentTab === index ? item.activeColor : item.color"
></uni-icons> -->
<image class="img" :src="currentTab === index ? item.activeIcon : item.icon" alt="" />
<!-- 徽章 -->
<view class="badge" v-if="item.badge && item.badge > 0">
<uni-badge
:text="item.badge > 99 ? '99+' : item.badge.toString()"
type="error"
size="small"
></uni-badge>
</view>
<!-- 红点 -->
<view class="red-dot" v-if="item.showRedDot"></view>
</view>
<!-- 文字 -->
<text class="tab-text" :class="{ active: currentTab === index }">
{{ item.text }}
</text>
<!-- 动画效果 -->
<!-- <view class="active-indicator" v-if="currentTab === index"></view> -->
</view>
</view>
</template>
<script setup>
import { ref, reactive, onMounted, nextTick } from 'vue';
import { onShow, onLoad } from "@dcloudio/uni-app";
import home from '@/static/home_nor.png'
import homeOn from '@/static/home_sel.png'
import classroom from "@/static/classroom.png"
import classroomOn from "@/static/classroomOn.png"
import live from "@/static/live.png"
import liveOn from "@/static/liveOn.png"
import education from '@/static/education.png'
import educationOn from '@/static/educationOn.png'
import my from '@/static/my.png'
import myOn from '@/static/myOn.png'
// 定义props
const props = defineProps({
// 可以添加自定义props
});
// 定义emits
const emit = defineEmits(['tabChange']);
// 当前选中的tab
const currentTab = ref(0);
// tabbar数据
const tabList = reactive([
{
icon: home,
activeIcon: homeOn,
text: '首页',
color: '#999999',
activeColor: '#007aff',
badge: 0,
showRedDot: false,
pagePath: '/pages/index/index'
},
{
icon: classroom,
activeIcon: classroomOn,
text: '患教学堂',
color: '#999999',
activeColor: '#007aff',
badge: 5,
showRedDot: false,
pagePath: '/pages/education/education'
},
{
icon: live,
activeIcon: liveOn,
text: '会议·直播',
color: '#999999',
activeColor: '#007aff',
badge: 0,
showRedDot: true,
pagePath: '/pages/meeting/meeting'
},
{
icon: education,
activeIcon:educationOn,
text: '继续教育',
color: '#999999',
activeColor: '#007aff',
badge: 12,
showRedDot: false,
pagePath: '/pages/education/continuing'
},
{
icon: my,
activeIcon: myOn,
text: '我的',
color: '#999999',
activeColor: '#007aff',
badge: 0,
showRedDot: false,
pagePath: '/pages/profile/profile'
}
]);
// 切换tab
const switchTab = (index, item) => {
if (currentTab.value === index) return;
// 更新当前tab
currentTab.value = index;
// 清除红点
if (item.showRedDot) {
item.showRedDot = false;
}
// 页面跳转
uni.switchTab({
url: item.pagePath,
fail: () => {
// 如果页面不存在,使用navigateTo
uni.navigateTo({
url: item.pagePath,
fail: () => {
uni.showToast({
title: '页面开发中',
icon: 'none'
});
}
});
}
});
// 触发父组件事件
emit('tabChange', {
index,
item
});
};
// 设置徽章数量
const setBadge = (index, count) => {
if (index >= 0 && index < tabList.length) {
tabList[index].badge = count;
}
};
// 显示红点
const showRedDot = (index) => {
if (index >= 0 && index < tabList.length) {
tabList[index].showRedDot = true;
}
};
// 隐藏红点
const hideRedDot = (index) => {
if (index >= 0 && index < tabList.length) {
tabList[index].showRedDot = false;
}
};
// 设置当前tab
const setCurrentTab = (index) => {
if (index >= 0 && index < tabList.length) {
currentTab.value = index;
}
};
// 获取当前tab信息
const getCurrentTab = () => {
return {
index: currentTab.value,
item: tabList[currentTab.value]
};
};
// 更新tabbar数据
const updateTabList = (newTabList) => {
if (Array.isArray(newTabList)) {
tabList.splice(0, tabList.length, ...newTabList);
}
};
// 暴露方法给父组件
defineExpose({
setBadge,
showRedDot,
hideRedDot,
setCurrentTab,
getCurrentTab,
updateTabList,
currentTab,
tabList
});
// 页面加载时获取当前页面路径
onLoad(() => {
nextTick(() => {
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
const currentPath = '/' + currentPage.route;
// 根据当前页面路径设置选中的tab
const tabIndex = tabList.findIndex(item => item.pagePath === currentPath);
if (tabIndex !== -1) {
currentTab.value = tabIndex;
}
});
});
// 页面显示时更新状态
onShow(() => {
// 可以在这里更新徽章数量等状态
console.log('Tabbar onShow - 当前tab:', currentTab.value);
});
// 组件挂载后
onMounted(() => {
console.log('Tabbar组件已挂载');
});
</script>
<style scoped>
.custom-tabbar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
overflow-x: hidden;
height: 120rpx;
background-color: #ffffff;
display: flex;
justify-content: space-around;
align-items: center;
border-top: 2rpx solid #f0f0f0;
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.1);
z-index: 999;
padding-bottom: env(safe-area-inset-bottom);
}
.tabbar-item {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
flex: 1;
height: 100%;
transition: all 0.3s ease;
}
.img{
width: 46rpx;
height: 46rpx;
}
.icon-container {
width:100%;
overflow-x: hidden;
position: relative;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 8rpx;
}
.badge {
position: absolute;
top: -8rpx;
right: -8rpx;
z-index: 10;
}
.red-dot {
position: absolute;
top: -4rpx;
right: -4rpx;
width: 16rpx;
height: 16rpx;
background-color: #ff0000;
border-radius: 50%;
border: 2rpx solid #ffffff;
z-index: 10;
}
.tab-text {
font-size: 20rpx;
color: #999999;
transition: all 0.3s ease;
font-weight: 400;
}
.tab-text.active {
color: #8B2316;
font-weight: 600;
transform: scale(1.05);
}
.active-indicator {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 40rpx;
height: 4rpx;
background: linear-gradient(90deg, #007aff, #0056b3);
border-radius: 2rpx;
animation: slideIn 0.3s ease;
}
@keyframes slideIn {
from {
width: 0;
opacity: 0;
}
to {
width: 40rpx;
opacity: 1;
}
}
/* 点击效果 */
.tabbar-item:active {
transform: scale(0.95);
}
/* 响应式设计 */
@media (max-width: 750rpx) {
.custom-tabbar {
height: 100rpx;
}
.tab-text {
font-size: 18rpx;
}
}
/* 深色模式支持 */
@media (prefers-color-scheme: dark) {
.custom-tabbar {
background-color: #1c1c1e;
border-top-color: #2c2c2e;
}
.tab-text {
color: #8e8e93;
}
.tab-text.active {
color: #0a84ff;
}
}
</style>