fix(h5): 小程序 WebView 通过 sbh 参数铺满刘海区

WebView 内 safe-area-inset-top 常为 0,改由小程序传入 statusBarHeight;
全屏洗底层上延并同步原生页背景色,修复刘海露白。
This commit is contained in:
jackyu66git
2026-08-25 01:18:16 +08:00
parent 96292d0e95
commit 9d4fb52d29
4 changed files with 35 additions and 3 deletions
+1 -1
View File
@@ -36,7 +36,7 @@ const showBack = computed(() => {
grid-template-columns: 44px 1fr 44px; grid-template-columns: 44px 1fr 44px;
align-items: center; align-items: center;
gap: 4px; gap: 4px;
padding: calc(8px + env(safe-area-inset-top, 0px)) 12px 4px; padding: calc(8px + var(--yxg-safe-top)) 12px 4px;
background: transparent; background: transparent;
pointer-events: none; pointer-events: none;
} }
+7
View File
@@ -17,6 +17,13 @@ describe('mpEmbed', () => {
expect(isMpEmbed()).toBe(true) expect(isMpEmbed()).toBe(true)
}) })
it('applies status bar height from ?sbh=', () => {
window.history.replaceState({}, '', '/psy/?mp=1&sbh=47')
initMpEmbed()
expect(document.documentElement.style.getPropertyValue('--yxg-safe-top')).toBe('47px')
expect(document.documentElement.style.getPropertyValue('--yxg-page-top')).toBe('calc(47px + 50px)')
})
it('returns false without mp query', () => { it('returns false without mp query', () => {
initMpEmbed() initMpEmbed()
expect(isMpEmbed()).toBe(false) expect(isMpEmbed()).toBe(false)
+14
View File
@@ -1,5 +1,15 @@
const MP_EMBED_KEY = 'yxg_mp_embed' const MP_EMBED_KEY = 'yxg_mp_embed'
const MP_QUERY = 'mp' const MP_QUERY = 'mp'
const SBH_QUERY = 'sbh'
const HEADER_H_PX = 50
function applySafeTopInset(px: number): void {
if (typeof document === 'undefined' || px <= 0) return
const root = document.documentElement
const safe = `${px}px`
root.style.setProperty('--yxg-safe-top', safe)
root.style.setProperty('--yxg-page-top', `calc(${safe} + ${HEADER_H_PX}px)`)
}
/** Apply document-level embed chrome (safe-area wash, hide HTML title). */ /** Apply document-level embed chrome (safe-area wash, hide HTML title). */
export function applyMpEmbedDom(): void { export function applyMpEmbedDom(): void {
@@ -15,6 +25,10 @@ export function initMpEmbed(): void {
if (params.get(MP_QUERY) === '1') { if (params.get(MP_QUERY) === '1') {
sessionStorage.setItem(MP_EMBED_KEY, '1') sessionStorage.setItem(MP_EMBED_KEY, '1')
} }
const sbh = params.get(SBH_QUERY)
if (sbh && /^\d+$/.test(sbh)) {
applySafeTopInset(parseInt(sbh, 10))
}
applyMpEmbedDom() applyMpEmbedDom()
} }
+13 -2
View File
@@ -37,6 +37,14 @@ body{
position:relative; position:relative;
z-index:1; z-index:1;
} }
html.mp-embed{
background-color:var(--color-bg-start);
background-image:var(--yxg-body-wash);
background-attachment:fixed;
}
html.mp-embed body{
background:transparent;
}
.app-shell.mp-embed{ .app-shell.mp-embed{
padding-bottom:env(safe-area-inset-bottom,0px); padding-bottom:env(safe-area-inset-bottom,0px);
isolation:isolate; isolation:isolate;
@@ -44,10 +52,14 @@ body{
.app-shell.mp-embed::before{ .app-shell.mp-embed::before{
content:""; content:"";
position:fixed; position:fixed;
inset:0; top:calc(-1 * var(--yxg-safe-top));
left:0;
right:0;
bottom:0;
z-index:0; z-index:0;
pointer-events:none; pointer-events:none;
background:var(--yxg-body-wash); background:var(--yxg-body-wash);
background-color:var(--color-bg-start);
} }
.app-footer{ .app-footer{
position:relative; position:relative;
@@ -297,4 +309,3 @@ a{color:inherit;text-decoration:none}
.fc-c .yxg-feed-cover{background:linear-gradient(145deg,#D6E8FF,#B0D0F5);color:#3A6FB0} .fc-c .yxg-feed-cover{background:linear-gradient(145deg,#D6E8FF,#B0D0F5);color:#3A6FB0}
.fc-d .yxg-feed-cover{background:linear-gradient(145deg,#D8F0DC,#B5E0BE);color:#3A8A4A} .fc-d .yxg-feed-cover{background:linear-gradient(145deg,#D8F0DC,#B5E0BE);color:#3A8A4A}
.fc-e .yxg-feed-cover{background:linear-gradient(145deg,#FFE6C8,#F5C98A);color:#B07A28} .fc-e .yxg-feed-cover{background:linear-gradient(145deg,#FFE6C8,#F5C98A);color:#B07A28}
)