Files
YGChatCS/src/components/TopNavBar/index.vue
duanshuwen 54a83bad5d refactor(top-nav-bar): add custom back prop
- 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
2026-07-20 19:12:11 +08:00

167 lines
3.6 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.

<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>