uniapp踩坑之项目:简易版不同角色显示不一样的tabbar和页面

Vue2项目中的多用户权限管理与底部导航组件实现
文章详细描述了如何在Vue2项目中为不同用户角色(管理员、财务和司机)创建定制的底部导航,包括`cc-myTabbar`组件的结构、组件间的交互以及`pages.json`的配置。

1.

pages下创建三个不同用户身份的“我的”页面。

显示第几个tabbar,0是管理员 1是财务 2是司机

2.

在uni_modules文件夹创建底部导航cc-myTabbar文件夹,在cc-myTabbar文件夹创建components文件夹,在components文件夹创建cc-myTabbar.vue组件

3.

在utils文件夹创建tabBar.js

4.

pages.json里指定路径

5.

在单页面引入底部导航组件

 

//cc-myTabbar.vue 底部导航组件
<template>
  <view class="page-total">
    <view class="tab-list">
      <view class="list" v-for="(item,index) in TabBarList" @click="onTabBar(item,index)" :style="{marginTop: (item.name == '') ?  '-88rpx' : '0px'}" :key="item.index">
        <image :src="item.acImg" mode="widthFix" v-show="tabBarShow ===index" :style="{width: (item.name == '') ?  '100rpx' : '54rpx',borderRadius: (item.name == '') ?  '24rpx' : '0rpx'}"></image>
        <image :src="item.img" mode="widthFix" v-show="tabBarShow != index" :style="{width: (item.name == '') ?  '100rpx' : '54rpx',borderRadius: (item.name == '') ?  '24rpx' : '0rpx'}"></image>
        <text :class="{'action':tabBarShow===index}">{{item.name}}</text>
      </view>
    </view>
  </view>
</template>

<script>
import tabBar from "@/utils/tabBar.js"
// 判断当前登陆用户角色
// 0 为管理员
// 1 为财务
// 2 为司机

// 三元表达式判断当前登陆的用户角色
// var user_type = uni.getStorageSync("userType")
var user_type = 0
let type = user_type === 0 ? 'admin' : user_type === 1 ? "finance" : "driver"

const state = {
  list: tabBar[type]
}
// console.log(user_type, 'user_type');
// console.log(type, 'type');
// console.log(state, 'state');
export default {
  data () {
    return {
      TabBarList: state.list,
      codeheight: 0,
      isOverall: 0,
      phoneModel: '',
    };
  },
  props: {
    tabBarShow: {
      type: Number,
      default: 0,
    }
  },
  mounted () {
    try {
      const res = uni.getSystemInfoSync();
      let that = this;
      // 获取系统信息
      uni.getSystemInfo({
        success (res) {
          console.log(res.brand) //手机牌子
          console.log(res.model) //手机型号
          console.log(res.screenWidth) //屏幕宽度
          console.log(res.screenHeight) //屏幕高度
          that.codeheight = Math.round(res.screenHeight);
          that.phoneModel = res.model
          if (res.model.search('iPhone')) {
            that.isOverall = 0;
          } else if (Math.round(res.screenHeight) > 740) {
            that.isOverall = 1;
          }
          console.log(that.isOverall);
        }
      });
    } catch (e) {
      // error
    }
  },
  methods: {
    // 底部导航 跳转
    onTabBar (item, index) {
      // this.tabBarShow = index;
      // console.log(item, 'item');
      // console.log(index, 'index');

      if (user_type == 2) { // 司机
        switch (item.name) {
          case '首页':
            uni.switchTab({
              url: '/pages/homePage/homePage'
            })
            break;
          case '':
            //   uni.switchTab({
            //     url: '/pages/scan/scan'
            //   })
            // 允许从相机和相册扫码
            uni.scanCode({
              success: function (res) {
                console.log('条码类型:' + res.scanType);
                console.log('条码内容:' + res.result);
              }
            });
            break;
          case '我的':
            uni.switchTab({
              url: '/pages/mineDriver/mineDriver'
            })
            break;
        }
      } else if (user_type == 0) { //管理员
        switch (item.name) {
          case '首页':
            uni.switchTab({
              url: '/pages/homePage/homePage'
            })
            break;
          case '':
            //   uni.switchTab({
            //     url: '/pages/scan/scan'
            //   })
            // 允许从相机和相册扫码
            uni.scanCode({
              success: function (res) {
                console.log('条码类型:' + res.scanType);
                console.log('条码内容:' + res.result);
              }
            });
            break;
          case '我的':
            uni.switchTab({
              url: '/pages/mine/mine'
            })
            break;
        }
      } else { // 财务
        switch (item.name) {
          case '首页':
            uni.switchTab({
              url: '/pages/homePage/homePage'
            })
            break;
          case '':
            //   uni.switchTab({
            //     url: '/pages/scan/scan'
            //   })
            // 允许从相机和相册扫码
            uni.scanCode({
              success: function (res) {
                console.log('条码类型:' + res.scanType);
                console.log('条码内容:' + res.result);
              }
            });
            break;
          case '我的':
            uni.switchTab({
              url: '/pages/mineFinance/mineFinance'
            })
            break;
        }
      }

    }
  }
}
</script>

