feat(小程序): 测评/调研/政策页适配沉浸式导航,标题区统一复用 PageHeader 并内置返回按钮

This commit is contained in:
Pine
2026-08-29 00:36:17 +08:00
parent f77c8adc07
commit 48ed5353bc
6 changed files with 28 additions and 27 deletions
+15 -2
View File
@@ -25,8 +25,9 @@ export function getTopInset() {
}
/** 统一固定标题区(fixed 不随滚动):像素字 kicker + 彩虹渐变标题 + 像素字注脚。
* back:传入函数=自定义返回;true=自动返回(无上一页则回首页 Tab)。
* 占位高度由 createSelectorQuery 实测 navbar 真实高度,绝无空白/覆盖/重复。 */
export function PageHeader({ no, title, en, sub }) {
export function PageHeader({ no, title, en, sub, back }) {
const { navH, windowWidth } = getTopInset();
// 标题区整体上移 65rpx:从状态栏让位空间中扣除(不是容器偏移,占位实测自动跟随,无空白)
const SHIFT_PX = Math.round((65 * (windowWidth || 375)) / 750);
@@ -40,7 +41,14 @@ export function PageHeader({ no, title, en, sub }) {
.boundingClientRect((r) => { if (r && r.height) setH(r.height); })
.exec();
});
}, [no, title, en, sub]);
}, [no, title, en, sub, back]);
const goBack = () => {
if (typeof back === 'function') { back(); return; }
const pages = Taro.getCurrentPages ? Taro.getCurrentPages() : [];
if (pages.length > 1) Taro.navigateBack({ delta: 1 });
else Taro.switchTab({ url: '/pages/index/index' });
};
return (
<>
@@ -48,6 +56,11 @@ export function PageHeader({ no, title, en, sub }) {
<View className="page-navbar-col">
{no ? <Text className="page-navbar-no">{no}</Text> : null}
<View className="page-navbar-titlerow">
{back ? (
<View className="page-navbar-back" hoverClass="pressed" onClick={goBack}>
<Text className="ic ic-arrow-left" aria-hidden />
</View>
) : null}
<Text className="page-navbar-title">{title}</Text>
{sub ? <Text className="page-navbar-sub">{sub}</Text> : null}
</View>
+1 -1
View File
@@ -1 +1 @@
export default { navigationBarTitleText: '政策测评' };
export default { navigationBarTitleText: '政策测评', navigationStyle: 'custom' };
+4 -1
View File
@@ -5,6 +5,7 @@ import { getUser } from '@/utils/auth';
import { request, cachedRequest } from '@/utils/api';
import { useTabIndex } from '@/utils/tab';
import Skeleton from '@/components/skeleton';
import { PageHeader } from '@/components/TopInset';
import './index.scss';
export default function Policy() {
@@ -76,6 +77,7 @@ export default function Policy() {
if (!loaded) {
return (
<View className="policy page-in">
<PageHeader no="00" title="政策适配测评" en="Policy" back />
<Text className="muted">正在加载测评</Text>
<View style={{ marginTop: 20 }}><Skeleton.Rows n={4} gap={18} /></View>
</View>
@@ -85,6 +87,7 @@ export default function Policy() {
if (result) {
return (
<View className="policy page-in">
<PageHeader no="02" title="适配结果" en="Result" back />
<View className="summary">{result.summary}</View>
<Text className="section-head">适配政策</Text>
@@ -141,9 +144,9 @@ export default function Policy() {
return (
<View className="policy quiz-center">
<PageHeader no="01" title="政策适配测评" en="Policy" back />
<View className="ot-quiz-head">
<View className="ot-quiz-top">
<Text className="ot-quiz-title">政策适配测评<Text className="ot-quiz-tag">5 </Text></Text>
<Text className="ot-progress-text">{current + 1} / {QUESTIONS.length} </Text>
</View>
<View className="ot-progress"><View className="ot-progress-fill" style={{ width: pct + '%' }} /></View>
+1 -1
View File
@@ -1 +1 @@
export default { navigationBarTitleText: 'OPC 创业伙伴调研' };
export default { navigationBarTitleText: 'OPC 创业伙伴调研', navigationStyle: 'custom' };
+4 -11
View File
@@ -4,6 +4,7 @@ import { useState, useEffect } from 'react';
import { getUser } from '@/utils/auth';
import { request, cachedRequest } from '@/utils/api';
import Skeleton from '@/components/skeleton';
import { PageHeader } from '@/components/TopInset';
import './index.scss';
/* 题目/区域/Likert 由后端 /api/survey/questions 下发填充 */
@@ -113,11 +114,7 @@ export default function Survey() {
if (stage === 'welcome') {
return (
<View className="sv page-in">
<View className="sv-head">
<Text className="sv-no">00</Text>
<Text className="sv-title">云南 OPC 创业伙伴调研</Text>
<Text className="sv-en">Survey</Text>
</View>
<PageHeader no="00" title="OPC 创业伙伴调研" en="Survey" back />
<Text className="sv-intro">
聊聊你在云南做的行业遇到的难题AI 赋能与政策诉求 {loaded ? SURVEY_QUESTIONS.length : '…'} 58 分钟匿名提交用于云南 OPC 创业生态建设与政策研究
</Text>
@@ -141,11 +138,7 @@ export default function Survey() {
if (stage === 'done') {
return (
<View className="sv page-in">
<View className="sv-head">
<Text className="sv-no">06</Text>
<Text className="sv-title">提交成功感谢参与</Text>
<Text className="sv-en">Thank you</Text>
</View>
<PageHeader no="06" title="提交成功,感谢参与!" en="Thank you" back />
<View className="sv-thanks">
<Text>你的回答已匿名记录将用于云南 OPC 创业生态建设与政策研究我们正在组织 OPC 伙伴社群与调研回访欢迎继续参与</Text>
</View>
@@ -165,9 +158,9 @@ export default function Survey() {
return (
<View className="sv">
<PageHeader no="01" title="创业伙伴调研" en="Quiz" back={() => { setStage('welcome'); scrollTop(); }} />
<View className="sv-quiz-head">
<View className="sv-quiz-top">
<Text className="sv-quiz-title">OPC 创业伙伴调研</Text>
<Text className="sv-progress-text">{current + 1} / {SURVEY_QUESTIONS.length}</Text>
</View>
<View className="sv-progress"><View className="sv-progress-fill" style={{ width: pct + '%' }} /></View>
+3 -11
View File
@@ -143,12 +143,9 @@ export default function Test() {
return (
<View className="ot quiz-center page-in">
<PageHeader no="01" title="OPC 创业基因测评" sub={version === 'quick' ? '快速版' : '完整版'} en="Assessment" back={backToWelcome} />
<View className="ot-quiz-head">
<View className="ot-quiz-top">
<View className="ot-quiz-left">
<View className="ot-back" onClick={backToWelcome}> 返回</View>
<Text className="ot-quiz-title">OPC 创业基因测评<Text className="ot-quiz-tag">{version === 'quick' ? '快速版' : '完整版'}</Text></Text>
</View>
<Text className="ot-progress-text">{current + 1} / {questions.length} </Text>
</View>
<View className="ot-progress"><View className="ot-progress-fill" style={{ width: pct + '%' }} /></View>
@@ -191,13 +188,8 @@ export default function Test() {
const level = r.adaptLevel || {};
return (
<View className="ot page-in">
<TopInset />
{/* 头部:类型码 + 人设 + 适配指数 */}
<View className="ot-head">
<Text className="ot-no">02</Text>
<Text className="ot-title">你的 OPC 画像</Text>
<Text className="ot-en">Report</Text>
</View>
{/* 头部:类型码 + 人设 + 适配指数(复用统一标题区) */}
<PageHeader no="02" title="你的 OPC 画像" en="Report" back={backToWelcome} />
<View className="ot-result-hero">
<View className="ot-hero-left">
<Text className="ot-code">{r.typeCode}</Text>