Files
xdd-uniapp-new/pkg_product/views/sojoumOrderDetails.vue
T

828 lines
26 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="order-details v12-px-3 v12-pt-3">
<!-- 订单状态 -->
<view class="status-section" v-if="!orderInfo.isGiftCardSend">
<view class="v12-font-28 v12-font-bold v12-primary-text v12-align-center v12-justify-between">
<text>{{orderInfo._status._title || ''}}</text>
<u-count-down v-if="orderInfo._status && ['1'].includes(orderInfo._status._type)" format="HH:mm:ss" autoStart :time="$global.diffSSS(orderInfo.confirmTimeout)" />
</view>
<view class="v12-font-24 v12-mt-3" style="color: #666;" v-if="orderInfo._status && ['1'].includes(orderInfo._status._type)">
您已下单成功请联系商家确认具体的入住时间
<view v-if="orderInfo.refundRejectReason && orderInfo.refundStatus === 3" class="v12-font-24 v12-mt-3 v12-primary-text">退款失败原因{{ orderInfo.refundRejectReason }}</view>
</view>
<view class="v12-font-24 v12-mt-3" style="color: #666;" v-if="orderInfo._status && ['2'].includes(orderInfo._status._type)">
已与商家确认入住时间请在入住时间内到店核销
<view v-if="orderInfo.refundRejectReason && orderInfo.refundStatus === 3" class="v12-font-24 v12-mt-3 v12-primary-text">退款失败原因{{ orderInfo.refundRejectReason }}</view>
</view>
<view class="v12-font-24 v12-mt-3" style="color: #666;" v-if="orderInfo._status && ['-1'].includes(orderInfo._status._type)">
订单正在申请退款中
</view>
<view class="v12-font-24 v12-mt-3 v12-primary-text" v-if="orderInfo._status && ['-3'].includes(orderInfo._status._type)">
原因{{ orderInfo.refundRejectReason }}
</view>
<view class="v12-font-24 v12-mt-3 v12-primary-text" v-if="orderInfo._status && ['-2'].includes(orderInfo._status._type)">
订单已成功取消订单费用退回原账户
</view>
<view class="v12-font-24 v12-mt-3 v12-primary-text" v-if="orderInfo._status && ['4', '3'].includes(orderInfo._status._type)">
订单核验成功
</view>
<view class="v12-font-24 v12-mt-3 v12-primary-text flex ai-center" v-if="orderInfo._status && [ '0'].includes(orderInfo._status._type)">
剩余<u-count-down format="HH:mm:ss" autoStart :time="$global.diffSSS(orderInfo.paymentTimeout)" />订单将自动取消
</view>
</view>
<!-- 商品信息 -->
<view class="product-section" >
<image class="product-image" :src="orderInfo.travelGroupOrderInfo.travelGroupProduct.mainImage" mode="aspectFill"></image>
<view class="product-info">
<view class="v12-font-32 v12-font-bold more_t">{{orderInfo.travelGroupOrderInfo.travelGroupProduct.name}}</view>
<view class="product-price">
<text style="font-size: 28rpx; color: #A1A1A1;">实付</text>
<text class="v12-primary-text v12-font-bold">
<text class="v12-font-26 v12-primary-text">¥</text>
<text class="v12-font-36 v12-primary-text">{{orderInfo.payPrice}}</text>
</text>
</view>
</view>
</view>
<view class="order-section">
<view class="info-item">
<text class="label">团购总价</text>
<text class="value">{{orderInfo.travelGroupOrderInfo.travelGroupProduct.price}}</text>
</view>
<view class="info-item" style="margin-bottom: 0rpx;">
<text class="label">满减优惠</text>
<text class="value">{{orderInfo.couponPrice}}</text>
</view>
</view>
<!-- 核销码 -->
<view class="verify-section" v-if="orderInfo._status && ['1','2'].includes(orderInfo._status._type)">
<view class="verify-title v12-font-28 v12-primary-text">核销码{{orderInfo.verifyCode}}</view>
<image class="qr-code" :src="orderInfo.verifyQrCode" mode="aspectFit"></image>
<view class="contact-buttons">
<button class="contact-btn merchant-phone" @click="showPhoneDialog('phone')">
<view>
<u-icon :name="webUrl + '/home/pho.png'" size="18"></u-icon>
</view>
<view>商家电话</view>
</button>
<button class="contact-btn merchant-wechat" @click="showPhoneDialog('wechat')">
<view>
<u-icon :name="webUrl + '/home/wx.png'" size="18"></u-icon>
</view>
<view>商家微信</view>
</button>
</view>
</view>
<u-popup :show="showPhonePopup" mode="center" round="10" :safe-area-inset-bottom="false">
<view class="phone-popup">
<view class="phone-title">{{ title }}</view>
<view class="phone-number">{{ popContent || '暂无'}}</view>
<view class="phone-actions v12-align-center" v-if="title === '商家电话'">
<!-- <button class="action-btn cancel" @click="showPhonePopup = false">取消</button>
<button class="action-btn call" @click="makePhoneCall">立即拨打</button> -->
<view class="v12-font-28 v12-primary-text v12-primary-border v12-radius-100 v12-primary-text v12-px-2" @click="contactMerchant('phone')">立即拨打</view><view class="v12-font-28 v12-dark-border v12-radius-100 v12-px-2" @click="showPhonePopup = false">取消</view>
</view>
<view class="phone-actions v12-align-center" v-if="title === '商家微信'">
<!-- <button class="action-btn cancel" @click="showPhonePopup = false">取消</button>
<button class="action-btn call" @click="makePhoneCall">立即拨打</button> -->
<view class="v12-font-28 v12-primary-text v12-primary-border v12-radius-100 v12-px-2" @click="contactMerchant('wechat')">立即复制</view><view class="v12-font-28 v12-dark-border v12-radius-100 v12-px-2" @click="showPhonePopup = false">取消</view>
</view>
<view class="phone-actions v12-align-center" v-if="title === '平台电话'" >
<!-- <button class="action-btn cancel" @click="showPhonePopup = false">取消</button>
<button class="action-btn call" @click="makePhoneCall">立即拨打</button> -->
<view v-if="title === '平台电话'" class="v12-font-28 v12-primary-text v12-primary-border v12-radius-100 v12-px-2" @click="contactMerchant('company')">立即拨打</view><view class="v12-font-28 v12-dark-border v12-radius-100 v12-px-2" @click="showPhonePopup = false">取消</view>
</view>
</view>
</u-popup>
<u-popup :show="showExperienceCouponPopup" bgColor="transparent" mode="center" round="10" :safe-area-inset-bottom="false">
<image class="" :src="webUrl + '/tiyan.png'" mode="widthFix" lazy-load="false">
</image>
<!-- <view class="experience-popup">
<view class="experience-title">体验券提醒</view>
<view class="experience-content">您有可领取的体验券可前往体验券页面领取</view>
</view> -->
<view class="experience-actions v12-align-center">
<view class="v12-font-28 v12-dark-border v12-radius-100 v12-px-2 close-btn" @click="handleCloseExperienceCouponPopup">暂不领取</view>
<view class="v12-font-28 v12-primary-text v12-primary-border v12-radius-100 v12-px-2 go-btn" @click="goExperienceCoupon">去领取体验券</view>
</view>
</u-popup>
<!-- 联系人信息 -->
<view class="contact-section" v-if="orderInfo.realName && orderInfo.userPhone">
<view class="section-title v12-font-28 v12-font-bold">联系人信息</view>
<u-divider></u-divider>
<view class="info-item">
<text class="label">姓名</text>
<text class="value" style="text-align: left; font-weight: 500">{{orderInfo.realName}}</text>
</view>
<view class="info-item">
<text class="label">联系电话</text>
<text class="value" style="text-align: left; font-weight: 500;">{{orderInfo.userPhone}}</text>
</view>
<view class="info-item">
<text class="label">入住时间</text>
<text class="value" style="text-align: left; font-weight: 500;">{{formatDate(orderInfo.travelGroupOrderInfo.orderStartDate)}}~{{formatDate(orderInfo.travelGroupOrderInfo.orderEndDate)}}</text>
</view>
</view>
<!-- 订单信息 -->
<view class="order-section">
<view class="info-item">
<text class="label">订单编号</text>
<text class="value">{{orderInfo.orderId}}</text>
<text class="copy-btn v12-primary-text v12-primary-border v12-ml-1 v12-px-1" @click="copyOrderNo">复制</text>
</view>
<view class="info-item">
<text class="label">下单时间</text>
<text class="value">{{orderInfo.createTime}}</text>
</view>
<view class="info-item">
<text class="label">订单类型</text>
<text class="value">{{ orderInfo.isGiftCardReceive > 0 || orderInfo.isGiftCardSend > 0 ? '礼包订单' : '其他类型'}}</text>
</view>
<view class="info-item">
<text class="label">支付状态</text>
<text class="value">{{ orderInfo.paid ? '已支付' : '未支付'}}</text>
</view>
<view class="info-item">
<text class="label">支付方式</text>
<text class="value">{{orderInfo.payTypeName}}</text>
</view>
</view>
<view
class="gift-wrap"
v-if="orderInfo.giftCardInfo !== null"
>
<view class="v12-justify-between v12-align-center">
<view class="v12-font-28 v12-font-bold v12-align-center">
<u-icon :name="webUrl + '/icon/gift-primary.png'" size="24"></u-icon>
{{ `已领取${orderInfo.giftCardInfo.receiveNum}/${orderInfo.giftCardInfo.giftNum}份礼包` }}
</view>
<view
v-if="orderInfo.giftCardInfo.refundNum > 0"
class="v12-font-bold v12-primary-text v12-font-24"
>{{ `剩余${orderInfo.giftCardInfo.refundNum}份已退回` }}</view>
</view>
<view
v-for="(receive, index) in orderInfo.giftCardInfo.receiveInfo"
:key="index"
class="v12-mt-3 v12-justify-between v12-align-center"
>
<view class="v12-font-24">{{ receive.userNickname }}</view>
<view class="v12-font-24">{{ receive.receiveStatus ? '已领取' : '未领取' }}</view>
</view>
</view>
<!-- 底部按钮 -->
<view class="bottom-buttons">
<button class="btn customer-service" @click="showPhoneDialog('company')">
<view>
<u-icon name="account" size="20"></u-icon>
</view>
<view>平台客服</view>
</button>
<view class="v12-align-center" v-if="orderInfo._status && ['1','2'].includes(orderInfo._status._type)">
<button class="btn v12-primary-border v12-primary-text modify-time" @click="modifyStayTime">修改入住时间</button>
<button class="btn v12-primary-border v12-primary-text refund" @click="applyRefund">申请退款</button>
</view>
<view class="v12-align-center" v-if="orderInfo._status && ['3'].includes(orderInfo._status._type)">
<button class="btn v12-primary-border v12-primary-text" @click="goEvaluate">立即评价</button>
</view>
<view class="v12-align-center" v-if="!orderInfo._status && ['1','2'].includes(orderInfo._status._type)">
<button class="btn v12-dark-border v12-dark-text modify-time" @click="showPhoneDialog('phone')">联系商家</button>
</view>
</view>
<!-- <Calendar
ref="calendar"
:minDay="orderInfo.minBookingDays"
@dateSelected="handleDateSelected">
</Calendar> -->
<DateRangePicker
ref="dateRangePicker"
:originDate="orderInfo.travelGroupOrderInfo.orderStartDate"
v-model="dateRange"
:show="showDatePicker"
:minBookingDays="orderInfo.minBookingDays"
:travelGroupProductId="orderInfo.travelGroupOrderInfo.travelGroupProduct.id"
@update:show="showDatePicker = false"
@input="handleDateSelected"
>
</DateRangePicker>
</view>
</template>
<script>
import { fetchSojoumOrderDetail,sojoumOrderCheckInTime, sojoumOrderCalendar } from "@/api/sojoumOrder";
import { checkExperienceCoupon } from '@/api/product'
import DateRangePicker from '@/components/DateRangePicker/DateRangePicker.vue'
export default {
components: {
DateRangePicker
},
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
dateRange: [null, null],
showDatePicker: false,
key: '',
popContent: '',
title: '',
orderInfo: {
travelGroupOrderInfo: {},
_status: {},
merchantPhone: '' // 添加商家电话字段
},
showPhonePopup: false, // 控制电话弹窗显示
isView: 0,
showExperienceCouponPopup: false,
experienceCouponId: null,
experienceCouponPopupDismissed: false,
orderStatusTimer: null
}
},
onLoad(otps) {
this.key = otps.id;
this.isView = otps.isView || 0;
this.experienceCouponPopupDismissed = false;
},
onShow() {
this.getSojoumOrderDetail();
},
onHide() {
this.stopOrderStatusPolling();
},
onUnload() {
uni.setStorageSync('needRefreshMyOrderList', 1)
this.stopOrderStatusPolling();
},
methods: {
handleDateRangeChange(dates) {
// if (dates && dates.length === 2) {
// [this.form.checkInDate, this.form.checkOutDate] = dates
// }
const params = {
orderId: this.key,
orderStartDate: dates[0],
orderEndDate: dates[1]
}
uni.showLoading({
title: '加载中...',
mask: true,
})
sojoumOrderCheckInTime(params).then(res => {
if (res.status === 200) {
uni.showToast({
title: '入住时间修改成功',
icon: 'success'
})
this.getSojoumOrderDetail();
}
}).finally(() => {
uni.hideLoading();
})
},
getDaysCount() {
// 根据开始日期和结束日期计算天数
const startDate = new Date(this.orderInfo.travelGroupOrderInfo.orderStartDate);
const endDate = new Date(this.orderInfo.travelGroupOrderInfo.orderEndDate);
const timeDiff = endDate - startDate;
const daysCount = Math.ceil(timeDiff / (1000 * 60 * 60 * 24));
return daysCount + 1;
},
handleDateSelected(dateRange) {
const params = {
orderId: this.key,
orderStartDate: dateRange[0],
orderEndDate: dateRange[1]
}
uni.showLoading({
title: '加载中...',
mask: true,
})
sojoumOrderCheckInTime(params).then(res => {
if (res.status === 200) {
uni.showToast({
title: '入住时间修改成功',
icon: 'success'
})
this.getSojoumOrderDetail();
}
uni.hideLoading();
}).finally(() => {
})
},
getMonthDay() {
const currentMonth = new Date().toISOString().slice(0, 7)
sojoumOrderCalendar({
travelGroupProductId: this.orderInfo.travelGroupOrderInfo.travelGroupProduct.id,
month: currentMonth
}).then(res => {
if (res.status === 200) {
this.$refs.calendar.showCalendar(res.data);
}
})
},
/**
* 获取旅居团购订单详情
*/
async getSojoumOrderDetail(options = {}) {
const { showLoading = true, checkCoupon = true } = options;
const params = {
key: this.key
}
if (showLoading) {
uni.showLoading({
title: '加载中...',
mask: true,
})
}
try {
const res = await fetchSojoumOrderDetail(params);
if (res.status === 200) {
this.orderInfo = res.data;
this.orderInfo.minBookingDays = this.getDaysCount();
this.startOrderStatusPolling();
if (checkCoupon) {
this.checkExperienceCouponStatus();
}
}
} finally {
if (showLoading) {
uni.hideLoading();
}
}
},
shouldPollOrderStatus() {
const statusType = this.orderInfo && this.orderInfo._status && this.orderInfo._status._type;
// 入住/核销成功后不再轮询
return !['3', '4'].includes(String(statusType || ''));
},
startOrderStatusPolling() {
if (!this.shouldPollOrderStatus()) {
this.stopOrderStatusPolling();
return;
}
if (this.orderStatusTimer) {
return;
}
this.orderStatusTimer = setInterval(() => {
this.getSojoumOrderDetail({ showLoading: false });
}, 5000);
},
stopOrderStatusPolling() {
if (this.orderStatusTimer) {
clearInterval(this.orderStatusTimer);
this.orderStatusTimer = null;
}
},
async checkExperienceCouponStatus() {
const orderId = this.orderInfo && this.orderInfo.orderId ? this.orderInfo.orderId : this.key;
if (!orderId) {
return;
}
try {
const res = await checkExperienceCoupon({ orderId });
if (!res || res.status !== 200) {
return;
}
const data = res.data || {};
const hasExperienceCoupon = Number(data.hasExperienceCoupon || 0);
const showPopup = Number(data.showPopup || 0);
if (!hasExperienceCoupon) {
return;
}
if (!showPopup) {
this.showExperienceCouponPopup = false;
return;
}
const couponId = data.couponId || null;
if (
this.experienceCouponPopupDismissed &&
couponId &&
couponId === this.experienceCouponId
) {
return;
}
this.experienceCouponId = couponId;
this.experienceCouponPopupDismissed = false;
this.showExperienceCouponPopup = true;
} catch (e) {
}
},
handleCloseExperienceCouponPopup() {
this.showExperienceCouponPopup = false;
this.experienceCouponPopupDismissed = true;
},
/**
* 格式化日期
* @param {string} dateStr - 格式为 yyyy-MM-dd 的日期字符串
* @returns {string} - 格式为 yyyy年MM月dd日 的日期字符串
*/
formatDate(dateStr) {
if (!dateStr) return '';
const [year, month, day] = dateStr.split('-');
return `${year}${month}${day}日`;
},
/**
* 复制订单编号
*/
copyOrderNo() {
uni.setClipboardData({
data: this.orderInfo.orderId,
success: () => {
uni.showToast({
title: '复制成功',
icon: 'success'
})
}
})
},
contactMerchant(type) {
if (type === 'phone') {
uni.makePhoneCall({
phoneNumber: this.orderInfo.merPhone,
})
} else if (type === 'company') {
uni.makePhoneCall({
phoneNumber: this.orderInfo.companyTel,
})
}
else if (type === 'wechat') {
uni.setClipboardData({
data: this.orderInfo.merWechat,
success: () => {
console.log('//微信号已复制/');
uni.showToast({
title: '微信号已复制',
icon: 'success'
})
}
})
}
},
contactCustomerService() {
// 这里可以添加跳转到客服页面或打开客服会话的逻辑
uni.makePhoneCall({
phoneNumber: this.orderInfo.merPhone,
fail: () => {
uni.showToast({
title: '拨打失败',
icon: 'none'
})
}
})
},
modifyStayTime() {
// 这里可以添加修改入住时间的逻辑,比如打开日期选择器
this.showDatePicker = true;
},
applyRefund() {
// 这里可以添加申请退款的逻辑,比如跳转到退款页面
uni.navigateTo({
url: '/pkg_product/views/sojoumOrderRefund?id=' + this.key
})
},
goEvaluate() {
const orderId = this.orderInfo.orderId
if (!orderId) {
uni.showToast({
title: '订单信息错误',
icon: 'none'
})
return
}
this.$yrouter.push({
path: '/pages/shop/GoodsEvaluate/index',
query: {
id: orderId,
isTravelGroup: 1
}
})
},
goExperienceCoupon() {
this.showExperienceCouponPopup = false;
this.experienceCouponPopupDismissed = false;
const couponId = this.experienceCouponId;
let url = '/pkg_product/views/experienceCoupon';
if (couponId) {
url += `?couponId=${couponId}`;
}
uni.navigateTo({
url
})
},
// 显示电话弹窗
showPhoneDialog(type) {
if (!this.orderInfo.merPhone && type === 'phone') {
uni.showToast({
title: '暂无商家电话',
icon: 'none'
});
return;
}
if (type === 'phone') {
this.title = '商家电话';
this.popContent = this.orderInfo.merPhone;
} else if (type === 'wechat') {
this.title = '商家微信';
this.popContent = this.orderInfo.merWechat;
} else if (type === 'company') {
this.title = '平台电话';
this.popContent = this.orderInfo.companyTel;
}
this.showPhonePopup = true;
},
// 拨打电话
makePhoneCall() {
if (!this.orderInfo.merchantPhone) return;
uni.makePhoneCall({
phoneNumber: this.orderInfo.merchantPhone,
success: () => {
this.showPhonePopup = false;
},
fail: () => {
uni.showToast({
title: '拨号失败',
icon: 'none'
});
}
});
},
}
}
</script>
<style lang="scss" scoped>
.close-btn{
width: 274rpx;
margin-right: 30rpx;
height: 52rpx;
opacity: 0;
}
.go-btn{
height: 52rpx;
margin-right: 10rpx;
opacity: 0;
}
.status-section,.product-section,.verify-section {
border-radius: 20rpx;
}
.order-details {
min-height: 100vh;
background-color: #f5f5f5;
padding-bottom: 140rpx !important;
.status-section {
background-color: #fff;
padding: 40rpx 30rpx;
.status-text {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
}
.status-desc {
font-size: 28rpx;
color: #666;
}
}
.product-section {
background-color: #fff;
margin-top: 20rpx;
padding: 30rpx;
display: flex;
.product-image {
width: 180rpx;
height: 180rpx;
border-radius: 12rpx;
}
.product-info {
flex: 1;
margin-left: 20rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
.product-title {
font-size: 28rpx;
color: #333;
line-height: 1.4;
}
.product-price {
margin-top: 20rpx;
color: #666;
.price {
color: #ff4d4f;
font-size: 32rpx;
font-weight: bold;
}
}
}
}
.verify-section {
background-color: #fff;
margin-top: 20rpx;
padding: 30rpx;
text-align: center;
.verify-title {
font-size: 32rpx;
color: #333;
margin-bottom: 30rpx;
}
.qr-code {
width: 300rpx;
height: 300rpx;
margin: 0 auto;
}
.contact-buttons {
display: flex;
justify-content: center;
margin-top: 30rpx;
.contact-btn {
margin: 0 20rpx;
padding: 0 20rpx;
border-radius: 40rpx;
font-size: 28rpx;
height: 60rpx;
line-height: 60rpx;
display: flex;
align-items: center;
&.merchant-phone {
background-color: #fff;
border: 2rpx solid #333;
color: #333;
}
&.merchant-wechat {
background-color: #fff;
border: 2rpx solid #333;
color: #333;
}
}
}
}
.experience-popup {
padding: 40rpx 50rpx;
border-radius: 20rpx;
background-color: #fff;
width: 560rpx;
box-sizing: border-box;
}
.experience-title {
font-size: 32rpx;
font-weight: bold;
text-align: center;
margin-bottom: 20rpx;
color: #333;
}
.experience-content {
font-size: 28rpx;
color: #666;
text-align: center;
margin-bottom: 40rpx;
}
.experience-actions {
position: absolute;
bottom: 60rpx;
width: 100%;
justify-content: center;
display: flex;
}
.contact-section,
.order-section {
background-color: #fff;
margin-top: 20rpx;
padding: 30rpx;
border-radius: 20rpx;
.section-title {
font-size: 32rpx;
color: #333;
margin-bottom: 20rpx;
}
.info-item {
display: flex;
align-items: center;
margin-bottom: 20rpx;
font-size: 26rpx;
.label {
color: #333;
width: 160rpx;
}
.value {
color: #333;
font-weight: 500;
flex: 1;
text-align: right;
font-size: 24rpx;
}
.copy-btn {
color: #1890ff;
border-radius: 40rpx;
}
}
}
.bottom-buttons {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: #fff;
padding: 26rpx 30rpx;
display: flex;
justify-content: space-between;
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
.btn {
margin: 0 10rpx;
height: 60rpx;
line-height: 60rpx;
text-align: center;
border-radius: 40rpx;
font-size: 26rpx;
width: fit-content;
&.customer-service {
background-color: #fff;
border: 2rpx solid #333;
color: #333;
display: flex;
align-items: center;
}
&.modify-time {
background-color: #fff;
}
&.refund {
background-color: #fff;
}
}
}
}
.phone-popup {
width: 400rpx;
background-color: #fff;
border-radius: 20rpx;
padding: 40rpx;
.phone-title {
font-size: 32rpx;
color: #333;
text-align: center;
margin-bottom: 30rpx;
font-weight: bold;
}
.phone-number {
font-size: 32rpx;
color: #333;
text-align: center;
margin-bottom: 40rpx;
}
.phone-actions {
display: flex;
justify-content: space-around;
gap: 20rpx;
.action-btn {
flex: 1;
height: 80rpx;
line-height: 80rpx;
text-align: center;
border-radius: 40rpx;
font-size: 28rpx;
&.cancel {
background-color: #f5f5f5;
color: #666;
}
&.call {
background-color: var(--v12-color-primary);
color: #fff;
}
}
}
}
.gift-wrap{
background: #fff;
border-radius: 20rpx;
margin-top: 30rpx;
padding: 30rpx;
}
</style>