information.vue 9.06 KB
<template>
	<view class="page">
		<!-- 自定义导航栏 -->
		<custom-navbar :title="currentNavbarTitle" :show-background="false" titleColor="#1f2937"
		@height-change="handleNavbarHeightChange" backgroundColor="#fff"></custom-navbar>

		<!-- 内容区域 -->
		<view class="content-wrapper" :style="{ marginTop: contentTopMargin }">
			<!-- 集团驾驶舱组件 -->
			<dashboard-page v-if="currentComponent === 'dashboard'" ref="dashboardPage" />
			
			<!-- 门店数据组件 -->
			<store-dashboard-page v-if="currentComponent === 'store-dashboard'" ref="storeDashboardPage" />
			
			<!-- 科技部数据组件 -->
			<tech-department-dashboard-page v-if="currentComponent === 'tech-department-dashboard'" ref="techDepartmentDashboardPage" />
			
			<!-- 事业部数据组件 -->
			<business-unit-dashboard-page v-if="currentComponent === 'business-unit-dashboard'" ref="businessUnitDashboardPage" />
			
			<!-- 拓客报表组件 -->
			<daily-report-page v-if="currentComponent === 'daily-report'" ref="dailyReportPage" />
			
		</view>

		<!-- 悬浮切换按钮 -->
		<view class="floating-switch-btn" @click="showSwitchMenu = !showSwitchMenu">
			<u-icon name="grid" size="24" color="#fff"></u-icon>
		</view>
		
		<!-- 切换菜单 -->
		<view class="switch-menu" v-if="showSwitchMenu">
			<view 
				class="menu-item" 
				v-for="item in componentList" 
				:key="item.key"
				:class="{ active: currentComponent === item.key }"
				@click="switchComponent(item.key)">
				<u-icon :name="item.icon" size="18" :color="currentComponent === item.key ? '#409EFF' : '#666'"></u-icon>
				<text class="menu-text">{{ item.label }}</text>
			</view>
		</view>

		<!-- 遮罩层,点击关闭菜单 -->
		<view class="mask" v-if="showSwitchMenu" @click="showSwitchMenu = false"></view>

		<!-- 自定义 tabBar -->
		<custom-tab-bar />
	</view>
</template>

<script>
	import CustomTabBar from '@/components/custom-tab-bar/index.vue'
	import CustomNavbar from '@/components/custom-navbar/custom-navbar.vue'
	// 引入页面组件
	import DashboardPage from '@/pagesA/dashboard/dashboard.vue'
	import StoreDashboardPage from '@/pagesA/store-dashboard/store-dashboard.vue'
	import TechDepartmentDashboardPage from '@/pagesA/tech-department-dashboard/tech-department-dashboard.vue'
	import BusinessUnitDashboardPage from '@/pagesA/business-unit-dashboard/business-unit-dashboard.vue'
	import DailyReportPage from '@/pagesA/dailyReport/dailyReport.vue'

	export default {
		components: {
			CustomTabBar,
			CustomNavbar,
			DashboardPage,
			StoreDashboardPage,
			TechDepartmentDashboardPage,
			BusinessUnitDashboardPage,
			DailyReportPage
		},
		data() {
			return {
				navbarHeightRpx: 0,
				currentComponent: '', // 当前显示的组件,根据权限动态设置
				showSwitchMenu: false, // 是否显示切换菜单
				menuData: [], // 从 API 获取的菜单数据
				componentListData: [] // 解析后的组件列表数据
			}
		},
		computed: {
			// 内容区域顶部间距
			contentTopMargin() {
				if (this.navbarHeightRpx > 0) {
					return (this.navbarHeightRpx + 20) + 'rpx'
				}
				return '100rpx'
			},
			// 组件列表(从动态数据获取)
			componentList() {
				return this.componentListData
			},
			// 根据当前组件动态返回导航栏标题
			currentNavbarTitle() {
				const component = this.componentList.find(item => item.key === this.currentComponent)
				return component ? component.label : '数据中心'
			}
		},
		onLoad() {
			// 加载菜单数据
			// this.loadMenuData()
		},
		onShow() {
			// 重新加载菜单数据
			this.loadMenuData()
			// 页面加载时初始化默认组件
			this.$nextTick(() => {
				this.initCurrentComponent()
			})
			// this.switchComponent('tech-department-dashboard')
		},
		watch: {
			// 监听组件切换,调用子组件的初始化方法
			currentComponent(newVal) {
				if (newVal) {
					this.$nextTick(() => {
						this.initCurrentComponent()
					})
				}
			},
			// 监听组件列表变化,设置默认组件
			componentList(newList) {
				if (newList.length > 0 && !this.currentComponent) {
					this.currentComponent = newList[0].key
				}
			}
		},
		methods: {
			// 加载菜单数据
			loadMenuData() {
				// 先从本地存储读取
				const cachedData = uni.getStorageSync('appMenuData')
				if (cachedData && Array.isArray(cachedData) && cachedData.length > 0) {
					this.menuData = cachedData
					this.parseMenuData()
					return
				}
				
				// 如果本地没有,则调用 API
				const userInfo = uni.getStorageSync('userInfo')
				if (!userInfo || !userInfo.userId) {
					return
				}
				
				this.API.getAppAuthorize().then(res => {
					if (res.code === 200 && res.data) {
						this.menuData = res.data
						uni.setStorageSync('appMenuData', res.data)
						this.parseMenuData()
					}
				}).catch(err => {
					console.error('获取菜单数据失败:', err)
				})
			},
			
			// 解析菜单数据
			parseMenuData() {
				if (!this.menuData || this.menuData.length === 0) {
					return
				}
				
				// 找到根节点(fullName 为 "app数据中心" 的节点)
				const rootNode = this.menuData.find(item => item.fullName === 'app数据中心')
				if (!rootNode || !rootNode.children) {
					return
				}
				
				// 解析每个子节点,转换为组件列表
				this.componentListData = rootNode.children
					.filter(item => item.isLeaf && item.children === null) // 只取叶子节点
					.map(item => {
						// description 字段包含图标名称
						const icon = (item.description || '').trim()
						// 根据 fullName 获取对应的 component key
						const key = this.getComponentKeyByFullName(item.fullName)
						
						return {
							key: key,
							label: item.fullName,
							icon: icon,
							sortCode: item.sortCode || 0
						}
					})
					.sort((a, b) => a.sortCode - b.sortCode) // 按 sortCode 排序
				
				// 如果列表不为空且当前组件为空,设置默认组件
				if (this.componentListData.length > 0 && !this.currentComponent) {
					this.currentComponent = this.componentListData[0].key
				}
			},
			
			// 根据 fullName 获取对应的 component key
			getComponentKeyByFullName(fullName) {
				const keyMap = {
					'集团驾驶舱': 'dashboard',
					'门店数据': 'store-dashboard',
					'科技部数据': 'tech-department-dashboard',
					'事业部数据': 'business-unit-dashboard',
					'拓客报表': 'daily-report'
				}
				
				return keyMap[fullName] || ''
			},
			// 处理导航栏高度变化
			handleNavbarHeightChange(heightInfo) {
				this.navbarHeightRpx = heightInfo.rpx || 0
			},
			// 切换组件
			switchComponent(key) {
				this.currentComponent = key
				this.showSwitchMenu = false
			},
			// 初始化当前组件
			initCurrentComponent() {
				const refMap = {
					'dashboard': 'dashboardPage',
					'store-dashboard': 'storeDashboardPage',
					'tech-department-dashboard': 'techDepartmentDashboardPage',
					'business-unit-dashboard': 'businessUnitDashboardPage',
					'daily-report': 'dailyReportPage'
				}
				
				const refName = refMap[this.currentComponent]
				if (refName && this.$refs[refName]) {
					const component = this.$refs[refName]
					if (component && typeof component.init === 'function') {
						component.init()
					}
				}
			}
		}
	}
