uni-app微信小程序动态切换tabBar,根据不同用户角色展示不同的tabBar

news2024/12/25 8:59:46

前言

在UniApp的开发小程序过程中,为了针对不同角色用户登录后的个性化需求。通过动态权限配置机制,能够根据用户的角色展示不同的TabBar。此项目是通过Uni-App命令行的方式搭建的Vue3+Vite+Ts+Pinia+Uni-ui的小程序项目

最终效果

  • 1、司机角色:
    在这里插入图片描述

  • 2、供应商角色:
    在这里插入图片描述

  • 3、司机且供应商角色:
    在这里插入图片描述

目前常规的实现方式,大多数都是封装一个tabbar组件,在需要显示tabbar的页面添加这个组件,在根据一个选中的index值来切换选中效果。

而我的实现方式:把所有有tabbar的页面全部引入在一个tabbarPage页面,根据角色userType,来动态显示页面

实现思路

1、常规登录:通过微信登录获取code
2、根据code获取openId
3、根据openId获取token,若token存在表:此用户已经登陆/绑定过,则根据token获取用户信息,根据角色直接进入项目页面;若token不存在,则跳转到登录页面
4、登录成功后,调用用户信息接口,根据角色直接进入项目页面

1、以下是封装了一个useLogin的hooks


export const useLogin = () => {
  const { proxy } = getCurrentInstance() as any
  //常规登录
  const judgmentLogin = () => {
    uni.login({
      provider: 'weixin', //使用微信登录
      success: async (loginRes) => {
        // 根据微信登录的code获取openid
        const res = await proxy.$api.getOpenid({ code: loginRes.code })
        if (res.success) {
          // console.log('res.data.openid----', res.data.openId)
          // 根据openid获取token
          openidLogin(res.data.openId)
          // 存储openid
          uni.setStorageSync('openId', res.data.openId)
        }
      }
    });
  }
  // 登录过的用户再次进入根据openid获取token,有token则直接进入当前用户的页面,没有则进入登录页面
  const openidLogin = (async (openId: string) => {
    // console.log('openId----', openId)
    const res = await proxy.$api.openIdLogin({ openId })
    if (res.success) {
      if (res.data) {
        // 存储token
        uni.setStorageSync('token', res.data)
        userInfo(openId)
      } else {
        uni.navigateTo({
          url: '/pages/login/login'
        })
      }
    }
  })
// 登录成功后(有token后)根据openid获取用户信息
  const userInfo = (async (openId: any) => {
    const res = await proxy.$api.getUserInfo({ openId })
    if (res.success) {
      console.log('获取登陆用户信息', res.data)
      uni.setStorageSync('userInfo', JSON.stringify(res.data))
      const userTypeList = ['scm_driver', 'scm_supplier', 'supplier_and_driver']
      // 遍历角色数组来存储当前用户的角色。此角色为userTypeList中的某一个并且此数组只能存在一个userTypeList里面的角色,不会同时存在两个
      res.data.roles.map((item: any) => {
        if (userTypeList.includes(item.roleKey)) {
          uni.setStorageSync('userType', item.roleKey)
        }
      })
      // 判断角色数组中只要有一个角色在userTypeList中,则进入当前用户的角色页面,否则进入无权限页面
      const flag = res.data.roles.some((item: any) => {
        return userTypeList.includes(item.roleKey)
      })
      // console.log('flag----', flag)
      if (flag && userTypeList.includes(uni.getStorageSync('userType'))) {
        setTimeout(() => {
          uni.reLaunch({
            url: '/pages/tabbarPage/tabbarPage'
          })
        }, 500)
      } else {
        uni.showToast({
          icon: 'none',
          title: '当前用户角色没有权限!'
        })
      }
    }
  })
  return {
    judgmentLogin,
    userInfo
  }
}

2、修改page.json中的tabBar

