Files
lgp-wx-plus/components/theme/ThemeNavbar.vue
2026-08-20 19:15:41 +08:00

204 lines
4.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<!-- PC 大屏不支持自定义顶栏留给微信拖拽区标题写到系统导航栏 -->
<view v-if="!pcMode" class="tn">
<view class="tn-fixed" :class="'tn--' + mode" :style="barStyle">
<view class="tn-status" :style="statusStyle" />
<view class="tn-inner" :style="innerStyle">
<view class="tn-left" @tap="onBack">
<u-icon v-if="showBack" name="arrow-left" :color="text" size="20" />
</view>
<text class="tn-title" :style="{ color: text }">{{ title }}</text>
<view class="tn-right">
<slot name="right" />
</view>
</view>
</view>
<view class="tn-ph" :style="phStyle" />
</view>
</template>
<script>
import { getActiveLayout, getActiveVars } from '@/utils/theme'
import { isPcWeixin } from '@/utils/device'
/**
* 自定义顶栏:色跟主题 token形态跟 chrome.navbar
*/
export default {
name: 'ThemeNavbar',
props: {
title: { type: String, default: '' },
showBack: { type: Boolean, default: true },
},
data() {
return {
statusBarHeight: 20,
innerHeight: 44,
// 量不到胶囊时按常见胶囊宽度让开,避免右侧按钮被挡住
capsulePadRight: 96,
mode: 'solid',
surface: '#ffffff',
text: '#1C1917',
border: '#E7DFD3',
}
},
computed: {
pcMode() {
return isPcWeixin()
},
navHeight() {
return this.statusBarHeight + this.innerHeight
},
barStyle() {
return {
background: this.surface,
borderColor: this.border,
}
},
statusStyle() {
return {
height: this.statusBarHeight + 'px',
}
},
/** 占位跟固定栏同高,用像素避免 env(safe-area) 在安卓微信为 0 时切内容 */
phStyle() {
return {
height: this.navHeight + 'px',
width: '100%',
}
},
innerStyle() {
return {
height: this.innerHeight + 'px',
paddingRight: this.capsulePadRight + 'px',
}
},
},
watch: {
title: {
immediate: true,
handler(val) {
this.syncPcTitle(val)
},
},
},
created() {
this.measure()
this.pullTheme()
this.syncPcTitle(this.title)
},
mounted() {
// 部分机型 created 时 statusBarHeight 还是 0挂载后再量一次
this.measure()
},
beforeUpdate() {
this.pullTheme()
},
methods: {
measure() {
try {
const sys = uni.getSystemInfoSync()
this.statusBarHeight = sys.statusBarHeight || 20
const menu = uni.getMenuButtonBoundingClientRect && uni.getMenuButtonBoundingClientRect()
if (menu && menu.height) {
this.innerHeight = (menu.top - this.statusBarHeight) * 2 + menu.height
const winW = Number(sys.windowWidth) || 375
this.capsulePadRight = Math.max(8, Math.round(winW - menu.left + 8))
}
} catch (err) {
this.statusBarHeight = 20
this.innerHeight = 44
}
},
pullTheme() {
const vars = getActiveVars() || {}
const chrome = ((getActiveLayout() || {}).chrome) || {}
this.mode = chrome.navbar || 'solid'
this.surface = vars['--color-surface'] || '#ffffff'
this.text = vars['--color-text'] || '#1C1917'
this.border = vars['--color-border'] || '#E7DFD3'
this.syncPcBarColor()
},
/** 系统导航栏底色跟主题表面色对齐,避免 PC 顶栏发灰 */
syncPcBarColor() {
if (!isPcWeixin()) return
const bg = this.surface || '#ffffff'
uni.setNavigationBarColor({
frontColor: '#000000',
backgroundColor: bg,
})
},
/** PC 走系统导航栏,动态标题(如编辑地址)要写过去 */
syncPcTitle(val) {
if (!isPcWeixin() || !val) return
uni.setNavigationBarTitle({ title: String(val) })
},
onBack() {
if (!this.showBack) return
const pages = getCurrentPages()
if (pages.length > 1) {
uni.navigateBack({ delta: 1 })
return
}
uni.switchTab({ url: '/pages/goods/index' })
},
},
}
</script>
<style scoped>
.tn {
display: block;
width: 100%;
}
.tn-ph {
display: block;
width: 100%;
overflow: hidden;
}
.tn-fixed {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 200;
}
.tn--line {
border-bottom: 1rpx solid;
}
.tn-inner {
display: flex;
align-items: center;
position: relative;
padding-left: 16rpx;
box-sizing: border-box;
}
.tn-left {
width: 80rpx;
flex-shrink: 0;
z-index: 1;
}
.tn-right {
width: auto;
min-width: 80rpx;
flex-shrink: 0;
margin-left: auto;
z-index: 1;
display: flex;
align-items: center;
justify-content: flex-end;
}
.tn-title {
position: absolute;
left: 160rpx;
right: 160rpx;
text-align: center;
font-size: 32rpx;
font-weight: 600;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
pointer-events: none;
}
</style>