125 lines
2.9 KiB
Vue
125 lines
2.9 KiB
Vue
<template>
|
||
<view class="tn">
|
||
<view class="tn-fixed" :class="'tn--' + mode" :style="barStyle">
|
||
<view class="tn-status" :style="{ height: statusBarHeight + 'px' }" />
|
||
<view class="tn-inner" :style="{ height: innerHeight + 'px' }">
|
||
<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="{ height: navHeight + 'px' }" />
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { getActiveLayout, getActiveVars } from '@/utils/theme'
|
||
|
||
/**
|
||
* 自定义顶栏:色跟主题 token,形态跟 chrome.navbar
|
||
*/
|
||
export default {
|
||
name: 'ThemeNavbar',
|
||
props: {
|
||
title: { type: String, default: '' },
|
||
showBack: { type: Boolean, default: true },
|
||
},
|
||
data() {
|
||
return {
|
||
statusBarHeight: 20,
|
||
innerHeight: 44,
|
||
mode: 'solid',
|
||
surface: '#ffffff',
|
||
text: '#1C1917',
|
||
border: '#E7DFD3',
|
||
}
|
||
},
|
||
computed: {
|
||
navHeight() {
|
||
return this.statusBarHeight + this.innerHeight
|
||
},
|
||
barStyle() {
|
||
return {
|
||
background: this.surface,
|
||
borderColor: this.border,
|
||
}
|
||
},
|
||
},
|
||
created() {
|
||
this.measure()
|
||
this.pullTheme()
|
||
},
|
||
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
|
||
}
|
||
} 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'
|
||
},
|
||
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-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;
|
||
padding: 0 16rpx;
|
||
}
|
||
.tn-left,
|
||
.tn-right {
|
||
width: 80rpx;
|
||
flex-shrink: 0;
|
||
}
|
||
.tn-title {
|
||
flex: 1;
|
||
text-align: center;
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
overflow: hidden;
|
||
white-space: nowrap;
|
||
text-overflow: ellipsis;
|
||
}
|
||
</style>
|