diff --git a/pwuniapp/App.vue b/pwuniapp/App.vue index 3d4f8af..4c4db41 100644 --- a/pwuniapp/App.vue +++ b/pwuniapp/App.vue @@ -40,6 +40,15 @@ export default { --tab-bg: #151D30; --tab-color: #94A3B8; --tab-active: #6366F1; + + /* 顶部与多端安全区变量 (小程序状态栏 / 原生胶囊避让 / H5 沉浸式自然留白) */ + --safe-header-gap: calc(var(--status-bar-height, 0px) + 36rpx); + --capsule-right-space: 0rpx; + + /* #ifdef MP-WEIXIN */ + --safe-header-gap: calc(var(--status-bar-height, 44px) + 20rpx); + --capsule-right-space: 210rpx; + /* #endif */ } /* 浅色暖阳晨曦主题 (Light Warm Sunset Morning) */ diff --git a/pwuniapp/pages/activity/list.vue b/pwuniapp/pages/activity/list.vue index c1571d9..0b5bfbb 100644 --- a/pwuniapp/pages/activity/list.vue +++ b/pwuniapp/pages/activity/list.vue @@ -231,7 +231,7 @@ const createActivity = () => { .activity-container { min-height: 100vh; background-color: #0A0F1D; - padding: calc(24rpx + env(safe-area-inset-top, 0px)) 32rpx calc(180rpx + env(safe-area-inset-bottom)); + padding: var(--safe-header-gap, 36rpx) 32rpx calc(180rpx + env(safe-area-inset-bottom)); } .tab-header { diff --git a/pwuniapp/pages/index/index.vue b/pwuniapp/pages/index/index.vue index 3247820..7a04f72 100644 --- a/pwuniapp/pages/index/index.vue +++ b/pwuniapp/pages/index/index.vue @@ -236,11 +236,18 @@ const navTo = (url) => { } .header-search { - padding: calc(20rpx + env(safe-area-inset-top, 0px)) 32rpx 20rpx; + padding-top: var(--safe-header-gap, 36rpx); + padding-right: calc(32rpx + var(--capsule-right-space, 0rpx)); + padding-bottom: 20rpx; + padding-left: 32rpx; background-color: #0A0F1D; position: sticky; top: 0; z-index: 50; + /* #ifdef MP-WEIXIN */ + /* 微信小程序端胶囊按钮避让 (capsule-space) */ + padding-right: calc(32rpx + var(--capsule-right-space, 210rpx)); + /* #endif */ .search-box { display: flex; diff --git a/pwuniapp/pages/order/list.vue b/pwuniapp/pages/order/list.vue index 2dbc2ba..568d59b 100644 --- a/pwuniapp/pages/order/list.vue +++ b/pwuniapp/pages/order/list.vue @@ -210,7 +210,7 @@ const rateExpert = (id) => { .order-list-container { min-height: 100vh; background-color: #0A0F1D; - padding: calc(24rpx + env(safe-area-inset-top, 0px)) 32rpx calc(160rpx + env(safe-area-inset-bottom)); + padding: var(--safe-header-gap, 36rpx) 32rpx calc(160rpx + env(safe-area-inset-bottom)); } .tab-header { diff --git a/pwuniapp/pages/user/index.vue b/pwuniapp/pages/user/index.vue index 51f0f1c..7ba6922 100644 --- a/pwuniapp/pages/user/index.vue +++ b/pwuniapp/pages/user/index.vue @@ -258,7 +258,7 @@ const navTo = (url) => { .user-container { min-height: 100vh; background-color: #0A0F1D; - padding: calc(24rpx + env(safe-area-inset-top, 0px)) 32rpx calc(160rpx + env(safe-area-inset-bottom)); + padding: var(--safe-header-gap, 36rpx) 32rpx calc(160rpx + env(safe-area-inset-bottom)); } .profile-card { diff --git a/server/tests/theme.spec.ts b/server/tests/theme.spec.ts index cb4e470..3fcde8c 100644 --- a/server/tests/theme.spec.ts +++ b/server/tests/theme.spec.ts @@ -358,8 +358,44 @@ describe('ThemeManager (TDD 测试套件: 暖色系与双主题设计系统)', ( } }); }); + + describe('10. 顶部安全距离小程序与 H5 多端兼容门禁校验', () => { + const rootDir = path.resolve(__dirname, '../../'); + const appVuePath = path.join(rootDir, 'pwuniapp', 'App.vue'); + const indexVuePath = path.join(rootDir, 'pwuniapp', 'pages', 'index', 'index.vue'); + const activityVuePath = path.join(rootDir, 'pwuniapp', 'pages', 'activity', 'list.vue'); + const orderVuePath = path.join(rootDir, 'pwuniapp', 'pages', 'order', 'list.vue'); + const userVuePath = path.join(rootDir, 'pwuniapp', 'pages', 'user', 'index.vue'); + + it('App.vue 必须在全局定义顶部安全间距变量与小程序/H5适配规则', () => { + const content = fs.readFileSync(appVuePath, 'utf-8'); + expect(content).toContain('--safe-header-gap'); + expect(content).toContain('--status-bar-height'); + }); + + it('四大 TabBar 页面顶部必须全部采用 --safe-header-gap 规范化安全留白', () => { + const files = [indexVuePath, activityVuePath, orderVuePath, userVuePath]; + for (const file of files) { + const content = fs.readFileSync(file, 'utf-8'); + const relativeName = path.relative(rootDir, file); + expect({ + file: relativeName, + hasSafeHeaderGap: content.includes('--safe-header-gap') + }).toEqual({ + file: relativeName, + hasSafeHeaderGap: true + }); + } + }); + + it('首页必须针对小程序端具备胶囊按钮避让属性', () => { + const content = fs.readFileSync(indexVuePath, 'utf-8'); + expect(content.includes('capsule-space') || content.includes('MP-WEIXIN')).toBe(true); + }); + }); }); +