diff --git a/apps/user-h5/src/components/AppHeader.vue b/apps/user-h5/src/components/AppHeader.vue index ec5a980..cc7fbe4 100644 --- a/apps/user-h5/src/components/AppHeader.vue +++ b/apps/user-h5/src/components/AppHeader.vue @@ -36,7 +36,7 @@ const showBack = computed(() => { grid-template-columns: 44px 1fr 44px; align-items: center; gap: 4px; - padding: calc(8px + env(safe-area-inset-top, 0px)) 12px 4px; + padding: calc(8px + var(--yxg-safe-top)) 12px 4px; background: transparent; pointer-events: none; } diff --git a/apps/user-h5/src/lib/mpEmbed.spec.ts b/apps/user-h5/src/lib/mpEmbed.spec.ts index c0ab93d..69f50a5 100644 --- a/apps/user-h5/src/lib/mpEmbed.spec.ts +++ b/apps/user-h5/src/lib/mpEmbed.spec.ts @@ -17,6 +17,13 @@ describe('mpEmbed', () => { 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', () => { initMpEmbed() expect(isMpEmbed()).toBe(false) diff --git a/apps/user-h5/src/lib/mpEmbed.ts b/apps/user-h5/src/lib/mpEmbed.ts index 15bf21f..075d758 100644 --- a/apps/user-h5/src/lib/mpEmbed.ts +++ b/apps/user-h5/src/lib/mpEmbed.ts @@ -1,5 +1,15 @@ const MP_EMBED_KEY = 'yxg_mp_embed' 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). */ export function applyMpEmbedDom(): void { @@ -15,6 +25,10 @@ export function initMpEmbed(): void { if (params.get(MP_QUERY) === '1') { sessionStorage.setItem(MP_EMBED_KEY, '1') } + const sbh = params.get(SBH_QUERY) + if (sbh && /^\d+$/.test(sbh)) { + applySafeTopInset(parseInt(sbh, 10)) + } applyMpEmbedDom() } diff --git a/apps/user-h5/src/styles/app.css b/apps/user-h5/src/styles/app.css index 1369e0f..d0f90bc 100644 --- a/apps/user-h5/src/styles/app.css +++ b/apps/user-h5/src/styles/app.css @@ -37,6 +37,14 @@ body{ position:relative; 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{ padding-bottom:env(safe-area-inset-bottom,0px); isolation:isolate; @@ -44,10 +52,14 @@ body{ .app-shell.mp-embed::before{ content:""; position:fixed; - inset:0; + top:calc(-1 * var(--yxg-safe-top)); + left:0; + right:0; + bottom:0; z-index:0; pointer-events:none; background:var(--yxg-body-wash); + background-color:var(--color-bg-start); } .app-footer{ 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-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} -)