xx-applets/src/components/layout/layout.vue

192 lines
4.7 KiB
Vue

<template>
<view class="page-layout" :style="{ backgroundColor: backgroundColor, minHeight: minHeight }">
<view
v-if="showHeader"
class="page-header"
:class="[textColor]"
:style="{
paddingTop: statusBarHeight + 'px',
height: headerHeight + 'px',
backgroundColor: headerBackgroundColor,
}"
>
<block v-if="btnType === 'city'">
<view class="page-index-btn change-city" :style="{ height: headerHeight + 'px' }" @click="changeCity">
<text class="iconfont icon-31dingwei"></text>
<text class="city">成都市</text>
</view>
</block>
<block v-if="btnType === 'back'">
<view class="page-index-btn back" :style="{ height: headerHeight + 'px' }" @click="onClick">
<text class="iconfont icon-fanhui"></text>
</view>
</block>
<view class="page-title">
<text class="title-text" :style="{ lineHeight: headerHeight + 'px' }">{{ title }}</text>
</view>
</view>
<view class="page-body" :style="{ paddingTop: bodyPaddingTop + 'px' }">
<slot></slot>
</view>
<view class="page-footer"></view>
</view>
</template>
<script>
import { mapState } from "vuex";
export default {
name: "component-layout",
data() {
return {
headerHeight: 0,
statusBarHeight: 0,
bodyPaddingTop: 0,
};
},
components: {},
props: {
minHeight: {
type: String,
default: "100vh",
},
backgroundColor: {
type: String,
default: "#F6F6F6",
},
headerBackgroundColor: {
type: String,
default: "#F6F6F6",
},
customBtn: {
type: Boolean,
default: false,
},
btnType: {
type: String,
default: "back",
},
title: {
type: String,
default: "",
},
textColor: {
type: String,
default: "dark",
},
showHeader: {
type: Boolean,
default: true,
},
},
computed: {
...mapState({
config: (state) => state.system.config,
}),
},
mounted() {
const { statusBarHeight, headerHeight } = this.config;
// #ifndef H5
this.statusBarHeight = statusBarHeight;
this.headerHeight = headerHeight;
// #endif
// #ifdef H5
this.statusBarHeight = 0;
this.headerHeight = this.$utils.rpx2px(headerHeight * 2);
// #endif
let safePaddingTop = this.statusBarHeight + this.headerHeight;
this.$emit("input", safePaddingTop);
if (this.showHeader) {
this.bodyPaddingTop = safePaddingTop;
}
},
methods: {
onClick() {
if (this.customBtn) {
this.$emit("onClickBtn");
} else {
uni.navigateBack({ delta: 1 });
}
},
changeCity() {
console.log("修改城市");
},
},
};
</script>
<style scoped lang="less">
.page-layout {
position: relative;
max-width: 750px;
width: 100%;
margin: 0 auto;
/* #ifdef H5 */
// 修复自定义tabBar后的遮挡问题
// padding-bottom: calc(@tabBarHeight - 50px);
/* #endif */
}
.page-header.dark {
.page-title,
.page-index-btn {
color: #2d2d2d;
}
}
.page-header.light {
.page-title,
.page-index-btn {
color: #ffffff;
}
}
.page-header {
z-index: 20;
position: fixed;
top: 0;
left: 0;
right: 0;
max-width: 750px;
width: 750rpx;
text-align: center;
margin: 0 auto;
.page-title {
width: 100%;
height: auto;
line-height: 0;
.title-text {
font-size: 30rpx;
font-weight: bold;
}
}
.page-index-btn {
position: absolute;
bottom: 0;
left: 0;
width: 180rpx;
padding-left: 30rpx;
line-height: 0;
display: flex;
align-items: center;
justify-content: flex-start;
}
.page-index-btn.change-city {
font-size: 24rpx;
.icon-31dingwei {
font-size: 40rpx;
}
.city {
margin-left: 5rpx;
}
}
.page-index-btn.back {
.icon-fanhui {
font-size: 40rpx;
font-weight: bold;
}
}
}
.page-body {
width: 100%;
}
.page-footer {
width: 100%;
}
</style>