366 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Vue
		
	
	
			
		
		
	
	
			366 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Vue
		
	
	
| <template>
 | |
|   <su-fixed
 | |
|     :noFixed="props.noFixed"
 | |
|     :alway="props.alway"
 | |
|     :bgStyles="props.bgStyles"
 | |
|     :val="0"
 | |
|     :index="props.zIndex"
 | |
|     noNav
 | |
|     :bg="props.bg"
 | |
|     :ui="props.ui"
 | |
|     :opacity="props.opacity"
 | |
|     :placeholder="props.placeholder"
 | |
|   >
 | |
|     <su-status-bar />
 | |
|     <!-- 
 | |
|       :class="[{ 'border-bottom': !props.opacity && props.bg != 'bg-none' }]"
 | |
|      -->
 | |
|     <view class="ui-navbar-box">
 | |
|       <view
 | |
|         class="ui-bar ss-p-x-20"
 | |
|         :class="state.isDark ? 'text-white' : 'text-black'"
 | |
|         :style="[{ height: sys_navBar - sys_statusBar + 'px' }]"
 | |
|       >
 | |
|         <view class="icon-box ss-flex">
 | |
|           <view class="icon-button icon-button-left ss-flex ss-row-center" @tap="onClickLeft">
 | |
|             <text class="sicon-back" v-if="hasHistory" />
 | |
|             <text class="sicon-home" v-else />
 | |
|           </view>
 | |
|           <view class="line"></view>
 | |
|           <view class="icon-button icon-button-right ss-flex ss-row-center" @tap="onClickRight">
 | |
|             <text class="sicon-more" />
 | |
|           </view>
 | |
|         </view>
 | |
|         <slot name="center">
 | |
|           <view class="center navbar-title">{{ title }}</view>
 | |
|         </slot>
 | |
|         <!-- #ifdef MP -->
 | |
|         <view :style="[state.capsuleStyle]"></view>
 | |
|         <!-- #endif -->
 | |
|       </view>
 | |
|     </view>
 | |
|   </su-fixed>
 | |
| </template>
 | |
| 
 | |
| <script setup>
 | |
|   /**
 | |
|    * 标题栏 - 基础组件navbar
 | |
|    *
 | |
|    * @param {Number}  zIndex = 100  							- 层级
 | |
|    * @param {Boolean}  back = true 							- 是否返回上一页
 | |
|    * @param {String}  backtext = ''  							- 返回文本
 | |
|    * @param {String}  bg = 'bg-white'  						- 公共Class
 | |
|    * @param {String}  status = ''  							- 状态栏颜色
 | |
|    * @param {Boolean}  alway = true							- 是否常驻
 | |
|    * @param {Boolean}  opacity = false  						- 是否开启透明渐变
 | |
|    * @param {Boolean}  noFixed = false  						- 是否浮动
 | |
|    * @param {String}  ui = ''									- 公共Class
 | |
|    * @param {Boolean}  capsule = false  						- 是否开启胶囊返回
 | |
|    * @param {Boolean}  stopBack = false 					    - 是否禁用返回
 | |
|    * @param {Boolean}  placeholder = true 					- 是否开启占位
 | |
|    * @param {Object}   bgStyles = {} 					    	- 背景样式
 | |
|    *
 | |
|    */
 | |
| 
 | |
|   import { computed, reactive, onBeforeMount, ref } from 'vue';
 | |
|   import sheep from '@/sheep';
 | |
|   import { onPageScroll } from '@dcloudio/uni-app';
 | |
|   import { showMenuTools, closeMenuTools } from '@/sheep/hooks/useModal';
 | |
| 
 | |
|   // 本地数据
 | |
|   const state = reactive({
 | |
|     statusCur: '',
 | |
|     capsuleStyle: {},
 | |
|     capsuleBack: {},
 | |
|     isDark: true,
 | |
|   });
 | |
| 
 | |
|   const sys_statusBar = sheep.$platform.device.statusBarHeight;
 | |
|   const sys_navBar = sheep.$platform.navbar;
 | |
| 
 | |
