diff --git a/miniprogram/src/app.scss b/miniprogram/src/app.scss index 85604b4..5c69507 100644 --- a/miniprogram/src/app.scss +++ b/miniprogram/src/app.scss @@ -394,3 +394,22 @@ page { -ms-overflow-style: none; scrollbar-width: none; } .ic-shield { -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.5'%3E%3Cpath d='M12 3l8 3v5c0 5-3.5 8-8 10-4.5-2-8-5-8-10V6z'/%3E%3Cpath d='M9 12l2 2 4-4'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.5'%3E%3Cpath d='M12 3l8 3v5c0 5-3.5 8-8 10-4.5-2-8-5-8-10V6z'/%3E%3Cpath d='M9 12l2 2 4-4'/%3E%3C/svg%3E"); } .ic-landmark { -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.5'%3E%3Cpath d='M3 10l9-6 9 6'/%3E%3Cpath d='M5 10v9M9.5 10v9M14.5 10v9M19 10v9M3 20h18'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.5'%3E%3Cpath d='M3 10l9-6 9 6'/%3E%3Cpath d='M5 10v9M9.5 10v9M14.5 10v9M19 10v9M3 20h18'/%3E%3C/svg%3E"); } .ic-users { -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.5'%3E%3Ccircle cx='9' cy='8' r='3.5'/%3E%3Cpath d='M2.5 20a6.5 6.5 0 0 1 13 0'/%3E%3Cpath d='M15.5 5a3.5 3.5 0 0 1 0 6.6'/%3E%3Cpath d='M17.5 14.4a6.5 6.5 0 0 1 4 5.6'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.5'%3E%3Ccircle cx='9' cy='8' r='3.5'/%3E%3Cpath d='M2.5 20a6.5 6.5 0 0 1 13 0'/%3E%3Cpath d='M15.5 5a3.5 3.5 0 0 1 0 6.6'/%3E%3Cpath d='M17.5 14.4a6.5 6.5 0 0 1 4 5.6'/%3E%3C/svg%3E"); } + +/* ============ 统一固定标题区(像素字 kicker + 彩虹渐变标题 + 像素字注脚) ============ */ +.page-navbar { + position: fixed; top: 0; left: 0; right: 0; z-index: 100; + padding: 0 28rpx; /* 标题区上下零冗余:高度 = 安全区 + 三行文字,占位实测自然贴合 */ + background: rgba(247, 249, 255, 0.88); + backdrop-filter: blur(20px) saturate(160%); + -webkit-backdrop-filter: blur(20px) saturate(160%); +} +.page-navbar-col { display: flex; flex-direction: column; } +.page-navbar-no { font-family: 'BubbledotICG', monospace; color: #a3abc9; font-size: 26rpx; letter-spacing: 2rpx; line-height: 1.15; } +.page-navbar-titlerow { display: flex; align-items: baseline; gap: 16rpx; line-height: 1.15; } +.page-navbar-title { + font-size: 40rpx; font-weight: 800; letter-spacing: -0.5rpx; line-height: 1.15; + background: linear-gradient(120deg, #8fc3ff 0%, #a8a0ff 45%, #e0a0ff 80%, #7fe0ff 100%); + -webkit-background-clip: text; background-clip: text; color: transparent; +} +.page-navbar-sub { font-size: 24rpx; color: #5a6aa3; } +.page-navbar-en { font-family: 'BubbledotICG', monospace; color: #5b5b5b; font-size: 24rpx; letter-spacing: 2rpx; line-height: 1.15; padding-bottom: 12rpx; } diff --git a/miniprogram/src/components/TopInset.jsx b/miniprogram/src/components/TopInset.jsx new file mode 100644 index 0000000..9b33710 --- /dev/null +++ b/miniprogram/src/components/TopInset.jsx @@ -0,0 +1,66 @@ +import { View, Text } from '@tarojs/components'; +import Taro from '@tarojs/taro'; +import { useState, useEffect } from 'react'; + +let cached = null; + +/** 顶部安全区(沉浸式自定义导航用):状态栏 + 胶囊高度。 */ +export function getTopInset() { + if (!cached) { + try { + const win = Taro.getWindowInfo ? Taro.getWindowInfo() : Taro.getSystemInfoSync(); + const statusBar = win.statusBarHeight || 44; + const windowWidth = win.windowWidth || 375; + let navH = statusBar + 44; + try { + const menu = Taro.getMenuButtonBoundingClientRect ? Taro.getMenuButtonBoundingClientRect() : null; + if (menu && menu.height) navH = statusBar + (menu.top - statusBar) * 2 + menu.height; + } catch { /* 无胶囊环境用默认 */ } + cached = { statusBar, navH, windowWidth }; + } catch { + cached = { statusBar: 44, navH: 88, windowWidth: 375 }; + } + } + return cached; +} + +/** 统一固定标题区(fixed 不随滚动):像素字 kicker + 彩虹渐变标题 + 像素字注脚。 + * 占位高度由 createSelectorQuery 实测 navbar 真实高度,绝无空白/覆盖/重复。 */ +export function PageHeader({ no, title, en, sub }) { + const { navH, windowWidth } = getTopInset(); + // 标题区整体上移 65rpx:从状态栏让位空间中扣除(不是容器偏移,占位实测自动跟随,无空白) + const SHIFT_PX = Math.round((65 * (windowWidth || 375)) / 750); + const topPad = Math.max(navH - SHIFT_PX, 24); // 下限:至少给状态栏留 24px + const [h, setH] = useState(0); + + useEffect(() => { + Taro.nextTick(() => { + Taro.createSelectorQuery() + .select('.page-navbar') + .boundingClientRect((r) => { if (r && r.height) setH(r.height); }) + .exec(); + }); + }, [no, title, en, sub]); + + return ( + <> + + + {no ? {no} : null} + + {title} + {sub ? {sub} : null} + + {en ? {en} : null} + + + + + ); +} + +/** 沉浸式顶部占位:配合页面 navigationStyle=custom 使用。 */ +export default function TopInset() { + const { navH } = getTopInset(); + return ; +} diff --git a/miniprogram/src/pages/booking/index.config.js b/miniprogram/src/pages/booking/index.config.js index 7d3c0ce..00aeddc 100644 --- a/miniprogram/src/pages/booking/index.config.js +++ b/miniprogram/src/pages/booking/index.config.js @@ -1 +1 @@ -export default { navigationBarTitleText: '活动' }; +export default { navigationBarTitleText: '活动', navigationStyle: 'custom' }; diff --git a/miniprogram/src/pages/content/index.config.js b/miniprogram/src/pages/content/index.config.js index 6b011a7..b5ac1b3 100644 --- a/miniprogram/src/pages/content/index.config.js +++ b/miniprogram/src/pages/content/index.config.js @@ -1 +1 @@ -export default { navigationBarTitleText: '资讯中心' }; +export default { navigationBarTitleText: '资讯中心', navigationStyle: 'custom' }; diff --git a/miniprogram/src/pages/index/index.config.js b/miniprogram/src/pages/index/index.config.js index cc300c9..b16c021 100644 --- a/miniprogram/src/pages/index/index.config.js +++ b/miniprogram/src/pages/index/index.config.js @@ -1 +1 @@ -export default { navigationBarTitleText: 'OPC · 为进化而设计' }; +export default { navigationBarTitleText: 'OPC · 为进化而设计', navigationStyle: 'custom' }; diff --git a/miniprogram/src/pages/mine/index.config.js b/miniprogram/src/pages/mine/index.config.js index 0851cd4..9a22a17 100644 --- a/miniprogram/src/pages/mine/index.config.js +++ b/miniprogram/src/pages/mine/index.config.js @@ -1 +1 @@ -export default { navigationBarTitleText: '我的' }; +export default { navigationBarTitleText: '我的', navigationStyle: 'custom' }; diff --git a/miniprogram/src/pages/test/index.config.js b/miniprogram/src/pages/test/index.config.js index 524166b..99fd946 100644 --- a/miniprogram/src/pages/test/index.config.js +++ b/miniprogram/src/pages/test/index.config.js @@ -1 +1 @@ -export default { navigationBarTitleText: 'OPC 创业测评' }; +export default { navigationBarTitleText: 'OPC 创业测评', navigationStyle: 'custom' };