全栈小学生 4b78c8b6dd up
2024-12-04 14:37:20 +08:00

439 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="ns-navbar-wrap" v-if="diyStore.mode !='decorate' && topStatusBarData" :class="topStatusBarData.style">
<view class="u-navbar" :class="{'fixed': props.scrollBool != -1, 'absolute': props.scrollBool == -1}" :style="{ backgroundColor: bgColor}">
<view class="navbar-inner" :style="{ width: '100%', height: placeholderHeight + 'px' }">
<view v-if="topStatusBarData.style == 'style-1'" class="content-wrap" :class="[topStatusBarData.textAlign]" :style="navbarInnerStyle">
<view v-if="isBack && isBackShow" class="back-wrap -ml-[16rpx] text-[27px] nc-iconfont nc-icon-zuoV6xx" :style="{ color: titleTextColor }" @tap="goBack"></view>
<view class="title-wrap" :style="styleOneFontSize">
{{ data.title }}
</view>
</view>
<view v-if="topStatusBarData.style == 'style-2'" class="content-wrap" :style="navbarInnerStyle" @click="diyStore.toRedirect(topStatusBarData.link)">
<view v-if="isBack && isBackShow" class="back-wrap -ml-[16rpx] text-[27px] nc-iconfont nc-icon-zuoV6xx" :style="{ color: titleTextColor }" @tap="goBack"></view>
<view class="title-wrap" :style="{ color: topStatusBarData.textColor }">
<view>
<image :src="img(topStatusBarData.imgUrl)" mode="heightFix"></image>
</view>
<view :style="{ color: topStatusBarData.textColor }">{{ data.title }}</view>
</view>
</view>
<view v-if="topStatusBarData.style == 'style-3'" :style="navbarInnerStyle" class="content-wrap">
<view v-if="isBack && isBackShow" class="back-wrap -ml-[16rpx] text-[27px] nc-iconfont nc-icon-zuoV6xx" :style="{ color: titleTextColor }" @tap="goBack"></view>
<view class="title-wrap" @click="diyStore.toRedirect(topStatusBarData.link)">
<image :src="img(topStatusBarData.imgUrl)" mode="heightFix"></image>
</view>
<view class="search" @click="diyStore.toRedirect(topStatusBarData.link)" :style="{ height: systemStore.menuButtonInfo.height - 2 + 'px', lineHeight: systemStore.menuButtonInfo.height - 2 + 'px' }">
<text class="nc-iconfont nc-icon-sousuo-duanV6xx1 text-[24rpx] absolute left-[20rpx]"></text>
<text class="text-[24rpx]">{{topStatusBarData.inputPlaceholder}}</text>
</view>
<view :style="{ 'width': capsuleWidth }"></view>
</view>
<view v-if="topStatusBarData.style == 'style-4'" :style="navbarInnerStyle" class="content-wrap">
<view v-if="isBack && isBackShow" class="back-wrap -ml-[16rpx] text-[27px] nc-iconfont nc-icon-zuoV6xx" :style="{ color: titleTextColor }" @tap="goBack"></view>
<text class="nc-iconfont nc-icon-dizhiguanliV6xx text-[28rpx]" :style="{ color: topStatusBarData.textColor }"></text>
<view class="title-wrap" @click.stop="locationVal.reposition()" :style="{ color: topStatusBarData.textColor }" v-if="systemStore.diyAddressInfo">{{ systemStore.diyAddressInfo.community }}</view>
<view class="title-wrap" @click.stop="locationVal.reposition()" :style="{ color: topStatusBarData.textColor }" v-else>{{ systemStore.defaultPositionAddress }}</view>
<text class="nc-iconfont nc-icon-youV6xx text-[26rpx]" @click.stop="locationVal.reposition()" :style="{ color: topStatusBarData.textColor }"></text>
</view>
</view>
</view>
<!-- 解决fixed定位后导航栏塌陷的问题 -->
<view v-if="props.isFill" class="u-navbar-placeholder" :style="{ width: '100%', paddingTop: placeholderHeight + 'px' }"></view>
</view>
</template>
<script setup lang="ts">
import { ref, computed, onMounted, getCurrentInstance, nextTick } from 'vue';
import { redirect, img } from '@/utils/common';
import useSystemStore from '@/stores/system';
import useDiyStore from '@/app/stores/diy';
import {useLocation} from '@/hooks/useLocation'
// 获取系统状态栏的高度
let systemInfo = uni.getSystemInfoSync();
let platform = systemInfo.platform;
const systemStore = useSystemStore();
const diyStore = useDiyStore();
const props = defineProps({
data: {
type: Object,
default: {}
},
// 标题的颜色
titleColor: {
type: String,
default: '#606266'
},
// 自定义返回逻辑
customBack: {
type: Function,
default: null
},
scrollBool: {
type: [String, Number],
default: -1
},
// 是否显示导航栏左边返回图标和辅助文字
isBack: {
type: Boolean,
default: true
},
isFill: {
type: Boolean,
default: true
}
})
const data = computed(() => {
return props.data;
});
const topStatusBarData = computed(() => {
if(props.data && props.data.topStatusBar)
return props.data.topStatusBar;
});
// 导航栏内部盒子的样式
const navbarInnerStyle = computed(() => {
let style = '';
if(props.isBack && isBackShow.value){
style += 'padding-left: 30rpx;';//30=>右边留边 44=>箭头宽度 10=>箭头的右maring
if(topStatusBarData.value.style == 'style-1') //样式一需要居中需要有右边padding辅助
style += 'padding-right:' + (40+30+10) + 'rpx;'; //30=>左边留边 44=>箭头宽度 10=>箭头的右maring
}else{
if(topStatusBarData.value.style == 'style-1') //样式一需要居中需要有右边padding辅助
style += 'padding-right: 30rpx;'; //右边留边
style += 'padding-left: 30rpx;'; //左边留边
}
// #ifdef MP
// 导航栏宽度,如果在小程序下,导航栏宽度为胶囊的左边到屏幕左边的距离
style += 'height:' + systemStore.menuButtonInfo.height + 'px;';
style += 'padding-top:' + systemStore.menuButtonInfo.top + 'px;';
style += 'padding-bottom: 8px;';
// #endif
return style;
})
// 样式一的字体大小
const styleOneFontSize = computed(() => {
let style = '';
// #ifdef H5
style += 'font-size: 28rpx;';
// #endif
// #ifdef MP
style += 'font-size: 32rpx;';
if (platform === 'ios') {
// 苹果(iOS)设备
style += 'font-weight: 500;';
} else if (platform === 'android') {
// 安卓(Android)设备
style += 'font-size: 36rpx;';
style += 'font-weight: 500;';
}
// #endif
style += `color: ${titleTextColor.value};`;
if(topStatusBarData.value.style == 'style-1'){
style += `text-align: ${topStatusBarData.value.textAlign};`;
}
return style;
})
const titleTextColor = computed(()=>{
let color = '';
if (props.scrollBool == 1) {
color = topStatusBarData.value.rollTextColor;
} else {
color = topStatusBarData.value.textColor;
}
return color;
})
const bgColor = computed(() => {
let color = '';
if (props.scrollBool == 1) {
color = topStatusBarData.value.rollBgColor;
} else {
color = topStatusBarData.value.bgColor;
}
return color;
})
/******************************* 存储滚动值-start ***********************/
// 键名和组件名一致即可
let componentsScrollVal = uni.getStorageSync('componentsScrollValGroup')
if(componentsScrollVal){
componentsScrollVal.TopTabbar = 0
uni.setStorageSync('componentsScrollValGroup', componentsScrollVal);
}else{
let obj = {
TopTabbar: 0
}
uni.setStorageSync('componentsScrollValGroup', obj);
}
/******************************* 存储滚动值-end ***********************/
/******************************* 返回按钮-start ***********************/
const isBackShow = ref(false);
let pages = getCurrentPages();
// 返回按钮的函数
const goBack = () => {
// 兼容小程序,未登录状态下点击某个功能跳转到登录页,不登录无法返回的情况
if(pages.length == 1 && pages[0].route == 'app/pages/auth/index'){
uni.getStorage({
key: 'loginBack',
success: (res: any) => {
res ? redirect(
{
...res.data,
mode: 'redirectTo'
}
) : redirect({ url: '/app/pages/index/index', mode: 'switchTab' })
},
fail: (res) => {
redirect({ url: '/app/pages/index/index', mode: 'switchTab' })
}
})
}else{
// 如果自定义了点击返回按钮的函数,则执行,否则执行返回逻辑
if (typeof props.customBack === 'function') {
props.customBack();
} else {
uni.navigateBack();
}
}
}
/******************************* 返回按钮-end ***********************/
// 微信胶囊宽度+right
const capsuleWidth = computed(() => {
let width = `calc(100vw - ${systemStore.menuButtonInfo.right}px + ${systemStore.menuButtonInfo.width}px + 10px)`;
return width;
})
// 导航栏塌陷的高度
const placeholderHeight = ref(0);
const instance = getCurrentInstance();
// #ifdef MP
let statusBarHeight = systemStore.menuButtonInfo.height + systemStore.menuButtonInfo.top + 8;
placeholderHeight.value = statusBarHeight || 0;
// #endif
const navbarPlaceholderHeight = () => {
nextTick(() => {
const query = uni.createSelectorQuery().in(instance);
query.select('.ns-navbar-wrap .u-navbar .content-wrap').boundingClientRect(data => {
placeholderHeight.value = data ? data.height : 0;
diyStore.topTabarHeight = placeholderHeight.value;
}).exec();
})
}
/************** 定位-start ****************/
let isOpenLocation = false;
if(topStatusBarData.value && topStatusBarData.value.style == 'style-4') {
isOpenLocation = true;
}
const locationVal = useLocation(isOpenLocation);
locationVal.onLoad();
locationVal.init();
/************** 定位-end ****************/
onMounted(() => {
navbarPlaceholderHeight();
if (pages.length > 1) {
isBackShow.value = true;
// 兼容小程序,未登录状态下点击某个功能跳转到登录页,不登录无法返回的情况
}else if(pages.length == 1 && pages[0].route == 'app/pages/auth/index'){
isBackShow.value = true;
}
// 刷新定位
locationVal.refresh();
});
// 页面onShow调用时也会触发改方法
const refresh = ()=>{
// 刷新定位
locationVal.refresh();
}
defineExpose({
refresh
})
</script>
<style scoped lang="scss">
/* #ifdef H5 */
.style-1,
.style-2,
.style-3 {
display: none;
}
/* #endif */
.u-navbar {
width: 100%;
transition: background 0.3s;
left: 0;
right: 0;
top: 0;
z-index: 991;
}
.navbar-inner {
display: flex;
justify-content: space-between;
position: relative;
align-items: center;
// padding-bottom: 20rpx;
// /* #ifdef H5 */
// padding-bottom: 40rpx;
// /* #endif */
}
.back-wrap {
padding-right: 10rpx;
line-height: 1;
.iconfont {
font-size: 40rpx;
}
}
.content-wrap {
display: flex;
align-items: center;
justify-content: flex-start;
flex: 1;
position: absolute;
left: 0;
right: 0;
top: 0;
height: 60rpx;
text-align: center;
flex-shrink: 0;
}
.title-wrap {
line-height: 1;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 32rpx;
color: #000000;
}
.ns-navbar-wrap {
&.style-2 {
.content-wrap {
.title-wrap {
display: flex;
align-items: center;
text-align: left;
>view {
height: 56rpx;
line-height: 56rpx;
max-width: 300rpx;
font-size: 28rpx;
image {
width: 100%;
height: 100%;
margin-right: 20rpx;
}
&:last-child {
max-width: 300rpx;
overflow: hidden; //超出的文本隐藏
text-overflow: ellipsis; //用省略号显示
white-space: nowrap; //不换行
flex: 1;
}
}
}
}
}
&.style-3 {
.content-wrap {
.title-wrap {
height: 60rpx;
max-width: 170rpx;
flex: initial;
text-align: center;
margin-right: 10rpx;
image {
height: 100%;
width: 100%;
}
}
.search {
flex: 1;
padding-right: 20rpx;
padding-left: 62rpx;
position: relative;
background-color: #fff;
text-align: left;
border-radius: 60rpx;
height: 60rpx;
line-height: 60rpx;
border: 1px solid #eeeeee;
color: rgb(102, 102, 102);
display: flex;
align-items: center;
margin-right: 10rpx;
overflow: hidden;
box-sizing: border-box;
text{
overflow: hidden; //超出的文本隐藏
text-overflow: ellipsis; //用省略号显示
white-space: nowrap; //不换行
}
.iconfont {
color: #909399;
font-size: 32rpx;
margin-right: 10rpx;
}
}
}
}
&.style-4 {
.content-wrap {
top: 0;
text-align: left;
padding-left: 30rpx;
/* #ifdef H5 */
padding-top: 10rpx;
padding-bottom: 10rpx;
/* #endif */
.title-wrap {
flex: none;
margin: 0 10rpx;
max-width: 360rpx;
font-size: 27rpx;
line-height: normal;
}
.nearby-store-name {
margin: 0 10rpx;
background: rgba(0, 0, 0, .2);
font-size: 22rpx;
border-radius: 40rpx;
padding: 10rpx 20rpx;
line-height: 1;
}
}
}
}
</style>