| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- <template>
- <view class="wrap" :class="{'wrap-shadow': shadow}">
- <StatusBar />
- <view class="nav-bar-wrap" :style="[getNavWrapStyle]">
- <!-- 状态栏高度 -->
- <view class="nav-bar flex">
- <view class="nav-bar_left" v-if="!hideLeft">
- <slot name='left'>
- <view class="left-btns" :class="{ 'left-btns_home': onlyHome || (!getIsHome && !onlyBack), 'left-btns_only-back': onlyBack && !onlyHome }">
- <view class="back" hover-class="hover-active" @click="go('back')">
- <image src="https://cdn.aliyinba.com/UploadFiles/shop2/number/nav_bar/nav-back.png" mode="aspectFill"></image>
- </view>
- <view class="home" hover-class="hover-active" @click="go('home')">
- <image src="https://cdn.aliyinba.com/UploadFiles/shop2/number/nav_bar/nav-home.png" mode="aspectFill"></image>
- </view>
- </view>
- </slot>
- </view>
-
- <view class="nav-bar_content flex flex-center flex-1 w-0" :class="{'right-slot': ifShowRight}" :style="[getNavBarContent]">
- <view class="nav-bar_content_title flex-1 w-0 ellipsis">
- <slot name="title">{{ title }}</slot>
- </view>
- <view class="nav-bar_content_right" v-if="ifShowRight">
- <slot name="right">
- <text>右侧插槽</text>
- <!-- <image class="warn-icon" :src="getFileUrl('/fault.png')" mode="aspectFill"></image> -->
- </slot>
- </view>
- </view>
- </view>
- </view>
- </view>
- </template>
- <script setup>
- import { computed, unref, useSlots } from 'vue'
- import StatusBar from "./StatusBar.vue"
- import { getFileUrl } from "@/utils/file.js";
-
- const systemInfo = uni.getWindowInfo();
- let menuButtonInfo = {}
- // #ifdef MP-WEIXIN
- menuButtonInfo = uni.getMenuButtonBoundingClientRect() // 右上角胶囊信息
- // #endif
-
- const emit = defineEmits(['back'])
- const props = defineProps({
- title: { type: String },
- hideLeft: { type: Boolean, default: false },
- onlyBack: { type: Boolean, default: false }, // 仅显示返回键,不显示首页
- onlyHome: { type: Boolean, default: false }, // 仅显示返回主页(首页)按钮,左上角永远回首页
- customBack: { type: Boolean, default: false }, // 为 true 时点击返回触发 @back,由父组件处理
- warn: { type: Boolean, default: false }, // 警告
- shadow: { type: Boolean, default: false }, // 警告
- })
- const slots = useSlots()
- // 是否显示返回首页
- const getIsHome = computed(() => {
- const pages = getCurrentPages(); // 获取路由栈
- return pages.length >= 2
- })
- // 是否显示右侧按钮
- const ifShowRight = computed(() => slots.right || props.warn)
- //
- const statusBarHeight = computed(() => systemInfo.statusBarHeight) // 状态栏高度
- const getNavWrapStyle = computed(() => {
- const { windowWidth } = systemInfo
- const { top, right, height } = menuButtonInfo
- return {
- padding: `${top - unref(statusBarHeight)}px ${windowWidth - right}px`,
- height: `${height + (top - unref(statusBarHeight)) * 2}px`
- }
- })
-
- const getNavBarContent = computed(() => {
- const { width } = menuButtonInfo
- const style = {}
- if(unref(ifShowRight)){
- style.paddingRight = width + 'px'
- }else{
- style.position = 'absolute'
- style.width = '100%'
- style.top = '0'
- style.bottom = '0'
- style.zIndex = '-1'
- style.padding = `0 ${width + 10}px`
- }
- return style
- })
-
- function go(type){
- switch (type){
- case 'back':
- if (props.customBack) {
- emit('back')
- } else {
- uni.navigateBack()
- }
- break;
- case 'home':
- // 首页为 tabBar 页面,用 switchTab
- uni.switchTab({ url: '/pages/index/index' });
- break;
- default:
- uni.navigateTo({ url: type })
- break;
- }
- }
- </script>
- <style scoped lang="scss">
- .wrap{
- position: sticky;
- z-index: 101;
- &-shadow{
- box-shadow: 0 1rpx 0 2rpx #F4F6FA;
- }
- .nav-bar-wrap{
- padding:4px 8px;
- height:40px;
- .nav-bar{
- height: 100%;
- position: relative;
- &_left{
- margin-right: 30rpx;
- flex: none;
- .left-btns{
- border-radius: 99rpx;
- background: #DDDDDD80;
- width: 182rpx;
- height: 100%;
- display: flex;
- align-items: center;
- &_home{
- width: 90rpx;
- .back{
- display: none !important;
- }
- }
- &_only-back{
- width: 90rpx;
- .home{
- display: none !important;
- }
- .back::after{
- display: none;
- }
- }
-
- .back, .home{
- flex: 1;
- width: 0;
- height: 100%;
- display: flex;
- justify-content: center;
- align-items: center;
- }
- .back{
- position: relative;
- &::after{
- position: absolute;
- right: 0;
- top: 50%;
- transform: translateY(-50%);
- content: ' ';
- display: block;
- clear: both;
- background: #CECECE80;
- width: 2rpx;
- height: 34rpx;
- }
- image{
- width: 18rpx;
- height: 32rpx;
- }
- }
- .home{
- image{
- width: 36rpx;
- height: 32rpx;
- }
- }
- }
- }
- &_content{
- &.right-slot{
- .nav-bar_content_title{
- text-align: left !important;
- }
- }
- &_title{
- text-align: center;
- font-size: 36rpx;
- color: #fff;
- // background: red;
- }
- &_right{
- flex: none;
- display: flex;
- align-items: center;
- margin: 0 26rpx;
- }
- }
- }
- }
- }
- </style>
|