HaniBlindBox/honey_box/components/page-container/page-container.vue
2026-02-03 13:39:57 +08:00

211 lines
4.0 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="page-container" :style="containerStyle">
<nav-header
:title="navTitle"
:showBack="showBack"
:backUrl="backUrl"
:color="navColor"
:backgroundColor="navBackgroundColor"
:fixed="fixed"
:statusBar="statusBar"
:shadow="shadow"
:dark="dark"
:height="navHeight"
:leftText="leftText"
:rightText="rightText"
:leftIcon="showBack ? 'back' : ''"
@clickLeft="onClickLeft"
@clickRight="onClickRight"
@clickTitle="onClickTitle">
<template #right>
<slot name="nav-right"></slot>
</template>
</nav-header>
<view class="page-container__content" :style="contentStyle">
<view class="page-container__divider" v-if="divider"></view>
<slot></slot>
</view>
</view>
</template>
<script>
import NavHeader from '@/components/nav-header/nav-header.vue'
export default {
name: 'PageContainer',
components: {
NavHeader
},
emits: ['clickLeft', 'clickRight', 'clickTitle'],
props: {
// 标题文字
title: {
type: String,
default: ''
},
// 是否暗黑模式
dark: {
type: Boolean,
default: false
},
// 是否显示返回按钮
showBack: {
type: Boolean,
default: false
},
// 左侧文字
leftText: {
type: String,
default: ''
},
// 右侧文字
rightText: {
type: String,
default: ''
},
// 返回页面路径,不传则返回上一页
backUrl: {
type: String,
default: ''
},
// 导航栏文字颜色
navColor: {
type: String,
default: '#000000'
},
// 导航栏背景颜色
navBackgroundColor: {
type: String,
default: 'transparent'
},
// 页面背景颜色(支持渐变)
backgroundColor: {
type: String,
default: ''
},
// 是否使用渐变背景
useGradient: {
type: Boolean,
default: true
},
// 是否固定导航栏在顶部
fixed: {
type: Boolean,
default: true
},
// 是否包含状态栏
statusBar: {
type: Boolean,
default: true
},
// 是否显示阴影
shadow: {
type: Boolean,
default: false
},
// 是否显示分隔线
divider: {
type: Boolean,
default: false
},
// 导航栏高度
navHeight: {
type: [Number, String],
default: 44
},
// 底部内边距
paddingBottom: {
type: String,
default: '0px'
}
},
data() {
return {
statusBarHeight: 20, // 默认状态栏高度
navbarHeight: 44, // 导航栏高度
navTitle: '' // 导航栏标题避免直接使用prop
}
},
computed: {
// 容器样式
containerStyle() {
if (this.backgroundColor) {
return 'background: ' + this.backgroundColor;
}
if (this.useGradient) {
return 'background: linear-gradient(180deg, #5FCDFF 0%, #F5F5F5 100%)';
}
return 'background-color: #F5F5F5';
},
// 内容区样式
contentStyle() {
return 'padding-bottom: ' + this.paddingBottom;
}
},
created() {
this.getStatusBarHeight();
// 转换导航栏高度
this.navbarHeight = typeof this.navHeight === 'number' ? this.navHeight : parseInt(this.navHeight);
// 初始化导航栏标题
this.navTitle = this.title;
},
watch: {
// 监听title属性变化
title(newVal) {
this.navTitle = newVal;
}
},
methods: {
// 获取状态栏高度
getStatusBarHeight() {
uni.getSystemInfo({
success: (res) => {
this.statusBarHeight = res.statusBarHeight || 20;
}
});
},
// 点击左侧
onClickLeft() {
this.$emit('clickLeft');
},
// 点击右侧
onClickRight() {
this.$emit('clickRight');
},
// 点击标题
onClickTitle() {
this.$emit('clickTitle');
},
// 设置标题的公共方法(供父组件调用)
setNavTitle(title) {
this.navTitle = title;
}
}
}
</script>
<style lang="scss">
.page-container {
width: 100vw;
min-height: 100vh;
box-sizing: border-box;
&__content {
width: 100%;
box-sizing: border-box;
position: relative;
}
&__divider {
width: 100%;
height: 4rpx;
background-color: rgba(0, 0, 0, 0.05);
position: relative;
top: 0;
left: 0;
right: 0;
z-index: 1;
margin-bottom: 10rpx;
}
}
</style>