168 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Vue
		
	
	
	
			
		
		
	
	
			168 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Vue
		
	
	
	
| <template>
 | |
| 	<view class="custom-tab-bar">
 | |
| 		<view class="tab-bar-border"></view>
 | |
| 		<view 
 | |
| 			class="tab-bar-item" 
 | |
| 			v-for="(item, index) in tabList" 
 | |
| 			:key="index" 
 | |
| 			@click="switchTab(item, index)"
 | |
| 		>
 | |
| 			<view class="item-container" :class="{ active: currentIndex === index }">
 | |
| 				<view class="icon-container">
 | |
| 					<image :src="currentIndex === index ? item.selectedIconPath : item.iconPath" class="tab-icon"></image>
 | |
| 					<!-- 添加消息提示点 -->
 | |
| 					<view v-if="item.isDot && index !== currentIndex" class="tab-badge"></view>
 | |
| 					<view v-if="item.count && item.count > 0 && index !== currentIndex" class="tab-badge-count">{{item.count}}</view>
 | |
| 				</view>
 | |
| 				<text class="tab-text" :class="{ active: currentIndex === index }">{{ item.text }}</text>
 | |
| 				
 | |
| 				<!-- 添加活跃项的动画效果 -->
 | |
| 				<view v-if="currentIndex === index" class="active-indicator"></view>
 | |
| 			</view>
 | |
| 		</view>
 | |
| 	</view>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| 	export default {
 | |
| 		data() {
 | |
| 			return {
 | |
| 				currentIndex: 0,
 | |
| 				tabList: []
 | |
| 			}
 | |
| 		},
 | |
| 		created() {
 | |
| 			// 从Vuex获取tabBar配置
 | |
| 			this.tabList = this.vuex_tabbar;
 | |
| 			
 | |
| 			// 根据当前页面路径设置激活项
 | |
| 			const pages = getCurrentPages();
 | |
| 			const currentPage = pages[pages.length - 1];
 | |
| 			const currentPath = '/' + currentPage.route;
 | |
| 			
 | |
| 			this.tabList.forEach((item, index) => {
 | |
| 				// 移除前导斜杠以匹配路由
 | |
| 				const itemPath = item.pagePath.startsWith('/') ? item.pagePath.substring(1) : item.pagePath;
 | |
| 				if (itemPath === currentPage.route) {
 | |
| 					this.currentIndex = index;
 | |
| 				}
 | |
| 			});
 | |
| 		},
 | |
| 		methods: {
 | |
| 			switchTab(item, index) {
 | |
| 				if (this.currentIndex === index) return;
 | |
| 				
 | |
| 				this.currentIndex = index;
 | |
| 				// 移除前导斜杠如果存在
 | |
| 				const pagePath = item.pagePath.startsWith('/') ? item.pagePath : '/' + item.pagePath;
 | |
| 				uni.switchTab({
 | |
| 					url: pagePath
 | |
| 				});
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| </script>
 | |
| 
 | |
| <style lang="scss" scoped>
 | |
| 	.custom-tab-bar {
 | |
| 		position: fixed;
 | |
| 		bottom: 0;
 | |
| 		left: 0;
 | |
| 		right: 0;
 | |
| 		height: 56px;
 | |
| 		background-color: #ffffff;
 | |
| 		display: flex;
 | |
| 		padding-bottom: env(safe-area-inset-bottom);
 | |
| 		box-shadow: 0 -1px 5px rgba(0, 0, 0, 0.05);
 | |
| 		z-index: 999;
 | |
| 		
 | |
| 		.tab-bar-border {
 | |
| 			position: absolute;
 | |
| 			left: 0;
 | |
| 			top: 0;
 | |
| 			width: 100%;
 | |
| 			height: 1px;
 | |
| 			background-color: #f5f5f5;
 | |
| 			transform: scaleY(0.5);
 | |
| 		}
 | |
| 		
 | |
| 		.tab-bar-item {
 | |
| 			flex: 1;
 | |
| 			display: flex;
 | |
| 			justify-content: center;
 | |
| 			align-items: center;
 | |
| 			height: 100%;
 | |
| 			
 | |
| 			.item-container {
 | |
| 				display: flex;
 | |
| 				flex-direction: column;
 | |
| 				align-items: center;
 | |
| 				justify-content: center;
 | |
| 				position: relative;
 | |
| 				padding: 5px 0;
 | |
| 				
 | |
| 				&.active {
 | |
| 					transform: scale(1.05);
 | |
| 					transition: all 0.2s ease;
 | |
| 				}
 | |
| 				
 | |
| 				.icon-container {
 | |
| 					position: relative;
 | |
| 					
 | |
| 					.tab-icon {
 | |
| 						width: 24px;
 | |
| 						height: 24px;
 | |
| 						margin-bottom: 3px;
 | |
| 					}
 | |
| 					
 | |
| 					.tab-badge {
 | |
| 						position: absolute;
 | |
| 						top: -2px;
 | |
| 						right: -2px;
 | |
| 						width: 8px;
 | |
| 						height: 8px;
 | |
| 						border-radius: 50%;
 | |
| 						background-color: #ff5252;
 | |
| 					}
 | |
| 					
 | |
| 					.tab-badge-count {
 | |
| 						position: absolute;
 | |
| 						top: -5px;
 | |
| 						right: -5px;
 | |
| 						min-width: 16px;
 | |
| 						height: 16px;
 | |
| 						border-radius: 8px;
 | |
| 						background-color: #ff5252;
 | |
| 						color: #ffffff;
 | |
| 						font-size: 10px;
 | |
| 						line-height: 16px;
 | |
| 						text-align: center;
 | |
| 						padding: 0 4px;
 | |
| 					}
 | |
| 				}
 | |
| 				
 | |
| 				.tab-text {
 | |
| 					font-size: 12px;
 | |
| 					color: #999999;
 | |
| 					line-height: 1.2;
 | |
| 					
 | |
| 					&.active {
 | |
| 						color: #2979FF;
 | |
| 						font-weight: 500;
 | |
| 					}
 | |
| 				}
 | |
| 				
 | |
| 				.active-indicator {
 | |
| 					position: absolute;
 | |
| 					bottom: -8px;
 | |
| 					left: 50%;
 | |
| 					transform: translateX(-50%);
 | |
| 					width: 16px;
 | |
| 					height: 3px;
 | |
| 					background-color: #2979FF;
 | |
| 					border-radius: 3px;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| </style>  |