Files
2026-10-16 22:40:02 +08:00

128 lines
2.8 KiB
Vue
Raw Permalink 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="apv-head" :style="headPad">
<!-- 左侧:返回按钮 + 可选标题前缀 -->
<view class="apv-head-left">
<view class="apv-back" hover-class="apv-back-active" @tap="onBack">
<FaIcon name="chevron-left" color="#1f2b48" :size="20" />
</view>
<text v-if="backText" class="apv-back-text">{{ backText }}</text>
</view>
<!-- 中间:标题 -->
<view class="apv-head-center">
<text class="apv-title">{{ title }}</text>
</view>
<!-- 右侧:可选操作槽(默认占位,避免标题被挤偏) -->
<view class="apv-head-right">
<slot name="right" />
</view>
</view>
</template>
<script setup>
import { computed } from 'vue'
import { mpHeadPad } from '@/utils/mpHead.js'
const props = defineProps({
/** 标题 */
title: { type: String, required: true },
/** 返回按钮旁的文字(不传则只显示箭头图标)。常见「返回」「关闭」。 */
backText: { type: String, default: '' },
/**
* 自定义返回行为。函数返回 false 时阻止默认 navigateBack。
* 例:detail 页面有未保存修改时拦截。
*/
beforeBack: { type: Function, default: null }
})
const emit = defineEmits(['back'])
function onBack() {
if (typeof props.beforeBack === 'function' && props.beforeBack() === false) return
emit('back')
const pages = getCurrentPages()
if (pages.length > 1) {
uni.navigateBack({ delta: 1 })
} else {
// 栈内只有自己(直链进入),回到子系统首页
uni.reLaunch({ url: '/pages/nav/nav' })
}
}
// 状态栏高度避让:胶囊可用则按胶囊底缘 + 8px,否则回退到 safe-area-inset-top
const headPad = computed(() => mpHeadPad(8))
</script>
<style lang="scss" scoped>
@import '@/src/styles/page-common.scss';
.apv-head {
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: space-between;
height: 88rpx;
padding: 0 $page-padding-x;
background: $color-card;
box-shadow: $shadow-header;
position: relative;
z-index: 10;
/* #ifdef MP-WEIXIN */
padding-top: 0; /* mpHeadPad 已注入 paddingTop;这里不再叠加 */
/* #endif */
}
.apv-head-left,
.apv-head-right {
display: flex;
align-items: center;
gap: 8rpx;
min-width: 120rpx;
flex-shrink: 0;
}
.apv-head-right {
justify-content: flex-end;
}
.apv-head-center {
flex: 1;
min-width: 0;
display: flex;
align-items: center;
justify-content: center;
padding: 0 16rpx;
}
.apv-back {
width: 56rpx;
height: 56rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: $radius-full;
transition: background 0.2s;
}
.apv-back-active {
background: $color-bg-page;
}
.apv-back-text {
font-size: 26rpx;
color: $color-text-secondary;
white-space: nowrap;
}
.apv-title {
max-width: 100%;
font-size: 32rpx;
font-weight: 600;
color: $color-text;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
</style>