feat:H5状态栏适配
This commit is contained in:
1 parent
3317d463a1
commit
8ad36b1d57
24 files changed
+271
-90
No files matched your search
+10
-4
@@ -610,6 +610,12 @@ page {
|
||||
@import url('./static/icon/self/iconfont.css');
|
||||
|
||||
// #ifdef H5
|
||||
:root {
|
||||
--native-status-bar-height: env(safe-area-inset-top, 0px);
|
||||
--app-shell-status-bar-height: 0px;
|
||||
--status-bar-height: var(--native-status-bar-height);
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
#app,
|
||||
@@ -633,8 +639,8 @@ uni-page-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
// #ifdef H5
|
||||
height: calc(100dvh - 50px - $im-nav-bar-height); // h5平台100vh是包含了底部高度,需要减去
|
||||
top: $im-nav-bar-height;
|
||||
height: calc(100dvh - 50px - $im-nav-bar-height - var(--status-bar-height, 0px)); // h5套壳时还要减去宿主app状态栏高度
|
||||
top: calc($im-nav-bar-height + var(--status-bar-height, 0px));
|
||||
overflow: hidden;
|
||||
min-height: 0;
|
||||
// #endif
|
||||
@@ -657,8 +663,8 @@ uni-page-wrapper {
|
||||
.page {
|
||||
position: relative;
|
||||
// #ifdef H5
|
||||
height: calc(100vh - $im-nav-bar-height); // h5平台100vh是包含了底部高度,需要减去
|
||||
top: $im-nav-bar-height;
|
||||
height: calc(100dvh - $im-nav-bar-height - var(--status-bar-height, 0px)); // h5套壳时还要减去宿主app状态栏高度
|
||||
top: calc($im-nav-bar-height + var(--status-bar-height, 0px));
|
||||
overflow: hidden;
|
||||
min-height: 0;
|
||||
// #endif
|
||||
|
||||
+4
-2
@@ -18,12 +18,14 @@ import * as recorder from './common/recorder-h5';
|
||||
import ImageResize from 'quill-image-resize-mp';
|
||||
import Quill from 'quill';
|
||||
import { patchH5Navigation } from '@/sheep/router/h5-navigation';
|
||||
import { initH5HostShell } from '@/sheep/platform/h5-shell';
|
||||
// 以下组件用于兼容部分手机聊天边框无法输入的问题
|
||||
window.Quill = Quill;
|
||||
window.ImageResize = { default: ImageResize };
|
||||
// 调试器
|
||||
// import VConsole from 'vconsole';
|
||||
// new VConsole();
|
||||
import VConsole from 'vconsole';
|
||||
new VConsole();
|
||||
initH5HostShell();
|
||||
patchH5Navigation();
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
</template>
|
||||
</wd-navbar>
|
||||
|
||||
<scroll-list v-if="userDetail?.member?.memberId" style="height: calc(100dvh - 88px)"
|
||||
<scroll-list v-if="userDetail?.member?.memberId" style="height: calc(100dvh - 88px - var(--status-bar-height, 0px))"
|
||||
:loadMoreStatus="loadMoreStatus" @refresh="refreshList" @loadMore="listLoadMore" @scroll="onScroll">
|
||||
<view class="w-full h-600rpx relative">
|
||||
<image class="w-full h-full absolute inset-0" :src="userDetail.member.memberAvatar" mode="aspectFill" />
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</template>
|
||||
</wd-navbar>
|
||||
|
||||
<scroll-view scroll-y style="height: calc(100dvh - 88px)">
|
||||
<scroll-view scroll-y style="height: calc(100dvh - 88px - var(--status-bar-height, 0px))">
|
||||
<view class="mx-4 my-2 text-size-base">举报类型</view>
|
||||
<view class="mx-4">
|
||||
<wd-radio-group v-model="form.reportType" shape="dot" size="large">
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</template>
|
||||
</wd-navbar>
|
||||
|
||||
<scroll-view scroll-y style="height: calc(100dvh - 88px)">
|
||||
<scroll-view scroll-y style="height: calc(100dvh - 88px - var(--status-bar-height, 0px))">
|
||||
<wd-textarea v-model="params.description" :maxlength="1000" clearable show-word-limit />
|
||||
<wd-tabs v-model="activeTab">
|
||||
<wd-tab title="发图文">
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</navigator>
|
||||
</template>
|
||||
</wd-navbar>
|
||||
<scroll-list style="height: calc(100dvh - 44px - 50px)" :loadMoreStatus="loadMoreStatus" @refresh="refreshList"
|
||||
<scroll-list style="height: calc(100dvh - 44px - 50px - var(--status-bar-height, 0px))" :loadMoreStatus="loadMoreStatus" @refresh="refreshList"
|
||||
@loadMore="listLoadMore">
|
||||
<view class="flex-col justify-center card-thin mx-20rpx px-30rpx py-30rpx mb-30rpx"
|
||||
v-for="(v, i) in listData" :key="v.id">
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<!-- #endif -->
|
||||
</wd-navbar>
|
||||
|
||||
<scroll-view style="height: calc(100dvh - 44px)" scroll-y>
|
||||
<scroll-view style="height: calc(100dvh - 44px - var(--status-bar-height, 0px))" scroll-y>
|
||||
<view
|
||||
class="mx-4 p-4 rounded-2 bg-gradient-to-b from-#111 to-#222 b-4 b-solid b-t-#D29E52/60 b-l-#D29E52/40 b-r-#D29E52/40 b-b-#D29E52/20">
|
||||
<view class="text-color-theme-dark font-900 font-italic text-xl mb-1">VIP</view>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</template>
|
||||
</wd-navbar>
|
||||
|
||||
<scroll-list style="height: calc(100dvh - 44px - 50px)" :loadMoreStatus="loadMoreStatus" @refresh="refreshList"
|
||||
<scroll-list style="height: calc(100dvh - 44px - 50px - var(--status-bar-height, 0px))" :loadMoreStatus="loadMoreStatus" @refresh="refreshList"
|
||||
@loadMore="listLoadMore">
|
||||
<view v-for="(item, index) in listData" :key="index" class="flex items-center justify-between px-4 py-2">
|
||||
<view class="flex items-center text-base overflow-hidden">
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
<swiper class="flex-1 overflow-hidden" :current="current" @change="(e) => (current = e.detail.current)"
|
||||
:duration="200">
|
||||
<swiper-item>
|
||||
<scroll-list class="h-full" :loadMoreStatus="loadMoreStatus0" @refresh="refreshList0" @loadMore="listLoadMore0"
|
||||
<scroll- list class="h-full" :loadMoreStatus="loadMoreStatus0" @refresh="refreshList0" @loadMore="listLoadMore0"
|
||||
:show-scrollbar="false" :refresherEnabled="true">
|
||||
<user-card v-for="user in listData0" :key="user.id" :data="user" @click="detail(user)" />
|
||||
</scroll-list>
|
||||
</scroll->
|
||||
</swiper-item>
|
||||
<swiper-item>
|
||||
<scroll-list class="h-full" :loadMoreStatus="loadMoreStatus1" @refresh="refreshList1" @loadMore="listLoadMore1"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</template>
|
||||
</wd-navbar>
|
||||
|
||||
<scroll-list style="height: calc(100dvh - 44px - 50px)" :loadMoreStatus="loadMoreStatus" @refresh="refreshList"
|
||||
<scroll-list style="height: calc(100dvh - 44px - var(--status-bar-height, 0px))" :loadMoreStatus="loadMoreStatus" @refresh="refreshList"
|
||||
@loadMore="listLoadMore">
|
||||
<moment-card v-for="item in listData" :data="item" :showChat="false" :showLike="false" />
|
||||
</scroll-list>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</template>
|
||||
</wd-navbar>
|
||||
|
||||
<scroll-list style="height: calc(100dvh - 44px - 50px)" :loadMoreStatus="loadMoreStatus" @refresh="refreshList"
|
||||
<scroll-list style="height: calc(100dvh - 44px - 50px - var(--status-bar-height, 0px))" :loadMoreStatus="loadMoreStatus" @refresh="refreshList"
|
||||
@loadMore="listLoadMore">
|
||||
<view class="flex items-center card-thin mx-20rpx px-30rpx py-30rpx mb-30rpx" v-for="(v, i) in listData"
|
||||
:key="v.id">
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<!-- #endif -->
|
||||
</wd-navbar>
|
||||
|
||||
<scroll-view style="height: calc(100dvh - 44px)" scroll-y>
|
||||
<scroll-view style="height: calc(100dvh - 44px - var(--status-bar-height, 0px))" scroll-y>
|
||||
<view
|
||||
class="mx-4 p-4 rounded-2 bg-gradient-to-b from-#111 to-#222 b-4 b-solid b-t-#D29E52/60 b-l-#D29E52/40 b-r-#D29E52/40 b-b-#D29E52/20">
|
||||
<view class="text-color-theme-dark font-900 font-italic text-xl mb-1">VIP</view>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
<wd-tabs v-model="activeTab" swipeable>
|
||||
<wd-tab title="我看过的">
|
||||
<scroll-list style="height: calc(100dvh - 44px - 50px)" :loadMoreStatus="loadMoreStatus_seenIt"
|
||||
<scroll-list style="height: calc(100dvh - 44px - 50px - var(--status-bar-height, 0px))" :loadMoreStatus="loadMoreStatus_seenIt"
|
||||
@refresh="refreshList_seenIt" @loadMore="listLoadMore_seenIt">
|
||||
<view class="h-10rpx"></view>
|
||||
<view-record-item v-if="listData_seenIt.length" v-for="user in listData_seenIt" :record="user"
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
</view>
|
||||
</template>
|
||||
</wd-navbar>
|
||||
<swiper :current="current" style="height: calc(100dvh - 44px - 50px)" @change="(e) => (current = e.detail.current)"
|
||||
:duration="200">
|
||||
<swiper :current="current" style="height: calc(100dvh - 44px - 50px - var(--status-bar-height, 0px))"
|
||||
@change="(e) => (current = e.detail.current)" :duration="200">
|
||||
<swiper-item v-for="(item, index) in segmentedItems" :key="index">
|
||||
<scroll-user :scene="item['search-action']" />
|
||||
</swiper-item>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
</wd-navbar>
|
||||
<scroll-view style="height: calc(100dvh - 44px);" scroll-y>
|
||||
<scroll-view style="height: calc(100dvh - 44px - var(--status-bar-height, 0px));" scroll-y>
|
||||
<view style="background: red; height: var(--status-bar-height);"></view>
|
||||
<!-- 用户信息 -->
|
||||
<view class="mx-20rpx mt-30rpx bg-color-dark rounded-12rpx flex justify-between items-center px-6 py-4">
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</navigator>
|
||||
</template>
|
||||
</wd-navbar>
|
||||
<scroll-list style="height: calc(100dvh - 44px - 50px)" :loadMoreStatus="loadMoreStatus" @refresh="refreshList"
|
||||
<scroll-list style="height: calc(100dvh - 44px - 50px - var(--status-bar-height, 0px))" :loadMoreStatus="loadMoreStatus" @refresh="refreshList"
|
||||
@loadMore="listLoadMore">
|
||||
<GiftRecordItem v-for="(v, i) in listData" :key="v.id" :item="v" @on-refresh="refreshList" />
|
||||
</scroll-list>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<wd-tab title="消费记录" />
|
||||
<wd-tab title="缘豆记录" />
|
||||
</wd-tabs>
|
||||
<view class="mt-15rpx mx-30rpx" style="height: calc(100dvh - 44px - 84rpx);">
|
||||
<view class="mt-15rpx mx-30rpx" style="height: calc(100dvh - 44px - 84rpx - var(--status-bar-height, 0px));">
|
||||
<scroll-list class="h-full" v-if="[0].includes(activeTab)" :loadMoreStatus="loadMoreStatus_withraw"
|
||||
@refresh="refreshList_withraw" @loadMore="listLoadMore_withraw">
|
||||
<WithrawRecordItem v-for="(v, i) in listData_withraw" :key="v.id" :item="v" />
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
</view>
|
||||
<view class="mt-30rpx mx-30rpx rounded-12rpx">
|
||||
<view class="text-base">礼物明细</view>
|
||||
<scroll-list class="mt-15rpx" style="height: calc(100dvh - 44px - 350rpx);" :loadMoreStatus="loadMoreStatus"
|
||||
<scroll-list class="mt-15rpx" style="height: calc(100dvh - 44px - 350rpx - var(--status-bar-height, 0px));" :loadMoreStatus="loadMoreStatus"
|
||||
@refresh="refreshList" @loadMore="listLoadMore">
|
||||
<view class="flex-col card-thin px-16rpx py-12rpx mb-15rpx" v-for="(v, i) in listData" :key="v.id">
|
||||
<text class="text-xs">{{ v.title }}</text>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</navigator>
|
||||
</template>
|
||||
</wd-navbar>
|
||||
<scroll-list style="height: calc(100dvh - 44px - 50px)" :loadMoreStatus="loadMoreStatus" @refresh="refreshList"
|
||||
<scroll-list style="height: calc(100dvh - 44px - 50px - var(--status-bar-height, 0px))" :loadMoreStatus="loadMoreStatus" @refresh="refreshList"
|
||||
@loadMore="listLoadMore">
|
||||
<WithrawRecordItem v-for="(v, i) in listData" :key="v.id" :item="v" @on-refresh="refreshList" />
|
||||
</scroll-list>
|
||||
|
||||
@@ -1,73 +1,60 @@
|
||||
<template>
|
||||
<scroll-view
|
||||
scroll-y
|
||||
refresher-enabled
|
||||
enable-back-to-top
|
||||
refresher-background="#222"
|
||||
:refresher-triggered="refresherTriggered"
|
||||
:refresher-threshold="100"
|
||||
@refresherabort="onRefresherAbort"
|
||||
@refresherrefresh="onRefresherRefresh"
|
||||
@scrolltolower="onScrollToLower"
|
||||
@scroll="scroll"
|
||||
>
|
||||
<scroll-view scroll-y refresher-enabled enable-back-to-top refresher-background="#222"
|
||||
:refresher-triggered="refresherTriggered" :refresher-threshold="100" @refresherabort="onRefresherAbort"
|
||||
@refresherrefresh="onRefresherRefresh" @scrolltolower="onScrollToLower" @scroll="scroll">
|
||||
<slot />
|
||||
<uni-load-more
|
||||
:status="loadMoreStatus"
|
||||
:content-text="loadMoreContent"
|
||||
@clickLoadMore="onScrollToLower"
|
||||
/>
|
||||
<uni-load-more :status="loadMoreStatus" :content-text="loadMoreContent" @clickLoadMore="onScrollToLower" />
|
||||
<view style="height: 100rpx"></view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue';
|
||||
import { reactive, ref } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
loadMoreStatus?: 'more' | 'loading' | 'noMore';
|
||||
}>(),
|
||||
{
|
||||
loadMoreStatus: 'noMore',
|
||||
},
|
||||
);
|
||||
const emit = defineEmits<{
|
||||
(e: 'refresh', done: () => void): void;
|
||||
(e: 'loadMore'): void;
|
||||
(e: 'scroll', event: any): void;
|
||||
}>();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
loadMoreStatus?: 'more' | 'loading' | 'noMore';
|
||||
}>(),
|
||||
{
|
||||
loadMoreStatus: 'noMore',
|
||||
},
|
||||
);
|
||||
const emit = defineEmits<{
|
||||
(e: 'refresh', done: () => void): void;
|
||||
(e: 'loadMore'): void;
|
||||
(e: 'scroll', event: any): void;
|
||||
}>();
|
||||
|
||||
const refresherTriggered = ref(false);
|
||||
const refresherTriggered = ref(false);
|
||||
|
||||
const loadMoreContent = reactive({
|
||||
contentdown: '正在加载...',
|
||||
contentrefresh: '正在加载...',
|
||||
contentnomore: '没有更多数据了',
|
||||
});
|
||||
const loadMoreContent = reactive({
|
||||
contentdown: '正在加载...',
|
||||
contentrefresh: '正在加载...',
|
||||
contentnomore: '没有更多数据了',
|
||||
});
|
||||
|
||||
// 下拉刷新中止
|
||||
const onRefresherAbort = () => {
|
||||
// 下拉刷新中止
|
||||
const onRefresherAbort = () => {
|
||||
refresherTriggered.value = false;
|
||||
};
|
||||
|
||||
// 触发下拉刷新
|
||||
const onRefresherRefresh = () => {
|
||||
refresherTriggered.value = true;
|
||||
emit('refresh', () => {
|
||||
refresherTriggered.value = false;
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
// 触发下拉刷新
|
||||
const onRefresherRefresh = () => {
|
||||
refresherTriggered.value = true;
|
||||
emit('refresh', () => {
|
||||
refresherTriggered.value = false;
|
||||
});
|
||||
};
|
||||
// 触发上拉加载
|
||||
const onScrollToLower = () => {
|
||||
if (props.loadMoreStatus === 'loading' || props.loadMoreStatus === 'noMore') {
|
||||
return;
|
||||
}
|
||||
emit('loadMore');
|
||||
};
|
||||
|
||||
// 触发上拉加载
|
||||
const onScrollToLower = () => {
|
||||
if (props.loadMoreStatus === 'loading' || props.loadMoreStatus === 'noMore') {
|
||||
return;
|
||||
}
|
||||
emit('loadMore');
|
||||
};
|
||||
|
||||
const scroll = (e: any) => {
|
||||
emit('scroll', e);
|
||||
};
|
||||
const scroll = (e: any) => {
|
||||
emit('scroll', e);
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,175 @@
|
||||
const H5_STATUS_BAR_STORAGE_KEY = '__friendship_h5_status_bar_height__';
|
||||
const H5_STATUS_BAR_QUERY_KEYS = ['statusBarHeight', 'safeTop', 'safeAreaTop', 'appStatusBarHeight'];
|
||||
const H5_MIN_STATUS_BAR_HEIGHT = 22;
|
||||
|
||||
function normalizeStatusBarHeight(value) {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
return null;
|
||||
}
|
||||
const normalizedValue = typeof value === 'string' ? value.replace(/px$/i, '').trim() : value;
|
||||
const height = Number.parseFloat(normalizedValue);
|
||||
if (!Number.isFinite(height)) {
|
||||
return null;
|
||||
}
|
||||
return Math.max(0, Math.min(height, 200));
|
||||
}
|
||||
|
||||
function parseMessageData(data) {
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
if (typeof data === 'string') {
|
||||
try {
|
||||
return JSON.parse(data);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function readStatusBarHeightFromQuery() {
|
||||
const searchParamsList = [];
|
||||
searchParamsList.push(new URLSearchParams(window.location.search));
|
||||
const hashQuery = window.location.hash.includes('?') ? window.location.hash.split('?')[1] : '';
|
||||
if (hashQuery) {
|
||||
searchParamsList.push(new URLSearchParams(hashQuery));
|
||||
}
|
||||
|
||||
for (const params of searchParamsList) {
|
||||
for (const key of H5_STATUS_BAR_QUERY_KEYS) {
|
||||
const height = normalizeStatusBarHeight(params.get(key));
|
||||
if (height !== null) {
|
||||
return height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function readStatusBarHeightFromWindow() {
|
||||
const candidates = [
|
||||
window.__APP_STATUS_BAR_HEIGHT__,
|
||||
window.__UNI_STATUS_BAR_HEIGHT__,
|
||||
window.__APP_SHELL_CONFIG__?.statusBarHeight,
|
||||
window.__UNI_WEBVIEW_CONFIG__?.statusBarHeight,
|
||||
];
|
||||
for (const candidate of candidates) {
|
||||
const height = normalizeStatusBarHeight(candidate);
|
||||
if (height !== null) {
|
||||
return height;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function readStatusBarHeightFromStorage() {
|
||||
try {
|
||||
return normalizeStatusBarHeight(window.localStorage.getItem(H5_STATUS_BAR_STORAGE_KEY));
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function readNativeStatusBarHeight() {
|
||||
if (typeof window === 'undefined') {
|
||||
return 0;
|
||||
}
|
||||
const rootStyle = window.getComputedStyle(document.documentElement);
|
||||
return normalizeStatusBarHeight(rootStyle.getPropertyValue('--native-status-bar-height')) ?? 0;
|
||||
}
|
||||
|
||||
function ensureMinShellStatusBarHeight(height) {
|
||||
if (height === null || height <= 0) {
|
||||
return 0;
|
||||
}
|
||||
return Math.max(height, H5_MIN_STATUS_BAR_HEIGHT);
|
||||
}
|
||||
|
||||
export function getH5HostStatusBarHeight() {
|
||||
if (typeof window === 'undefined') {
|
||||
return 0;
|
||||
}
|
||||
return ensureMinShellStatusBarHeight(
|
||||
readStatusBarHeightFromQuery() ??
|
||||
readStatusBarHeightFromWindow() ??
|
||||
readStatusBarHeightFromStorage() ??
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyH5HostStatusBarHeight(height) {
|
||||
if (typeof window === 'undefined') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const safeTop = ensureMinShellStatusBarHeight(normalizeStatusBarHeight(height));
|
||||
const nativeSafeTop = readNativeStatusBarHeight();
|
||||
const finalSafeTop = Math.max(nativeSafeTop, safeTop);
|
||||
const safeTopValue = `${safeTop}px`;
|
||||
const finalSafeTopValue = `${finalSafeTop}px`;
|
||||
const rootStyle = document.documentElement.style;
|
||||
const bodyStyle = document.body?.style;
|
||||
|
||||
rootStyle.setProperty('--app-shell-status-bar-height', safeTopValue);
|
||||
rootStyle.setProperty('--status-bar-height', finalSafeTopValue);
|
||||
bodyStyle?.setProperty('--app-shell-status-bar-height', safeTopValue);
|
||||
bodyStyle?.setProperty('--status-bar-height', finalSafeTopValue);
|
||||
|
||||
window.__APP_STATUS_BAR_HEIGHT__ = safeTop;
|
||||
|
||||
try {
|
||||
window.localStorage.setItem(H5_STATUS_BAR_STORAGE_KEY, String(safeTop));
|
||||
} catch (error) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
window.dispatchEvent(
|
||||
new CustomEvent('app-shell-status-bar-change', {
|
||||
detail: { height: finalSafeTop, appHeight: safeTop, nativeHeight: nativeSafeTop },
|
||||
}),
|
||||
);
|
||||
|
||||
return finalSafeTop;
|
||||
}
|
||||
|
||||
function resolveMessageStatusBarHeight(message) {
|
||||
const data = parseMessageData(message?.data);
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return normalizeStatusBarHeight(
|
||||
data.statusBarHeight ??
|
||||
data.safeTop ??
|
||||
data.safeAreaTop ??
|
||||
data.payload?.statusBarHeight ??
|
||||
data.payload?.safeTop,
|
||||
);
|
||||
}
|
||||
|
||||
export function initH5HostShell() {
|
||||
if (typeof window === 'undefined') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const safeTop = applyH5HostStatusBarHeight(getH5HostStatusBarHeight());
|
||||
if (window.__FRIENDSHIP_H5_SHELL_READY__) {
|
||||
return safeTop;
|
||||
}
|
||||
|
||||
window.__FRIENDSHIP_H5_SHELL_READY__ = true;
|
||||
window.setAppShellStatusBarHeight = (nextHeight) => applyH5HostStatusBarHeight(nextHeight);
|
||||
window.addEventListener('message', (message) => {
|
||||
const nextHeight = resolveMessageStatusBarHeight(message);
|
||||
if (nextHeight !== null) {
|
||||
applyH5HostStatusBarHeight(nextHeight);
|
||||
}
|
||||
});
|
||||
window.addEventListener('load', () => {
|
||||
applyH5HostStatusBarHeight(getH5HostStatusBarHeight());
|
||||
});
|
||||
|
||||
return safeTop;
|
||||
}
|
||||
@@ -12,6 +12,7 @@
|
||||
import { isEmpty } from 'lodash-es';
|
||||
// #ifdef H5
|
||||
import { isWxBrowser } from '@/sheep/helper/utils';
|
||||
import { getH5HostStatusBarHeight } from './h5-shell';
|
||||
// #endif
|
||||
import wechat from './provider/wechat/index.js';
|
||||
import apple from './provider/apple';
|
||||
@@ -19,6 +20,12 @@ import share from './share';
|
||||
import Pay from './pay';
|
||||
|
||||
const device = uni.getWindowInfo();
|
||||
// #ifdef H5
|
||||
const h5StatusBarHeight = getH5HostStatusBarHeight();
|
||||
if (h5StatusBarHeight > 0) {
|
||||
device.statusBarHeight = h5StatusBarHeight;
|
||||
}
|
||||
// #endif
|
||||
|
||||
const os = uni.getDeviceInfo().platform;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight + 'px';
|
||||
const statusBarHeight = `var(--status-bar-height, ${sheep.$platform.device.statusBarHeight}px)`;
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.uni-status-bar {
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
<template>
|
||||
<view :style="{ height: addUnit(height) }">
|
||||
<view :class="`wd-navbar ${customClass} ${fixed ? 'is-fixed' : ''} ${bordered ? 'is-border' : ''}`" :style="rootStyle">
|
||||
<view :class="`wd-navbar ${customClass} ${fixed ? 'is-fixed' : ''} ${bordered ? 'is-border' : ''}`"
|
||||
:style="rootStyle">
|
||||
<view class="wd-navbar__content">
|
||||
<view class="wd-navbar__capsule" v-if="$slots.capsule">
|
||||
<slot name="capsule" />
|
||||
</view>
|
||||
|
||||
<view :class="`wd-navbar__left ${leftDisabled ? 'is-disabled' : ''}`" @click="handleClickLeft" v-else-if="!$slots.left">
|
||||
<view :class="`wd-navbar__left ${leftDisabled ? 'is-disabled' : ''}`" @click="handleClickLeft"
|
||||
v-else-if="!$slots.left">
|
||||
<wd-icon v-if="leftArrow" name="arrow-left" custom-class="wd-navbar__arrow" />
|
||||
<view v-if="leftText" class="wd-navbar__text">{{ leftText }}</view>
|
||||
</view>
|
||||
@@ -19,10 +21,12 @@
|
||||
<slot name="title" />
|
||||
<block v-if="!$slots.title && title">{{ title }}</block>
|
||||
</view>
|
||||
<view :class="`wd-navbar__right ${rightDisabled ? 'is-disabled' : ''}`" @click="handleClickRight" v-if="$slots.right || rightText">
|
||||
<view :class="`wd-navbar__right ${rightDisabled ? 'is-disabled' : ''}`" @click="handleClickRight"
|
||||
v-if="$slots.right || rightText">
|
||||
<slot name="right" />
|
||||
|
||||
<view v-if="!$slots.right && rightText" class="wd-navbar__text" hover-class="wd-navbar__text--hover" :hover-stay-time="70">
|
||||
<view v-if="!$slots.right && rightText" class="wd-navbar__text" hover-class="wd-navbar__text--hover"
|
||||
:hover-stay-time="70">
|
||||
{{ rightText }}
|
||||
</view>
|
||||
</view>
|
||||
@@ -52,7 +56,7 @@ const emit = defineEmits(['click-left', 'click-right'])
|
||||
|
||||
const height = ref<number | ''>('') // 占位高度
|
||||
|
||||
const { statusBarHeight } = uni.getSystemInfoSync()
|
||||
let { statusBarHeight } = uni.getSystemInfoSync()
|
||||
|
||||
watch(
|
||||
[() => props.fixed, () => props.placeholder],
|
||||
@@ -68,7 +72,7 @@ const rootStyle = computed(() => {
|
||||
style['z-index'] = props.zIndex
|
||||
}
|
||||
if (props.safeAreaInsetTop) {
|
||||
style['padding-top'] = addUnit(statusBarHeight || 0)
|
||||
style['padding-top'] = `var(--status-bar-height, ${addUnit(statusBarHeight || 0)})`
|
||||
}
|
||||
return `${objToStyle(style)}${props.customStyle}`
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user