red-packet-item.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. <template>
  2. <view class="red-packet-item" :class="{ 'is-disabled': isDisabled }">
  3. <view class="left-part">
  4. <view class="amount-box">
  5. <text class="symbol">¥</text>
  6. <text class="amount">{{ info.amount || 0 }}</text>
  7. </view>
  8. <view class="condition">满 ¥{{ info.condition || 0 }}使用</view>
  9. </view>
  10. <view class="right-part">
  11. <view class="info-top">
  12. <view class="title-row">
  13. <view class="tag" :class="info.type === 2 ? 'surprise' : 'normal'">
  14. {{ info.typeName || (info.type === 2 ? '惊喜红包' : '普通红包') }}
  15. </view>
  16. <text class="title">{{ info.title }}</text>
  17. </view>
  18. <view class="date">{{ info.endTime }}到期</view>
  19. </view>
  20. <view class="action-box">
  21. <view v-if="status === 0" class="btn-use" @click="onUse">立即使用</view>
  22. <view v-else-if="status === 1" class="stamp used">
  23. <text>已使用</text>
  24. </view>
  25. <view v-else-if="status === 2" class="stamp expired">
  26. <text>已过期</text>
  27. </view>
  28. </view>
  29. </view>
  30. </view>
  31. </template>
  32. <script>
  33. export default {
  34. name: "red-packet-item",
  35. props: {
  36. info: {
  37. type: Object,
  38. default: () => ({})
  39. }
  40. },
  41. computed: {
  42. // 0: unused, 1: used, 2: expired
  43. status() {
  44. return this.info.status || 0;
  45. },
  46. isDisabled() {
  47. return this.status !== 0;
  48. }
  49. },
  50. methods: {
  51. onUse() {
  52. this.$emit('use', this.info);
  53. }
  54. }
  55. }
  56. </script>
  57. <style lang="scss" scoped>
  58. .red-packet-item {
  59. display: flex;
  60. background-color: #ffffff;
  61. border-radius: 16rpx;
  62. margin: 20rpx 24rpx;
  63. position: relative;
  64. overflow: hidden;
  65. box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
  66. &.is-disabled {
  67. .left-part {
  68. color: #999;
  69. .amount-box {
  70. color: #999;
  71. }
  72. }
  73. .right-part {
  74. .title {
  75. color: #999;
  76. }
  77. .tag {
  78. background-color: #ccc;
  79. color: #fff;
  80. }
  81. }
  82. }
  83. .left-part {
  84. width: 200rpx;
  85. display: flex;
  86. flex-direction: column;
  87. justify-content: center;
  88. align-items: center;
  89. color: #e02020;
  90. border-right: 1px dashed #eeeeee;
  91. position: relative;
  92. padding: 30rpx 0;
  93. &::before, &::after {
  94. content: '';
  95. position: absolute;
  96. right: -10rpx;
  97. width: 20rpx;
  98. height: 20rpx;
  99. background-color: #f5f5f5; // Assume page bg is #f5f5f5
  100. border-radius: 50%;
  101. }
  102. &::before { top: -10rpx; }
  103. &::after { bottom: -10rpx; }
  104. .amount-box {
  105. display: flex;
  106. align-items: baseline;
  107. font-weight: bold;
  108. .symbol {
  109. font-size: 28rpx;
  110. }
  111. .amount {
  112. font-size: 60rpx;
  113. line-height: 1;
  114. }
  115. }
  116. .condition {
  117. font-size: 22rpx;
  118. margin-top: 10rpx;
  119. }
  120. }
  121. .right-part {
  122. flex: 1;
  123. padding: 30rpx 24rpx;
  124. display: flex;
  125. flex-direction: column;
  126. justify-content: space-between;
  127. position: relative;
  128. .info-top {
  129. .title-row {
  130. display: flex;
  131. align-items: center;
  132. flex-wrap: wrap;
  133. margin-bottom: 16rpx;
  134. .tag {
  135. font-size: 20rpx;
  136. padding: 2rpx 8rpx;
  137. border-radius: 4rpx;
  138. margin-right: 10rpx;
  139. &.normal {
  140. background-color: #fcebeb;
  141. color: #e02020;
  142. }
  143. &.surprise {
  144. background-color: #fff0e5;
  145. color: #ff6a00;
  146. }
  147. }
  148. .title {
  149. font-size: 28rpx;
  150. color: #333;
  151. font-weight: 500;
  152. }
  153. }
  154. .date {
  155. font-size: 22rpx;
  156. color: #999;
  157. }
  158. }
  159. .action-box {
  160. position: absolute;
  161. right: 24rpx;
  162. bottom: 30rpx;
  163. // For status buttons aligned with date or bottom right
  164. }
  165. .btn-use {
  166. background-color: #e02020;
  167. color: #fff;
  168. font-size: 24rpx;
  169. padding: 10rpx 24rpx;
  170. border-radius: 30rpx;
  171. }
  172. .stamp {
  173. width: 100rpx;
  174. height: 100rpx;
  175. border: 2rpx solid #ccc;
  176. border-radius: 50%;
  177. display: flex;
  178. justify-content: center;
  179. align-items: center;
  180. transform: rotate(-30deg);
  181. opacity: 0.6;
  182. text {
  183. font-size: 24rpx;
  184. color: #999;
  185. font-weight: bold;
  186. }
  187. &.used {
  188. border-color: #999;
  189. text { color: #999; }
  190. }
  191. &.expired {
  192. border-color: #999;
  193. text { color: #999; }
  194. }
  195. }
  196. }
  197. }
  198. </style>