工单大厅
This commit is contained in:
200
wuye-manager-uniapp/components/navbar/navbar.vue
Normal file
200
wuye-manager-uniapp/components/navbar/navbar.vue
Normal file
@@ -0,0 +1,200 @@
|
||||
<template>
|
||||
<!--
|
||||
外层容器:默认为空壳,仅用于包裹
|
||||
如果开启 placeholder,则通过 style 撑开高度
|
||||
-->
|
||||
<view
|
||||
class="nav-wrapper"
|
||||
:style="{
|
||||
background: props.bgColor
|
||||
}"
|
||||
>
|
||||
<!-- 【占位层】:只在开启 placeholder 时渲染,纯粹为了撑高度 -->
|
||||
<view
|
||||
v-if="placeholder"
|
||||
class="nav-placeholder"
|
||||
:style="{ height: totalNavHeight + 'px' }"
|
||||
></view>
|
||||
|
||||
<!-- 【功能层】:Fixed 定位,脱离文档流,永远显示在最上层 -->
|
||||
<view class="nav-fixed-layer" :style="fixedLayerStyle">
|
||||
<!-- 状态栏区域(用于沉浸式背景填充) -->
|
||||
<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
|
||||
|
||||
<!-- 导航栏主体 -->
|
||||
<view class="nav-main" :style="{ height: navBarHeight + 'px' }">
|
||||
<!-- 左侧 -->
|
||||
<view class="nav-left" :style="{ width: leftWidth + 'px' }">
|
||||
<slot name="left">
|
||||
<view class="back-btn" @click="goBack" v-if="showBack">
|
||||
<uni-icons type="left" size="20" color="inherit"></uni-icons>
|
||||
<text v-if="backText" class="back-text">{{ backText }}</text>
|
||||
</view>
|
||||
</slot>
|
||||
</view>
|
||||
|
||||
<!-- 中间 -->
|
||||
<view class="nav-center">
|
||||
<slot name="center">
|
||||
<text class="nav-title" :style="{ color: titleColor }">{{ title }}</text>
|
||||
</slot>
|
||||
</view>
|
||||
|
||||
<!-- 右侧 -->
|
||||
<view class="nav-right" :style="{ width: rightWidth + 'px' }">
|
||||
<slot name="right"></slot>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
|
||||
// --- Props ---
|
||||
interface Props {
|
||||
title?: string
|
||||
bgColor?: string
|
||||
titleColor?: string
|
||||
showBack?: boolean
|
||||
backText?: string
|
||||
placeholder?: boolean // 是否开启“占位层”
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
title: '标题',
|
||||
bgColor: 'transparent',
|
||||
titleColor: '#333333',
|
||||
showBack: true,
|
||||
backText: '',
|
||||
placeholder: true // 默认开启占位,防止遮挡
|
||||
})
|
||||
|
||||
// --- 状态 ---
|
||||
const statusBarHeight = ref(0)
|
||||
const navBarHeight = ref(44)
|
||||
const capsuleHeight = ref(0)
|
||||
|
||||
// --- 计算属性 ---
|
||||
const totalNavHeight = computed(() => statusBarHeight.value + navBarHeight.value)
|
||||
|
||||
// 2. 功能层样式:Fixed 定位,负责视觉展示
|
||||
const fixedLayerStyle = computed(() => ({
|
||||
backgroundColor: props.bgColor,
|
||||
zIndex: 9999
|
||||
}))
|
||||
|
||||
const leftWidth = computed(() => {
|
||||
// #ifdef MP-WEIXIN
|
||||
return capsuleHeight.value || 40
|
||||
// #endif
|
||||
// #ifndef MP-WEIXIN
|
||||
return 40
|
||||
// #endif
|
||||
})
|
||||
const rightWidth = computed(() => leftWidth.value)
|
||||
|
||||
// --- 生命周期 ---
|
||||
onMounted(() => {
|
||||
initNavBar()
|
||||
})
|
||||
|
||||
// --- 方法 ---
|
||||
const initNavBar = () => {
|
||||
const windowInfo = uni.getWindowInfo()
|
||||
statusBarHeight.value = windowInfo.statusBarHeight || 0
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
const menuInfo = uni.getMenuButtonBoundingClientRect()
|
||||
if (menuInfo.top && menuInfo.height) {
|
||||
const gap = menuInfo.top - statusBarHeight.value
|
||||
navBarHeight.value = (gap > 0 ? gap : 4) * 2 + menuInfo.height
|
||||
capsuleHeight.value = menuInfo.height
|
||||
} else {
|
||||
navBarHeight.value = 44
|
||||
capsuleHeight.value = 0
|
||||
}
|
||||
// #endif
|
||||
|
||||
// #ifndef MP-WEIXIN
|
||||
navBarHeight.value = 44
|
||||
// #endif
|
||||
}
|
||||
|
||||
const goBack = () => {
|
||||
uni.navigateBack()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 【外层容器】:文档流中的普通盒子 */
|
||||
.nav-wrapper {
|
||||
width: 100%;
|
||||
/* 这里不设置 position,让它老老实实在文档流里呆着 */
|
||||
}
|
||||
|
||||
/* 【占位层】:看不见摸不着,只有高度 */
|
||||
.nav-placeholder {
|
||||
width: 100%;
|
||||
/* 仅通过 height 撑开父容器 */
|
||||
}
|
||||
|
||||
/* 【功能层】:脱离文档流,悬浮在页面上方 */
|
||||
.nav-fixed-layer {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
box-sizing: border-box;
|
||||
/* 视觉上的背景色在这里 */
|
||||
}
|
||||
|
||||
.status-bar {
|
||||
width: 100%;
|
||||
pointer-events: none; /* 防止拦截点击 */
|
||||
}
|
||||
|
||||
.nav-main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 20rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.nav-left,
|
||||
.nav-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.nav-center {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.back-text {
|
||||
font-size: 28rpx;
|
||||
margin-left: 4rpx;
|
||||
color: inherit;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user