2025-01-09 16:16:11 +08:00
|
|
|
|
<template>
|
|
|
|
|
<view
|
|
|
|
|
class="cl-page"
|
|
|
|
|
:class="[
|
|
|
|
|
`theme-${app.theme.name}`,
|
|
|
|
|
{
|
|
|
|
|
'is-fullscreen': fullscreen,
|
2025-01-09 16:40:44 +08:00
|
|
|
|
'is-safe-area-bottom': fullscreen,
|
2025-01-09 16:16:11 +08:00
|
|
|
|
},
|
|
|
|
|
]"
|
|
|
|
|
:style="{
|
|
|
|
|
padding: parseRpx(padding),
|
2025-01-09 16:40:44 +08:00
|
|
|
|
height
|
2025-01-09 16:16:11 +08:00
|
|
|
|
}"
|
|
|
|
|
>
|
|
|
|
|
<!-- 加载框 -->
|
|
|
|
|
<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="{
|
2025-01-09 16:40:44 +08:00
|
|
|
|
backgroundColor: background,
|
|
|
|
|
backgroundImage: 'url(' + backgroundImage + ')',
|
2025-01-09 16:16:11 +08:00
|
|
|
|
}"
|
|
|
|
|
></view>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script lang="ts">
|
2025-01-09 16:40:44 +08:00
|
|
|
|
import { onPageScroll } from "@dcloudio/uni-app";
|
|
|
|
|
import { computed, defineComponent, ref, reactive, getCurrentInstance, onMounted } from "vue";
|
|
|
|
|
import { useApp, useCool} from "/@/cool";
|
2025-01-09 16:16:11 +08:00
|
|
|
|
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,
|
2025-01-09 16:40:44 +08:00
|
|
|
|
// 背景图片
|
|
|
|
|
backgroundImage: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: "",
|
|
|
|
|
},
|
2025-01-09 16:16:11 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
|
|
|
|
|
// 是否显示导航栏
|
2025-01-09 16:40:44 +08:00
|
|
|
|
const statusBar = computed(() => {
|
|
|
|
|
return info?.isCustomNavbar ? props.statusBar : false;
|
|
|
|
|
});
|
2025-01-09 16:16:11 +08:00
|
|
|
|
// 背景色
|
|
|
|
|
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
|
2025-01-09 16:40:44 +08:00
|
|
|
|
h = screenHeight - (statusBar ? statusBarHeight : 0);
|
2025-01-09 16:16:11 +08:00
|
|
|
|
if (!info?.isCustomNavbar) {
|
|
|
|
|
h -= 44;
|
2025-01-09 16:40:44 +08:00
|
|
|
|
h -= statusBarHeight;
|
2025-01-09 16:16:11 +08:00
|
|
|
|
}
|
2025-01-09 16:40:44 +08:00
|
|
|
|
|
2025-01-09 16:16:11 +08:00
|
|
|
|
// #endif
|
2025-01-09 16:40:44 +08:00
|
|
|
|
if (props.fullscreen) return h + "px";
|
2025-01-09 16:16:11 +08:00
|
|
|
|
|
|
|
|
|
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")
|
2025-01-09 16:40:44 +08:00
|
|
|
|
.boundingClientRect((a: any) => {
|
2025-01-09 16:16:11 +08:00
|
|
|
|
uni.createSelectorQuery()
|
|
|
|
|
.in(proxy)
|
|
|
|
|
.select(".safe-area-bottom")
|
2025-01-09 16:40:44 +08:00
|
|
|
|
.boundingClientRect((b: any) => {
|
2025-01-09 16:16:11 +08:00
|
|
|
|
const scrollTop = top + (a?.height || 0) - (b?.bottom || 0);
|
|
|
|
|
|
|
|
|
|
uni.pageScrollTo({
|
|
|
|
|
scrollTop,
|
|
|
|
|
duration: 100,
|
|
|
|
|
});
|
|
|
|
|
})
|
|
|
|
|
.exec();
|
|
|
|
|
})
|
|
|
|
|
.exec();
|
|
|
|
|
};
|
2025-01-09 16:40:44 +08:00
|
|
|
|
const scrollTop = ref(0);
|
2025-01-09 16:16:11 +08:00
|
|
|
|
|
2025-01-09 16:40:44 +08:00
|
|
|
|
onPageScroll((e: any) => {
|
|
|
|
|
scrollTop.value = e.scrollTop;
|
|
|
|
|
});
|
2025-01-09 16:16:11 +08:00
|
|
|
|
return {
|
|
|
|
|
app,
|
|
|
|
|
background,
|
|
|
|
|
height,
|
|
|
|
|
refs,
|
|
|
|
|
setRefs,
|
2025-01-09 16:40:44 +08:00
|
|
|
|
scrollTop,
|
2025-01-09 16:16:11 +08:00
|
|
|
|
loader,
|
|
|
|
|
parseRpx,
|
|
|
|
|
statusBar,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
</script>
|