fix(h5): 统一 nh=1 与 sbh 顶距逻辑,与 index.html 首屏一致
applyMpEmbedDom 在原生顶栏模式读取 session sbh;补充 nh+sbh 单测。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,6 +4,9 @@ import { applyMpEmbedDom, initMpEmbed, isMpEmbed, isMpNativeHeader } from './mpE
|
|||||||
describe('mpEmbed', () => {
|
describe('mpEmbed', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
sessionStorage.clear()
|
sessionStorage.clear()
|
||||||
|
document.documentElement.className = ''
|
||||||
|
document.documentElement.style.removeProperty('--yxg-safe-top')
|
||||||
|
document.documentElement.style.removeProperty('--yxg-page-top')
|
||||||
window.history.replaceState({}, '', '/psy/')
|
window.history.replaceState({}, '', '/psy/')
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -37,6 +40,17 @@ describe('mpEmbed', () => {
|
|||||||
expect(document.documentElement.style.getPropertyValue('--yxg-page-top')).toBe('4px')
|
expect(document.documentElement.style.getPropertyValue('--yxg-page-top')).toBe('4px')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('applies sbh in native header mode with ?nh=1&sbh=', () => {
|
||||||
|
window.history.replaceState({}, '', '/psy/?mp=1&nh=1&sbh=12')
|
||||||
|
initMpEmbed()
|
||||||
|
expect(isMpNativeHeader()).toBe(true)
|
||||||
|
expect(sessionStorage.getItem('yxg_sbh')).toBe('12')
|
||||||
|
expect(document.documentElement.style.getPropertyValue('--yxg-page-top')).toBe('12px')
|
||||||
|
window.history.replaceState({}, '', '/psy/?mp=1&nh=1')
|
||||||
|
applyMpEmbedDom()
|
||||||
|
expect(document.documentElement.style.getPropertyValue('--yxg-page-top')).toBe('12px')
|
||||||
|
})
|
||||||
|
|
||||||
it('returns false without mp query', () => {
|
it('returns false without mp query', () => {
|
||||||
initMpEmbed()
|
initMpEmbed()
|
||||||
expect(isMpEmbed()).toBe(false)
|
expect(isMpEmbed()).toBe(false)
|
||||||
|
|||||||
@@ -7,12 +7,16 @@ const SBH_KEY = 'yxg_sbh'
|
|||||||
const HEADER_H_PX = 50
|
const HEADER_H_PX = 50
|
||||||
const MP_CONTENT_TOP_PX = 4
|
const MP_CONTENT_TOP_PX = 4
|
||||||
|
|
||||||
/** Native cover-view handles logo; H5 only needs a tiny gap below web-view top. */
|
/** 小程序顶栏在 web-view 外,H5 内容区仅留极小顶距 */
|
||||||
function applyNativeHeaderMode(): void {
|
function applyNativeHeaderInset(topPx: number): void {
|
||||||
if (typeof document === 'undefined') return
|
if (typeof document === 'undefined') return
|
||||||
const root = document.documentElement
|
const root = document.documentElement
|
||||||
root.style.setProperty('--yxg-safe-top', '0px')
|
root.style.setProperty('--yxg-safe-top', '0px')
|
||||||
root.style.setProperty('--yxg-page-top', `${MP_CONTENT_TOP_PX}px`)
|
root.style.setProperty('--yxg-page-top', `${topPx}px`)
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyNativeHeaderMode(): void {
|
||||||
|
applyNativeHeaderInset(MP_CONTENT_TOP_PX)
|
||||||
}
|
}
|
||||||
|
|
||||||
function applySafeTopInset(px: number): void {
|
function applySafeTopInset(px: number): void {
|
||||||
@@ -30,27 +34,29 @@ function readStoredSbh(): number {
|
|||||||
return parseInt(raw, 10)
|
return parseInt(raw, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** True when mini-program renders the brand header above web-view. */
|
|
||||||
export function isMpNativeHeader(): boolean {
|
export function isMpNativeHeader(): boolean {
|
||||||
if (typeof window === 'undefined') return false
|
if (typeof window === 'undefined') return false
|
||||||
return sessionStorage.getItem(MP_NATIVE_HEADER_KEY) === '1'
|
return sessionStorage.getItem(MP_NATIVE_HEADER_KEY) === '1'
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Apply document-level embed chrome (safe-area wash, hide HTML title). */
|
|
||||||
export function applyMpEmbedDom(): void {
|
export function applyMpEmbedDom(): void {
|
||||||
if (typeof document === 'undefined' || !isMpEmbed()) return
|
if (typeof document === 'undefined' || !isMpEmbed()) return
|
||||||
document.title = '\u200b'
|
document.title = '\u200b'
|
||||||
document.documentElement.classList.add('mp-embed')
|
document.documentElement.classList.add('mp-embed')
|
||||||
if (isMpNativeHeader()) {
|
if (isMpNativeHeader()) {
|
||||||
document.documentElement.classList.add('mp-native-header')
|
document.documentElement.classList.add('mp-native-header')
|
||||||
applyNativeHeaderMode()
|
const stored = readStoredSbh()
|
||||||
|
if (stored > 0) {
|
||||||
|
applyNativeHeaderInset(stored)
|
||||||
|
} else {
|
||||||
|
applyNativeHeaderMode()
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const stored = readStoredSbh()
|
const stored = readStoredSbh()
|
||||||
if (stored > 0) applySafeTopInset(stored)
|
if (stored > 0) applySafeTopInset(stored)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Persist ?mp=1 from mini-program web-view entry. Call once before router mount. */
|
|
||||||
export function initMpEmbed(): void {
|
export function initMpEmbed(): void {
|
||||||
if (typeof window === 'undefined') return
|
if (typeof window === 'undefined') return
|
||||||
const params = new URLSearchParams(window.location.search)
|
const params = new URLSearchParams(window.location.search)
|
||||||
@@ -59,7 +65,13 @@ export function initMpEmbed(): void {
|
|||||||
}
|
}
|
||||||
if (params.get(NH_QUERY) === '1') {
|
if (params.get(NH_QUERY) === '1') {
|
||||||
sessionStorage.setItem(MP_NATIVE_HEADER_KEY, '1')
|
sessionStorage.setItem(MP_NATIVE_HEADER_KEY, '1')
|
||||||
applyNativeHeaderMode()
|
const nativeSbh = params.get(SBH_QUERY)
|
||||||
|
if (nativeSbh && /^\d+$/.test(nativeSbh)) {
|
||||||
|
sessionStorage.setItem(SBH_KEY, nativeSbh)
|
||||||
|
applyNativeHeaderInset(parseInt(nativeSbh, 10))
|
||||||
|
} else {
|
||||||
|
applyNativeHeaderMode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!isMpNativeHeader()) {
|
if (!isMpNativeHeader()) {
|
||||||
const sbh = params.get(SBH_QUERY)
|
const sbh = params.get(SBH_QUERY)
|
||||||
@@ -71,7 +83,6 @@ export function initMpEmbed(): void {
|
|||||||
applyMpEmbedDom()
|
applyMpEmbedDom()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** True when H5 runs inside WeChat mini-program web-view (no H5 tab bar). */
|
|
||||||
export function isMpEmbed(): boolean {
|
export function isMpEmbed(): boolean {
|
||||||
if (typeof window === 'undefined') return false
|
if (typeof window === 'undefined') return false
|
||||||
return sessionStorage.getItem(MP_EMBED_KEY) === '1'
|
return sessionStorage.getItem(MP_EMBED_KEY) === '1'
|
||||||
|
|||||||
Reference in New Issue
Block a user