Files
collab-ledger/frontend/app/src/components/AppNavbar.vue
T
2026-05-26 11:54:24 +08:00

150 lines
3.1 KiB
Vue

<template>
<view class="app-navbar" :style="navbarStyle">
<view class="app-navbar__content" :style="contentStyle">
<view class="app-navbar__left" @tap="handleLeftTap">
<AtIcon v-if="showBack" value="chevron-left" size="24" />
<AtIcon v-else-if="leftIcon" :value="leftIcon" size="22" />
</view>
<text class="app-navbar__title">{{ title }}</text>
<view class="app-navbar__right" />
</view>
</view>
<view class="app-navbar-placeholder" :style="placeholderStyle" />
</template>
<script setup lang="ts">
import Taro from '@tarojs/taro'
import { computed } from 'vue'
defineOptions({ inheritAttrs: false })
const props = defineProps<{
title: string
showBack?: boolean
leftIcon?: string
fallbackUrl?: string
}>()
const emit = defineEmits<{
leftClick: []
}>()
interface MenuButtonRect {
top: number
height: number
}
const DEFAULT_STATUS_BAR_HEIGHT = 20
const DEFAULT_CONTENT_HEIGHT = 44
const systemInfo = Taro.getSystemInfoSync()
const statusBarHeight = systemInfo.statusBarHeight || DEFAULT_STATUS_BAR_HEIGHT
const menuButtonRect = getMenuButtonRect()
const navContentHeight = menuButtonRect
? menuButtonRect.height + (menuButtonRect.top - statusBarHeight) * 2
: DEFAULT_CONTENT_HEIGHT
const navbarStyle = computed(() => ({
height: `${statusBarHeight + navContentHeight}px`,
paddingTop: `${statusBarHeight}px`
}))
const contentStyle = computed(() => ({
height: `${navContentHeight}px`
}))
const placeholderStyle = computed(() => ({
height: `${statusBarHeight + navContentHeight}px`
}))
function getMenuButtonRect(): MenuButtonRect | undefined {
if (!Taro.getMenuButtonBoundingClientRect) return undefined
const rect = Taro.getMenuButtonBoundingClientRect()
if (!rect || rect.height <= 0) return undefined
return {
top: rect.top,
height: rect.height
}
}
function handleLeftTap() {
if (props.showBack) {
goBack()
return
}
if (props.leftIcon) emit('leftClick')
}
function goBack() {
if (Taro.getCurrentPages().length > 1) {
Taro.navigateBack()
return
}
if (props.fallbackUrl) Taro.reLaunch({ url: props.fallbackUrl })
}
</script>
<style lang="scss">
.app-navbar {
position: fixed;
top: 0;
left: 0;
z-index: 99;
box-sizing: border-box;
width: 100%;
overflow: hidden;
color: $text-primary;
background: $bg-page;
border-bottom: 1px solid $border-color-light;
}
.app-navbar-placeholder {
width: 100%;
}
.app-navbar__content {
position: relative;
display: flex;
align-items: center;
width: 100%;
}
.app-navbar__left,
.app-navbar__right {
z-index: 1;
display: flex;
flex: 0 0 96px;
align-items: center;
height: 100%;
}
.app-navbar__left {
justify-content: flex-start;
padding-left: $space-lg;
color: $text-primary;
}
.app-navbar__right {
justify-content: flex-end;
padding-right: $space-lg;
}
.app-navbar__title {
position: absolute;
right: 0;
left: 0;
max-width: 100%;
padding: 0 120px;
overflow: hidden;
font-size: 18PX;
font-weight: 400;
line-height: 1.2;
color: $text-primary;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>