NavHeader.vue 2.85 KB
<!--
 * @Date: 2026-01-29 21:09:28
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2026-02-10 16:30:00
 * @FilePath: /manulife-weapp/src/components/navigation/NavHeader.vue
 * @Description: 通用导航头组件,用于页面顶部固定导航栏,展示页面标题。
 * @Usage:
 * <NavHeader title="首页" />
 * <NavHeader title="透明头" background="transparent" textColor="#000" :overlay="true" />
-->
<template>
  <!-- Placeholder to prevent content from being hidden behind fixed header -->
  <div v-if="!overlay" class="w-full h-[250rpx]"></div>
  <!-- Fixed Header -->
  <div 
    class="fixed top-0 left-0 z-50 w-full h-[250rpx] pt-[100rpx] transition-colors duration-300"
    :class="[!background ? 'bg-gradient-to-b from-[#1E3A8A] to-[#2563EB]' : '']"
    :style="background ? { background: background } : {}"
  >
    <div class="relative w-full h-full flex items-center justify-center px-[32rpx]">
      <div v-if="canGoBack" class="absolute left-[32rpx] flex items-center justify-center w-[60rpx] h-[60rpx]" @tap="goBack">
        <IconFont name="left" size="18" :color="textColor" />
      </div>
      <span class="text-[35rpx] font-normal" :style="{ color: textColor }">{{ title }}</span>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import Taro from '@tarojs/taro'
import IconFont from '@/components/icons/IconFont.vue'

/**
 * Props definition
 * @property {String} title - Page title
 * @property {Boolean} [showBack] - Whether to show back button. If undefined, auto-detects based on page stack.
 * @property {String} [background] - Custom background style (CSS value)
 * @property {String} [textColor] - Custom text/icon color (default #fff)
 * @property {Boolean} [overlay] - Whether to overlay content (no placeholder)
 * @property {Boolean} [preventDefaultBack] - Whether to prevent default navigateBack when @back is emitted
 */
const props = defineProps({
  title: {
    type: String,
    required: true
  },
  showBack: {
    type: Boolean,
    default: undefined
  },
  background: {
    type: String,
    default: ''
  },
  textColor: {
    type: String,
    default: '#fff'
  },
  overlay: {
    type: Boolean,
    default: false
  },
  preventDefaultBack: {
    type: Boolean,
    default: false
  }
})

const emit = defineEmits(['back'])

const canGoBack = ref(false)

/**
 * Initialize back button state
 */
onMounted(() => {
  if (props.showBack !== undefined) {
    canGoBack.value = props.showBack
  } else {
    const pages = Taro.getCurrentPages()
    canGoBack.value = pages.length > 1
  }
})

const goBack = () => {
  // 触发 back 事件
  // 父组件可以通过 @back 自定义返回行为
  // 例如:登录页可以跳转到首页而非返回上一页
  emit('back')

  // 如果没有阻止默认行为,执行默认的 navigateBack
  if (!props.preventDefaultBack) {
    Taro.navigateBack()
  }
}
</script>