s-coupon-block.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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">
  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 bgStyle = computed(() => {
  66. // 直接从 props.styles 解构
  67. const {
  68. bgType,
  69. bgImg,
  70. bgColor
  71. } = props.styles;
  72. // 根据 bgType 返回相应的样式
  73. return {
  74. background: bgType === 'img' ? `url(${bgImg}) no-repeat top center / 100% 100%` : bgColor
  75. };
  76. });
  77. // 格式化【折扣类型】
  78. const formatCouponDiscountType = (coupon) => {
  79. if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
  80. return 'reduce'
  81. }
  82. if (coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
  83. return 'percent'
  84. }
  85. return `未知【${coupon.discountType}】`
  86. }
  87. // 格式化【折扣】
  88. const formatCouponDiscountValue = (coupon) => {
  89. if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
  90. return floatToFixed2(coupon.discountPrice)
  91. }
  92. if (coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
  93. return coupon.discountPercent
  94. }
  95. return `未知【${coupon.discountType}】`
  96. }
  97. // 格式化【有效期限】
  98. const formatValidityType = (row) => {
  99. if (row.validityType === CouponTemplateValidityTypeEnum.DATE.type) {
  100. return `${formatDate(row.validStartTime)} 至 ${formatDate(row.validEndTime)}`
  101. }
  102. if (row.validityType === CouponTemplateValidityTypeEnum.TERM.type) {
  103. return `领取后第 ${row.fixedStartTerm} - ${row.fixedEndTerm} 天内可用`
  104. }
  105. return '未知【' + row.validityType + '】'
  106. }
  107. const couponList = ref([]);
  108. // 立即领取优惠券
  109. async function onGetCoupon(id) {
  110. const {
  111. error,
  112. msg
  113. } = await CouponApi.takeCoupon(id);
  114. if (error === 0) {
  115. uni.showToast({
  116. title: msg,
  117. icon: 'none',
  118. });
  119. return
  120. }
  121. await getCouponTemplateList()
  122. }
  123. const getCouponTemplateList = async () => {
  124. const {
  125. data
  126. } = await CouponApi.getCouponTemplateListByIds(props.data.couponIds.join(','));
  127. couponList.value = data;
  128. }
  129. onMounted(() => {
  130. getCouponTemplateList()
  131. });
  132. </script>
  133. <style lang="scss" scoped>
  134. .scroll-box {
  135. .coupon-box {
  136. display: flex;
  137. justify-content: space-around;
  138. .card-btn {
  139. width: 140rpx;
  140. height: 50rpx;
  141. border-radius: 25rpx;
  142. font-size: 24rpx;
  143. line-height: 50rpx;
  144. &.vertical {
  145. width: 50rpx;
  146. height: 140rpx;
  147. margin: auto 20rpx auto 0;
  148. .btn-text {
  149. font-size: 24rpx;
  150. text-align: center;
  151. writing-mode: vertical-lr;
  152. }
  153. }
  154. }
  155. .coupon-item {
  156. &:nth-of-type(1) {
  157. margin-left: 0 !important;
  158. }
  159. }
  160. }
  161. }
  162. </style>