feat: app功能基本实现
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user