hn-hlw-app/components/full-page.vue
2026-07-27 11:26:39 +08:00

94 lines
2.0 KiB
Vue

<template>
<view class="full-page" :style="pageStyle">
<view v-if="hasHeader" class="page-header">
<slot name="header"></slot>
</view>
<view class="page-main" :style="mainStyle">
<view v-if="customScroll" class="page-scroll">
<slot></slot>
</view>
<scroll-view v-else :scroll-with-animation="animation" scroll-y="true" :scroll-top="scrollTop" class="page-scroll"
@scrolltolower="scrolltolower" @scroll="onScroll">
<slot></slot>
</scroll-view>
</view>
<view v-if="hasFooter" class="page-footer">
<slot name="footer"></slot>
</view>
<!-- #ifdef MP-->
<view class="safeareaBottom"></view>
<!-- #endif -->
</view>
</template>
<script setup>
import { computed, useSlots, ref } from 'vue';
import useDebounce from '@/hooks/useDebounce';
const emits = defineEmits(['reachBottom']);
const props = defineProps({
animation: { type: Boolean, default: false },
customScroll: { type: Boolean, default: false },
mainStyle: { default: '' },
pageStyle: { default: '' }
});
const slots = useSlots();
const hasHeader = computed(() => !!slots.header);
const hasFooter = computed(() => !!slots.footer);
const scrollTop = ref(0);
const disableScroll = ref(false);
const scrolltolower = useDebounce(() => {
emits('reachBottom');
});
const onScroll = useDebounce((e) => {
if (disableScroll.value) return;
scrollTop.value = e.detail.scrollTop;
});
function scrollToBottom() {
disableScroll.value = true;
scrollTop.value = 999999;
setTimeout(() => {
disableScroll.value = false;
}, 500);
}
defineExpose({
scrollToBottom
})
</script>
<style lang="scss" scoped>
.full-page {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
.page-header,
.page-footer {
flex-shrink: 0;
}
.page-main {
flex-grow: 1;
position: relative;
}
.page-scroll {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.safeareaBottom {
flex-shrink: 0;
height: env(safe-area-inset-bottom);
}
</style>