MonthlyBestSeller.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. <template>
  2. <view class="new-products u-skeleton-fillet">
  3. <view
  4. class="head-item"
  5. @click="goDetail('/pages/tabtar/goodsType', false, true)"
  6. :style="{ backgroundImage: `url(${bgImage || ''})` }"
  7. >
  8. <view class="top-left">
  9. <view class="top-left-title">热销产品</view>
  10. <view class="top-left-tip">新品上市优惠热销</view>
  11. </view>
  12. <view class="top-right" style="color: #e2ac40">
  13. 查看更多
  14. <!-- <text class="iconfont u-font24">&#xe6c7;</text> -->
  15. <uv-icon name="arrow-right" size="24rpx" color="#e2ac40"></uv-icon>
  16. </view>
  17. </view>
  18. <view
  19. class="new-products-main"
  20. v-if="(hotList && hotList.length > 0) || skeletonShow"
  21. >
  22. <swiper
  23. class="month-list"
  24. :indicator-dots="false"
  25. :autoplay="false"
  26. :display-multiple-items="itemsDis"
  27. @change="imgActiveFun"
  28. :circular="false"
  29. >
  30. <swiper-item
  31. class="item"
  32. @click="
  33. goProductDetails('/pages/shop/goodsDetails?id=' + item.productId)
  34. "
  35. v-for="item in hotList.length > 0 ? hotList : 1"
  36. :key="item.id"
  37. >
  38. <!-- ?x-oss-process=style/w_350 -->
  39. <image
  40. v-if="item && item.coverImage"
  41. :src="`${item.coverImage}`"
  42. mode="aspectFill"
  43. >
  44. </image>
  45. <view class="list-num">
  46. <rich-text
  47. :nodes="$mUtil.priceBigSmall(item.minSalePrice)"
  48. ></rich-text>
  49. </view>
  50. </swiper-item>
  51. </swiper>
  52. <view class="slide-box">
  53. <view class="dotBox" v-if="hotList.length > 0">
  54. <view
  55. class="dotBox_item"
  56. v-for="(v, i) in lineList"
  57. :key="i"
  58. :class="{ active_dotBox: activeBannerIndex == i }"
  59. ></view>
  60. </view>
  61. </view>
  62. </view>
  63. <noData v-else :config="{ top: 1, content: '暂无商品~' }"></noData>
  64. </view>
  65. </template>
  66. <script setup>
  67. import { ref, onMounted } from "vue";
  68. import { shopProductList_Api } from "@/api/shop";
  69. const props = defineProps({
  70. hotList: {
  71. type: Array,
  72. default: () => []
  73. },
  74. skeletonShow: {
  75. type: Boolean,
  76. default: false
  77. },
  78. bgImage: {
  79. type: String,
  80. default: ''
  81. },
  82. itemsDis: {
  83. type: Number,
  84. default: 1
  85. },
  86. lineList: {
  87. type: Number,
  88. default: 0
  89. },
  90. activeBannerIndex: {
  91. type: Number,
  92. default: 0
  93. }
  94. });
  95. const emit = defineEmits(['goDetail', 'goProductDetails', 'imgActiveFun']);
  96. const hotList = ref([]); //本月热销
  97. const lineList = ref(0);
  98. const itemsDis = ref(1);
  99. const activeBannerIndex = ref(0);
  100. const goDetail = (url, isNeedLogin, tabShow) => {
  101. emit('goDetail', url, isNeedLogin, tabShow);
  102. };
  103. const goProductDetails = (url) => {
  104. emit('goProductDetails', url);
  105. };
  106. const imgActiveFun = (e) => {
  107. activeBannerIndex.value = e.detail.current;
  108. };
  109. /**本月热销 */
  110. const hotSale = () => {
  111. shopProductList_Api({
  112. limit: 12,
  113. hot: 1,
  114. }).then((res) => {
  115. if (res && res.code == 200) {
  116. let list = res.data || [];
  117. hotList.value = res.data;
  118. if (hotList.value.length > 2) {
  119. lineList.value = hotList.value.length - 2;
  120. }
  121. if (list.length <= 3) {
  122. itemsDis.value = list.length;
  123. }
  124. if (list.length > 3 && list.length <= 6) {
  125. itemsDis.value = 3;
  126. }
  127. if (list.length > 6 && list.length <= 9) {
  128. itemsDis.value = 3;
  129. }
  130. if (list.length > 9 && list.length <= 12) {
  131. itemsDis.value = 3;
  132. }
  133. }
  134. });
  135. };
  136. onMounted(() => {
  137. hotSale();
  138. });
  139. defineExpose({
  140. init: hotSale,
  141. });
  142. </script>
  143. <style scoped lang="scss">
  144. .new-products {
  145. margin: 30rpx 0;
  146. background: rgba(249, 244, 225, 0.7);
  147. padding-bottom: 30rpx;
  148. box-sizing: border-box;
  149. border-radius: 10rpx;
  150. overflow: hidden;
  151. .new-products-main {
  152. box-sizing: border-box;
  153. margin: 20rpx 30rpx;
  154. background-color: #ffffff;
  155. padding-bottom: 20rpx;
  156. border-radius: 10rpx;
  157. }
  158. }
  159. .head-item {
  160. display: flex;
  161. align-items: center;
  162. justify-content: space-between;
  163. padding: 27rpx 30rpx;
  164. box-sizing: border-box;
  165. overflow: hidden;
  166. background-size: 100% 100%;
  167. background-repeat: no-repeat;
  168. .top-left {
  169. .top-left-title {
  170. font-size: 36rpx;
  171. font-family: PingFang SC, PingFang SC-Bold;
  172. font-weight: 700;
  173. }
  174. .top-left-tip {
  175. font-size: 24rpx;
  176. font-family: PingFang SC, PingFang SC-Regular;
  177. font-weight: 400;
  178. margin-top: 5rpx;
  179. }
  180. }
  181. .top-right {
  182. width: 165rpx;
  183. height: 67rpx;
  184. line-height: 67rpx;
  185. background: #ffffff;
  186. border-radius: 34rpx;
  187. box-sizing: border-box;
  188. font-size: 24rpx;
  189. font-family: PingFang SC, PingFang SC-Regular;
  190. font-weight: 400;
  191. text-align: center;
  192. display: flex;
  193. align-items: center;
  194. justify-content: center;
  195. }
  196. }
  197. .month-list {
  198. position: relative;
  199. padding-bottom: 20rpx;
  200. height: 350rpx;
  201. ::v-deep uni-swiper {
  202. height: 350rpx;
  203. }
  204. .item {
  205. margin: 28rpx 0;
  206. text-align: center;
  207. height: 350rpx;
  208. width: 217rpx;
  209. image {
  210. width: 217rpx;
  211. margin: 0 auto;
  212. height: 217rpx;
  213. border-radius: 10rpx;
  214. }
  215. .list-num {
  216. margin-top: 16rpx;
  217. font-size: 36rpx;
  218. line-height: 24rpx;
  219. color: #00bf5a;
  220. font-weight: bold;
  221. text-align: center;
  222. }
  223. }
  224. ::v-deep swiper-item {
  225. width: 33.333%;
  226. }
  227. }
  228. .slide-box {
  229. display: flex;
  230. justify-content: center;
  231. }
  232. .dotBox {
  233. height: 14rpx;
  234. overflow: hidden;
  235. border-radius: 14rpx;
  236. background-color: #ededed;
  237. display: flex;
  238. justify-content: center;
  239. .dotBox_item {
  240. width: 45rpx;
  241. height: 14rpx;
  242. border-radius: 2rpx;
  243. background-color: #ededed;
  244. transition: all 0.5s;
  245. }
  246. .active_dotBox {
  247. width: 45rpx;
  248. background: linear-gradient(109deg, #fb6b3e 20%, #feaf6b 85%);
  249. transition: all 0.5s;
  250. }
  251. }
  252. </style>