mi-assessment/uniapp/components/Navbar/index.vue
zpc 4387b15de0 feat(mine): 完成我的页面改造
- 实现未登录/已登录两种状态样式
- 添加常用功能入口:我的订单、往期测评、联系我们、邀请新用户
- 添加其他功能入口:关于、用户协议、隐私政策、退出登录
- 实现退出登录二次确认弹窗
- 修复 uni.scss 中 SCSS 导入路径问题
- 整理 .gitignore 文件,移除 unpackage 构建目录
2026-02-10 00:12:01 +08:00

225 lines
4.2 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.

<script setup>
/**
* 自定义导航栏组件
*
* Props:
* - title: 标题文字
* - showBack: 是否显示返回按钮
* - transparent: 是否透明背景
* - textColor: 文字颜色 (light/dark)
* - backgroundColor: 背景颜色
*
* Events:
* - back: 点击返回按钮
*
* Slots:
* - left: 左侧自定义内容
* - right: 右侧自定义内容
* - default: 中间自定义内容替代title
*/
import { computed } from 'vue'
import { useNavbar } from '../../composables/useNavbar.js'
const props = defineProps({
title: {
type: String,
default: ''
},
showBack: {
type: Boolean,
default: true
},
transparent: {
type: Boolean,
default: false
},
textColor: {
type: String,
default: 'dark',
validator: (value) => ['light', 'dark'].includes(value)
},
backgroundColor: {
type: String,
default: '#FFFFFF'
}
})
const emit = defineEmits(['back'])
const { statusBarHeight, navbarHeight, totalNavbarHeight } = useNavbar()
// 导航栏容器样式
const navbarStyle = computed(() => {
const style = {
paddingTop: `${statusBarHeight.value}px`,
height: `${totalNavbarHeight.value}px`
}
if (!props.transparent) {
style.backgroundColor = props.backgroundColor
}
return style
})
// 导航栏内容样式
const contentStyle = computed(() => ({
height: `${navbarHeight.value}px`
}))
// 占位元素样式
const placeholderStyle = computed(() => ({
height: `${totalNavbarHeight.value}px`
}))
// 文字颜色
const textColorValue = computed(() => {
return props.textColor === 'light' ? '#FFFFFF' : '#333333'
})
// 返回按钮颜色
const backIconColor = computed(() => {
return props.textColor === 'light' ? '#FFFFFF' : '#333333'
})
/**
* 处理返回
*/
function handleBack() {
emit('back')
const pages = getCurrentPages()
if (pages.length > 1) {
uni.navigateBack()
} else {
uni.switchTab({
url: '/pages/index/index'
})
}
}
</script>
<template>
<view class="navbar-wrapper">
<!-- 导航栏 -->
<view
class="navbar"
:class="{ 'navbar--transparent': transparent }"
:style="navbarStyle"
>
<view class="navbar__content" :style="contentStyle">
<!-- 左侧区域 -->
<view class="navbar__left">
<slot name="left">
<view
v-if="showBack"
class="navbar__back"
@click="handleBack"
>
<view class="navbar__back-icon" :style="{ borderColor: backIconColor }"></view>
</view>
</slot>
</view>
<!-- 中间区域 -->
<view class="navbar__center">
<slot>
<text
class="navbar__title"
:style="{ color: textColorValue }"
>{{ title }}</text>
</slot>
</view>
<!-- 右侧区域 -->
<view class="navbar__right">
<slot name="right"></slot>
</view>
</view>
</view>
<!-- 占位元素 -->
<view v-if="!transparent" class="navbar__placeholder" :style="placeholderStyle"></view>
</view>
</template>
<style scoped lang="scss">
.navbar-wrapper {
position: relative;
}
.navbar {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
&--transparent {
background-color: transparent;
}
}
.navbar__content {
display: flex;
align-items: center;
padding: 0 24rpx;
}
.navbar__left,
.navbar__right {
width: 80rpx;
flex-shrink: 0;
}
.navbar__left {
display: flex;
align-items: center;
justify-content: flex-start;
}
.navbar__right {
display: flex;
align-items: center;
justify-content: flex-end;
}
.navbar__center {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.navbar__title {
font-size: 34rpx;
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.navbar__back {
display: flex;
align-items: center;
justify-content: center;
width: 60rpx;
height: 60rpx;
}
.navbar__back-icon {
width: 20rpx;
height: 20rpx;
border-left: 4rpx solid #333;
border-bottom: 4rpx solid #333;
transform: rotate(45deg);
margin-left: 8rpx;
}
.navbar__placeholder {
width: 100%;
}
</style>