main-layout.vue 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <template>
  2. <view class="layout-container">
  3. <!-- 顶部填充区 -->
  4. <view :style="statusBarStyle"></view>
  5. <!-- 顶部胶囊区 -->
  6. <view class="capsule-box" :style="capsuleBarStyle">
  7. <view class="icon-wrap" v-if="showBack || showHome">
  8. <view v-if="showBack" class="icon-box" :style="iconBoxStyle" @click="goBackPage">
  9. <uni-icons type="back" color="#FFFFFF" :size="iconSize"></uni-icons>
  10. </view>
  11. <view v-if="showHome" class="icon-box" :style="iconBoxStyle" @click="goIndexPage">
  12. <uni-icons type="home" color="#FFFFFF" :size="iconSize"></uni-icons>
  13. </view>
  14. </view>
  15. </view>
  16. <!-- 内容区 -->
  17. <view class="content-box">
  18. <slot></slot>
  19. </view>
  20. <!-- 底部填充区 -->
  21. <view :style="bottomBoxStyle"></view>
  22. </view>
  23. </template>
  24. <script setup>
  25. import { computed, ref } from 'vue';
  26. import { useSafeAreaStore } from '@/stores/safeArea.js';
  27. import router from '@/common/constants/router';
  28. defineProps({
  29. showHome: {
  30. type: Boolean,
  31. default: false
  32. },
  33. showBack: {
  34. type: Boolean,
  35. default: false
  36. }
  37. });
  38. /**
  39. * 安全区
  40. */
  41. const safeAreaStore = useSafeAreaStore();
  42. /**
  43. * 状态栏样式
  44. */
  45. const statusBarStyle = computed(() => {
  46. return {
  47. height: safeAreaStore.statusBarHeight+'px'
  48. }
  49. });
  50. /**
  51. * 胶囊区样式
  52. */
  53. const capsuleBarStyle = computed(() => {
  54. return {
  55. height: safeAreaStore.capsuleBarHeight+'px',
  56. width: safeAreaStore.capsuleBarLeft+'px',
  57. 'padding-top': safeAreaStore.capsuleBarMarginTop+'px',
  58. 'padding-bottom': safeAreaStore.capsuleBarMarginBottom+'px'
  59. }
  60. });
  61. /**
  62. * 图标容器样式
  63. */
  64. const iconBoxStyle = computed(() => {
  65. return {
  66. width: safeAreaStore.capsuleBarContentHeight-5+'px',
  67. height: safeAreaStore.capsuleBarContentHeight-5+'px'
  68. }
  69. });
  70. /**
  71. * 图标大小
  72. */
  73. const iconSize = computed(() => safeAreaStore.capsuleBarContentHeight-10);
  74. /**
  75. * 底部填充区样式
  76. */
  77. const bottomBoxStyle = computed(() => {
  78. return {
  79. height: safeAreaStore.bottomHeight+'px'
  80. }
  81. });
  82. /**
  83. * 返回主页
  84. */
  85. const goIndexPage = () => {
  86. uni.reLaunch({
  87. url: router.INDEX_URL
  88. });
  89. };
  90. /**
  91. * 返回上一页
  92. */
  93. const goBackPage = () => {
  94. uni.navigateBack();
  95. };
  96. </script>
  97. <style lang="scss" scoped>
  98. .layout-container {
  99. display: flex;
  100. flex-direction: column;
  101. min-height: 100vh;
  102. background: linear-gradient(180deg, #B9D3FF 0%, #F2F7FF 22.23%);
  103. .capsule-box {
  104. padding-left: 24rpx;
  105. padding-right: 24rpx;
  106. .icon-wrap {
  107. display: flex;
  108. justify-content: left;
  109. height: 100%;
  110. align-items: center;
  111. .icon-box {
  112. margin-left: 16rpx;
  113. display: flex;
  114. align-items: center;
  115. justify-content: center;
  116. border-radius: 50%;
  117. opacity: 0.2;
  118. background: rgba(0, 0, 0, 1);
  119. }
  120. .icon-box:first-child {
  121. margin-left: 0rpx;
  122. }
  123. }
  124. }
  125. .content-box {
  126. /* 内容区域占满剩余空间 */
  127. flex-grow: 1;
  128. padding: 0 24rpx 16rpx 24rpx;
  129. }
  130. }
  131. </style>