<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>
|