- add customBack prop to enable explicit custom back handling - rewrite back navigation logic to use the new prop instead of inferring from emit listeners - remove unused getCurrentInstance import - update three AIGC page components to use the custom-back prop
167 lines
3.6 KiB
Vue
167 lines
3.6 KiB
Vue
<template>
|
||
<view :class="navBarClass" :style="navBarStyle">
|
||
<!-- 状态栏占位 -->
|
||
<view :style="{ height: statusBarHeight + 'px' }" v-if="!hideStatusBar"></view>
|
||
|
||
<!-- 导航栏内容 -->
|
||
<view class="flex flex-items-center flex-justify-between border-box pl-8 pr-8" :style="navContentStyle">
|
||
<!-- 左侧返回按钮 -->
|
||
<view class="nav-bar-left flex flex-items-center flex-justify-center" v-if="showBack" @click="handleBack">
|
||
<uni-icons type="left" size="20" :color="backIconColor" />
|
||
</view>
|
||
|
||
<!-- 中间标题区域 -->
|
||
<view :class="[
|
||
'nav-bar-center flex flex-items-center flex-justify-center',
|
||
`nav-bar-center--${titleAlign}`,
|
||
]">
|
||
<slot name="title">
|
||
<text class="font-size-17 font-500 color-000" :style="{ color: titleColor }">
|
||
{{ title }}
|
||
</text>
|
||
</slot>
|
||
</view>
|
||
|
||
<!-- 右侧操作区域 -->
|
||
<view class="nav-bar-right">
|
||
<slot name="right"></slot>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { computed, onMounted, ref } from "vue";
|
||
|
||
// 定义props
|
||
const props = defineProps({
|
||
// 标题文本
|
||
title: {
|
||
type: String,
|
||
default: "",
|
||
},
|
||
// 是否固定在顶部
|
||
fixed: {
|
||
type: Boolean,
|
||
default: false,
|
||
},
|
||
// 是否显示返回按钮
|
||
showBack: {
|
||
type: Boolean,
|
||
default: true,
|
||
},
|
||
// 背景颜色
|
||
background: {
|
||
type: String,
|
||
default: "$theme-color-100",
|
||
},
|
||
// 标题颜色
|
||
titleColor: {
|
||
type: String,
|
||
default: "#000",
|
||
},
|
||
// 返回按钮图标颜色
|
||
backIconColor: {
|
||
type: String,
|
||
default: "#000",
|
||
},
|
||
// 是否隐藏状态栏占位
|
||
hideStatusBar: {
|
||
type: Boolean,
|
||
default: false,
|
||
},
|
||
// 自定义z-index
|
||
zIndex: {
|
||
type: Number,
|
||
default: 999,
|
||
},
|
||
// 标题对齐方式
|
||
titleAlign: {
|
||
type: String,
|
||
default: "center", // 'center' | 'left'
|
||
validator: (value) => ["center", "left"].includes(value),
|
||
},
|
||
alignWithMenuButton: {
|
||
type: Boolean,
|
||
default: false,
|
||
},
|
||
customBack: {
|
||
type: Boolean,
|
||
default: false,
|
||
},
|
||
});
|
||
|
||
// 定义emits
|
||
const emit = defineEmits(["back"]);
|
||
|
||
// 系统信息
|
||
const statusBarHeight = ref(0);
|
||
const navBarHeight = ref(44); // 默认导航栏高度
|
||
|
||
// 获取系统信息
|
||
onMounted(() => {
|
||
const systemInfo = uni.getSystemInfoSync();
|
||
const systemStatusBarHeight = systemInfo.statusBarHeight || 0;
|
||
statusBarHeight.value = systemStatusBarHeight;
|
||
|
||
// 根据平台设置导航栏高度
|
||
if (systemInfo.platform === "ios") {
|
||
navBarHeight.value = 44;
|
||
} else {
|
||
navBarHeight.value = 48;
|
||
}
|
||
|
||
if (
|
||
props.alignWithMenuButton &&
|
||
typeof uni.getMenuButtonBoundingClientRect === "function"
|
||
) {
|
||
const menuButton = uni.getMenuButtonBoundingClientRect();
|
||
|
||
if (menuButton?.height && typeof menuButton.top === "number") {
|
||
statusBarHeight.value = Math.max(menuButton.top, systemStatusBarHeight);
|
||
navBarHeight.value = menuButton.height;
|
||
}
|
||
}
|
||
});
|
||
|
||
// 计算导航栏样式类
|
||
const navBarClass = computed(() => {
|
||
return [
|
||
"top-nav-bar",
|
||
{
|
||
"top-nav-bar--fixed": props.fixed,
|
||
},
|
||
];
|
||
});
|
||
|
||
// 计算导航栏样式
|
||
const navBarStyle = computed(() => {
|
||
return {
|
||
background: props.background,
|
||
zIndex: props.zIndex,
|
||
};
|
||
});
|
||
|
||
const navContentStyle = computed(() => {
|
||
return {
|
||
height: navBarHeight.value + "px",
|
||
};
|
||
});
|
||
|
||
// 处理返回事件
|
||
const handleBack = () => {
|
||
if (props.customBack) {
|
||
emit("back");
|
||
return;
|
||
}
|
||
// 如果没有监听back事件,默认执行返回上一页
|
||
uni.navigateBack({
|
||
delta: 1,
|
||
});
|
||
};
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
@import "./styles/index.scss";
|
||
</style>
|