"tabBar": {
		"color": "#a6b9cb",
		"selectedColor": "#355db4",
		"list": [
			{
				"pagePath": "pages/supplierMyorder/supplierMyorder"
			},
			{
				"pagePath": "pages/driverMyorder/driverMyorder"
			},
			{
				"pagePath": "pages/mycar/mycar"
			},
			{
				"pagePath": "pages/driverPersonal/driverPersonal"
			}
		]
	},

3、关键页面tabbarPage.vue

<template>
  <div class="tabbar_page flex-box flex-col">
    <div
      class="page_wrap"
      v-if="userType === 'scm_supplier'"
      v-show="active === 'supplierMyorder'"
    >
      <supplier-myorder
        ref="supplierMyorder"
        :show="active === 'supplierMyorder'"
      />
    </div>
    <div
      class="page_wrap"
      v-if="userType === 'scm_supplier'"
      v-show="active === 'supplierPersonal'"
    >
      <supplier-personal
        ref="supplierPersonal"
        :show="active === 'supplierPersonal'"
      />
    </div>
    <div
      class="page_wrap"
      v-if="userType === 'scm_driver'"
      v-show="active === 'driverMyorder'"
    >
      <driver-myorder ref="driverMyorder" :show="active === 'driverMyorder'" />
    </div>
    <div
      class="page_wrap"
      v-if="userType === 'scm_driver'"
      v-show="active === 'mycar'"
    >
      <mycar ref="mycar" :show="active === 'mycar'" />
    </div>
    <div
      class="page_wrap"
      v-if="userType === 'scm_driver'"
      v-show="active === 'driverPersonal'"
    >
      <driver-personal
        ref="driverPersonal"
        :show="active === 'driverPersonal'"
      />
    </div>
    <div
      class="page_wrap"
      v-if="userType === 'supplier_and_driver'"
      v-show="active === 'supplierMyorder'"
    >
      <supplier-myorder
        ref="supplierMyorder"
        :show="active === 'supplierMyorder'"
      />
    </div>
    <div
      class="page_wrap"
      v-if="userType === 'supplier_and_driver'"
      v-show="active === 'driverMyorder'"
    >
      <driver-myorder ref="driverMyorder" :show="active === 'driverMyorder'" />
    </div>
    <div
      class="page_wrap"
      v-if="userType === 'supplier_and_driver'"
      v-show="active === 'mycar'"
    >
      <mycar ref="mycar" :show="active === 'mycar'" />
    </div>
    <div
      class="page_wrap"
      v-if="userType === 'supplier_and_driver'"
      v-show="active === 'supplierPersonal'"
    >
      <supplier-personal
        ref="supplierPersonal"
        :show="active === 'supplierPersonal'"
      />
    </div>
    <view class="tab">
      <view
        v-for="(item, index) in tabbarOptions"
        :key="index"
        class="tab-item"
        @click="switchTab(item, index)"
      >
        <image
          class="tab_img"
          :src="currentIndex == index ? item.selectedIconPath : item.iconPath"
        ></image>
        <view
          class="tab_text"
          :style="{ color: currentIndex == index ? selectedColor : color }"
          >{{ item.text }}</view
        >
      </view>
    </view>
  </div>
</template>

<script lang="ts" setup>
import supplierMyorder from '@/pages/supplierMyorder/supplierMyorder.vue'
import supplierPersonal from '@/pages/supplierPersonal/supplierPersonal.vue'
import driverMyorder from '@/pages/driverMyorder/driverMyorder.vue'
import mycar from '@/pages/mycar/mycar.vue'
import driverPersonal from '@/pages/driverPersonal/driverPersonal.vue'
let color = ref('#666666')
let selectedColor = ref('#355db4')
let currentIndex = ref(0)

const active = ref('')
const switchTab = (item: any, index: any) => {
  // console.log('tabbar----switchTab-----list', item, index)
  currentIndex.value = index
  active.value = item.name
}

