s-coupon-block.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <!-- 装修营销组件:优惠券 -->
  2. <template>
  3. <scroll-view
  4. class="scroll-box"
  5. scroll-x
  6. scroll-anchoring
  7. :style="[bgStyle, { marginLeft: `${data.space}px` }]"
  8. >
  9. <view
  10. class="coupon-box ss-flex"
  11. :style="couponList.length === 2 ? couponBoxStyleTwo : couponBoxStyleNormal"
  12. >
  13. <view
  14. class="coupon-item"
  15. :style="[couponBg, { marginLeft: `${data.space}px` }]"
  16. v-for="(item, index) in couponList"
  17. :key="index"
  18. >
  19. <su-coupon
  20. :size="SIZE_LIST[columns - 1]"
  21. :textColor="data.textColor"
  22. background=""
  23. :couponId="item.id"
  24. :title="formatCouponTitle(item)"
  25. :type="formatCouponDiscountType(item)"
  26. :value="formatCouponDiscountValue(item)"
  27. :sellBy="formatValidityType(item)"
  28. :surplus="item.totalCount === -1 ? -1 : item.totalCount - item.takeCount"
  29. >
  30. <template v-slot:btn>
  31. <!-- 两列时,领取按钮坚排 -->
  32. <button
  33. v-if="columns === 2"
  34. @click.stop="onGetCoupon(item.id)"
  35. class="ss-reset-button card-btn vertical"
  36. :style="[btnStyles]"
  37. >
  38. <view class="btn-text">立即领取</view>
  39. </button>
  40. <button
  41. v-else
  42. class="ss-reset-button card-btn"
  43. :style="[btnStyles]"
  44. @click.stop="onGetCoupon(item.id)"
  45. >
  46. 立即领取
  47. </button>
  48. </template>
  49. </su-coupon>
  50. </view>
  51. </view>
  52. </scroll-view>
  53. </template>
  54. <script setup>
  55. import sheep from '@/sheep';
  56. import CouponApi from '@/sheep/api/promotion/coupon';
  57. import { ref, onMounted, computed } from 'vue';
  58. import { CouponTemplateValidityTypeEnum, PromotionDiscountTypeEnum } from '@/sheep/helper/const';
  59. import { floatToFixed2, formatDate } from '@/sheep/helper/utils';
  60. import { formatDiscountPercent } from '@/sheep/hooks/useGoods';
  61. const props = defineProps({
  62. data: {
  63. type: Object,
  64. default: () => ({}),
  65. },
  66. styles: {
  67. type: Object,
  68. default: () => ({}),
  69. },
  70. });
  71. const { columns, button } = props.data;
  72. const SIZE_LIST = ['lg', 'md', 'xs'];
  73. const couponBg = {
  74. background: `url(${sheep.$url.cdn(props.data.bgImg)}) no-repeat top center / 100% 100%`,
  75. };
  76. const btnStyles = {
  77. background: button.bgColor,
  78. color: button.color,
  79. };
  80. // 两列优惠券时的排版方式
  81. const couponBoxStyleNormal = {
  82. display: 'flex',
  83. 'justify-content': 'space-between',
  84. };
  85. // 非两列优惠券时的排版方式
  86. const couponBoxStyleTwo = {
  87. display: 'flex',
  88. 'justify-content': 'space-around',
  89. };
  90. // 设置背景样式
  91. const bgStyle = computed(() => {
  92. // 直接从 props.styles 解构
  93. const { bgType, bgImg, bgColor } = props.styles;
  94. // 根据 bgType 返回相应的样式
  95. return {
  96. background: bgType === 'img' ? `url(${bgImg}) no-repeat top center / 100% 100%` : bgColor,
  97. };
  98. });
  99. // 格式化【折扣类型】
  100. const formatCouponDiscountType = (coupon) => {
  101. if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
  102. return 'reduce';
  103. }
  104. if (coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
  105. return 'percent';
  106. }
  107. return `未知【${coupon.discountType}】`;
  108. };
  109. // 格式化【折扣】
  110. const formatCouponDiscountValue = (coupon) => {
  111. if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
  112. return floatToFixed2(coupon.discountPrice);
  113. }
  114. if (coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
  115. return formatDiscountPercent(coupon.discountPercent);
  116. }
  117. return `未知【${coupon.discountType}】`;
  118. };
  119. // 格式化【有效期限】
  120. const formatValidityType = (row) => {
  121. if (row.validityType === CouponTemplateValidityTypeEnum.DATE.type) {
  122. return `${formatDate(row.validStartTime)} 至 ${formatDate(row.validEndTime)}`;
  123. }
  124. if (row.validityType === CouponTemplateValidityTypeEnum.TERM.type) {
  125. return `领取后第 ${row.fixedStartTerm} - ${row.fixedEndTerm} 天内可用`;
  126. }
  127. return '未知【' + row.validityType + '】';
  128. };
  129. // 格式化【优惠券标题】
  130. const formatCouponTitle = (coupon) => {
  131. return `满${floatToFixed2(coupon.usePrice)}元${
  132. coupon.discountType === PromotionDiscountTypeEnum.PRICE.type
  133. ? ',减' + floatToFixed2(coupon.discountPrice) + '元'
  134. : ',打' + formatDiscountPercent(coupon.discountPercent) + '折'
  135. }`;
  136. };
  137. const couponList = ref([]);
  138. // 立即领取优惠券
  139. async function onGetCoupon(id) {
  140. const { error, msg } = await CouponApi.takeCoupon(id);
  141. if (error === 0) {
  142. uni.showToast({
  143. title: msg,
  144. icon: 'none',
  145. });
  146. return;
  147. }
  148. await getCouponTemplateList();
  149. }
  150. const getCouponTemplateList = async () => {
  151. const { data } = await CouponApi.getCouponTemplateListByIds(props.data.couponIds.join(','));
  152. couponList.value = data;
  153. };
  154. onMounted(() => {
  155. getCouponTemplateList();
  156. });
  157. </script>
  158. <style lang="scss" scoped>
  159. .card-btn {
  160. width: 140rpx;
  161. height: 50rpx;
  162. border-radius: 25rpx;
  163. font-size: 24rpx;
  164. line-height: 50rpx;
  165. &.vertical {
  166. width: 50rpx;
  167. height: 140rpx;
  168. margin: auto 20rpx auto 0;
  169. .btn-text {
  170. font-size: 24rpx;
  171. text-align: center;
  172. writing-mode: vertical-lr;
  173. }
  174. }
  175. }
  176. .coupon-item {
  177. &:nth-of-type(1) {
  178. margin-left: 0 !important;
  179. }
  180. }
  181. </style>