更新记录

1.1.3(2024-07-03) 下载此版本

修改适配小程序,区分小程序和H5.APP,不同权限

1.1.2(2024-06-28) 下载此版本

新增菜单权限,模拟不同账号登录获取不同菜单

1.1.1(2024-06-27) 下载此版本

解决微信小程序,H5第一次点击闪烁的问题,App没测试

查看更多

平台兼容性

Vue2 Vue3
App 快应用 微信小程序 支付宝小程序 百度小程序 字节小程序 QQ小程序
HBuilderX 4.02 app-vue app-nvue
钉钉小程序 快手小程序 飞书小程序 京东小程序
H5-Safari Android Browser 微信浏览器(Android) QQ浏览器(Android) Chrome IE Edge Firefox PC-Safari
组件:
<template>
    <view class="tabbar_pages">
        <view class="uni-tabbar">
            <view class="tababr_item tabbar_find" v-for="(item,index) in tabbarListPage" :key="index"
                @click="tabbarSave(index)">
                <view class="tabbar_icon" v-if="item.type == 0">
                    <image :src="item.icon_select" class="select_img" mode="" v-if="index == pagePathIndex"></image>
                    <image :src="item.icon" mode="" v-else></image>
                </view>
                <view class="find_icon" v-if="item.type == 1">
                    <view class="icon">
                        <image :src="item.icon_select" class="select_img" mode="" v-if="index == pagePathIndex">
                        </image>
                        <image :src="item.icon" mode="" v-else></image>
                    </view>
                </view>
                <view class="tababr_text">{{item.text}}</view>
            </view>
        </view>
    </view>
</template>

<script>
    export default {
        props: { 
            pagePathIndex: {
                default: 0,
                type: Number
            },
            tabbarListPage:{
                default:()=>[],
                type:Array
            }
        },
        data() {
            return {
                showPage: false,
                page: '',  
            };
        },
        methods: {
            tabbarSave(index) {
                this.$emit('tabbarSave', index)
            }
        }
    }
</script>

<style lang="scss">
    .uni-tabbar {
        position: fixed;
        bottom: 0;
        left: 0;
        z-index: 999;
        width: 100%;
        display: flex;
        justify-content: space-around;
        height: 100upx;
        box-sizing: border-box;
        background-color: #fff;
        box-shadow: 0px 0px 17rpx 1rpx rgba(206, 206, 206, 0.32);

        .tabbar_find {
            text-align: center;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;

            .find_icon {
                width: 60px;
                height: 55px;
                margin-top: -30px;
                background-color: #ffffff;
                display: flex;
                align-items: center;
                justify-content: center;
                border-radius: 50%;
                box-shadow: 0px 0px -17rpx 1rpx rgba(206, 206, 206, 0.32);

                .icon {
                    background-color: #3668FC;
                    width: 42px;
                    height: 42px;
                    border-radius: 50%;
                    display: flex;
                    align-items: center;
                    justify-content: center;

                    image {
                        width: 28px;
                        height: 28px;
                    }

                    .select_img {
                        animation: tabbar-item-button-click 0.2s forwards 1;
                    }

                }
            }
        }

        .tababr_item {
            font-size: 20rpx;
            text-align: center;
            width: 25%;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;

            .tabbar_icon {
                height: 25px;
                width: 25px;

                .select_img {
                    animation: tabbar-item-button-click 0.2s forwards 1;
                }

                image {
                    width: 100%;
                    height: 100%;
                }
            }

            .tababr_text {
                line-height: 24rpx;
                font-size: 24rpx;
                margin-top: 2px;
                color: #999;
            }
        }
    }

    /* 点击动画 start */

    @keyframes tabbar-item-button-click {
        from {
            transform: scale(0.5);
        }

        to {
            transform: scale(1);
        }
    }
