refactor: 优化跨端导航适配与页面文案体验

- 新增微信小程序胶囊区域避让布局逻辑
- 统一首页导航与标题对齐规则
- 更新多处演示提示文案为正式表述
- 调整个人中心账户状态显示
- 优化产品页分享按钮条件渲染
This commit is contained in:
hujun
2026-09-20 14:18:55 +08:00
parent 69130d11e7
commit 046a03e5e9
12 changed files with 110 additions and 43 deletions
+1 -1
View File
@@ -65,7 +65,7 @@ export function saveAssessmentDraft(type: string, step: number, form: Assessment
uni.setStorageSync('assessmentDraft', payload)
}
export function showAgreementNotice(title: string): void {
uni.showModal({ title, content: '正式协议尚未配置。当前为功能演示,勾选仅记录本地选择,不会发起实名认证、查询外部数据或上传资料。正式服务开放前,将展示完整协议供您阅读与确认。', showCancel: false, confirmText: '我知道了' })
uni.showModal({ title, content: '完整协议将在相关服务开放时提供。当前勾选仅保存您的选择,不会发起实名认证、查询外部数据或上传资料。', showCancel: false, confirmText: '我知道了' })
}
export type AssessmentProgress = { percent: number, basicDone: boolean, incomeDone: boolean, assetsDone: boolean, authorizationSelected: boolean }
+66 -3
View File
@@ -5,13 +5,32 @@ export type PageLayout = {
pageStyle: () => string,
contentStyle: (offset: number, minimum: boolean) => string,
statusStyle: (offset: number) => string,
navigationStyle: () => string,
navigationTitleStyle: () => string,
navigationActionStyle: (headerHeight: number) => string,
navigationBrandStyle: (headerHeight: number) => string,
bottomStyle: (padding: number) => string
}
// 原生渲染不支持 vh/calc,统一以窗口尺寸计算,并随旋转更新。
export function usePageLayout(): PageLayout {
const windowInfo = ref(uni.getWindowInfo())
const refresh = () => { windowInfo.value = uni.getWindowInfo() }
const capsuleLeft = ref(-1)
const capsuleTop = ref(0)
const capsuleHeight = ref(0)
const readCapsule = () => {
// #ifdef MP-WEIXIN
try {
const capsule = uni.getMenuButtonBoundingClientRect()
const valid = capsule.width > 0 && capsule.height > 0 && capsule.left > 0 && capsule.left < windowInfo.value.windowWidth
capsuleLeft.value = valid ? capsule.left : -1
capsuleTop.value = valid ? capsule.top : 0
capsuleHeight.value = valid ? capsule.height : 0
} catch (_error) { capsuleLeft.value = -1; capsuleTop.value = 0; capsuleHeight.value = 0 }
// #endif
}
readCapsule()
const refresh = () => { windowInfo.value = uni.getWindowInfo(); readCapsule() }
onMounted(() => refresh())
// #ifdef APP
onResize((_options) => { refresh() })
@@ -22,7 +41,51 @@ export function usePageLayout(): PageLayout {
onUnmounted(() => { uni.offWindowResize(handleResize) })
// #endif
const rpx = (value: number): number => value * windowInfo.value.windowWidth / 750
const status = (): number => windowInfo.value.statusBarHeight ?? 0
const status = (): number => Math.max(windowInfo.value.statusBarHeight ?? 0, windowInfo.value.safeAreaInsets?.top ?? 0)
const navigationStyle = (): string => {
// 只在微信端横向避让胶囊,保持业务导航原有高度。
// #ifdef MP-WEIXIN
const reserved = capsuleLeft.value > 0 ? windowInfo.value.windowWidth - capsuleLeft.value + 8 : 104
return 'padding-right:' + reserved + 'px;'
// #endif
// #ifndef MP-WEIXIN
return ''
// #endif
}
const navigationTitleStyle = (): string => {
// 标题左右使用相同留白,以屏幕中心对齐,同时避开微信胶囊。
// #ifdef MP-WEIXIN
const reserved = capsuleLeft.value > 0 ? windowInfo.value.windowWidth - capsuleLeft.value + 8 : 104
const inset = Math.max(rpx(112), reserved)
return 'left:' + inset + 'px;right:' + inset + 'px;'
// #endif
// #ifndef MP-WEIXIN
return ''
// #endif
}
const navigationActionStyle = (headerHeight: number): string => {
// 微信通知按钮与系统胶囊等高、顶部对齐;App 保持导航行内居中。
// #ifdef MP-WEIXIN
const size = capsuleHeight.value > 0 ? capsuleHeight.value : 32
const top = capsuleHeight.value > 0 ? Math.max(0, capsuleTop.value - status()) : Math.max(0, (rpx(headerHeight) - size) / 2)
const right = capsuleLeft.value > 0 ? windowInfo.value.windowWidth - capsuleLeft.value + 8 : 104
return 'position:absolute;top:' + top + 'px;right:' + right + 'px;width:' + size + 'px;height:' + size + 'px;'
// #endif
// #ifndef MP-WEIXIN
return ''
// #endif
}
const navigationBrandStyle = (headerHeight: number): string => {
// Logo 保留自身比例,与胶囊共享垂直中心,不改变登录页和启动页的 Logo。
// #ifdef MP-WEIXIN
const height = rpx(68)
const center = capsuleHeight.value > 0 ? capsuleTop.value - status() + capsuleHeight.value / 2 : rpx(headerHeight) / 2
return 'align-self:flex-start;margin-top:' + Math.max(0, center - height / 2) + 'px;height:' + height + 'px;'
// #endif
// #ifndef MP-WEIXIN
return ''
// #endif
}
const pageStyle = (): string => 'min-height:' + windowInfo.value.windowHeight + 'px;'
const contentStyle = (offset: number, minimum: boolean): string => {
// #ifdef WEB
@@ -35,5 +98,5 @@ export function usePageLayout(): PageLayout {
}
const statusStyle = (offset: number): string => 'height:' + (status() + rpx(offset)) + 'px;'
const bottomStyle = (padding: number): string => 'padding-bottom:' + (rpx(padding) + (windowInfo.value.safeAreaInsets?.bottom ?? 0)) + 'px;'
return { pageStyle, contentStyle, statusStyle, bottomStyle }
return { pageStyle, contentStyle, statusStyle, navigationStyle, navigationTitleStyle, navigationActionStyle, navigationBrandStyle, bottomStyle }
}