|   const props = defineProps({
 | |
|     zIndex: {
 | |
|       type: Number,
 | |
|       default: 100,
 | |
|     },
 | |
| 
 | |
|     title: {
 | |
|       //返回文本
 | |
|       type: String,
 | |
|       default: '',
 | |
|     },
 | |
|     bg: {
 | |
|       type: String,
 | |
|       default: 'bg-white',
 | |
|     },
 | |
|     // 常驻
 | |
|     alway: {
 | |
|       type: Boolean,
 | |
|       default: true,
 | |
|     },
 | |
|     opacity: {
 | |
|       //是否开启滑动渐变
 | |
|       type: Boolean,
 | |
|       default: true,
 | |
|     },
 | |
|     noFixed: {
 | |
|       //是否浮动
 | |
|       type: Boolean,
 | |
|       default: true,
 | |
|     },
 | |
|     ui: {
 | |
|       type: String,
 | |
|       default: '',
 | |
|     },
 | |
|     capsule: {
 | |
|       //是否开启胶囊返回
 | |
|       type: Boolean,
 | |
|       default: false,
 | |
|     },
 | |
|     stopBack: {
 | |
|       type: Boolean,
 | |
|       default: false,
 | |
|     },
 | |
|     placeholder: {
 | |
|       type: [Boolean],
 | |
|       default: false,
 | |
|     },
 | |
|     bgStyles: {
 | |
|       type: Object,
 | |
|       default() {},
 | |
|     },
 | |
|   });
 | |
| 
 | |
|   const emits = defineEmits(['navback', 'clickLeft']);
 | |
|   const hasHistory = sheep.$router.hasHistory();
 | |
| 
 | |
|   onBeforeMount(() => {
 | |
|     init();
 | |
|   });
 | |
| 
 | |
|   onPageScroll((e) => {
 | |
|     let top = e.scrollTop;
 | |
|     state.isDark = top < sheep.$platform.navbar;
 | |
|   });
 | |
| 
 | |
|   function onClickLeft() {
 | |
|     if (hasHistory) {
 | |
|       sheep.$router.back();
 | |
|     } else {
 | |
|       sheep.$router.go('/pages/index/index');
 | |
|     }
 | |
|     emits('clickLeft');
 | |
|   }
 | |
|   function onClickRight() {
 | |
|     showMenuTools();
 | |
|   }
 | |
| 
 | |
|   // 初始化
 | |
|   const init = () => {
 | |
|     // #ifdef MP-ALIPAY
 | |
|     my.hideAllFavoriteMenu();
 | |
|     // #endif
 | |
|     state.capsuleStyle = {
 | |
|       width: sheep.$platform.capsule.width + 'px',
 | |
|       height: sheep.$platform.capsule.height + 'px',
 | |
|     };
 | |
| 
 | |
|     state.capsuleBack = state.capsuleStyle;
 | |
|   };
 | |
| </script>
 | |
| 
 | |
| <style lang="scss" scoped>
 | |