</script>

<style lang="scss" scoped>

	.content-wrapper {
		position: absolute;
		left: 0;
		top: 0;
		width: 100%;
		height: calc(100% - 100rpx); // 减去 tabBar 高度
		overflow-y: auto;
		overflow-x: hidden;
		
		// 确保子组件占满容器
		> view {
			width: 100%;
			min-height: 100%;
		}
	}

	// 悬浮切换按钮
	.floating-switch-btn {
		position: fixed;
		right: 50rpx;
		bottom: 200rpx; // 在 tabBar 上方
		width: 100rpx;
		height: 100rpx;
		background: linear-gradient(135deg, #409EFF 0%, #67C23A 100%);
		border-radius: 50%;
		display: flex;
		align-items: center;
		justify-content: center;
		box-shadow: 0 8rpx 24rpx rgba(64, 158, 255, 0.4);
		z-index: 1001; // 确保在 tabBar (z-index: 999) 上方
		transition: all 0.3s ease;

		&:active {
			transform: scale(0.95);
		}
	}

	// 切换菜单
	.switch-menu {
		position: fixed;
		right: 30rpx;
		bottom: 270rpx;
		background: #fff;
		border-radius: 24rpx;
		padding: 20rpx 0;
		box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.15);
		z-index: 1002; // 确保在按钮上方
		min-width: 240rpx;
		animation: slideUp 0.3s ease;

		.menu-item {
			display: flex;
			align-items: center;
			padding: 24rpx 32rpx;
			transition: all 0.2s ease;

			&:active {
				background-color: #f5f7fa;
			}

			&.active {
				background-color: #ecf5ff;

				.menu-text {
					color: #409EFF;
					font-weight: 600;
				}
			}

			.menu-text {
				margin-left: 16rpx;
				font-size: 28rpx;
				color: #333;
			}
		}
	}

	// 遮罩层
	.mask {
		position: fixed;
		left: 0;
		top: 0;
		width: 100%;
		height: 100%;
		background-color: rgba(0, 0, 0, 0.3);
		z-index: 1000; // 在 tabBar 上方,但在按钮和菜单下方
		animation: fadeIn 0.3s ease;
	}

	@keyframes slideUp {
		from {
			opacity: 0;
			transform: translateY(20rpx);
		}
		to {
			opacity: 1;
			transform: translateY(0);
		}
	}

	@keyframes fadeIn {
		from {
			opacity: 0;
		}
		to {
			opacity: 1;
		}
	}
</style>