index.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <template>
  2. <ComponentsHeader v-bind="$props" />
  3. <view class="banner" :style="{ padding: `0 ${gap}px` }">
  4. <!-- 单图模式 -->
  5. <view v-if="mode === 'single'" class="single-image">
  6. <image :src="images[0]?.image || `http://iph.href.lu/400x200?text=1`" :style="{ borderRadius: `${radius}px` }" mode="aspectFill" @click="_handleClick(images[0].urlMap?.internal_url)" />
  7. </view>
  8. <!-- 轮播图模式 -->
  9. <swiper
  10. v-else-if="mode === 'swiper' || mode === 'swiper-no-dots'"
  11. :autoplay="true"
  12. :interval="swiperDuration"
  13. :circular="true"
  14. :indicator-dots="mode === 'swiper'"
  15. class="swiper"
  16. :style="{ borderRadius: `${radius}px` }"
  17. >
  18. <swiper-item v-for="(item, index) in images" :key="index">
  19. <image @click="_handleClick(item.urlMap?.internal_url)" :src="item.image || `http://iph.href.lu/400x200?text=${index}`" :style="{ borderRadius: `${radius}px` }" mode="aspectFill" />
  20. </swiper-item>
  21. </swiper>
  22. <!-- 网格模式 -->
  23. <view v-else-if="mode === 'grid'" class="grid-container" :style="{ borderRadius: `${radius}px` }">
  24. <view v-for="(item, index) in images.slice(0, 4)" :key="index" class="grid-item">
  25. <image @click="_handleClick(item.urlMap?.internal_url)" :src="item.image || `http://iph.href.lu/400x200?text=${index}`" mode="widthFix" :style="{ borderRadius: `${radius}px` }" />
  26. </view>
  27. </view>
  28. <!-- 双图模式 -->
  29. <view v-else-if="mode === 'double'" class="double-container" :style="{ borderRadius: `${radius}px` }">
  30. <view v-for="(item, index) in images.slice(0, 2)" :key="index" class="double-item">
  31. <image @click="_handleClick(item.urlMap?.internal_url)" :src="item.image || `http://iph.href.lu/400x200?text=${index}`" :style="{ borderRadius: `${radius}px` }" mode="aspectFill" />
  32. </view>
  33. </view>
  34. </view>
  35. </template>
  36. <script setup>
  37. import ComponentsHeader from '../ComponentsHeader';
  38. defineProps({
  39. images: {
  40. type: Array,
  41. default: () => [],
  42. },
  43. mode: {
  44. type: String,
  45. default: 'single',
  46. validator: (value) => ['single', 'swiper', 'swiper-no-dots', 'grid', 'double'].includes(value),
  47. },
  48. radius: {
  49. type: Number,
  50. default: 0,
  51. },
  52. swiperDuration: {
  53. type: Number,
  54. default: 3000,
  55. },
  56. gap: {
  57. type: Number,
  58. default: 0,
  59. },
  60. title: {
  61. type: String,
  62. default: '',
  63. },
  64. showTitle: {
  65. type: Boolean,
  66. default: false,
  67. },
  68. });
  69. const _handleClick = (url) => {
  70. if (url) {
  71. uni.navigateTo({
  72. url,
  73. fail: (err) => {
  74. uni.switchTab({
  75. url,
  76. });
  77. },
  78. });
  79. }
  80. };
  81. </script>
  82. <style lang="less" scoped>
  83. .navigator {
  84. width: 100%;
  85. height: 100%;
  86. }
  87. .banner {
  88. width: 100%;
  89. overflow: hidden;
  90. box-sizing: border-box;
  91. .single-image {
  92. width: 100%;
  93. height: 150px;
  94. overflow: hidden;
  95. image {
  96. width: 100%;
  97. height: 100%;
  98. }
  99. }
  100. .swiper {
  101. width: 100%;
  102. height: 150px;
  103. image {
  104. width: 100%;
  105. height: 100%;
  106. }
  107. }
  108. .grid-container {
  109. display: grid;
  110. grid-template-rows: repeat(2, 1fr);
  111. grid-template-columns: repeat(2, 1fr);
  112. gap: 4px;
  113. width: 100%;
  114. .grid-item {
  115. image {
  116. width: 100%;
  117. height: 100%;
  118. }
  119. }
  120. }
  121. .double-container {
  122. display: flex;
  123. gap: 4px;
  124. width: 100%;
  125. .double-item {
  126. flex: 1;
  127. height: 150px;
  128. image {
  129. width: 100%;
  130. height: 100%;
  131. }
  132. }
  133. }
  134. }
  135. </style>