<style scoped lang="scss">
@import 'cc-myTabbar.scss';
</style>

//在components文件夹里创建cc-myTabbar.scss
//cc-myTabbar.scss
/* 主要颜色 */
$base: #508AF1; // 基础颜色

.page-total {
  position: fixed;
  left: 0;
  bottom: 0;
  width: 100%;
  // height: 100rpx;
}

.tab-list {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  height: 140rpx;
  padding-bottom: 20rpx;
  background-color: #FFFFFF;

  // border-top: 1px solid #e8e8e8;
  .list {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 38%;
    height: 120rpx;

    image {
      width: 48rpx;
      height: 48rpx;
      background-color: white;


    }

    text {
      color: #707070;
      font-weight: 900;
      font-size: 24rpx;
      margin-top: 10rpx;
    }

    .action {
      color: $base;
    }
  }
}
//tabBar.js
// 小程序管理者
const admin = [
  {
    pagePath: "/pages/homePage/homePage",
    index: 0,
    name: '首页',
    img: '/static/images/tabBar/tab_01.png',
    acImg: '/static/images/tabBar/tab_02.png'
  },
  // {
  //   index: 2,
  //   name: '',
  //   img: '/static/images/tabBar/tab_03.png',
  //   acImg: '/static/images/tabBar/tab_04.png'
  // },
  {
    pagePath: "/pages/mine/mine",
    index: 1,
    name: '我的',
    img: '/static/images/tabBar/tab_05.png',
    acImg: '/static/images/tabBar/tab_06.png'
  },
]
// 财务
const finance = [
  {
    pagePath: "/pages/homePage/homePage",
    index: 0,
    name: '首页',
    img: '/static/images/tabBar/tab_01.png',
    acImg: '/static/images/tabBar/tab_02.png'
  },
  // {
  //   index: 1,
  //   name: '',
  //   img: '/static/images/tabBar/tab_03.png',
  //   acImg: '/static/images/tabBar/tab_04.png'
  // },
  {
    pagePath: "/pages/mineFinance/mineFinance",
    index: 1,
    name: '我的',
    img: '/static/images/tabBar/tab_05.png',
    acImg: '/static/images/tabBar/tab_06.png'
  },
]

// 司机
const driver = [
  {
    pagePath: "/pages/homePage/homePage",
    index: 0,
    name: '首页',
    img: '/static/images/tabBar/tab_01.png',
    acImg: '/static/images/tabBar/tab_02.png'
  },
  // {
  //   pagePath: "/pages/scan/scan",
  //   index: 1,
  //   name: '',
  //   img: '/static/images/tabBar/tab_03.png',
  //   acImg: '/static/images/tabBar/tab_04.png'
  // },
  {
    pagePath: "/pages/mineDriver/mineDriver",
    index: 1,
    name: '我的',
    img: '/static/images/tabBar/tab_05.png',
    acImg: '/static/images/tabBar/tab_06.png'
  },
]