onLoad((option: any) => {
  currentIndex.value = option.index || 0
  active.value = option.name || tabbarOptions.value[0].name
})
onShow(() => {
  active.value = active.value || tabbarOptions.value[0].name
  currentIndex.value = currentIndex.value || 0
})
const userType = computed(() => {
  return uni.getStorageSync('userType')
})
const tabbarOptions = computed(() => {
  return {
    scm_supplier: [
      {
        name: 'supplierMyorder',
        pagePath: '/pages/supplierMyorder/supplierMyorder',
        iconPath: '/static/tabbar/order.png',
        selectedIconPath: '/static/tabbar/order_active.png',
        text: '我的订单'
      },
      {
        name: 'supplierPersonal',
        pagePath: '/pages/supplierPersonal/supplierPersonal',
        iconPath: '/static/tabbar/my.png',
        selectedIconPath: '/static/tabbar/my_active.png',
        text: '个人中心'
      }
    ],
    scm_driver: [
      {
        name: 'driverMyorder',
        pagePath: '/pages/driverMyorder/driverMyorder',
        iconPath: '/static/tabbar/waybill.png',
        selectedIconPath: '/static/tabbar/waybill_active.png',
        text: '我的运单'
      },
      {
        name: 'mycar',
        pagePath: '/pages/mycar/mycar',
        iconPath: '/static/tabbar/car.png',
        selectedIconPath: '/static/tabbar/car_active.png',
        text: '我的车辆'
      },
      {
        name: 'driverPersonal',
        pagePath: '/pages/driverPersonal/driverPersonal',
        iconPath: '/static/tabbar/my.png',
        selectedIconPath: '/static/tabbar/my_active.png',
        text: '个人中心'
      }
    ],
    supplier_and_driver: [
      {
        name: 'supplierMyorder',
        pagePath: '/pages/supplierMyorder/supplierMyorder',
        iconPath: '/static/tabbar/order.png',
        selectedIconPath: '/static/tabbar/order_active.png',
        text: '我的订单'
      },
      {
        name: 'driverMyorder',
        pagePath: '/pages/driverMyorder/driverMyorder',
        iconPath: '/static/tabbar/order.png',
        selectedIconPath: '/static/tabbar/order_active.png',
        text: '我的运单'
      },
      {
        name: 'mycar',
        pagePath: '/pages/mycar/mycar',
        iconPath: '/static/tabbar/car.png',
        selectedIconPath: '/static/tabbar/car_active.png',
        text: '我的车辆'
      },
      {
        name: 'supplierPersonal',
        pagePath: '/pages/supplierPersonal/supplierPersonal',
        iconPath: '/static/tabbar/my.png',
        selectedIconPath: '/static/tabbar/my_active.png',
        text: '个人中心'
      }
    ]
  }[userType.value]
})
</script>

<style lang="scss" scoped>
.tabbar_page {
  height: 100%;
  .page_wrap {
    height: calc(100% - 84px);
    &.hidden {
      display: none;
    }
  }
  .tab {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    height: 100rpx;
    background: white;
    display: flex;
    justify-content: center;
    align-items: center;
    padding-bottom: env(safe-area-inset-bottom); // 适配iphoneX的底部

    .tab-item {
      flex: 1;
      text-align: center;
      display: flex;
      justify-content: center;
      align-items: center;
      flex-direction: column;

      .tab_img {
        width: 45rpx;
        height: 45rpx;
      }

      .tab_text {
        font-size: 25rpx;
        margin: 9rpx 0;
      }
    }
  }
}
.flex-box {
  display: -webkit-box;
  display: -webkit-flex;
  display: flex;
}
.flex-col {
  flex-direction: column
}
</style>

相关文章

基于ElementUi再次封装基础组件文档


Vue3+Vite+Ts+Pinia+Qiankun后台管理系统


vue3+ts基于Element-plus再次封装基础组件文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1699882.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kubernetes(K8S) 集群环境搭建指南

