@ -0,0 +1,207 @@ | |||
<template> | |||
<view class="page"> | |||
<!-- 导航栏 --> | |||
<navbar title="礼包列表" leftClick @leftClick="$utils.navigateBack" bgColor="#E3441A" color="#fff" /> | |||
<!-- 订单筛选 --> | |||
<view class="tabs"> | |||
<uv-tabs :list="tabs" | |||
:activeStyle="{color : '#fff', fontWeight : 600}" | |||
lineColor="#fff" | |||
:inactiveStyle="{color: 'rgba(255,255,255,.8)'}" | |||
lineHeight="8rpx" | |||
lineWidth="50rpx" | |||
:current="current" | |||
@click="clickTabs"></uv-tabs> | |||
</view> | |||
<view class="list"> | |||
<view class="item" v-for="(item, index) in list" @click="toGiftDetail(item.id)" :key="index"> | |||
<view class="content"> | |||
<view class="top"> | |||
<view class="service"> | |||
{{ item.title }} | |||
</view> | |||
<view class="status"> | |||
<text>{{ item.state === 0 ? '待领取' : '已领取' }}</text> | |||
</view> | |||
</view> | |||
<view class="main"> | |||
<view class="left"> | |||
<image mode="aspectFill" :src="item.image && item.image.split(',')[0]"></image> | |||
</view> | |||
<view class="right"> | |||
<view class="text-hidden-1"> | |||
赠送人:{{item.senderName}} | |||
</view> | |||
<view class="text-hidden-1"> | |||
赠送时间:{{item.createTime}} | |||
</view> | |||
<view class="text-hidden-2"> | |||
祝福语:{{item.message}} | |||
</view> | |||
</view> | |||
</view> | |||
</view> | |||
<view class="bottom"> | |||
<view class="price"> | |||
<text class="total-title">礼包价值:</text> | |||
<text class="unit">¥</text> | |||
<text class="num">{{item.price}}</text> | |||
<text class="c-unit">元</text> | |||
</view> | |||
<view @click.stop="receiveGift(item)" class="btn" v-if="item.state === 0"> | |||
立即领取 | |||
</view> | |||
</view> | |||
</view> | |||
<view style="margin-top: 20rpx; min-width: 700rpx;"> | |||
<uv-empty mode="list" v-if="list.length === 0"></uv-empty> | |||
</view> | |||
</view> | |||
</view> | |||
</template> | |||
<script> | |||
import mixinsList from '@/mixins/list.js' | |||
export default { | |||
mixins: [mixinsList], | |||
data() { | |||
return { | |||
mixinsListApi: 'getGiftList', | |||
tabs: [ | |||
{ | |||
name: '我赠送的' | |||
}, | |||
{ | |||
name: '我收到的' | |||
} | |||
], | |||
current : 0, | |||
} | |||
}, | |||
methods: { | |||
clickTabs({index}){ | |||
}, | |||
// 跳转礼包详情 | |||
toGiftDetail(id) { | |||
uni.navigateTo({ | |||
url: '/pages_order/order/giftDetail?id=' + id | |||
}) | |||
}, | |||
// 领取礼包 | |||
receiveGift(item) { | |||
uni.showModal({ | |||
title: '提示', | |||
content: '确认领取该礼包吗?', | |||
success: async (res) => { | |||
if (res.confirm) { | |||
await this.$http.post('/gift/receive', { | |||
id: item.id | |||
}) | |||
uni.showToast({ | |||
title: '领取成功', | |||
icon: 'success' | |||
}) | |||
this.getData() | |||
} | |||
} | |||
}) | |||
} | |||
} | |||
} | |||
</script> | |||
<style scoped lang="scss"> | |||
.list { | |||
.item { | |||
width: calc(100% - 40rpx); | |||
background-color: #fff; | |||
margin: 20rpx; | |||
box-sizing: border-box; | |||
border-radius: 16rpx; | |||
padding: 30rpx; | |||
.content { | |||
.top { | |||
display: flex; | |||
justify-content: space-between; | |||
align-items: center; | |||
font-size: 34rpx; | |||
.status { | |||
font-weight: 600; | |||
color: #FFAC2F; | |||
flex-shrink: 0; | |||
margin-left: 20rpx; | |||
} | |||
} | |||
.main { | |||
display: flex; | |||
margin: 20rpx 0rpx; | |||
.left { | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
width: 180rpx; | |||
height: 180rpx; | |||
image { | |||
width: 95%; | |||
height: 95%; | |||
border-radius: 10rpx; | |||
} | |||
} | |||
.right { | |||
display: flex; | |||
flex-direction: column; | |||
justify-content: space-between; | |||
width: calc(100% - 200rpx); | |||
color: #777; | |||
font-size: 26rpx; | |||
padding: 30rpx 20rpx; | |||
box-sizing: border-box; | |||
margin-left: 20rpx; | |||
border-radius: 10rpx; | |||
background-color: #F8F8F8; | |||
} | |||
} | |||
} | |||
.bottom { | |||
display: flex; | |||
justify-content: space-between; | |||
font-size: 25rpx; | |||
.price { | |||
.num { | |||
font-size: 36rpx; | |||
} | |||
.num, | |||
.unit, | |||
.c-unit { | |||
color: $uni-color; | |||
} | |||
} | |||
.btn { | |||
border: 1px solid #C7C7C7; | |||
padding: 10rpx 20rpx; | |||
border-radius: 40rpx; | |||
color: #575757; | |||
} | |||
} | |||
} | |||
} | |||
</style> |
@ -0,0 +1,238 @@ | |||
<template> | |||
<view class="instant-gift"> | |||
<navbar title="立即送礼" leftClick @leftClick="$utils.navigateBack" /> | |||
<!-- 主图片展示区 --> | |||
<view class="main-image"> | |||
<image :src="selectedGift.image" mode="aspectFill"></image> | |||
</view> | |||
<!-- 礼品选择列表 --> | |||
<scroll-view scroll-x class="gift-list"> | |||
<view | |||
class="gift-item" | |||
v-for="(item, index) in giftList" | |||
:key="index" | |||
:class="{ active: selectedIndex === index }" | |||
@click="selectGift(index)" | |||
> | |||
<image :src="item.image" mode="aspectFill"></image> | |||
<text class="gift-name">{{item.name}}</text> | |||
</view> | |||
</scroll-view> | |||
<!-- 祝福语区域 --> | |||
<view class="blessing-area"> | |||
<view class="blessing-title">送祝福给TA</view> | |||
<view class="blessing-input"> | |||
<input type="text" v-model="blessing" placeholder="蛇年到,福气绕。钱包满满当当!" /> | |||
</view> | |||
</view> | |||
<!-- 底部区域 --> | |||
<view class="bottom-area"> | |||
<view class="countdown">距离礼包失效:{{countdownText}}</view> | |||
<button class="send-btn" @click="sendGift">立即送礼</button> | |||
</view> | |||
</view> | |||
</template> | |||
<script> | |||
export default { | |||
data() { | |||
return { | |||
selectedIndex: 0, | |||
blessing: '', | |||
countdown: 24 * 60 * 60, // 倒计时秒数 | |||
countdownTimer: null, | |||
giftList: [ | |||
{ | |||
name: '蛇行大运', | |||
image: 'https://picb3.photophoto.cn/38/090/38090873_1.jpg' | |||
}, | |||
{ | |||
name: '蛇来运转', | |||
image: 'https://picb3.photophoto.cn/38/090/38090873_1.jpg' | |||
}, | |||
{ | |||
name: '2025', | |||
image: 'https://picb3.photophoto.cn/38/090/38090873_1.jpg' | |||
}, | |||
{ | |||
name: '身体健康', | |||
image: 'https://picb3.photophoto.cn/38/090/38090873_1.jpg' | |||
} | |||
] | |||
} | |||
}, | |||
computed: { | |||
selectedGift() { | |||
return this.giftList[this.selectedIndex] | |||
}, | |||
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: { | |||
navigateBack() { | |||
uni.navigateBack() | |||
}, | |||
selectGift(index) { | |||
this.selectedIndex = index | |||
}, | |||
sendGift() { | |||
// 实现送礼逻辑 | |||
uni.showToast({ | |||
title: '送礼成功', | |||
icon: 'success' | |||
}) | |||
}, | |||
startCountdown() { | |||
this.countdownTimer = setInterval(() => { | |||
if (this.countdown > 0) { | |||
this.countdown-- | |||
} else { | |||
clearInterval(this.countdownTimer) | |||
} | |||
}, 1000) | |||
} | |||
}, | |||
mounted() { | |||
this.startCountdown() | |||
}, | |||
beforeDestroy() { | |||
if (this.countdownTimer) { | |||
clearInterval(this.countdownTimer) | |||
} | |||
} | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
.instant-gift { | |||
min-height: 100vh; | |||
background: #fff; | |||
.nav-header { | |||
display: flex; | |||
align-items: center; | |||
height: 88rpx; | |||
padding: 0 30rpx; | |||
.back-icon, .more-icon { | |||
width: 60rpx; | |||
text-align: center; | |||
} | |||
.title { | |||
flex: 1; | |||
text-align: center; | |||
font-size: 32rpx; | |||
font-weight: 500; | |||
} | |||
} | |||
.main-image { | |||
width: 100%; | |||
height: 400rpx; | |||
image { | |||
width: 100%; | |||
height: 100%; | |||
} | |||
} | |||
.gift-list { | |||
padding: 30rpx; | |||
white-space: nowrap; | |||
.gift-item { | |||
display: inline-block; | |||
width: 200rpx; | |||
margin-right: 20rpx; | |||
text-align: center; | |||
position: relative; | |||
z-index: 1; | |||
border: 4rpx solid transparent; | |||
padding: 0 10rpx 10rpx 10rpx; | |||
&.active { | |||
position: relative; | |||
z-index: 2; | |||
border: 4rpx solid $uni-color; | |||
border-radius: 12rpx; | |||
} | |||
image { | |||
width: 100%; | |||
height: 200rpx; | |||
border-radius: 12rpx; | |||
} | |||
.gift-name { | |||
display: block; | |||
font-size: 28rpx; | |||
margin-top: 10rpx; | |||
} | |||
} | |||
} | |||
.blessing-area { | |||
padding: 30rpx; | |||
.blessing-title { | |||
font-size: 30rpx; | |||
color: #666; | |||
margin-bottom: 20rpx; | |||
} | |||
.blessing-input { | |||
background: #FFF5F5; | |||
padding: 20rpx; | |||
border-radius: 12rpx; | |||
border: 2rpx solid #FFE0E0; | |||
input { | |||
width: 100%; | |||
height: 60rpx; | |||
color: #333; | |||
font-size: 28rpx; | |||
} | |||
} | |||
} | |||
.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; | |||
} | |||
.send-btn { | |||
width: calc(100%); | |||
height: 88rpx; | |||
line-height: 88rpx; | |||
background: linear-gradient(to right, #FF4B4B, $uni-color); | |||
color: #fff; | |||
border-radius: 44rpx; | |||
font-size: 32rpx; | |||
font-weight: 500; | |||
} | |||
} | |||
} | |||
</style> |
@ -0,0 +1,232 @@ | |||
<template> | |||
<view class="receive-gift"> | |||
<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.name}}</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.senderName}}</text> | |||
<text class="label">的祝福</text> | |||
</view> | |||
<view class="blessing-content"> | |||
{{giftInfo.message}} | |||
</view> | |||
</view> | |||
<!-- 底部区域 --> | |||
<view class="bottom-area"> | |||
<view class="countdown">距离礼包失效:{{countdownText}}</view> | |||
<button class="receive-btn" @click="receiveGift" :disabled="giftInfo.state !== 0">{{giftInfo.state === 0 ? '立即领取' : '已领取'}}</button> | |||
</view> | |||
</view> | |||
</template> | |||
<script> | |||
export default { | |||
data() { | |||
return { | |||
giftId: '', | |||
giftInfo: { | |||
name: '', | |||
image: '', | |||
price: 0, | |||
senderName: '', | |||
message: '', | |||
state: 0, // 0-未领取 1-已领取 | |||
expireTime: '' | |||
}, | |||
countdown: 24 * 60 * 60, // 倒计时秒数 | |||
countdownTimer: null | |||
} | |||
}, | |||
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: { | |||
// 获取礼品信息 | |||
async getGiftInfo() { | |||
try { | |||
const res = await this.$http.get(`/gift/detail/${this.giftId}`) | |||
this.giftInfo = res.data | |||
// 计算倒计时 | |||
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() { | |||
try { | |||
await this.$http.post('/gift/receive', { | |||
id: this.giftId | |||
}) | |||
uni.showToast({ | |||
title: '领取成功', | |||
icon: 'success' | |||
}) | |||
this.giftInfo.state = 1 | |||
} catch (e) { | |||
uni.showToast({ | |||
title: '领取失败', | |||
icon: 'none' | |||
}) | |||
} | |||
}, | |||
// 开始倒计时 | |||
startCountdown() { | |||
this.countdownTimer = setInterval(() => { | |||
if (this.countdown > 0) { | |||
this.countdown-- | |||
} else { | |||
clearInterval(this.countdownTimer) | |||
} | |||
}, 1000) | |||
} | |||
}, | |||
onLoad(options) { | |||
if (options.id) { | |||
this.giftId = options.id | |||
this.getGiftInfo() | |||
} | |||
}, | |||
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; | |||
} | |||
} | |||
} | |||
} | |||
</style> |