</style>
<template>
    <view class="start-index">
        <!-- #ifdef H5 || APP -->
        <view v-for="(flag, index) in tabbarList">
            <component v-if="currentIndex === index" :is="componentNames[index].name" :key="index"></component>
        </view>
        <!-- #endif -->
        <!-- #ifdef MP-WEIXIN -->
        <view :style="{display: componentNames[currentIndex].name === 'index' ? '' : 'none'}">
          <scroll-view class="custom-tabbar-page" scroll-y enable-back-to-top @scrolltolower="tabbarScrollLower">
            <index ref="index"></index>
          </scroll-view>
        </view>
        <view :style="{display: componentNames[currentIndex].name === 'commu' ? '' : 'none'}">
          <scroll-view class="custom-tabbar-page" scroll-y enable-back-to-top @scrolltolower="tabbarScrollLower">
            <commu ref="commu"></commu>
          </scroll-view>
        </view>
        <view  :style="{display: componentNames[currentIndex].name === 'find' ? '' : 'none'}">
          <scroll-view class="custom-tabbar-page" scroll-y enable-back-to-top @scrolltolower="tabbarScrollLower">
            <find ref="find"></find>
          </scroll-view>
        </view>
        <view :style="{display: componentNames[currentIndex].name === 'news' ? '' : 'none'}">
          <scroll-view class="custom-tabbar-page" scroll-y enable-back-to-top @scrolltolower="tabbarScrollLower">
            <news ref="news"></news>
          </scroll-view>
        </view>
        <view  :style="{display: componentNames[currentIndex].name === 'my' ? '' : 'none'}">
          <scroll-view class="custom-tabbar-page" scroll-y enable-back-to-top @scrolltolower="tabbarScrollLower">
            <my ref="my"></my>
          </scroll-view>
        </view> 
        <!-- #endif -->
        <tabbar :pagePathIndex="currentIndex" :tabbarListPage="tabbarList" @tabbarSave="switchTabbar"></tabbar>
    </view>
</template>

<script>
    //需要引入所有菜单
    import index from './index/index.vue'
    import commu from './commu/index.vue'
    import find from './find/index.vue'
    import news from './news/index.vue'
    import my from './my/index.vue'
    import tabbar from '../components/tabbar/tabbar.vue'
    export default {
        components: {
            index,
            commu,
            find,
            news,
            my
        },
        data() {
            return {
                currentIndex: 0, 
                tabbarList: uni.getStorageSync('tabbarListPage'), //动态获取菜单
                componentNames: uni.getStorageSync('componentNames') // 组件名称数组
            }
        },
        onLoad(options) {
            let token = uni.getStorageSync('token')
            if (!token) {
                uni.navigateTo({
                    url: '/pages/login/index'
                })
            }
            const index = Number(options.index || 0) 
            this.switchTabbar(index)
        },
        methods: {
            // 切换
            switchTabbar(index) {
                this.switchChangeTabbar(index)
                if (index !== 1) {
                    this.$refs?.commRef?.stopAllVideo()
                }
            },
            //有瀑布流页面在此设置滚动到底部
            tabbarScrollLower(e) {
                console.log(e)
            },
            // 切换导航页面
            switchChangeTabbar(index) { 
                this.currentIndex = index
            }
        }
    }
</script>

<style>

</style>
登录页面

<template>
    <view class="container">
        <view class="form-group">
            <input v-model="username" type="text" placeholder="用户名">
        </view>
        <view class="form-group">
            <input v-model="password" type="password" placeholder="密码">
        </view>
        <view class="form-group">
            <button @tap="login">登录</button>
        </view>
        <view>账号和密码(所有菜单):admin   123456</view>
        <view>账号和密码(部分菜单):123456   123456</view>
    </view>
</template>

<script>
    import {componentNames,tabbarListPage,componentNames1,tabbarListPage1} from '../../utils/dataPage.js'
    export default {
        data() {
            return {
                username: 'admin',
                password: '123456',
                //简单模拟后端返回的菜单数据和组件名称数据列表, 
                componentNames: componentNames, //组件名称:需要根据前端组件名称返回
                tabbarListPage: tabbarListPage,//菜单列表
                componentNames1:componentNames1,
                tabbarListPage1:tabbarListPage1,
            };
        },
        methods: {
            login() {
                if(this.username === 'admin'){
                    //登录完成之后获取菜单,菜单保存到本地
                    uni.setStorageSync('tabbarListPage', this.tabbarListPage)
                    uni.setStorageSync('componentNames', this.componentNames)
                    uni.setStorageSync('token', '123456789453213')
                    uni.redirectTo({
                        url: '/pages/preloading',
                    })
                }else{
                    //登录完成之后获取菜单,菜单保存到本地
                    uni.setStorageSync('tabbarListPage', this.tabbarListPage1)
                    uni.setStorageSync('componentNames', this.componentNames1)
                    uni.setStorageSync('token', '123456789453213')
                    uni.redirectTo({
                        url: '/pages/preloading',
                    })
                }

            }
        }
    };
</script>

<style scoped>
    .container {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        height: 100vh;
    }

    .form-group {
        margin-bottom: 20px;
    }

    input {
        width: 300px;
        padding: 10px;
        border: 1px solid #ccc;
        border-radius: 5px;
    }

    button {
        width: 300px;
        padding: 10px;
        background-color: #007bff;
        color: #fff;
        border: none;
        border-radius: 5px;
        cursor: pointer;
    }
</style>

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问