Tabbar 权限机制梳理(用于说明白“还有 tabbar 的权限”这一块)
2 小时前更新
路由来源与当前模块识别
- 各个 tab 页(商城首页、租赁管理首页、餐饮工作台等)在各自页面的
onShow里写入当前路由到 Pinia:- 典型代码(比如 [Workbench.vue](file:///d:/work/code/wat-front-end-h5/src/pages/community/workbench/Workbench.vue#L336-L357)、[BuildingList.vue](file:///d:/work/code/wat-front-end-h5/src/pages/rental-manage/building/BuildingList.vue#L742-L761)、[Mine.vue](file:///d:/work/code/wat-front-end-h5/src/pages/rental-manage/mine/Mine.vue#L13-L22)):ts
const commonStore = useCommonStore() const { ctx } = getCurrentInstance() onShow(() => { commonStore.setCommonData('curTabbarRoute', ctx.route) commonStore.setCommonData('isUpdateTabbar', false) })
- 典型代码(比如 [Workbench.vue](file:///d:/work/code/wat-front-end-h5/src/pages/community/workbench/Workbench.vue#L336-L357)、[BuildingList.vue](file:///d:/work/code/wat-front-end-h5/src/pages/rental-manage/building/BuildingList.vue#L742-L761)、[Mine.vue](file:///d:/work/code/wat-front-end-h5/src/pages/rental-manage/mine/Mine.vue#L13-L22)):
useTabbar钩子里通过curTabbarRoute反推出“当前属于哪个业务模块”:- 预先把所有 tabbar 项按模块归类成
modulePagePaths:tsconst modulePagePaths = computed(() => { const map: Record<TabbarItem['module'], string[]> = { default: [], rentalManage: [], mealAdmin: [], } tabbarList.value.forEach((item) => { map[item.module].push(item.pagePath) }) return map }) - 根据当前路由查找到所属模块:ts
const currentModule = computed(() => { const currentPagePath = curTabbarRoute.value return ( (Object.entries(modulePagePaths.value).find(([_, paths]) => paths.includes(currentPagePath), )?.[0] as TabbarItem['module']) || 'default' ) })
- 预先把所有 tabbar 项按模块归类成
- 各个 tab 页(商城首页、租赁管理首页、餐饮工作台等)在各自页面的
按模块过滤 Tabbar(模块级权限控制)
useTabbar中定义完整的tabbarList,每一项标记module: 'default' | 'rentalManage' | 'mealAdmin'(见 [useTabbar.ts](file:///d:/work/code/wat-front-end-h5/src/hooks/useTabbar.ts#L1-L121))。- 再通过
currentModule计算出当前模块下应该显示的 tabbar 项:tsconst filteredTabbarList = computed(() => { return tabbarList.value.filter((item) => item.module === currentModule.value) }) WatTabbar组件只渲染filteredTabbarList(见 [WatTabbar.vue](file:///d:/work/code/wat-front-end-h5/src/components/wat-tabbar/WatTabbar.vue#L1-L35)):vue<wd-tabbar :model-value="curTabbarRoute" @change="handleTabbarChange"> <block v-for="(item, index) in filteredTabbarList" :key="index"> <!-- 根据 iconType 决定展示方式,这里略 --> </block> </wd-tabbar>- 这样一来:
- 当当前路由在
默认商城模块时,只能看到商城相关 tab(首页/商城/购物车/停车优惠/我的)。 - 当当前路由在
租赁管理模块时,只能看到租赁相关 tab(首页/房产/数据概览 等)。 - 当当前路由在
餐饮管理模块时,只能看到餐饮工作台、数据概览、订单等 tab。
- 当当前路由在
- 这个就是“模块级的 Tabbar 权限控制”:不同业务角色或业务入口进来后,只暴露与当前模块相关的底部导航,避免跨模块互相跳转。
Tabbar 高亮与路由联动
useTabbar中通过watch(curTabbarRoute)在路由变化时自动维护active状态:tsconst setTabbarItemActive = () => { for (const item of tabbarList.value) { item.active = item.pagePath === curTabbarRoute.value } commonStore.setCommonData('isUpdateTabbar', true) } watch( () => curTabbarRoute.value, () => { if (isUpdateTabbar.value) return setTabbarItemActive() }, { immediate: true }, )WatTabbar使用curTabbarRoute作为wd-tabbar的model-value,并在@change事件中调用uni.switchTab({ url: \/${value}` })`,保证点击底部导航后走的是统一的 tabbar 路由切换逻辑。
Tabbar 与主题(皮肤)联动
- [tabbar.vue](file:///d:/work/code/wat-front-end-h5/src/layouts/tabbar.vue#L1-L74) 中通过
useTabbar拿到currentModule,再配合useTheme做主题切换:tsconst { currentModule } = useTabbar() const { theme, themeVars, switchTheme, toggleTheme } = useTheme() watchEffect(() => { switchTheme(currentModule.value) }) const themeClass = computed(() => { switch (currentModule.value) { case 'rentalManage': return 'rental-theme' default: return 'mall-theme' } }) - 同一套框架下,不同模块不仅 tabbar 不同,整体主题色、样式也一起切换,实现“模块隔离 + 视觉上也区分开”。
- [tabbar.vue](file:///d:/work/code/wat-front-end-h5/src/layouts/tabbar.vue#L1-L74) 中通过
Web / App 自定义 Tabbar 替换原生
- 底层用的是自定义 Tabbar Layout:
- H5 端通过 Teleport 挂到 uni 原生
.uni-tabbar的位置上,并主动移除原生 tabbar(见 [tabbar.vue](file:///d:/work/code/wat-front-end-h5/src/layouts/tabbar.vue#L27-L60))。 - App 端在
onShow里调用uni.hideTabBar()隐藏原生,再用自定义 Tabbar 占位。
- H5 端通过 Teleport 挂到 uni 原生
- 这样 route 拦截 + 自定义 tabbar 的权限过滤 是一套统一逻辑,保证多端行为一致。
- 底层用的是自定义 Tabbar Layout:
简历第 4 点(整合登录拦截 + 路由拦截 + Tabbar 权限)的优化写法
下面给你一个直接可用的“第 4 点”版本,把你之前的登录/路由/权限这块和 Tabbar 权限一并说清楚(偏真实项目说明风格):
4)负责前端登录与权限体系设计与落地:基于 uni-app 的路由拦截统一做登录校验,按 pages 元信息动态生成登录白名单,未登录访问受保护页面时自动重定向到登录页并带上 redirect;在 HTTP 拦截器中统一处理 401,结合节流避免重复弹登录。封装基于 Pinia 的
useTabbar钩子,将底部导航抽象为按业务模块(商城、租赁管理、餐饮管理)划分的配置表,通过当前路由反推所在模块并过滤可见 Tabbar 项,同时结合自定义 Tabbar + Teleport 替换原生 Tabbar,在 H5/APP 端实现“模块隔离的导航权限控制”和按模块切换主题皮肤。
如果你觉得太长,可以用一个稍微精简一点的版本:
4)搭建完整登录与前端权限体系:路由层通过白名单做登录拦截,401 由 HTTP 拦截器统一处理并引导重新登录;封装基于 Pinia 的
useTabbar,按业务模块(商城/租赁管理/餐饮管理)动态过滤底部导航项,并在 H5/APP 端用自定义 Tabbar 替换原生 Tabbar,实现多模块隔离的导航权限和主题切换。
你可以根据你简历整体篇幅选择“完整版”或“精简版”,内容上已经把“还有 tabbar 的权限”这一块融合进去了。