export default {
  admin,
  finance,
  driver
}
// pages.json
{
  "pages": [
    {
      "path": "pages/homePage/homePage",
      "style": {
        "navigationBarTitleText": "首页"
        // "navigationStyle": "custom"
      }
    },
    {
      "path": "pages/login",
      "style": {
        "navigationBarTitleText": "登录"
      }
    },
    {
      "path": "pages/register",
      "style": {
        "navigationBarTitleText": "注册"
      }
    },
    {
      "path": "pages/work/work",
      "style": {
        "navigationBarTitleText": "工作台"
      }
    },
    {
      "path": "pages/mine/mine", //管理员
      "style": {
        "navigationBarTitleText": "我的"
      }
    },
    {
      "path": "pages/mineDriver/mineDriver", // 司机
      "style": {
        "navigationBarTitleText": "我的"
      }
    },
    {
      "path": "pages/mineFinance/mineFinance", // 财务
      "style": {
        "navigationBarTitleText": "我的"
      }
    },
    {
      "path": "pages/mine/avatar/index",
      "style": {
        "navigationBarTitleText": "修改头像"
      }
    },
    {
      "path": "pages/mine/info/index",
      "style": {
        "navigationBarTitleText": "个人信息"
      }
    },
    {
      "path": "pages/mine/info/edit",
      "style": {
        "navigationBarTitleText": "编辑资料"
      }
    },
    {
      "path": "pages/mine/pwd/index",
      "style": {
        "navigationBarTitleText": "修改密码"
      }
    },
    {
      "path": "pages/mine/setting/index",
      "style": {
        "navigationBarTitleText": "应用设置"
      }
    },
    {
      "path": "pages/mine/help/index",
      "style": {
        "navigationBarTitleText": "常见问题"
      }
    },
    {
      "path": "pages/mine/about/index",
      "style": {
        "navigationBarTitleText": "关于我们"
      }
    },
  ],
  "tabBar": {
    "custom": true, // 隐藏tabBar
    "color": "#000000",
    "selectedColor": "#508af1", // 选中颜色
    "borderStyle": "white",
    "backgroundColor": "#ffffff",
    "list": [
      {
        "pagePath": "pages/homePage/homePage"
        // "iconPath": "static/images/tabbar/tab_01.png",
        // "selectedIconPath": "static/images/tabbar/tab_02.png",
        // "text": "首页"
      },
      // {
      //   "pagePath": "pages/work/work",
      //   "iconPath": "static/images/tabbar/work.png",
      //   "selectedIconPath": "static/images/tabbar/work_.png",
      //   "text": "工作台"
      // },
      {
        "pagePath": "pages/mine/mine"
        // "iconPath": "static/images/tabbar/tab_09.png",
        // "selectedIconPath": "static/images/tabbar/tab_10.png",
        // "text": "我的"
      },
      {
        "pagePath": "pages/mineDriver/mineDriver"
        // "iconPath": "static/images/tabbar/tab_09.png",
        // "selectedIconPath": "static/images/tabbar/tab_10.png",
        // "text": "我的"
      },
      {
        "pagePath": "pages/mineFinance/mineFinance"
        // "iconPath": "static/images/tabbar/tab_09.png",
        // "selectedIconPath": "static/images/tabbar/tab_10.png",
        // "text": "我的"
      }
    ]
  },
  "globalStyle": {
    "navigationBarTextStyle": "black",
    "navigationBarTitleText": "RuoYi",
    "navigationBarBackgroundColor": "#FFFFFF"
  }
}
// 单页面 
// mine.vue管理员版"我的"页面 / mineDriver.vue司机版"我的"页面 / mineFinance.vue财务版"我的"页面

