recommendCategory.vue 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. <template>
  2. <view class="category-box box">
  3. <swiper
  4. :indicator-dots="false"
  5. :current="current"
  6. :style="{ height: swiperHeight + 'rpx' }"
  7. @change="onSwiperChange"
  8. class="swiper"
  9. >
  10. <swiper-item v-for="(page, pageIndex) in pageList" :key="pageIndex">
  11. <view class="category-list">
  12. <view class="category-item" v-for="(item, index) in page" :key="index" @click="handleClick(item)">
  13. <image :src="item.dictImage" mode="aspectFill"></image>
  14. <view>{{ item.dictLabel || '' }}</view>
  15. </view>
  16. </view>
  17. </swiper-item>
  18. </swiper>
  19. <view v-if="list.length > perPage" class="indicator">
  20. <view
  21. class="indicator-bar"
  22. :class="{ active: pageIndex === current }"
  23. v-for="(page, pageIndex) in pageList"
  24. :key="pageIndex"
  25. ></view>
  26. </view>
  27. </view>
  28. </template>
  29. <script>
  30. export default {
  31. name: 'recommendCategory',
  32. props: {
  33. list: {
  34. type: Array,
  35. default: () => []
  36. }
  37. },
  38. data() {
  39. return {
  40. current: 0
  41. }
  42. },
  43. computed: {
  44. perPage() {
  45. return 8
  46. },
  47. isSingleRow() {
  48. return this.pageList.length > 0 && this.pageList.every(page => page.length <= 4)
  49. },
  50. swiperHeight() {
  51. return this.isSingleRow ? 190 : 364
  52. },
  53. pageList() {
  54. const pages = []
  55. for (let i = 0; i < this.list.length; i += this.perPage) {
  56. pages.push(this.list.slice(i, i + this.perPage))
  57. }
  58. return pages
  59. }
  60. },
  61. methods: {
  62. onSwiperChange(e) {
  63. this.current = e.detail.current
  64. },
  65. handleClick(item) {
  66. if (item.dictValue) {
  67. uni.navigateTo({
  68. url: '/pages_shopping/home/productList?tuiCateId=' + item.dictValue + '&title=' + encodeURIComponent(item.dictLabel || '')
  69. })
  70. } else if (item.page) {
  71. uni.navigateTo({
  72. url: item.page
  73. })
  74. }
  75. this.$emit('click', item)
  76. }
  77. }
  78. }
  79. </script>
  80. <style lang="scss" scoped>
  81. .box {
  82. background: #FFFFFF;
  83. border-radius: 16rpx;
  84. margin: 24rpx;
  85. box-sizing: border-box;
  86. padding: 26rpx 0 6rpx 0;
  87. }
  88. .swiper {
  89. height: 364rpx;
  90. }
  91. .category-list {
  92. display: flex;
  93. align-items: center;
  94. justify-content: flex-start;
  95. flex-wrap: wrap;
  96. }
  97. .category-item {
  98. width: 25%;
  99. font-family: PingFang SC, PingFang SC;
  100. font-weight: 400;
  101. font-size: 24rpx;
  102. color: #222222;
  103. display: flex;
  104. flex-direction: column;
  105. align-items: center;
  106. margin-bottom: 20rpx;
  107. image {
  108. width: 104rpx;
  109. height: 104rpx;
  110. margin-bottom: 26rpx;
  111. border-radius: 16rpx;
  112. }
  113. }
  114. .indicator {
  115. display: flex;
  116. justify-content: center;
  117. align-items: center;
  118. margin-top: 6rpx;
  119. .indicator-bar {
  120. width: 40rpx;
  121. height: 4rpx;
  122. border-radius: 2rpx;
  123. background: rgba(37, 131, 235, 0.3);
  124. margin: 0 6rpx;
  125. transition: background 0.3s;
  126. &.active {
  127. background: #2583EB;
  128. }
  129. }
  130. }
  131. </style>