s-goods-card.vue 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. <template>
  2. <!-- 商品卡片 -->
  3. <view>
  4. <!-- 1 100%宽卡片列表-->
  5. <view v-if="mode === 1 && state.goodsList.length" class="goods-sl-box">
  6. <view
  7. class="goods-box"
  8. v-for="item in state.goodsList"
  9. :key="item.id"
  10. :style="[{ marginBottom: data.space * 2 + 'rpx' }]"
  11. >
  12. <s-goods-column
  13. class=""
  14. size="sl"
  15. :goodsFields="goodsFields"
  16. :tagStyle="tagStyle"
  17. :data="item"
  18. :titleColor="goodsFields.title?.color"
  19. :subTitleColor="goodsFields.subtitle.color"
  20. :topRadius="data.borderRadiusTop"
  21. :bottomRadius="data.borderRadiusBottom"
  22. @click="sheep.$router.go('/pages/goods/index', { id: item.id })"
  23. >
  24. <template v-slot:cart>
  25. <button class="ss-reset-button cart-btn" :style="[buyStyle]">
  26. {{ buyNowStyle.mode === 1 ? buyNowStyle.text : '' }}
  27. </button>
  28. </template>
  29. </s-goods-column>
  30. </view>
  31. </view>
  32. <!-- 2 双列瀑布流列表-->
  33. <view
  34. v-if="mode === 2 && state.goodsList.length"
  35. class="goods-md-wrap ss-flex ss-flex-wrap ss-col-top"
  36. >
  37. <view class="goods-list-box">
  38. <view
  39. class="left-list"
  40. :style="[{ paddingRight: data.space + 'rpx', marginBottom: data.space + 'px' }]"
  41. v-for="item in state.leftGoodsList"
  42. :key="item.id"
  43. >
  44. <s-goods-column
  45. class="goods-md-box"
  46. size="md"
  47. :goodsFields="goodsFields"
  48. :tagStyle="tagStyle"
  49. :data="item"
  50. :titleColor="goodsFields.title?.color"
  51. :subTitleColor="goodsFields.subtitle.color"
  52. :topRadius="data.borderRadiusTop"
  53. :bottomRadius="data.borderRadiusBottom"
  54. :titleWidth="330 - marginLeft - marginRight"
  55. @click="sheep.$router.go('/pages/goods/index', { id: item.id })"
  56. @getHeight="mountMasonry($event, 'left')"
  57. >
  58. <template v-slot:cart>
  59. <button class="ss-reset-button cart-btn" :style="[buyStyle]">
  60. {{ buyNowStyle.mode === 1 ? buyNowStyle.text : '' }}
  61. </button>
  62. </template>
  63. </s-goods-column>
  64. </view>
  65. </view>
  66. <view class="goods-list-box">
  67. <view
  68. class="right-list"
  69. :style="[{ paddingLeft: data.space + 'rpx', marginBottom: data.space + 'px' }]"
  70. v-for="item in state.rightGoodsList"
  71. :key="item.id"
  72. >
  73. <s-goods-column
  74. class="goods-md-box"
  75. size="md"
  76. :goodsFields="goodsFields"
  77. :tagStyle="tagStyle"
  78. :data="item"
  79. :titleColor="goodsFields.title?.color"
  80. :subTitleColor="goodsFields.subtitle.color"
  81. :topRadius="data.borderRadiusTop"
  82. :bottomRadius="data.borderRadiusBottom"
  83. :titleWidth="330 - marginLeft - marginRight"
  84. @click="sheep.$router.go('/pages/goods/index', { id: item.id })"
  85. @getHeight="mountMasonry($event, 'right')"
  86. >
  87. <template v-slot:cart>
  88. <button class="ss-reset-button cart-btn" :style="[buyStyle]">
  89. {{ buyNowStyle.mode === 1 ? buyNowStyle.text : '' }}
  90. </button>
  91. </template>
  92. </s-goods-column>
  93. </view>
  94. </view>
  95. </view>
  96. <!-- 3 30%卡片列表-->
  97. <view v-if="mode === 3 && state.goodsList.length" class="goods-lg-box">
  98. <view
  99. class="goods-box"
  100. :style="[{ marginBottom: data.space + 'px' }]"
  101. v-for="item in state.goodsList"
  102. :key="item.id"
  103. >
  104. <s-goods-column
  105. class="goods-card"
  106. size="lg"
  107. :goodsFields="goodsFields"
  108. :data="item"
  109. :tagStyle="tagStyle"
  110. :titleColor="goodsFields.title?.color"
  111. :subTitleColor="goodsFields.subtitle.color"
  112. :topRadius="data.borderRadiusTop"
  113. :bottomRadius="data.borderRadiusBottom"
  114. @tap="sheep.$router.go('/pages/goods/index', { id: item.id })"
  115. >
  116. <template v-slot:cart>
  117. <button class="ss-reset-button cart-btn" :style="[buyStyle]">
  118. {{ buyNowStyle.mode === 1 ? buyNowStyle.text : '' }}
  119. </button>
  120. </template>
  121. </s-goods-column>
  122. </view>
  123. </view>
  124. </view>
  125. </template>
  126. <script setup>
  127. /**
  128. * 商品模板,装修商品卡片
  129. * @description style 1:带tab 2:瀑布流,横向两个,上图下内容 3:大图,横向一个
  130. */
  131. import { computed, reactive, onMounted } from 'vue';
  132. import sheep from '@/sheep';
  133. const state = reactive({
  134. goodsList: [],
  135. leftGoodsList: [],
  136. rightGoodsList: [],
  137. });
  138. const props = defineProps({
  139. data: {
  140. type: Object,
  141. default() {},
  142. },
  143. styles: {
  144. type: Object,
  145. default() {},
  146. },
  147. });
  148. const { mode, tagStyle, buyNowStyle, goodsFields, goodsIds } = props.data ?? {};
  149. const { marginLeft, marginRight } = props.styles ?? {};
  150. async function getGoodsListByIds(ids) {
  151. let { data } = await sheep.$api.goods.ids({ ids });
  152. return data;
  153. }
  154. onMounted(async () => {
  155. state.goodsList = await getGoodsListByIds(goodsIds.join(','));
  156. if (mode === 2) {
  157. mountMasonry();
  158. }
  159. });
  160. // 加载瀑布流
  161. let count = 0;
  162. let leftHeight = 0;
  163. let rightHeight = 0;
  164. function mountMasonry(height = 0, where = 'left') {
  165. if (!state.goodsList[count]) return;
  166. if (where === 'left') leftHeight += height;
  167. if (where === 'right') rightHeight += height;
  168. if (leftHeight <= rightHeight) {
  169. state.leftGoodsList.push(state.goodsList[count]);
  170. } else {
  171. state.rightGoodsList.push(state.goodsList[count]);
  172. }
  173. count++;
  174. }
  175. // 购买按钮样式
  176. const buyStyle = computed(() => {
  177. if (buyNowStyle.mode == 1) {
  178. // button
  179. return {
  180. background: `linear-gradient(to right, ${buyNowStyle.color1}, ${buyNowStyle.color2})`,
  181. };
  182. }
  183. if (buyNowStyle.mode == 2) {
  184. // image
  185. return {
  186. width: '54rpx',
  187. height: '54rpx',
  188. background: `url(${sheep.$url.cdn(buyNowStyle.src)}) no-repeat`,
  189. backgroundSize: '100% 100%',
  190. };
  191. }
  192. });
  193. </script>
  194. <style lang="scss" scoped>
  195. .goods-md-wrap {
  196. width: 100%;
  197. }
  198. .goods-list-box {
  199. width: 50%;
  200. box-sizing: border-box;
  201. .left-list {
  202. &:nth-last-child(1) {
  203. margin-bottom: 0 !important;
  204. }
  205. }
  206. .right-list {
  207. &:nth-last-child(1) {
  208. margin-bottom: 0 !important;
  209. }
  210. }
  211. }
  212. .goods-box {
  213. &:nth-last-of-type(1) {
  214. margin-bottom: 0 !important;
  215. }
  216. }
  217. .goods-md-box,
  218. .goods-sl-box,
  219. .goods-lg-box {
  220. position: relative;
  221. .cart-btn {
  222. position: absolute;
  223. bottom: 18rpx;
  224. right: 20rpx;
  225. z-index: 11;
  226. height: 50rpx;
  227. line-height: 50rpx;
  228. padding: 0 20rpx;
  229. border-radius: 25rpx;
  230. font-size: 24rpx;
  231. color: #fff;
  232. }
  233. }
  234. </style>