s-coupon-block.vue 4.6 KB

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