custom-tabbar.uvue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <template>
  2. <view class="custom-tabbar">
  3. <view v-for="(item, index) in visibleTabList" :key="index" class="tab-item" @click="handleTabClick(index)">
  4. <image class="tab-icon" :src="currentVisibleIndex == index ? item.selectedIconPath : item.iconPath" mode="aspectFit"></image>
  5. <text :class="['tab-text', currentVisibleIndex == index ? 'tab-text-active' : '']">
  6. {{ item.text }}
  7. </text>
  8. </view>
  9. </view>
  10. </template>
  11. <script setup lang="uts">
  12. import { ref, computed } from 'vue'
  13. // Props
  14. type Props = {
  15. current?: number
  16. hide0:number
  17. hide1:number
  18. hide2:number
  19. hide3:number
  20. }
  21. const props = withDefaults(defineProps<Props>(), {
  22. current: 0,
  23. hide0:1,
  24. hide1:1,
  25. hide2:1,
  26. hide3:1
  27. })
  28. // Tab 列表配置
  29. type TabItem = {
  30. pagePath: string
  31. text: string
  32. iconPath: string
  33. selectedIconPath: string
  34. }
  35. const tabList: TabItem[] = [
  36. {
  37. pagePath: '/pages/index/index',
  38. text: '首页',
  39. iconPath: '/static/images/custom-tabbar/11.png',
  40. selectedIconPath: '/static/images/custom-tabbar/22.png'
  41. },
  42. {
  43. pagePath: '/pages/order/index',
  44. text: '工单',
  45. iconPath: '/static/images/custom-tabbar/33.png',
  46. selectedIconPath: '/static/images/custom-tabbar/44.png'
  47. },
  48. {
  49. pagePath: '/pages/worktime/index',
  50. text: '工时',
  51. iconPath: '/static/images/custom-tabbar/77.png',
  52. selectedIconPath: '/static/images/custom-tabbar/88.png'
  53. },
  54. {
  55. pagePath: '/pages/score/index',
  56. text: '工分',
  57. iconPath: '/static/images/custom-tabbar/55.png',
  58. selectedIconPath: '/static/images/custom-tabbar/66.png'
  59. }
  60. ]
  61. // 计算可见的 tab 列表
  62. const visibleTabList = computed(() => {
  63. const hideValues = [props.hide0, props.hide1, props.hide2, props.hide3]
  64. return tabList.filter((_, index) => {
  65. return index < hideValues.length && hideValues[index] === 1
  66. })
  67. })
  68. // 计算当前选中项在可见列表中的索引
  69. const currentVisibleIndex = computed(() => {
  70. const hideValues = [props.hide0, props.hide1, props.hide2, props.hide3]
  71. let visibleIndex = 0
  72. for (let i = 0; i < props.current; i++) {
  73. // 如果前面的 tab 是可见的,则可见索引增加
  74. if (i < hideValues.length && hideValues[i] === 1) {
  75. visibleIndex++
  76. }
  77. }
  78. // 检查当前 tab 是否可见
  79. if (props.current >= hideValues.length || hideValues[props.current] !== 1) {
  80. // 如果当前 tab 不可见,返回第一个可见的 tab 索引
  81. return 0
  82. }
  83. return visibleIndex
  84. })
  85. // Tab 点击事件
  86. const handleTabClick = (index: number): void => {
  87. // 将可见索引转换回原始索引
  88. const hideValues = [props.hide0, props.hide1, props.hide2, props.hide3]
  89. let originalIndex = 0
  90. let visibleCount = 0
  91. for (let i = 0; i < tabList.length; i++) {
  92. if (i < hideValues.length && hideValues[i] === 1) {
  93. if (visibleCount === index) {
  94. originalIndex = i
  95. break
  96. }
  97. visibleCount++
  98. }
  99. }
  100. if (originalIndex == props.current) {
  101. return
  102. }
  103. const item = tabList[originalIndex]
  104. uni.redirectTo({
  105. url: item.pagePath
  106. })
  107. }
  108. </script>
  109. <style lang="scss">
  110. .custom-tabbar {
  111. position: fixed;
  112. bottom: 0;
  113. left: 0;
  114. right: 0;
  115. z-index: 1000;
  116. height: 150rpx;
  117. background-color: #ffffff;
  118. border-top: 1rpx solid #e5e5e5;
  119. flex-direction: row;
  120. justify-content: space-around;
  121. align-items: center;
  122. padding-bottom: env(safe-area-inset-bottom);
  123. }
  124. .tab {
  125. &-item {
  126. flex: 1;
  127. justify-content: center;
  128. align-items: center;
  129. }
  130. &-icon {
  131. width: 48rpx;
  132. height: 48rpx;
  133. margin-bottom: 8rpx;
  134. }
  135. &-text {
  136. font-size: 24rpx;
  137. color: #666666;
  138. &-active {
  139. color: #0081ff;
  140. }
  141. }
  142. }
  143. </style>