Kubernetes&#xff08;简称K8s&#xff09;是一个开源的容器编排平台&#xff0c;旨在自动化部署、扩展和管理容器化应用。K8S环境搭建过程比较复杂&#xff0c;涉及到非常多组件安装和系统配置&#xff0c;本文将会详细介绍如何在服务器上搭建好Kubernetes集群环境。 在学习…

MybatisPlus中自定义sql

背景 在开发过程中&#xff0c;可能会出现除了where条件&#xff0c;其它sql比较复杂&#xff0c;这时候就需要用到自定义sql了。 问题 如&#xff1a;用户状态为正常的数据年龄加一&#xff08;所有用户年龄加一&#xff09; 数据库中sql&#xff1a; UPDATE USER SET…

Go GORM介绍

GORM 是一个功能强大的 Go 语言 ORM&#xff08;对象关系映射&#xff09;库&#xff0c;它提供了一种方便的方式来与 SQL 数据库进行交互&#xff0c;而不需要编写大量的 SQL 代码。 GORM的关键特性 全功能的ORM&#xff1a;支持几乎所有的ORM功能&#xff0c;包括模型定义、基…

【漏洞复现】英飞达医学影像存档与通信系统 WebJobUpload 任意文件上传漏洞

0x01 产品简介 英飞达医学影像存档与通信系统 Picture Archiving and Communicaton System&#xff0c;它是应用在医院影像科室的系统&#xff0c;主要的任务就是把日常产生的各种医学影像(包括核磁&#xff0c;CT&#xff0c;超声&#xff0c;各种X光机&#xff0c;各种红外仪…

如何编辑 PDF 中的文本?4个有效的编辑PDF方法

PDF 文件可以轻松打开和查看&#xff0c;但修改要复杂得多 - 尤其是在 PDF 中的文本编辑方面。 知道如何离线编辑 PDF 中的文本对于任何需要快速更改而无需在线加载文档或担心安全问题的人来说都非常有益。它使用户能够更好地控制他们的文档&#xff0c;并有更广泛的字体和图形…

详解 Scala 的集合类型

一、集合简介 1. 类型 序列 Seq&#xff1a;类似于 Java 中的 List 接口集 Set&#xff1a;类似于 Java 中的 Set 接口映射 Map&#xff1a;类似于 Java 中的 Map 接口所有的集合都扩展自 Iterable 特质 2. 不可变集合 位于 scala.collection.immutable 包&#xff0c;指该集…

【Linux】fork和exec中的信号继承探索

fork和exec中的信号继承探索 一、结论二、代码验证2.1 代码编写2.2 代码执行 三、linux源码验证四、APUE中的验证五、其他 一、结论 fork时子进程会继承父进程的信号处理方式&#xff0c;包括父进程设置信号为SIG_DFL或SIG_IGN或捕获后设置自定义处理函数。exce时子进程会继承…

有些错误,常犯常新、常新常犯:记录一个使用element-plus的tooltip组件的错误

使用element-plus的tooltip组件&#xff0c;最开始的写法是这样的&#xff1a; <el-tooltipclass"box-item"effect"dark"content"tooltip content" ><el-button v-if"isDisabled" :underline"false" type"pr…

一文扫尽Nas常用Docker软件

NAS&#xff08;Network Attached Storage&#xff0c;网络附加存储&#xff09;设备上的Docker软件选择取决于您的具体需求和用途。以下是一些NAS上常用的Docker软件推荐&#xff1a; Docker管理工具&#xff1a; Watchtower&#xff1a;它可以自动更新Docker容器中的镜像&…

从零开始学Vue3--环境搭建

1.搭建环境 下载nodejs nodejs下载地址 更新npm npm install -g npm 设置npm源&#xff0c;加快下载速度 npm config set registry https://registry.npmmirror.com 使用脚手架创建项目 npm create vuelatest 根据你的需要选择对应选项 进入新建的项目下载依赖 npm in…

kaggle竞赛实战3

