【uni-app】根据角色/身份切换显示不同的 自定义 tabbar

发布于:2025-08-16 ⋅ 阅读:(19) ⋅ 点赞:(0)

自定义 tabbar

pages.json 配置文件

{
  "tabBar": {
    "custom": true,
    "color": "#7A7E83",
    "selectedColor": "#3cc51f",
    "backgroundColor": "#ffffff",
    // list 最少两个,最多只能配置五个,所以放五个核心页面
    "list": [
      {
        "iconPath": "static/tabbar/home.png",
        "selectedIconPath": "static/tabbar/home_active.png",
        "pagePath": "pages/index/index",
        "text": "首页",
        "visible": true,
      },
      {
        "iconPath": "static/tabbar/contract.png",
        "selectedIconPath": "static/tabbar/contract_active.png",
        "pagePath": "pages/contract/index",
        "text": "合同平台",
        "visible": true,
      },
      {
        "iconPath": "static/tabbar/oa.png",
        "selectedIconPath": "static/tabbar/oa_active.png",
        "pagePath": "pages/oa/index",
        "text": "OA办公",
        "visible": true,
      },
      {
        "iconPath": "static/tabbar/seal.png",
        "selectedIconPath": "static/tabbar/seal_active.png",
        "pagePath": "pages/seal/index",
        "text": "印章管理",
        "visible": true,
      },
      {
        "iconPath": "static/tabbar/my.png",
        "selectedIconPath": "static/tabbar/my_active.png",
        "pagePath": "pages/my/index",
        "text": "我的",
        "visible": true,
      }
    ]
  }
}

角色配置

根据角色/身份自定义 tabbar 的方案

  • 企业身份:显示首页、合同平台、OA办公、印章管理、我的这五项
  • 个人身份:首页、我的这两项

tabbarList.ts

import type { TabBar } from '@uni-helper/vite-plugin-uni-pages'

interface TabbarItem {
  iconPath: string
  selectedIconPath: string
  pagePath: string
  text: string
  visible?: boolean
}

// visible: false 让 H5 模式隐藏原生的 tabbar,显示自定义的 tabbar
export const companyTabbarList: TabbarItem[] = [
  {
    iconPath: '/static/tabbar/home.png',
    selectedIconPath: '/static/tabbar/home_active.png',
    pagePath: 'pages/index/index',
    text: '首页',
    visible: false,
  },
  {
    iconPath: '/static/tabbar/contract.png',
    selectedIconPath: '/static/tabbar/contract_active.png',
    pagePath: 'pages/contract/index',
    text: '合同平台',
    visible: false,
  },
  {
    iconPath: '/static/tabbar/oa.png',
    selectedIconPath: '/static/tabbar/oa_active.png',
    pagePath: 'pages/oa/index',
    text: 'OA审批',
    visible: false,
  },
  {
    iconPath: '/static/tabbar/seal.png',
    selectedIconPath: '/static/tabbar/seal_active.png',  
    pagePath: 'pages/seal/index',
    text: '印章管理',
    visible: false,
  },
  {
    iconPath: '/static/tabbar/my.png',
    selectedIconPath: '/static/tabbar/my_active.png',
    pagePath: 'pages/my/index',
    text: '我的',
    visible: false,
  },
]

export const personalTabbarList: TabbarItem[] = [
  {
    iconPath: '/static/tabbar/home.png',
    selectedIconPath: '/static/tabbar/home_active.png',
    pagePath: 'pages/index/index',
    text: '首页',
    visible: false,
  },
  {
    iconPath: '/static/tabbar/my.png',
    selectedIconPath: '/static/tabbar/my_active.png',
    pagePath: 'pages/my/index',
    text: '我的',
    visible: false,
  },
]


const _tabbar: TabBar = {
  custom: true,
  color: '#999999',
  selectedColor: '#1161ff',
  backgroundColor: '#ffffff',
  borderStyle: 'black',
  height: '50px',
  fontSize: '12px',
  iconWidth: '24px',
  spacing: '3px',
  list: companyTabbarList as unknown as TabBar['list'],
}

