敢为人鲜小程序前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

231 lines
4.6 KiB

3 months ago
  1. <template>
  2. <view class="receive-gift">
  3. <navbar title="礼品领取" leftClick @leftClick="$utils.navigateBack" />
  4. <!-- 主图片展示区 -->
  5. <view class="main-image">
  6. <image :src="giftInfo.image" mode="aspectFill"></image>
  7. </view>
  8. <!-- 礼品信息区域 -->
  9. <view class="gift-info">
  10. <view class="gift-name">{{giftInfo.name}}</view>
  11. <view class="gift-value">
  12. <text>礼品价值</text>
  13. <text class="price">{{giftInfo.price}}</text>
  14. </view>
  15. </view>
  16. <!-- 祝福语区域 -->
  17. <view class="blessing-area">
  18. <view class="sender-info">
  19. <text class="label">来自</text>
  20. <text class="sender">{{giftInfo.senderName}}</text>
  21. <text class="label">的祝福</text>
  22. </view>
  23. <view class="blessing-content">
  24. {{giftInfo.message}}
  25. </view>
  26. </view>
  27. <!-- 底部区域 -->
  28. <view class="bottom-area">
  29. <view class="countdown">距离礼包失效{{countdownText}}</view>
  30. <button class="receive-btn" @click="receiveGift" :disabled="giftInfo.state !== 0">{{giftInfo.state === 0 ? '立即领取' : '已领取'}}</button>
  31. </view>
  32. </view>
  33. </template>
  34. <script>
  35. export default {
  36. data() {
  37. return {
  38. giftId: '',
  39. giftInfo: {
  40. name: '',
  41. image: '',
  42. price: 0,
  43. senderName: '',
  44. message: '',
  45. state: 0, // 0-未领取 1-已领取
  46. expireTime: ''
  47. },
  48. countdown: 24 * 60 * 60, // 倒计时秒数
  49. countdownTimer: null
  50. }
  51. },
  52. computed: {
  53. countdownText() {
  54. const hours = Math.floor(this.countdown / 3600)
  55. const minutes = Math.floor((this.countdown % 3600) / 60)
  56. const seconds = this.countdown % 60
  57. return `${hours}${minutes}${seconds}`
  58. }
  59. },
  60. methods: {
  61. // 获取礼品信息
  62. async getGiftInfo() {
  63. try {
  64. const res = await this.$http.get(`/gift/detail/${this.giftId}`)
  65. this.giftInfo = res.data
  66. // 计算倒计时
  67. if (this.giftInfo.expireTime) {
  68. const expireTime = new Date(this.giftInfo.expireTime).getTime()
  69. const now = new Date().getTime()
  70. this.countdown = Math.max(0, Math.floor((expireTime - now) / 1000))
  71. this.startCountdown()
  72. }
  73. } catch (e) {
  74. uni.showToast({
  75. title: '获取礼品信息失败',
  76. icon: 'none'
  77. })
  78. }
  79. },
  80. // 领取礼品
  81. async receiveGift() {
  82. try {
  83. await this.$http.post('/gift/receive', {
  84. id: this.giftId
  85. })
  86. uni.showToast({
  87. title: '领取成功',
  88. icon: 'success'
  89. })
  90. this.giftInfo.state = 1
  91. } catch (e) {
  92. uni.showToast({
  93. title: '领取失败',
  94. icon: 'none'
  95. })
  96. }
  97. },
  98. // 开始倒计时
  99. startCountdown() {
  100. this.countdownTimer = setInterval(() => {
  101. if (this.countdown > 0) {
  102. this.countdown--
  103. } else {
  104. clearInterval(this.countdownTimer)
  105. }
  106. }, 1000)
  107. }
  108. },
  109. onLoad(options) {
  110. if (options.id) {
  111. this.giftId = options.id
  112. this.getGiftInfo()
  113. }
  114. },
  115. beforeDestroy() {
  116. if (this.countdownTimer) {
  117. clearInterval(this.countdownTimer)
  118. }
  119. }
  120. }
  121. </script>
  122. <style lang="scss" scoped>
  123. .receive-gift {
  124. min-height: 100vh;
  125. background: #fff;
  126. .main-image {
  127. width: 100%;
  128. height: 400rpx;
  129. image {
  130. width: 100%;
  131. height: 100%;
  132. }
  133. }
  134. .gift-info {
  135. padding: 30rpx;
  136. .gift-name {
  137. font-size: 36rpx;
  138. font-weight: 600;
  139. color: #333;
  140. margin-bottom: 20rpx;
  141. }
  142. .gift-value {
  143. font-size: 28rpx;
  144. color: #666;
  145. .price {
  146. color: #E3441A;
  147. font-weight: 600;
  148. margin-left: 10rpx;
  149. }
  150. }
  151. }
  152. .blessing-area {
  153. padding: 30rpx;
  154. background: #FFF5F5;
  155. margin: 30rpx;
  156. border-radius: 12rpx;
  157. .sender-info {
  158. text-align: center;
  159. margin-bottom: 20rpx;
  160. .label {
  161. color: #666;
  162. font-size: 28rpx;
  163. }
  164. .sender {
  165. color: #333;
  166. font-size: 32rpx;
  167. font-weight: 600;
  168. margin: 0 10rpx;
  169. }
  170. }
  171. .blessing-content {
  172. color: #333;
  173. font-size: 30rpx;
  174. line-height: 1.6;
  175. text-align: center;
  176. }
  177. }
  178. .bottom-area {
  179. position: fixed;
  180. left: 0;
  181. bottom: 0;
  182. width: 100%;
  183. box-sizing: border-box;
  184. padding: 20rpx 30rpx calc(30rpx + env(safe-area-inset-bottom)) 30rpx;
  185. background: #fff;
  186. box-shadow: 0 -2rpx 10rpx rgba(0,0,0,0.05);
  187. z-index: 10;
  188. .countdown {
  189. text-align: center;
  190. font-size: 28rpx;
  191. color: #666;
  192. margin-bottom: 20rpx;
  193. font-weight: 500;
  194. }
  195. .receive-btn {
  196. width: 100%;
  197. height: 88rpx;
  198. line-height: 88rpx;
  199. background: linear-gradient(to right, #FF4B4B, #E3441A);
  200. color: #fff;
  201. border-radius: 44rpx;
  202. font-size: 32rpx;
  203. font-weight: 500;
  204. &[disabled] {
  205. background: #ccc;
  206. opacity: 0.8;
  207. }
  208. }
  209. }
  210. }
  211. </style>