|
|
- <template>
- <view class="receive-gift">
-
- <template v-if="isOpeningEnd">
-
- <navbar title="礼品领取" leftClick @leftClick="$utils.navigateBack" />
-
- <!-- 主图片展示区 -->
- <view class="main-image">
- <image :src="giftInfo.image" mode="aspectFill"></image>
- </view>
-
- <!-- 礼品信息区域 -->
- <view class="gift-info">
- <view class="gift-name">{{giftInfo.title}}</view>
- <view class="gift-value">
- <text>礼品价值:</text>
- <text class="price">¥{{giftInfo.price}}</text>
- </view>
- </view>
-
- <!-- 祝福语区域 -->
- <view class="blessing-area">
- <view class="sender-info">
- <text class="label">来自</text>
- <text class="sender">{{giftInfo.name}}</text>
- <text class="label">的祝福</text>
- </view>
- <view class="blessing-content">
- {{ giftInfo.giveTitle }}
- </view>
- </view>
-
- <!-- 底部区域 -->
- <view class="bottom-area">
- <!-- <view class="countdown">距离礼包失效:{{countdownText}}</view> -->
- <!-- <button class="receive-btn"
- @click="receiveGift"
- :disabled="giftInfo.giveStatus !== 0">
- {{giftInfo.giveStatus === 0 ? '立即领取' : '已领取'}}
- </button> -->
-
- <button class="receive-btn"
- v-if="giftInfo.giveStatus != 1"
- @click="openAddress">
- 立即领取
- </button>
- </view>
- </template>
-
- <!-- 礼物开启动画弹窗 -->
- <uv-popup ref="giftPopup"
- mode="center"
- :round="20"
- :closeable="false"
- :closeOnClickOverlay="false"
- :maskClick="false"
- :customStyle="{backgroundColor: 'transparent', padding: 0}"
- overlayOpacity="0.8">
- <view class="gift-card" :class="{ 'open': isOpening }">
- <view class="gift-icon" :class="{ 'bounce': !isOpening }">
- <uv-icon name="gift-fill" size="120" color="#FFD700"></uv-icon>
- </view>
- <view class="gift-content">
- <view class="gift-title" :class="{ 'fade': isOpening }">
- {{ giftInfo.name }}送你一份礼物
- </view>
- <view class="gift-open-btn"
- @click="openGift"
- :class="{ 'pulse': !isOpening }">
- <text>开</text>
- <view class="btn-sparkle"></view>
- </view>
- <view class="gift-tip" :class="{ 'fade': isOpening }">
- {{ giftInfo.giveTitle }}
- </view>
- </view>
- </view>
- </uv-popup>
-
- <!-- 抽奖弹窗 -->
- <uv-popup ref="lotteryPopup"
- mode="center"
- :round="20"
- :closeable="false"
- :maskClick="false"
- :closeOnClickOverlay="false"
- :customStyle="{backgroundColor: 'transparent', padding: 0}"
- overlayOpacity="0.8">
- <view class="lottery-card">
- <view class="lottery-title">{{ giftInfo.name }}为您精选了一份抽奖礼包</view>
- <view class="gift-tip">
- {{ giftInfo.giveTitle }}
- </view>
- <view class="lottery-content">
- <view class="product-image">
- <image :src="giftInfo.image" mode="aspectFill"></image>
- </view>
- <view class="product-info">
- <view class="product-name">{{giftInfo.title}}</view>
- <view class="product-price">¥{{giftInfo.price}}</view>
- </view>
- </view>
-
- <view class="lottery-btn" @click="startLottery" v-if="!isSpinning">
- 试试手气
- </view>
-
- <view class="lottery-result" v-if="showResult">
- <text v-if="isWinner">恭喜您中奖了!</text>
- <text v-else>很遗憾,下次再来!</text>
- </view>
-
- <view class="lottery-btn"
- @click="openAddress"
- v-if="isWinner && giftInfo.giveStatus != 1">
- 立即领取
- </view>
- </view>
- </uv-popup>
-
-
- <!-- 地址选择 -->
- <uv-popup ref="addressPopup" :round="30" style="padding-bottom: 90rpx;">
-
- <view class="addressPopupTitle">
- 填写地址就能收礼了
- </view>
-
- <!-- <view class="tabs">
- <uv-tabs :list="tabs"
- :activeStyle="{color : 'rgb(235, 51, 0)', fontWeight : 600}"
- lineColor="#fff"
- :inactiveStyle="{color: 'rgba(235, 51, 0, 0.8)'}"
- lineHeight="8rpx"
- lineWidth="50rpx"
- :current="addressCurrent"
- @click="clickTabs"></uv-tabs>
- </view> -->
-
- <addressList
- ref="addressList"
- height="60vh"
- v-if="addressCurrent == 1"
- @select="receiveGift" />
-
- <view class="redactAddressForm"
- v-else>
-
- <redactAddressForm
- ref="redactAddressForm"
- @saveOrUpdate="receiveGift"
- />
-
- <view
- @click="$refs.redactAddressForm.onSubmit"
- class="save">确认收礼</view>
- </view>
-
- </uv-popup>
-
- <loginPopup ref="loginPopup" @login="getGiftInfo"/>
- </view>
- </template>
-
- <script>
- import addressList from '../components/address/addressList.vue'
- import redactAddressForm from '../components/address/redactAddressForm.vue'
- import loginPopup from '@/components/config/loginPopup.vue'
- export default {
- components : {
- addressList,
- redactAddressForm,
- loginPopup,
- },
- data() {
- return {
- giftId: '',
- giftInfo: {
- },
- countdown: 24 * 60 * 60, // 倒计时秒数
- countdownTimer: null,
-
- // 领奖
- isOpening: false,
- isOpeningEnd : false,
-
- // 抽奖
- isSpinning: false,
- showResult: false,
- isWinner: false,
-
- // 地址
- addressTotal: 0,
- tabs: [
- {
- name: '新地址'
- },
- {
- name: '现有地址'
- }
- ],
- addressCurrent : 0,
- }
- },
- computed: {
- countdownText() {
- const hours = Math.floor(this.countdown / 3600)
- const minutes = Math.floor((this.countdown % 3600) / 60)
- const seconds = this.countdown % 60
- return `${hours}时${minutes}分${seconds}秒`
- }
- },
- methods: {
- // 打开礼物动画
- openGift() {
- this.isOpening = true
- setTimeout(() => {
- this.$refs.giftPopup.close()
- this.isOpeningEnd = true
- }, 1000)
- },
- // 开始抽奖
- startLottery() {
- if (this.isSpinning) return
- uni.showLoading({
- title: '抽奖中...',
- })
-
- this.isSpinning = true
- this.showResult = false
-
- // 模拟抽奖过程
- setTimeout(() => {
-
- this.$api('getGiveShopLottery', {
- orderId : this.giftId,
- }).then(res => {
- uni.hideLoading()
- this.showResult = true
- if(res.code == 200){
- this.isWinner = !!res.result
- }
- })
-
- // this.isSpinning = false
-
- // 这里可以根据实际接口返回决定是否中奖
- // this.isWinner = Math.random() > 0.5
-
- }, 2000)
- },
- // 获取礼品信息
- async getGiftInfo() {
- try {
- const res = await this.$api('getOrderDetail', {
- id: this.giftId
- })
- this.giftInfo = res.result
-
- this.$nextTick(() => {
- // 获取信息后显示弹窗
- if(this.giftInfo.isGive == 3){
- this.$refs.lotteryPopup.open()
- }else{
- this.$refs.giftPopup.open()
- }
- })
-
- // 计算倒计时
- // if (this.giftInfo.expireTime) {
- // const expireTime = new Date(this.giftInfo.expireTime).getTime()
- // const now = new Date().getTime()
- // this.countdown = Math.max(0, Math.floor((expireTime - now) / 1000))
- // this.startCountdown()
- // }
- } catch (e) {
- uni.showToast({
- title: '获取礼品信息失败',
- icon: 'none'
- })
- }
- },
- // 领取礼品
- async receiveGift(address) {
- try {
- let res = await this.$api('getGiveShop', {
- orderId : this.giftId,
- address : address.address,
- addressDetails : address.addressDetails,
- name : address.name,
- phone : address.phone,
- })
- if(res.code == 200){
- this.$refs.addressPopup.close()
- uni.showToast({
- title: '领取成功',
- icon: 'success'
- })
- }
- this.giftInfo.giveStatus = 1
- } catch (e) {
- uni.showToast({
- title: '领取失败',
- icon: 'none'
- })
- }
- },
- // 开始倒计时
- startCountdown() {
- this.countdownTimer = setInterval(() => {
- if (this.countdown > 0) {
- this.countdown--
- } else {
- clearInterval(this.countdownTimer)
- }
- }, 1000)
- },
- // 打开选择地址
- openAddress() {
- this.$refs.addressPopup.open('bottom')
- },
- // 获取地址列表
- getAddressList() {
- // 获取地址列表
- this.$refs.addressList.getAddressList().then(res => {
- this.addressTotal = res.total
- })
- },
- clickTabs({index}){
- this.addressCurrent = index
- if(index == 1){
- this.$nextTick(() => {
- this.getAddressList()
- })
- }
- },
- },
- onLoad(options) {
- if (options.shareId) {
- uni.setStorageSync('shareId', options.shareId)
- }
- if (options.id) {
- this.giftId = options.id
- if(uni.getStorageSync('token')){
- this.getGiftInfo()
- }else{
- this.$refs.loginPopup.open()
- }
- }
- },
- onShow() {
- },
- beforeDestroy() {
- if (this.countdownTimer) {
- clearInterval(this.countdownTimer)
- }
- }
- }
- </script>
-
- <style lang="scss" scoped>
- .receive-gift {
- min-height: 100vh;
- background: #fff;
-
- .main-image {
- width: 100%;
- height: 400rpx;
-
- image {
- width: 100%;
- height: 100%;
- }
- }
-
- .gift-info {
- padding: 30rpx;
-
- .gift-name {
- font-size: 36rpx;
- font-weight: 600;
- color: #333;
- margin-bottom: 20rpx;
- }
-
- .gift-value {
- font-size: 28rpx;
- color: #666;
-
- .price {
- color: #E3441A;
- font-weight: 600;
- margin-left: 10rpx;
- }
- }
- }
-
- .blessing-area {
- padding: 30rpx;
- background: #FFF5F5;
- margin: 30rpx;
- border-radius: 12rpx;
-
- .sender-info {
- text-align: center;
- margin-bottom: 20rpx;
-
- .label {
- color: #666;
- font-size: 28rpx;
- }
-
- .sender {
- color: #333;
- font-size: 32rpx;
- font-weight: 600;
- margin: 0 10rpx;
- }
- }
-
- .blessing-content {
- color: #333;
- font-size: 30rpx;
- line-height: 1.6;
- text-align: center;
- }
- }
-
- .bottom-area {
- position: fixed;
- left: 0;
- bottom: 0;
- width: 100%;
- box-sizing: border-box;
- padding: 20rpx 30rpx calc(30rpx + env(safe-area-inset-bottom)) 30rpx;
- background: #fff;
- box-shadow: 0 -2rpx 10rpx rgba(0,0,0,0.05);
- z-index: 10;
-
- .countdown {
- text-align: center;
- font-size: 28rpx;
- color: #666;
- margin-bottom: 20rpx;
- font-weight: 500;
- }
-
- .receive-btn {
- width: 100%;
- height: 88rpx;
- line-height: 88rpx;
- background: linear-gradient(to right, #FF4B4B, #E3441A);
- color: #fff;
- border-radius: 44rpx;
- font-size: 32rpx;
- font-weight: 500;
-
- &[disabled] {
- background: #ccc;
- opacity: 0.8;
- }
- }
- }
- }
-
- .addressPopupTitle{
- padding: 40rpx;
- font-size: 32rpx;
- font-weight: 900;
- text-align: center;
- }
- .redactAddressForm{
- padding: 0 40rpx;
- padding-bottom: 40rpx;
- .save {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 90%;
- height: 80rpx;
- border-radius: 40rpx;
- color: white;
- font-size: 28rpx;
- margin: 0rpx auto;
- background: $uni-color;
- margin-top: 150rpx;
- }
- }
-
- // 普通礼包开启动画
- .gift-card {
- position: relative;
- background: $uni-color;
- border-radius: 20rpx;
- padding: 60rpx 40rpx;
- width: 600rpx;
- transform-origin: center;
- transition: all 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55);
-
- .gift-icon {
- position: absolute;
- top: -60rpx;
- left: 50%;
- transform: translateX(-50%);
- width: 120rpx;
- height: 120rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- transition: all 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
- transform-origin: center bottom;
- animation: giftBounce 2s infinite;
- }
-
- .gift-content {
- margin-top: 60rpx;
- transform-origin: center;
- transition: all 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
- color: #fff;
- text-align: center;
-
- .gift-open-btn {
- position: relative;
- width: 120rpx;
- height: 120rpx;
- border-radius: 50%;
- background: linear-gradient(135deg, #FF4B4B, #E3441A);
- margin: 40rpx auto;
- display: flex;
- align-items: center;
- justify-content: center;
- cursor: pointer;
- overflow: hidden;
- box-shadow: 0 6rpx 20rpx rgba(227, 68, 26, 0.3);
-
- text {
- color: #fff;
- font-size: 36rpx;
- font-weight: bold;
- z-index: 1;
- }
-
- .btn-sparkle {
- position: absolute;
- top: -50%;
- left: -50%;
- width: 200%;
- height: 200%;
- background: linear-gradient(90deg,
- rgba(255,255,255,0) 0%,
- rgba(255,255,255,0.2) 50%,
- rgba(255,255,255,0) 100%);
- transform: rotate(45deg);
- animation: sparkle 2s infinite;
- }
-
- &.pulse {
- animation: pulse 2s infinite;
- }
- }
- .gift-title{
- color: #fff;
- font-size: 32rpx;
- font-weight: bold;
- margin-bottom: 20rpx;
- }
-
- .gift-title, .gift-tip {
- transition: all 0.5s ease;
-
- &.fade {
- opacity: 0;
- transform: translateY(-20rpx);
- }
- }
-
- .gift-icon {
- &.bounce {
- animation: giftBounce 2s infinite;
- }
- }
- }
-
- &.open {
- transform: perspective(1000px) rotateY(720deg) scale(0.5);
- opacity: 0;
-
- .gift-icon {
- transform: translateX(-50%) translateY(-200%) scale(1.5) rotate(720deg);
- opacity: 0;
- }
-
- .gift-content {
- transform: scale(0) rotate(-720deg);
- opacity: 0;
- }
- }
- }
-
- @keyframes sparkle {
- 0% {
- transform: rotate(45deg) translateX(-100%);
- }
- 50% {
- transform: rotate(45deg) translateX(100%);
- }
- 100% {
- transform: rotate(45deg) translateX(100%);
- }
- }
-
- @keyframes pulse {
- 0% {
- transform: scale(1);
- }
- 50% {
- transform: scale(1.05);
- }
- 100% {
- transform: scale(1);
- }
- }
-
- // 修改原有的giftBounce动画
- @keyframes giftBounce {
- 0%, 100% {
- transform: translateX(-50%) translateY(0) rotate(0deg);
- }
- 25% {
- transform: translateX(-50%) translateY(-15rpx) rotate(-5deg);
- }
- 75% {
- transform: translateX(-50%) translateY(-15rpx) rotate(5deg);
- }
- }
-
- // 抽奖动画
- .lottery-card {
- width: 600rpx;
- background: linear-gradient(135deg, #FF6B6B, #E3441A);
- border-radius: 20rpx;
- padding: 40rpx;
- text-align: center;
-
- .lottery-title {
- color: #fff;
- font-size: 32rpx;
- font-weight: bold;
- margin-bottom: 20rpx;
- }
- .gift-tip{
- color: #fff;
- font-size: 28rpx;
- margin-bottom: 40rpx;
- }
-
- .lottery-content {
- background: #fff;
- border-radius: 16rpx;
- padding: 30rpx;
- margin: 0 auto 30rpx;
-
- .product-image {
- width: 300rpx;
- height: 300rpx;
- margin: 0 auto 20rpx;
- border-radius: 8rpx;
- overflow: hidden;
-
- image {
- width: 100%;
- height: 100%;
- }
- }
-
- .product-info {
- text-align: center;
-
- .product-name {
- font-size: 28rpx;
- color: #333;
- margin-bottom: 10rpx;
- }
-
- .product-price {
- font-size: 36rpx;
- color: #E3441A;
- font-weight: bold;
- }
- }
- }
-
- .lottery-btn {
- margin-top: 40rpx;
- background: #FFD700;
- color: #E3441A;
- padding: 20rpx 60rpx;
- border-radius: 40rpx;
- display: inline-block;
- font-weight: bold;
- box-shadow: 0 6rpx 20rpx rgba(255, 215, 0, 0.3);
- }
-
- .lottery-result {
- margin-top: 30rpx;
- color: #fff;
- font-size: 32rpx;
- font-weight: bold;
- animation: fadeIn 0.5s ease;
- }
- }
- </style>
|