yfs/components/nav-header/nav-header.vue
2025-05-03 12:51:13 +08:00

373 lines
7.6 KiB
Vue

<template>
<view class="custom-nav-header" :class="{'custom-nav-header--dark': dark}">
<!-- 导航栏内容 -->
<view class="custom-nav-header__content" :class="{ 'custom-nav-header--fixed': fixed, 'custom-nav-header--shadow': shadow }"
:style="{ 'background-color': themeBgColor }">
<!-- 状态栏 -->
<view v-if="statusBar" class="custom-nav-header__status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
<!-- 导航内容 -->
<view class="custom-nav-header__header" :style="{ color: themeColor, backgroundColor: themeBgColor, height: navbarHeight + 'px' }">
<!-- 左侧区域 -->
<view @click="onClickLeft" class="custom-nav-header__header-btns custom-nav-header__header-btns-left" :style="{ width: leftWidth + 'px' }">
<slot name="left">
<view class="custom-nav-header__content-view" v-if="leftIcon">
<view class="custom-nav-header__icon" :style="{ 'border-color': themeColor }"></view>
</view>
<view class="custom-nav-header-btn-text" v-if="leftText">
<text :style="{ color: themeColor, fontSize: '14px' }">{{ leftText }}</text>
</view>
</slot>
</view>
<!-- 中间标题区域 -->
<view class="custom-nav-header__header-container" @click="onClickTitle">
<slot>
<view class="custom-nav-header__header-container-inner" v-if="innerTitle">
<text class="custom-nav-bar-text custom-nav-ellipsis-1" :style="{ color: themeColor }">{{ innerTitle }}</text>
</view>
</slot>
</view>
<!-- 右侧区域 -->
<view @click="onClickRight" class="custom-nav-header__header-btns custom-nav-header__header-btns-right" :style="{ width: rightWidth + 'px' }">
<slot name="right">
<view class="custom-nav-header-btn-text" v-if="rightText">
<text class="custom-nav-bar-right-text" :style="{ color: themeColor }">{{ rightText }}</text>
</view>
</slot>
</view>
</view>
</view>
<!-- 占位符 -->
<view class="custom-nav-header__placeholder" v-if="fixed">
<view v-if="statusBar" :style="{ height: statusBarHeight + 'px' }"></view>
<view class="custom-nav-header__placeholder-view" :style="{ height: navbarHeight + 'px' }"></view>
</view>
</view>
</template>
<script>
export default {
name: 'NavHeader',
props: {
// 是否暗黑模式
dark: {
type: Boolean,
default: false
},
// 标题文字
title: {
type: String,
default: ''
},
// 左侧文字
leftText: {
type: String,
default: ''
},
// 右侧文字
rightText: {
type: String,
default: ''
},
// 左侧图标
leftIcon: {
type: String,
default: ''
},
// 右侧图标
rightIcon: {
type: String,
default: ''
},
// 是否显示返回按钮
showBack: {
type: Boolean,
default: false
},
// 是否显示返回文字
showBackText: {
type: Boolean,
default: false
},
// 返回页面路径,不传则返回上一页
backUrl: {
type: String,
default: ''
},
// 文字颜色
color: {
type: String,
default: ''
},
// 背景颜色
backgroundColor: {
type: String,
default: ''
},
// 是否固定在顶部
fixed: {
type: Boolean,
default: true
},
// 是否包含状态栏
statusBar: {
type: Boolean,
default: true
},
// 是否显示阴影
shadow: {
type: Boolean,
default: false
},
// 导航栏高度
height: {
type: [Number, String],
default: 44
},
// 左侧宽度
leftWidth: {
type: [Number, String],
default: 60
},
// 右侧宽度
rightWidth: {
type: [Number, String],
default: 60
}
},
data() {
return {
statusBarHeight: 20, // 默认状态栏高度
innerTitle: '', // 内部使用的标题
navbarHeight: 44 // 导航栏高度
}
},
computed: {
// 导航栏主题背景色
themeBgColor() {
if (this.dark) {
if (this.backgroundColor) {
return this.backgroundColor;
} else {
return this.dark ? '#333' : '#FFF';
}
}
return this.backgroundColor || '#FFF';
},
// 导航栏主题文字色
themeColor() {
if (this.dark) {
if (this.color) {
return this.color;
} else {
return this.dark ? '#fff' : '#333';
}
}
return this.color || '#333';
}
},
created() {
this.getStatusBarHeight();
this.innerTitle = this.title;
// 转换导航栏高度
this.navbarHeight = typeof this.height === 'number' ? this.height : parseInt(this.height);
},
watch: {
title(newVal) {
this.innerTitle = newVal;
}
},
methods: {
// 获取状态栏高度
getStatusBarHeight() {
uni.getSystemInfo({
success: (res) => {
this.statusBarHeight = res.statusBarHeight;
}
});
},
// 返回页面
goBack() {
this.onClickLeft();
},
// 点击左侧按钮
onClickLeft() {
this.$emit('clickLeft');
if (this.backUrl) {
// 如果指定了返回页面路径,则跳转到指定页面
this.$customRouter.navigateTo(this.backUrl, {}, 'redirectTo')
.catch(err => {
console.log('返回页面失败', err);
this.$customRouter.navigateTo(this.backUrl, {}, 'switchTab')
.catch(err => {
console.log('返回页面失败1', err);
});
});
} else {
var pages = getCurrentPages();
if (pages.length > 1) {
uni.navigateBack({
delta: 1,
fail: (err) => {
console.log('返回页面失败2', err);
}
});
} else {
this.$customRouter.navigateTo('/pages/shouye/index', {}, 'switchTab');
}
}
},
// 点击右侧按钮
onClickRight() {
this.$emit('clickRight');
},
// 点击标题
onClickTitle() {
this.$emit('clickTitle');
}
}
}
</script>
<style lang="scss">
$nav-height: 44px;
.custom-nav-header {
/* 整体容器 */
width: 100%;
&__content {
/* 内容区 */
position: relative;
background-color: transparent;
}
&__status-bar {
/* 状态栏 */
height: 20px;
}
&__header {
/* 头部导航 */
display: flex;
flex-direction: row;
height: $nav-height;
padding: 0 10px;
font-size: 14px;
}
&__header-btns {
/* 按钮通用样式 */
display: flex;
flex-wrap: nowrap;
flex-direction: row;
width: 120rpx;
justify-content: center;
align-items: center;
}
&__header-btns-left {
/* 左侧按钮 */
display: flex;
justify-content: flex-start;
align-items: center;
}
&__header-btns-right {
/* 右侧按钮 */
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
}
&__header-container {
/* 标题容器 */
display: flex;
flex: 1;
padding: 0 10px;
overflow: hidden;
}
&__header-container-inner {
/* 标题内部容器 */
display: flex;
flex: 1;
flex-direction: row;
align-items: center;
justify-content: center;
font-size: 14px;
overflow: hidden;
}
&__icon {
/* 返回图标 */
width: 12px;
height: 12px;
border-left: 2px solid;
border-bottom: 2px solid;
transform: rotate(45deg);
}
&__content-view {
display: flex;
align-items: center;
justify-content: center;
}
&__placeholder {
/* 占位符 */
width: 100%;
}
&__placeholder-view {
height: $nav-height;
}
/* 修饰样式 */
&--fixed {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 98;
}
&--shadow {
box-shadow: 0 1px 6px #ccc;
}
&--dark {
background-color: #333;
}
}
.custom-nav-header-btn-text {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
line-height: 12px;
}
.custom-nav-bar-text {
font-size: 16px;
font-weight: 500;
}
.custom-nav-bar-right-text {
font-size: 12px;
}
.custom-nav-ellipsis-1 {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
</style>