export const tabBar = _tabbar

export const ROLE_TABBAR_CONFIG = {
  company: companyTabbarList,
  personal: personalTabbarList,
}

状态管理

  • 登录后获取用户角色/身份
  • 根据角色/身份切换 tabbar 配置
  • 监听路由变化,根据当前路由判断是否需要切换 tabbar 配置

tabbarStore.ts

import { reactive} from 'vue'
import { ROLE_TABBAR_CONFIG } from './tabbarList'


export const tabbarStore = reactive({
  // 当前选中的 tabbar 索引
  curIdx: 0,
  // 当前用户角色/身份
  userRole: 'company', // company | personal
  // 根据角色获取 tabbar 配置
  // 根据角色获取tabbar配置
  get currentTabbarList() {
    return ROLE_TABBAR_CONFIG[this.userRole] || []
  },
  // 切换 tabbar 配置
  switchRole(role: 'company' | 'personal') {
    this.userRole = role
    this.curIdx = 0
    uni.setStorageSync('userRole', role)
    uni.setStorageSync('tabbarIndex', 0)
  },
  // 初始化
  init() {
    this.userRole = uni.getStorageSync('userRole') || 'company'
    this.curIdx = uni.getStorageSync('tabbarIndex') || 0
  }
})

使用Wot UI 的 tabbar 组件

<script setup lang="ts">
import { tabbarStore } from './tabbarStore'
import { computed, watch } from 'vue'

// 使用 computed 确保响应式更新
const tabbarList = computed(() => tabbarStore.currentTabbarList)

// 监听角色变化,重新初始化 tabbar 索引
watch(() => tabbarStore.userRole, () => {
  initTabbarIndex()
}, { immediate: false, deep: true })

// 根据当前页面路径初始化 tabbar 状态
const initTabbarIndex = () => {
  const pages = getCurrentPages()
  if (pages.length > 0) {
    const currentPage = pages[pages.length - 1]
    const currentRoute = currentPage.route
    const currentIndex = tabbarList.value.findIndex(item => item.pagePath === currentRoute)
    if (currentIndex !== -1) {
      tabbarStore.curIdx = currentIndex
      uni.setStorageSync('tabbarIndex', currentIndex)
    }
  }
}

const handleActiveTab = ({ value }) => {
  const targetPage = tabbarList.value[value]
  if (targetPage) {
    tabbarStore.curIdx = value
    uni.setStorageSync('tabbarIndex', value)
    uni.switchTab({ url: `/${targetPage.pagePath}` })
  }
}

// 组件挂载时初始化 tabbar 状态
onMounted(() => {
  tabbarStore.init()
  initTabbarIndex()
})
</script>

<template>
  <view class="custom-tabbar">
    <wd-tabbar v-model="tabbarStore.curIdx" bordered safeareainsetbottom placeholde fixed activeColor="var(--main-color)"
      inactiveColor="#999999" @change="handleActiveTab">
      <wd-tabbar-item v-for="(value, index) in tabbarList" :key="value.selectedIconPath" :title="value.text">
        <template #icon>
          <img :src="tabbarStore.curIdx === index ? value.selectedIconPath : value.iconPath" class="w-24px h-24px" alt="">
        </template>
      </wd-tabbar-item>
    </wd-tabbar>
  </view>
</template>

<style scoped>

</style>


切换身份

// 用户登录成功后
const handleLoginSuccess = (userInfo) => {
  const userRole = userInfo.userType === 1 ? 'company' : 'personal'
  tabbarStore.switchRole(userRole)
  
  // 跳转到对应角色的首页
  uni.reLaunch({
    url: `/${tabbarStore.currentTabbarList[0].pagePath}`
  })
}

超过五个菜单?

这样的话还是从需求上去解决,最多只显示五个菜单(因为我们要使用uni.switchTab),其他菜单可以放到首页或者专门的一个 tabbar 页面中去让用户点击进入,如二级菜单

参考

在这里插入图片描述

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到