|   .icon-box {
 | |
|     box-shadow: 0px 0px 4rpx rgba(51, 51, 51, 0.08), 0px 4rpx 6rpx 2rpx rgba(102, 102, 102, 0.12);
 | |
|     border-radius: 30rpx;
 | |
|     width: 134rpx;
 | |
|     height: 56rpx;
 | |
|     margin-left: 8rpx;
 | |
|     border: 1px solid rgba(#fff, 0.4);
 | |
|     .line {
 | |
|       width: 2rpx;
 | |
|       height: 24rpx;
 | |
|       background: #e5e5e7;
 | |
|     }
 | |
|     .sicon-back {
 | |
|       font-size: 32rpx;
 | |
|     }
 | |
|     .sicon-home {
 | |
|       font-size: 32rpx;
 | |
|     }
 | |
|     .sicon-more {
 | |
|       font-size: 32rpx;
 | |
|     }
 | |
|     .icon-button {
 | |
|       width: 67rpx;
 | |
|       height: 56rpx;
 | |
|       &-left:hover {
 | |
|         background: rgba(0, 0, 0, 0.16);
 | |
|         border-radius: 30rpx 0px 0px 30rpx;
 | |
|       }
 | |
|       &-right:hover {
 | |
|         background: rgba(0, 0, 0, 0.16);
 | |
|         border-radius: 0px 30rpx 30rpx 0px;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   .navbar-title {
 | |
|     font-size: 36rpx;
 | |
|   }
 | |
|   .tools-icon {
 | |
|     font-size: 40rpx;
 | |
|   }
 | |
|   .ui-navbar-box {
 | |
|     background-color: transparent;
 | |
|     width: 100%;
 | |
| 
 | |
|     .ui-bar {
 | |
|       position: relative;
 | |
|       z-index: 2;
 | |
|       white-space: nowrap;
 | |
|       display: flex;
 | |
|       position: relative;
 | |
|       align-items: center;
 | |
|       justify-content: space-between;
 | |
| 
 | |
|       .left {
 | |
|         @include flex-bar;
 | |
| 
 | |
|         .back {
 | |
|           @include flex-bar;
 | |
| 
 | |
|           .back-icon {
 | |
|             @include flex-center;
 | |
|             width: 56rpx;
 | |
|             height: 56rpx;
 | |
|             margin: 0 10rpx;
 | |
|             font-size: 46rpx !important;
 | |
| 
 | |
|             &.opacityIcon {
 | |
|               position: relative;
 | |
|               border-radius: 50%;
 | |
|               background-color: rgba(127, 127, 127, 0.5);
 | |
| 
 | |
|               &::after {
 | |
|                 content: '';
 | |
|                 display: block;
 | |
|                 position: absolute;
 | |
|                 height: 200%;
 | |
|                 width: 200%;
 | |
|                 left: 0;
 | |
|                 top: 0;
 | |
|                 border-radius: inherit;
 | |
|                 transform: scale(0.5);
 | |
|                 transform-origin: 0 0;
 | |
|                 opacity: 0.1;
 | |
|                 border: 1px solid currentColor;
 | |
|                 pointer-events: none;
 | |
|               }
 | |
| 
 | |
|               &::before {
 | |
|                 transform: scale(0.9);
 | |
|               }
 | |
|             }
 | |
|           }
 | |
| 
 | |
|           /* #ifdef  MP-ALIPAY */
 | |
|           ._icon-back {
 | |
|             opacity: 0;
 | |
|           }
 | |
| 
 | |
|           /* #endif */
 | |
|         }
 | |
| 
 | |
|         .capsule {
 | |
|           @include flex-bar;
 | |
|           border-radius: 100px;
 | |
|           position: relative;
 | |
| 
 | |
|           &.dark {
 | |
|             background-color: rgba(255, 255, 255, 0.5);
 | |
|           }
 | |
| 
 | |
|           &.light {
 | |
|             background-color: rgba(0, 0, 0, 0.15);
 | |
|           }
 | |
| 
 | |
|           &::after {
 | |
|             content: '';
 | |
|             display: block;
 | |
|             position: absolute;
 | |
|             height: 60%;
 | |
|             width: 1px;
 | |
|             left: 50%;
 | |
|             top: 20%;
 | |
|             background-color: currentColor;
 | |
|             opacity: 0.1;
 | |
|             pointer-events: none;
 | |
|           }
 | |
| 
 | |
|           &::before {
 | |
|             content: '';
 | |
|             display: block;
 | |
|             position: absolute;
 | |
|             height: 200%;
 | |
|             width: 200%;
 | |
|             left: 0;
 | |
|             top: 0;
 | |
|             border-radius: inherit;
 | |
|             transform: scale(0.5);
 | |
|             transform-origin: 0 0;
 | |
|             opacity: 0.1;
 | |
|             border: 1px solid currentColor;
 | |
|             pointer-events: none;
 | |
|           }
 | |
| 
 | |
|           .capsule-back,
 | |
|           .capsule-home {
 | |
|             @include flex-center;
 | |
|             flex: 1;
 | |
|           }
 | |
| 
 | |
|           &.isFristPage {
 | |
|             .capsule-back,
 | |
|             &::after {
 | |
|               display: none;
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       .right {
 | |
|         @include flex-bar;
 | |
| 
 | |
|         .right-content {
 | |
|           @include flex;
 | |
|           flex-direction: row-reverse;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       .center {
 | |
|         @include flex-center;
 | |
|         text-overflow: ellipsis;
 | |
|         // text-align: center;
 | |
|         position: absolute;
 | |
|         left: 50%;
 | |
|         transform: translateX(-50%);
 | |
| 
 | |
|         .image {
 | |
|           display: block;
 | |
|           height: 36px;
 | |
|           max-width: calc(100vw - 200px);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     .ui-bar-bg {
 | |
|       position: absolute;
 | |
|       width: 100%;
 | |
|       height: 100%;
 | |
|       top: 0;
 | |
|       z-index: 1;
 | |
|       pointer-events: none;
 | |
|     }
 | |
|   }
 | |
| </style>
 |