CustomNavigationBar.vue 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <script setup lang="ts">
  2. import { onMounted, ref } from 'vue'
  3. import { safeAreaInsets } from '@/utils'
  4. const props = withDefaults(defineProps<Props>(), {
  5. title: '页面标题',
  6. showBack: true,
  7. backIconColor: '#000000',
  8. backgroundColor: '#ffffff',
  9. textColor: '#333333',
  10. height: '88rpx',
  11. })
  12. // Props
  13. interface Props {
  14. title?: string
  15. showBack?: boolean
  16. backIconColor?: string
  17. backgroundColor?: string
  18. textColor?: string
  19. }
  20. // 导航栏高度
  21. const navBarHeight = ref('44px')
  22. const navBarTop = ref('44px')
  23. const topSafeAreaHeight = safeAreaInsets?.top || 0
  24. // 返回按钮点击事件
  25. function handleBack() {
  26. uni.navigateBack({
  27. delta: 1, // 返回层数,1表示返回上一页
  28. })
  29. }
  30. // 计算导航栏高度
  31. onMounted(() => {
  32. // #ifdef MP-WEIXIN
  33. uni.getSystemInfo({
  34. success: (res) => {
  35. const menuButtonInfo = uni.getMenuButtonBoundingClientRect()
  36. console.log('设备顶部信息:', res)
  37. console.log('胶囊信息:', menuButtonInfo)
  38. // 顶部导航栏高度 = 状态栏高度 + 胶囊的高度
  39. navBarHeight.value = `${menuButtonInfo.height}px`
  40. navBarTop.value = `${menuButtonInfo.top}px`
  41. }
  42. })
  43. // #endif
  44. })
  45. </script>
  46. <template>
  47. <view class="top-nav" :style="{
  48. paddingTop: `${topSafeAreaHeight}px`,
  49. backgroundColor: props.backgroundColor,
  50. }">
  51. <view class="custom-navbar">
  52. <view v-if="props.showBack" class="back-btn" @tap="handleBack">
  53. <up-icon name="arrow-left" size="36rpx" :color="props.textColor" />
  54. </view>
  55. <view class="nav-title" :style="{
  56. color: props.textColor,
  57. }">
  58. {{ props.title }}
  59. </view>
  60. <view v-if="props.showBack" class="right-space" />
  61. </view>
  62. </view>
  63. </template>
  64. <style scoped>
  65. /* 顶部导航栏 */
  66. .top-nav {
  67. background: #ffffff;
  68. box-shadow: 0rpx 8rpx 7rpx 0rpx rgba(233, 233, 233, 0.17);
  69. position: fixed;
  70. /* 固定定位 */
  71. top: 0;
  72. /* 顶部对齐 */
  73. left: 0;
  74. /* 左侧对齐 */
  75. right: 0;
  76. /* 右侧对齐 */
  77. z-index: 999;
  78. /* 确保在其他元素之上 */
  79. padding-top: var(--safe-area-inset-top);
  80. /* 适配安全区域 */
  81. }
  82. /* 自定义导航栏 */
  83. .custom-navbar {
  84. display: flex;
  85. align-items: center;
  86. justify-content: space-between;
  87. padding: 20rpx 30rpx;
  88. height: 88rpx;
  89. box-sizing: border-box;
  90. }
  91. /* 返回按钮 */
  92. .back-btn {
  93. width: 60rpx;
  94. height: 60rpx;
  95. display: flex;
  96. align-items: center;
  97. justify-content: center;
  98. }
  99. .back-icon {
  100. font-size: 36rpx;
  101. color: #000000;
  102. font-weight: bold;
  103. }
  104. /* 导航栏标题 */
  105. .nav-title {
  106. font-size: 34rpx;
  107. font-weight: bold;
  108. flex: 1;
  109. text-align: center;
  110. }
  111. /* 右侧占位 */
  112. .right-space {
  113. width: 60rpx;
  114. }
  115. </style>