<template>
  <view class="page">

    <!-- tabBarShow:显示第几个tabbar 0是管理员 1是财务 2是司机-->
    <cc-myTabbar :tabBarShow="0"></cc-myTabbar> 

  </view>
</template>

<script>
  export default {
    
    data() {
      return {

      };
    },
    onReady() {
      uni.hideTabBar()
    },

    methods: {

    }
  }
</script>

<style scoped lang="scss">
  page {
    padding-bottom: 140rpx;

  }
</style>

上一篇文章,

vue2踩坑之项目:vue2+element实现前端导出_vue2导出 type为text/plain 找不到状态code值-优快云博客文章浏览阅读392次,点赞8次,收藏9次。vue2踩坑之项目:vue2+element实现前端导出。安装插件依赖 npm i --save xlsx@0.17.0 file-saver@2.0.5,单页面引入 前端导出插件_vue2导出 type为text/plain 找不到状态code值https://blog.youkuaiyun.com/weixin_43928112/article/details/135685385

<think>根据用户需求,我们需要在UniApp中实现根据用户角色动态显示不同自定义TabBar的功能。结合引用内容,我们可以通过以下步骤实现: ### 实现思路 1. **用户登录时获取角色信息**并存储到本地存储(如`uni.setStorageSync`) 2. **创建多个TabBar组件**(不同角色对应不同TabBar) 3. **在页面中动态加载对应角色TabBar组件** 4. **切换角色时刷新TabBar** ### 具体步骤 #### 1. 用户登录时存储角色信息 在登录成功回调中,将用户角色类型存储到本地 ```javascript // 登录方法示例 methods: { async login() { const res = await uni.login() // 获取用户信息(包含角色) const userInfo = await this.$api.getUserInfo(res.code) // 存储角色类型 (假设userType: 1-家政人员, 2-司机) uni.setStorageSync('userType', userInfo.userType) // 根据角色跳转到对应首页 if (userInfo.userType === 1) { uni.reLaunch({ url: '/pages/homekeeper/index' }) } else { uni.reLaunch({ url: '/pages/driver/index' }) } } } ``` #### 2. 创建不同角色TabBar组件 ```bash components/ ├── tabbar/ │ ├── HomeKeeperTabbar.vue # 家政人员TabBar │ └── DriverTabbar.vue # 司机TabBar ``` #### 3. 动态加载TabBar组件 在页面中使用动态组件`<component :is="currentTabbar">` ```vue <!-- 页面模板 (如pages/index/index.vue) --> <template> <view> <!-- 页面内容 --> <!-- 动态TabBar --> <component :is="currentTabbar" :currentPage="currentPage" @change="handleTabChange" /> </view> </template> <script setup> import { ref, computed } from 'vue' import HomeKeeperTabbar from '@/components/tabbar/HomeKeeperTabbar.vue' import DriverTabbar from '@/components/tabbar/DriverTabbar.vue' // 获取当前角色类型 const userType = uni.getStorageSync('userType') // 计算当前TabBar组件 const currentTabbar = computed(() => { return userType === 1 ? HomeKeeperTabbar : DriverTabbar }) // 当前激活的页面索引 const currentPage = ref(0) // 处理Tab切换 const handleTabChange = (index) => { currentPage.value = index } </script> ``` #### 4. 角色切换时更新TabBar 当用户切换角色时,需要重新加载页面以更新TabBar ```javascript // 切换角色方法示例 function switchRole(userType) { uni.setStorageSync('userType', userType) uni.reLaunch({ url: '/pages/index/index' }) // 重新加载页面 } ``` ### 解决关键问题 #### 问题1:如何获取用户角色- 在登录接口返回中获取角色标识(如`userType`) - 存储在本地缓存(`uni.setStorageSync`) #### 问题2:如何避免页面闪烁? - 使用`v-if`控制组件显示时机 - 在`onShow`生命周期中更新角色状态 ```vue <script setup> import { ref, onMounted } from 'vue' const userType = ref(0) const showTabbar = ref(false) onMounted(() => { // 从缓存获取角色 userType.value = uni.getStorageSync('userType') || 0 showTabbar.value = true // 确保组件正确渲染后再显示 }) </script> <template> <!-- 动态组件使用v-if控制 --> <component v-if="showTabbar" :is="currentTabbar" /> </template> ``` #### 问题3:如何适配不同平台? - **微信小程序**:使用`"custom": true`配置自动隐藏原生TabBar[^1] - **其他平台**:在`onMounted`中调用`uni.hideTabBar()` ```javascript onMounted(() => { // 非微信小程序需手动隐藏原生TabBar if (process.env.UNI_PLATFORM !== 'mp-weixin') { uni.hideTabBar() } }) ``` ### 完整示例:家政人员TabBar组件 ```vue <!-- components/tabbar/HomeKeeperTabbar.vue --> <template> <view class="custom-tabbar"> <view v-for="(item, index) in tabList" :key="index" @click="switchTab(index)"> <image :src="currentPage === index ? item.selectedIconPath : item.iconPath"/> <text :style="{color: currentPage === index ? activeColor : color}">{{item.text}}</text> </view> </view> </template> <script setup> defineProps(['currentPage']) const tabList = [ { pagePath: "/pages/homekeeper/index", text: "首页", iconPath: "/static/tabbar/home.png", selectedIconPath: "/static/tabbar/home_active.png" }, { pagePath: "/pages/homekeeper/order", text: "订单", iconPath: "/static/tabbar/order.png", selectedIconPath: "/static/tabbar/order_active.png" } ] const switchTab = (index) => { uni.switchTab({ url: tabList[index].pagePath }) } </script> ``` ### 注意事项 1. **角色初始化**:在`App.vue`的`onLaunch`中检查登录状态 2. **缓存管理**:角色变更时及时更新缓存并重载页面 3. **组件复用**:相同功能项可提取为公共组件 4. **安全区域**:使用`uni.getSystemInfoSync()`获取安全区域高度适配全面屏 > 提示:此方案适用于角色类型较少的情况。如果角色类型多且差异大,建议使用完全独立的TabBar组件 §§相关问题§§ 1. 如何在UniApp中实现用户角色权限管理系统? 2. 自定义TabBar如何实现动画效果? 3. UniApp中如何全局监听用户角色变化?</think>在 UniApp 中实现根据用户角色动态显示不同自定义 TabBar,可以按照以下步骤操作: ### 实现方案 #### 1. 用户登录时存储角色信息 ```javascript // 登录回调函数 async onLoginSuccess(res) { if (res.code === 200) { // 存储用户角色信息 uni.setStorageSync("userRole", res.data.roleType); // 1-普通用户,2-管理员,3-商家 // 跳转到对应角色的首页 uni.reLaunch({ url: '/pages/index/index' }); } } ``` #### 2. 创建多个 TabBar 组件 按角色创建不同组件: ``` components/ ├── tabbar/ │ ├── CustomerTabbar.vue // 普通用户 │ ├── AdminTabbar.vue // 管理员 │ └── MerchantTabbar.vue // 商家 ``` #### 3. 创建动态加载器组件 ```vue <!-- components/tabbar/DynamicTabbar.vue --> <template> <component :is="currentTabbar" :currentPage="currentPage" @change="handleTabChange" /> </template> <script> import CustomerTabbar from './CustomerTabbar.vue'; import AdminTabbar from './AdminTabbar.vue'; import MerchantTabbar from './MerchantTabbar.vue'; export default { components: { CustomerTabbar, AdminTabbar, MerchantTabbar }, props: ['currentPage'], computed: { currentTabbar() { const role = uni.getStorageSync('userRole') || 1; // 根据角色返回对应组件 switch(role) { case 2: return 'AdminTabbar'; case 3: return 'MerchantTabbar'; default: return 'CustomerTabbar'; } } }, methods: { handleTabChange(index) { this.$emit('change', index); } } } </script> ``` #### 4.页面中使用动态 TabBar ```vue <!-- pages/index/index.vue --> <template> <view> <!-- 页面内容 --> <!-- 动态TabBar --> <DynamicTabbar :currentPage="currentPage" @change="switchTab" /> </view> </template> <script> import DynamicTabbar from '@/components/tabbar/DynamicTabbar.vue'; export default { components: { DynamicTabbar }, data() { return { currentPage: 0 } }, methods: { switchTab(index) { this.currentPage = index; // 实际切换页面的逻辑 const pages = ['/pages/home', '/pages/cart', '/pages/profile']; uni.switchTab({ url: pages[index] }); } } } </script> ``` #### 5. 配置 pages.json ```json { "pages": [ {"path": "pages/home", "style": {}}, {"path": "pages/cart", "style": {}}, {"path": "pages/profile", "style": {}} ], "tabBar": { "custom": true, "list": [ {"pagePath": "pages/home"}, {"pagePath": "pages/cart"}, {"pagePath": "pages/profile"} ] } } ``` ### 不同角色 TabBar 示例 #### 普通用户 TabBar ```vue <!-- CustomerTabbar.vue --> <template> <view class="tabbar"> <view v-for="(item, index) in tabs" :key="index" @click="switchTab(index)"> <image :src="currentPage === index ? item.selectedIcon : item.icon" /> <text>{{ item.text }}</text> </view> </view> </template> <script> export default { props: ['currentPage'], data() { return { tabs: [ { text: "首页", icon: "/static/home.png", selectedIcon: "/static/home-active.png" }, { text: "购物车", icon: "/static/cart.png", selectedIcon: "/static/cart-active.png" }, { text: "我的", icon: "/static/user.png", selectedIcon: "/static/user-active.png" } ] } }, methods: { switchTab(index) { this.$emit('change', index); } } } </script> ``` #### 管理员 TabBar ```vue <!-- AdminTabbar.vue --> <template> <view class="tabbar"> <view v-for="(item, index) in adminTabs" :key="index" @click="switchTab(index)"> <image :src="currentPage === index ? item.selectedIcon : item.icon" /> <text>{{ item.text }}</text> </view> </view> </template> <script> export default { props: ['currentPage'], data() { return { adminTabs: [ { text: "仪表盘", icon: "/static/dashboard.png", selectedIcon: "/static/dashboard-active.png" }, { text: "数据统计", icon: "/static/stats.png", selectedIcon: "/static/stats-active.png" }, { text: "系统设置", icon: "/static/settings.png", selectedIcon: "/static/settings-active.png" } ] } }, methods: { switchTab(index) { this.$emit('change', index); } } } </script> ``` ### 关键实现点 1. **角色存储与获取**: - 登录时使用 `uni.setStorageSync` 存储用户角色[^2] - 通过 `uni.getStorageSync` 获取当前角色 2. **动态组件切换**: - 使用 Vue 动态组件 `<component :is="currentTabbar">` - 根据角色计算返回对应组件 3. **角色变更处理**: ```javascript // 角色变更时刷新页面 function onRoleChanged(newRole) { uni.setStorageSync('userRole', newRole); uni.reLaunch({ url: '/pages/index/index' }); } ``` 4. **安全区域适配**: ```css /* 适配全面屏底部安全区域 */ .tabbar { padding-bottom: constant(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom); } ``` ### 注意事项 1. **首次加载处理**: - 在 `App.vue` 的 `onLaunch` 中检查登录状态 - 未登录用户使用默认角色 2. **性能优化**: - 使用 `v-if` 替代 `v-show` 避免隐藏组件继续渲染 - 较复杂 TabBar 使用 `lazy-load` 延迟加载 3. **状态同步**: - 使用 Vuex 管理全局角色状态 - 角色变更时通过 Vuex 通知所有页面 > 提示:对于角色类型较多的系统,建议使用配置化的 TabBar 数据,通过 API 动态获取角色对应的 TabBar 配置[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值