247 lines
4.7 KiB
Vue
247 lines
4.7 KiB
Vue
<template>
|
||
<view
|
||
class="cl-page"
|
||
:class="[
|
||
`theme-${app.theme.name}`,
|
||
{
|
||
'is-fullscreen': fullscreen,
|
||
'is-safe-area-bottom': fullscreen,
|
||
},
|
||
]"
|
||
:style="{
|
||
padding: parseRpx(padding),
|
||
height
|
||
}"
|
||
>
|
||
<!-- 加载框 -->
|
||
<cl-loading-mask
|
||
fullscreen
|
||
:loading="loader.loading"
|
||
:text="loader.text"
|
||
:border="loader.border"
|
||
/>
|
||
|
||
<!-- 提示 -->
|
||
<cl-toast :ref="setRefs('toast')" />
|
||
|
||
<!-- 确认框 -->
|
||
<cl-confirm :ref="setRefs('confirm')" />
|
||
|
||
<!-- 状态栏 -->
|
||
<!-- #ifndef MP-ALIPAY -->
|
||
<cl-status-bar v-if="statusBar" :background-color="statusBarBackground" />
|
||
<!-- #endif -->
|
||
|
||
<!-- 内容插槽 -->
|
||
<slot></slot>
|
||
|
||
<!-- 底部安全区域 -->
|
||
<view class="safe-area-bottom" v-if="!fullscreen"></view>
|
||
</view>
|
||
|
||
<!-- 背景色 -->
|
||
<view
|
||
class="cl-page__bg"
|
||
:style="{
|
||
backgroundColor: background,
|
||
backgroundImage: 'url(' + backgroundImage + ')',
|
||
}"
|
||
></view>
|
||
</template>
|
||
|
||
<script lang="ts">
|
||
import { onPageScroll } from "@dcloudio/uni-app";
|
||
import { computed, defineComponent, ref, reactive, getCurrentInstance, onMounted } from "vue";
|
||
import { useApp, useCool} from "/@/cool";
|
||
import { parseRpx } from "/@/cool/utils";
|
||
import { isString } from "lodash-es";
|
||
|
||
export default defineComponent({
|
||
name: "cl-page",
|
||
|
||
props: {
|
||
// 是否全屏显示,高度100%
|
||
fullscreen: Boolean,
|
||
// 內间距
|
||
padding: {
|
||
type: [Number, String],
|
||
default: 0,
|
||
},
|
||
// 是否显示状态栏
|
||
statusBar: {
|
||
type: Boolean,
|
||
default: true,
|
||
},
|
||
// 状态栏背景色
|
||
statusBarBackground: String,
|
||
// 页面背景色
|
||
backgroundColor: String,
|
||
// 背景图片
|
||
backgroundImage: {
|
||
type: String,
|
||
default: "",
|
||
},
|
||
},
|
||
|
||
setup(props) {
|
||
const { refs, setRefs, router } = useCool();
|
||
const app = useApp();
|
||
const info = router.info();
|
||
const {
|
||
statusBarHeight = 0,
|
||
screenHeight,
|
||
windowHeight,
|
||
safeAreaInsets,
|
||
} = uni.getSystemInfoSync();
|
||
|
||
const { proxy }: any = getCurrentInstance();
|
||
|
||
// 是否显示导航栏
|
||
const statusBar = computed(() => {
|
||
return info?.isCustomNavbar ? props.statusBar : false;
|
||
});
|
||
// 背景色
|
||
const background = computed(() => {
|
||
return (
|
||
props.backgroundColor ||
|
||
router.info()?.style?.backgroundColor ||
|
||
router.globalStyle.backgroundColor ||
|
||
"#ffffff"
|
||
);
|
||
});
|
||
|
||
// 全屏高
|
||
const height = computed(() => {
|
||
if (!props.fullscreen) {
|
||
return "auto";
|
||
}
|
||
|
||
let h = 0;
|
||
|
||
// #ifdef H5
|
||
h = windowHeight;
|
||
// #endif
|
||
// #ifndef H5
|
||
h = screenHeight - (statusBar ? statusBarHeight : 0);
|
||
if (!info?.isCustomNavbar) {
|
||
h -= 44;
|
||
h -= statusBarHeight;
|
||
}
|
||
|
||
// #endif
|
||
if (props.fullscreen) return h + "px";
|
||
|
||
return h - (safeAreaInsets?.bottom || 0) + "px";
|
||
});
|
||
|
||
// 加载框配置
|
||
const loader = reactive({
|
||
loading: false,
|
||
border: false,
|
||
text: "加载中",
|
||
});
|
||
|
||
// 显示加载框
|
||
function showLoading(options?: ClLoading.MaskOptions) {
|
||
loader.loading = true;
|
||
|
||
if (isString(options)) {
|
||
loader.text = options;
|
||
} else {
|
||
Object.assign(loader, options);
|
||
}
|
||
}
|
||
|
||
// 隐藏加载框
|
||
function hideLoading() {
|
||
loader.loading = false;
|
||
}
|
||
|
||
// 提示框
|
||
function showToast(options: ClToast.Options) {
|
||
refs.toast?.open(options);
|
||
}
|
||
|
||
// 确认框
|
||
function showConfirm(options: ClConfirm.Options) {
|
||
refs.confirm?.open(options);
|
||
}
|
||
|
||
// 提示框
|
||
function showTips(message: string, callback?: () => void) {
|
||
refs.confirm?.open({
|
||
title: "提示",
|
||
message,
|
||
showCancelButton: false,
|
||
callback,
|
||
} as ClConfirm.Options);
|
||
}
|
||
|
||
// 扩展
|
||
const page = router.currentPage();
|
||
|
||
if (page) {
|
||
page["cl-page"] = {
|
||
loaded: false,
|
||
showLoading,
|
||
hideLoading,
|
||
showToast,
|
||
showConfirm,
|
||
showTips,
|
||
};
|
||
|
||
onMounted(() => {
|
||
page["cl-page"].loaded = true;
|
||
});
|
||
}
|
||
|
||
// 滚动事件
|
||
proxy.$root.scrollTo = (top: number) => {
|
||
// 减去自定义导航栏高度
|
||
top -= info?.isCustomNavbar ? statusBarHeight : 0;
|
||
|
||
// 减去间距
|
||
if (props.padding) {
|
||
const [t] = parseRpx(props.padding).split(" ");
|
||
top -= uni.upx2px(parseInt(t));
|
||
}
|
||
|
||
uni.createSelectorQuery()
|
||
.in(proxy)
|
||
.select(".cl-page")
|
||
.boundingClientRect((a: any) => {
|
||
uni.createSelectorQuery()
|
||
.in(proxy)
|
||
.select(".safe-area-bottom")
|
||
.boundingClientRect((b: any) => {
|
||
const scrollTop = top + (a?.height || 0) - (b?.bottom || 0);
|
||
|
||
uni.pageScrollTo({
|
||
scrollTop,
|
||
duration: 100,
|
||
});
|
||
})
|
||
.exec();
|
||
})
|
||
.exec();
|
||
};
|
||
const scrollTop = ref(0);
|
||
|
||
onPageScroll((e: any) => {
|
||
scrollTop.value = e.scrollTop;
|
||
});
|
||
return {
|
||
app,
|
||
background,
|
||
height,
|
||
refs,
|
||
setRefs,
|
||
scrollTop,
|
||
loader,
|
||
parseRpx,
|
||
statusBar,
|
||
};
|
||
},
|
||
});
|
||
</script>
|