接前文&#xff0c;本文主要做以下几件事&#xff1a; 1、把前面处理完的几个表拼成一个大表 2、做特征衍生&#xff08;把离散特征和连续特征两两组合得出&#xff09; # In[89]: #开始拼接表 transaction pd.concat([new_transaction, history_transaction], axis0, ignor…

STM32 USART的字符编码(发送器的实现逻辑)

目录 概述 1 字符编码 1.1 USART 字符说明 1.2 字长编程 2 发送器 2.1 字符发送 2.2 可配置的停止位 2.3 配置停止位方法 3 单字节通信 4 中断字符 5 空闲字符 概述 本文主要讲述STM32 USART的发送端功能实现的原理&#xff0c;包括字节编码长度&#xff0c;发送器…

Cyber Weekly #8

赛博新闻 1、微软召开年度发布会Microsoft Build 2024 本周&#xff08;5.22&#xff09;微软召开了年度发布会&#xff0c;Microsoft Build 2024&#xff0c;发布了包括大杀器 Copilot Studio 在内的 50 项更新。主要包括&#xff1a; 硬件层面&#xff1a;与英伟达 & A…

网络空间安全数学基础·群

重点&#xff1a; 1. 群及子群的定义及相关结论 2. 群的判断,子群的判断 3. 群的阶,元素的阶,它们的相互关系 4. 同态,同构,核子群 2.1群的定义 定义&#xff1a;设G是一非空集合。如果在G上定义了一个代数运算&#xff0c;称为乘法&#xff0c;记为ab&#xff0c;而且这个运…

【STL】C++ vector基本使用

目录 一 vector常见构造 1 空容器构造函数&#xff08;默认构造函数&#xff09; 2 Fill 构造函数 3 Range 构造函数 4 拷贝构造函数 5 C11构造 二 vector迭代器 1 begin && end 2 rbegin && rend 3 补充排序 三 vector 容量操作 1 size 2 resize …

进程信号(1)

目录 一、信号 1.1、生活中的信号 1.2、Linux中的信号 二、信号处理常见方式 三、信号的产生 3.1、简单理解信号的保存和发送 3.2、键盘产生信号 3.3、核心转储 3.4、系统调用接口产生信号 3.4.1、kill 3.4.2、raise 3.4.3、abort 3.5、软件条件产生信号 3.6、硬…

【操作系统】发展与分类(手工操作、批处理、分时操作、实时操作)

2.操作系统发展与分类 思维导图 手工操作阶段&#xff08;此阶段无操作系统&#xff09; 需要人工干预 缺点&#xff1a; 1.用户独占全机&#xff0c;资源利用率低&#xff1b; 2.CPU等待手工操作&#xff0c;CPU利用不充分。 批处理阶段&#xff08;操作系统开始出现&#x…

firewalld 防火墙

firewalld概述 Linux系统防火墙从CentOS7开始的默认防火墙工作在网络层&#xff0c;属于包过滤防火墙 Firewalld和iptables的关系 netfilter 位于Linux内核中的包过滤功能体系称为Linux防火墙的“内核态” firewalld Centos默认的管理防火墙规则的工具称为防火墙的“用…

【C++】右值引用 移动语义

目录 前言一、右值引用与移动语义1.1 左值引用和右值引用1.2 右值引用使用场景和意义1.3 右值引用引用左值及其一些更深入的使用场景分析1.3.1 完美转发 二、新的类功能三、可变参数模板 前言 本篇文章我们继续来聊聊C11新增的一些语法——右值引用&#xff0c;我们在之前就已…

sqli-lib4-6关教程

SERIES-4 输入?id1 输入?id2-1&#xff0c;说明该数据类型为字符型 输入?id1’ 输入?id1"&#xff0c;说明闭合符号为" 输入?id1")– 输入?id1") order by 3– 输入?id1") order by 4– 数据共三列&#xff0c;输入?id-1") union selec…