REFACTOR:礼品功能重构

This commit is contained in:
LinCyJang
2025-10-24 01:31:50 +08:00
parent 705d64d238
commit d1bbea6e9b
8 changed files with 986 additions and 58 deletions
+22
View File
@@ -79,3 +79,25 @@ export function createGroupBuyGift(data) {
export function createSojoumGroupBuyGift(key, data) {
return request.post("/travel/giftCardOrder/create/" + key, data);
}
/**
* 旅居团购礼品卡订单详情
* @param {*} params
* @returns
*/
export function fetchSojoumGroupBuyGiftDetail(params) {
return request.get("/travel/giftCard/info",params, {
login: true
})
}
/**
* 领取旅居团购礼品卡
* @param {*} params
* @returns
*/
export function receiveSojoumGroupBuyGift(params) {
return request.post("/travel/giftCard/receive", params, {
login: true
})
}
@@ -0,0 +1,569 @@
<template>
<view class="date-range-picker">
<u-popup :show="show" @close="handleClose" mode="center" round="16" closeable>
<view class="picker-container">
<view class="picker-header">
<text class="title">选择日期范围</text>
</view>
<view class="calendar">
<view class="calendar-header">
<view class="month-nav">
<text class="nav-btn" @click="changeMonth(-1)"></text>
<text class="month-text">{{ currentYear }}{{ currentMonth + 1 }}</text>
<text class="nav-btn" @click="changeMonth(1)"></text>
</view>
<view class="weekdays">
<text v-for="day in ['日', '一', '二', '三', '四', '五', '六']" :key="day" class="weekday">
{{ day }}
</text>
</view>
</view>
<view class="days">
<view
v-for="(day, index) in calendarDays"
:key="index"
class="day"
:class="{
'empty': !day,
'selected': isSelected(day),
'in-range': isInRange(day),
'start-date': isStartDate(day),
'end-date': isEndDate(day),
'disabled': isDisabled(day),
'booked': getDateStatus(day) === 1,
'unavailable': getDateStatus(day) === 2,
'available': getDateStatus(day) === 0
}"
@click="selectDate(day)"
>
<text>{{ day || '' }}</text>
<view class="v12-font-20" v-if="day && getDateStatus(day) !== null">{{ getDateStatus(day) }}</view>
</view>
</view>
</view>
<view class="picker-footer">
<button class="btn btn-confirm" @click="confirmSelect">确定</button>
</view>
</view>
</u-popup>
</view>
</template>
<script>
import { sojoumOrderCalendar } from "@/api/sojoumOrder";
export default {
name: 'DateRangePicker',
props: {
show: {
type: Boolean,
default: false
},
value: {
type: Array,
default: () => [null, null]
},
minDate: {
type: [String, Date],
default: null
},
maxDate: {
type: [String, Date],
default: null
},
format: {
type: String,
default: 'YYYY-MM-DD'
},
travelGroupProductId: {
type: String,
default: ''
},
minBookingDays: {
type: Number,
default: 0
},
},
data() {
return {
currentYear: new Date().getFullYear(),
currentMonth: new Date().getMonth(),
startDate: null,
endDate: null,
activeCalendar: 'start', // 'start' or 'end'
tempStartDate: null,
tempEndDate: null,
dateStatusMap: {} // 存储日期状态
}
},
computed: {
calendarDays() {
const days = []
const firstDay = new Date(this.currentYear, this.currentMonth, 1)
const lastDay = new Date(this.currentYear, this.currentMonth + 1, 0)
// 填充月初空白天数
for (let i = 0; i < firstDay.getDay(); i++) {
days.push(null)
}
// 填充当月天数
for (let i = 1; i <= lastDay.getDate(); i++) {
days.push(i)
}
// 填充月末空白天数
const remainingDays = 42 - days.length // 保持6行固定高度
for (let i = 0; i < remainingDays; i++) {
days.push(null)
}
return days
}
},
watch: {
show(newVal) {
if (newVal) {
this.initDates()
this.getDays()
}
},
currentMonth() {
this.getDays()
},
currentYear() {
this.getDays()
},
value: {
handler(newVal) {
if (newVal && newVal.length === 2) {
this.startDate = newVal[0] ? new Date(newVal[0]) : null
this.endDate = newVal[1] ? new Date(newVal[1]) : null
this.tempStartDate = this.startDate
this.tempEndDate = this.endDate
}
},
immediate: true
}
},
methods: {
getDays(){
uni.showLoading({
title: '加载中...',
mask: true,
})
sojoumOrderCalendar({
travelGroupProductId: this.travelGroupProductId,
month: `${this.currentYear}-${String(this.currentMonth + 1).padStart(2, '0')}`
}).then(res => {
if (res.data) {
// 更新日期状态映射
this.dateStatusMap = {}
res.data.forEach(day => {
// inventoryStatus int 状态 (0:可预约, 1:已被预约, 2:不可预约)
this.dateStatusMap[day.date] = day.inventoryStatus === 0 ? '可预约' : day.inventoryStatus === 1 ? '已被预约' : '不可预约'
})
}
}).finally(() => {
uni.hideLoading()
})
},
getDateStatus(day) {
if (!day) return null
const date = this.formatDate(this.getDateFromDay(day))
return this.dateStatusMap[date]
},
isDisabled(day) {
if (!day) return true
const date = this.getDateFromDay(day)
// 禁用过去的日期(今天之前的日期)
const today = new Date()
today.setHours(0, 0, 0, 0)
if (date < today) return true
// 检查最小和最大日期限制
if (this.minDate && date < new Date(this.minDate)) return true
if (this.maxDate && date > new Date(this.maxDate)) return true
// 检查预约状态
const status = this.getDateStatus(day)
// 只允许选择可预约的日期(状态为"可预约"),其他状态都禁用
return status !== '可预约'
},
initDates() {
this.tempStartDate = this.startDate
this.tempEndDate = this.endDate
if (this.startDate) {
this.currentYear = this.startDate.getFullYear()
this.currentMonth = this.startDate.getMonth()
} else {
const now = new Date()
this.currentYear = now.getFullYear()
this.currentMonth = now.getMonth()
}
},
changeMonth(delta) {
let newMonth = this.currentMonth + delta
if (newMonth < 0) {
this.currentYear--
newMonth = 11
} else if (newMonth > 11) {
this.currentYear++
newMonth = 0
}
this.currentMonth = newMonth
},
formatDate(date) {
if (!date) return ''
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
},
getDateFromDay(day) {
return day ? new Date(this.currentYear, this.currentMonth, day) : null
},
// isDisabled(day) {
// if (!day) return true
// const date = this.getDateFromDay(day)
// // 禁用过去的日期(今天之前的日期)
// const today = new Date()
// today.setHours(0, 0, 0, 0)
// if (date < today) return true
// // 检查最小和最大日期限制
// if (this.minDate && date < new Date(this.minDate)) return true
// if (this.maxDate && date > new Date(this.maxDate)) return true
// return false
// },
isSelected(day) {
if (!day) return false
const date = this.getDateFromDay(day)
return this.isStartDate(day) || this.isEndDate(day)
},
isStartDate(day) {
if (!day || !this.tempStartDate) return false
const date = this.getDateFromDay(day)
return date.getTime() === this.tempStartDate.getTime()
},
isEndDate(day) {
if (!day || !this.tempEndDate) return false
const date = this.getDateFromDay(day)
return date.getTime() === this.tempEndDate.getTime()
},
isInRange(day) {
if (!day || !this.tempStartDate || !this.tempEndDate) return false
const date = this.getDateFromDay(day)
return date > this.tempStartDate && date < this.tempEndDate
},
selectDate(day) {
if (!day || this.isDisabled(day)) return
const selectedDate = this.getDateFromDay(day)
// 如果点击已选择的日期,则取消选择
if (this.tempStartDate && selectedDate.getTime() === this.tempStartDate.getTime()) {
this.tempStartDate = null
this.tempEndDate = null
this.activeCalendar = 'start'
return
}
if (this.tempEndDate && selectedDate.getTime() === this.tempEndDate.getTime()) {
this.tempEndDate = null
return
}
if (this.activeCalendar === 'start') {
if (this.tempEndDate && selectedDate > this.tempEndDate) {
// 如果选择的开始日期大于结束日期,清空结束日期
this.tempEndDate = null
}
this.tempStartDate = selectedDate
this.activeCalendar = 'end'
} else {
if (selectedDate < this.tempStartDate) {
// 如果选择的结束日期小于开始日期,将其设为开始日期
this.tempStartDate = selectedDate
} else {
this.tempEndDate = selectedDate
}
}
},
clearDates() {
this.tempStartDate = null
this.tempEndDate = null
this.activeCalendar = 'start'
},
confirmSelect() {
// 验证选择的日期数量
if (!this.tempStartDate || !this.tempEndDate) {
uni.showToast({
title: '请选择起始和结束日期',
icon: 'none'
})
return
}
// 计算选择的天数
const daysDiff = Math.floor((this.tempEndDate - this.tempStartDate) / (1000 * 60 * 60 * 24)) + 1
// 必须要选够天数
if (daysDiff !== this.minBookingDays) {
uni.showToast({
title: `请选择${this.minBookingDays}`,
icon: 'none'
})
return
}
// 验证选择的日期范围内是否包含禁用日期
const currentDate = new Date(this.tempStartDate)
while (currentDate <= this.tempEndDate) {
const day = currentDate.getDate()
if (this.isDisabled(day)) {
uni.showToast({
title: '所选日期范围包含不可预约日期,请重新选择',
icon: 'none'
})
return
}
currentDate.setDate(currentDate.getDate() + 1)
}
// 验证通过,更新日期并关闭弹窗
this.startDate = this.tempStartDate
this.endDate = this.tempEndDate
this.$emit('input', [
this.startDate ? this.formatDate(this.startDate) : null,
this.endDate ? this.formatDate(this.endDate) : null
])
this.handleClose()
},
handleClose() {
this.$emit('update:show', false)
this.$emit('close')
}
}
}
</script>
<style lang="scss" scoped>
.date-range-picker {
.picker-container {
width: 690rpx;
background: #FFFFFF;
border-radius: 24rpx;
padding: 30rpx;
box-sizing: border-box;
}
.picker-header {
text-align: center;
margin-bottom: 30rpx;
.title {
font-size: 32rpx;
font-weight: bold;
color: #333333;
}
}
.date-display {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 30rpx;
padding: 20rpx;
background: #F8F8F8;
border-radius: 12rpx;
.date-input {
flex: 1;
.label {
font-size: 24rpx;
color: #999999;
margin-bottom: 8rpx;
display: block;
}
.value {
font-size: 28rpx;
color: #333333;
&.placeholder {
color: #999999;
}
}
}
.separator {
margin: 0 20rpx;
color: #999999;
font-size: 28rpx;
}
}
.calendar {
.calendar-header {
margin-bottom: 20rpx;
.month-nav {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20rpx;
padding: 0 20rpx;
.month-text {
font-size: 28rpx;
color: #333333;
font-weight: bold;
}
.nav-btn {
padding: 10rpx 20rpx;
color: #666666;
font-size: 32rpx;
}
}
.weekdays {
display: flex;
justify-content: space-around;
.weekday {
width: 14.28%;
text-align: center;
font-size: 24rpx;
color: #999999;
}
}
}
.days {
display: flex;
flex-wrap: wrap;
.day {
width: 14.28%;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
color: #333333;
position: relative;
flex-direction: column;
&:not(.selected):not(.disabled) {
color: #4B97EB;
}
.status-dot {
width: 8rpx;
height: 8rpx;
border-radius: 50%;
margin-top: 4rpx;
}
&.empty {
pointer-events: none;
}
&.disabled {
color: #CCCCCC;
pointer-events: none;
}
&.selected {
background: #C52733;
color: #FFFFFF;
.status-dot {
background: #FFFFFF;
}
}
&.in-range {
background: rgba(197, 39, 51, 0.1);
}
&.start-date {
border-top-left-radius: 8rpx;
border-bottom-left-radius: 8rpx;
}
&.end-date {
border-top-right-radius: 8rpx;
border-bottom-right-radius: 8rpx;
}
&.available .status-dot {
background: #4CAF50;
}
&.booked .status-dot {
background: #FF9800;
}
&.unavailable .status-dot {
background: #F44336;
}
}
}
}
.picker-footer {
margin-top: 30rpx;
display: flex;
justify-content: space-between;
padding: 0 20rpx;
.btn {
width: 100%;
height: 80rpx;
border-radius: 40rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
&.btn-clear {
background: #F8F8F8;
color: #999999;
}
&.btn-confirm {
background: #C52733;
color: #FFFFFF;
}
}
}
}
</style>
+3 -2
View File
@@ -631,7 +631,8 @@ export default {
this.$yrouter.push({
path: "/pkg_product/views/sojoumOrderDetails",
query: {
id: order.orderId
id: order.orderId,
isView: 1
}
});
}
@@ -763,7 +764,7 @@ export default {
status = "待付款"
break;
case 1:
status = order.isTravelGroup === 1 ? "待使用" : "待发货付款"
status = order.isTravelGroup === 1 ? "待使用" : "待发货"
break;
case 2:
status = order.isTravelGroup === 1 ? "待使用" : "待收货"
+9 -4
View File
@@ -69,7 +69,7 @@
</u-popup>
<!-- 联系人信息 -->
<view class="contact-section">
<view class="contact-section" v-if="isView === 0">
<view class="section-title v12-font-28 v12-font-bold">联系人信息</view>
<u-divider></u-divider>
<view class="info-item">
@@ -135,7 +135,7 @@
<!-- 底部按钮 -->
<view class="bottom-buttons">
<button class="btn customer-service" @click="showPhoneDialog('phone')">平台客服</button>
<button class="btn customer-service" @click="showPhoneDialog('company')">平台客服</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>
@@ -170,11 +170,13 @@ export default {
_status: {},
merchantPhone: '' // 添加商家电话字段
},
showPhonePopup: false // 控制电话弹窗显示
showPhonePopup: false, // 控制电话弹窗显示
isView: 0
}
},
onLoad(otps) {
this.key = otps.id;
this.isView = otps.isView || 0;
this.getSojoumOrderDetail();
},
methods: {
@@ -324,7 +326,7 @@ export default {
},
// 显示电话弹窗
showPhoneDialog(type) {
if (!this.orderInfo.merPhone) {
if (!this.orderInfo.merPhone && type === 'phone') {
uni.showToast({
title: '暂无商家电话',
icon: 'none'
@@ -337,6 +339,9 @@ export default {
} 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;
},
@@ -0,0 +1,213 @@
<template>
<u-popup :show="show" @close="close" mode="center" round="16" closeable>
<view class="gift-address-form">
<view class="form-title">填写您的信息</view>
<view class="form-content">
<view class="form-item">
<text class="label">姓名</text>
<input
type="text"
v-model="form.realName"
placeholder="请填写姓名"
class="input"
/>
</view>
<view class="form-item">
<text class="label">联系电话</text>
<input
type="number"
v-model="form.phone"
placeholder="请填写联系电话"
maxlength="11"
class="input"
/>
</view>
<view class="form-item">
<text class="label">入住时间</text>
<view class="date-picker" @click="showDatePicker = true">
<text v-if="form.checkInDate && form.checkOutDate">
{{ form.checkInDate }} {{ form.checkOutDate }}
</text>
<text v-else class="placeholder">请选择入住时间</text>
<text class="calendar-icon"></text>
</view>
</view>
</view>
<date-range-picker
v-model="dateRange"
:show="showDatePicker"
:travelGroupProductId="mid"
:minBookingDays="minBookingDays"
@update:show="showDatePicker = false"
@input="handleDateRangeChange"
/>
<view class="form-footer">
<button class="submit-btn" @click="submitForm">点击确定</button>
</view>
</view>
</u-popup>
</template>
<script>
import DateRangePicker from '@/components/DateRangePicker/DateRangePicker.vue'
export default {
name: 'GiftAddressForm',
components: {
DateRangePicker
},
props: {
show: {
type: Boolean,
default: false
},
unavailableDates: {
type: Array,
default: () => []
},
mid: {
type: String,
default: ''
},
minBookingDays: {
type: Number,
default: 0
}
},
data() {
return {
form: {
realName: '',
phone: '',
checkInDate: '',
checkOutDate: ''
},
showDatePicker: false,
dateRange: [null, null]
}
},
methods: {
close() {
this.$emit('close')
this.showDatePicker = false
},
handleDateRangeChange(dates) {
if (dates && dates.length === 2) {
[this.form.checkInDate, this.form.checkOutDate] = dates
}
},
submitForm() {
if (!this.form.realName) {
uni.showToast({
title: '请填写姓名',
icon: 'none'
})
return
}
if (!this.form.phone || !/^1\d{10}$/.test(this.form.phone)) {
uni.showToast({
title: '请填写正确的手机号',
icon: 'none'
})
return
}
if (!this.form.checkInDate || !this.form.checkOutDate) {
uni.showToast({
title: '请选择入住时间',
icon: 'none'
})
return
}
this.$emit('submit', this.form)
this.close()
}
}
}
</script>
<style lang="scss" scoped>
.gift-address-form {
width: 650rpx;
background: #FFFFFF;
border-radius: 32rpx;
padding: 40rpx;
box-sizing: border-box;
.form-title {
font-size: 32rpx;
font-weight: bold;
text-align: center;
margin-bottom: 40rpx;
}
.form-content {
.form-item {
margin-bottom: 30rpx;
.label {
font-size: 28rpx;
color: #333333;
margin-bottom: 16rpx;
display: block;
}
.input {
width: 100%;
height: 80rpx;
background: #F8F8F8;
border-radius: 12rpx;
padding: 0 24rpx;
font-size: 28rpx;
}
.date-picker {
height: 80rpx;
background: #F8F8F8;
border-radius: 12rpx;
padding: 0 24rpx;
display: flex;
align-items: center;
justify-content: space-between;
.placeholder {
color: #999999;
font-size: 28rpx;
}
.calendar-icon {
font-size: 32rpx;
}
}
}
}
.form-footer {
margin-top: 40rpx;
.submit-btn {
width: 100%;
height: 88rpx;
background: #C52733;
border-radius: 44rpx;
color: #FFFFFF;
font-size: 32rpx;
display: flex;
align-items: center;
justify-content: center;
}
}
}
</style>]]>
+108 -46
View File
@@ -6,7 +6,10 @@
top: card.productImageY*2 + 'rpx',
left: card.productImageX*2 + 'rpx'
}">
<image class="pro-image" :src="card.giftProducts[0].productImage" mode="aspectFit|aspectFill|widthFix" lazy-load="false" @error="" @load="">
<image v-if="!isTravelGroup" class="pro-image" :src="card.giftProducts[0].productImage" mode="aspectFit|aspectFill|widthFix" lazy-load="false">
</image>
<image v-if="isTravelGroup" class="pro-image" :src="card.image" mode="aspectFit|aspectFill|widthFix" lazy-load="false">
</image>
</view>
@@ -18,36 +21,49 @@
</view>
</view>
<view class="blind-box" v-if="card.isBlind">
<u-icon :name="webUrl + '/orderIcon/礼物.png'" size="30" ></u-icon>
<text class="v12-font-30 v12-dark-text v12-font-bold v12-ml-2">您收到一份来自朋友的神秘礼物</text>
</view>
<view class="btn-wrap">
<button v-if="!isReceive && myGift.isCurrentUser !== 1" class="share-btn v12-white-text v12-primary" @click="setAddress(0)">
填写地址并收下
</button>
<button v-if="card.canTransfer !== 0 && !isReceive && myGift.isCurrentUser !== 1" open-type="share" class="share-btn v12-white v12-primary-text v12-d-flex" >
点击转赠给好友
<u-icon :name="webUrl + '/icon/share.png'" ></u-icon>
</button>
</view>
<view v-if="myGift.isCurrentUser === 1 && !card.isBlind" @click="toOrder" style="z-index: 10; display: flex;flex-direction: column;align-items: center;">
<view class="address-btn v12-white-text v12-primary">
您已领取礼包
<view v-if="!isTravelGroup">
<view class="blind-box" v-if="card.isBlind">
<u-icon :name="webUrl + '/orderIcon/礼物.png'" size="30" ></u-icon>
<text class="v12-font-30 v12-dark-text v12-font-bold v12-ml-2">您收到一份来自朋友的神秘礼物</text>
</view>
<view class="info-btn v12-text-center v12-font-32 v12-mt-3">查看礼包详情>></view>
</view>
<view v-if="myGift.isCurrentUser === 1 && card.isBlind" style="z-index: 10; display: flex;flex-direction: column;align-items: center;">
<view style="width: fit-content;" class="address-btn v12-white-text v12-primary" @click="toOrder">
您已领取礼包去看看>>
<view class="btn-wrap">
<button v-if="!isReceive && myGift.isCurrentUser !== 1" class="share-btn v12-white-text v12-primary" @click="setAddress(0)">
填写地址并收下
</button>
<button v-if="card.canTransfer !== 0 && !isReceive && myGift.isCurrentUser !== 1" open-type="share" class="share-btn v12-white v12-primary-text v12-d-flex" >
点击转赠给好友
<u-icon :name="webUrl + '/icon/share.png'" ></u-icon>
</button>
</view>
<view class="info-btn v12-text-center v12-font-32 v12-mt-3" @click.stop="searchGift">我也要送礼</view>
<view v-if="myGift.isCurrentUser === 1 && !card.isBlind" @click="toOrder" style="z-index: 10; display: flex;flex-direction: column;align-items: center;">
<view class="address-btn v12-white-text v12-primary">
您已领取礼包
</view>
<view class="info-btn v12-text-center v12-font-32 v12-mt-3">查看礼包详情>></view>
</view>
<view v-if="myGift.isCurrentUser === 1 && card.isBlind" style="z-index: 10; display: flex;flex-direction: column;align-items: center;">
<view style="width: fit-content;" class="address-btn v12-white-text v12-primary" @click="toOrder">
您已领取礼包去看看>>
</view>
<view class="info-btn v12-text-center v12-font-32 v12-mt-3" @click.stop="searchGift">我也要送礼</view>
</view>
<view v-if="isReceive && myGift.isCurrentUser !== 1" @click="toHome" style="z-index: 10; display: flex;flex-direction: column;align-items: center;">
<view class="address-btn v12-white-text v12-primary">
礼包已被领取
</view>
<view class="info-btn v12-text-center v12-font-32 v12-mt-3" style="z-index: 10">去商城看看>></view>
</view>
</view>
<view v-if="isReceive && myGift.isCurrentUser !== 1" @click="toHome" style="z-index: 10; display: flex;flex-direction: column;align-items: center;">
<view class="address-btn v12-white-text v12-primary">
礼包已被领取
<view v-if="isTravelGroup">
<view class="btn-wrap">
<button class="share-btn v12-white-text v12-primary" @click="setShowAddressForm(true)">
填写地址并收下
</button>
<button open-type="share" class="share-btn v12-white v12-primary-text v12-d-flex" >
点击转赠给好友
<u-icon :name="webUrl + '/icon/share.png'" ></u-icon>
</button>
</view>
<view class="info-btn v12-text-center v12-font-32 v12-mt-3" style="z-index: 10">去商城看看>></view>
</view>
<view class="tips">
<view class="tip-text v12-mr-1" @click="showTips">
@@ -56,26 +72,35 @@
</view>
</view>
<giftTips ref="giftTips" :richText="giftNotice"></giftTips>
<AddressDialog ref="addressDialog" @save="getReceive"></AddressDialog>
<AddressList ref="AddressList" :addressList="address" @save="getReceive"></AddressList>
<GiftAddressForm
ref="giftAddressForm"
:show="showAddressForm"
:unavailableDates="unavailableDates"
:mid="card.travelGroupProduct.id"
:minBookingDays="card.travelGroupProduct.minBookingDays"
@close="closeAddressForm"
@submit="handleAddressSubmit"
/>
</view>
</template>
<script>
import { getGiftCardSendNotice, getGiftCardReceive } from '@/api/gift'
import { getGiftCardSendNotice, getGiftCardReceive, receiveSojoumGroupBuyGift } from '@/api/gift'
import cookie from "@/utils/store/cookie";
import { getAddressList } from '@/api/user'
import giftTips from './giftTips.vue'
import AddressDialog from './AddressDialog.vue'
import AddressList from './AddressList.vue'
import GiftAddressForm from './GiftAddressForm.vue'
export default {
name: 'GiftCard',
components: {
giftTips,
AddressDialog,
AddressList
GiftAddressForm
},
props: {
isTravelGroup: {
type: Boolean,
default: false
},
// 组件属性
card: {
type: Object,
@@ -91,8 +116,9 @@ export default {
webUrl: this.$VUE_APP_RESOURCES_URL,
// 组件数据
giftNotice: '',
address: [],
order: ''
order: '',
showAddressForm: false,
unavailableDates: ['2025-08-13', '2025-08-14', '2025-08-15', '2025-08-16', '2025-08-17', '2025-08-18', '2025-08-19', '2025-08-20', '2025-08-21', '2025-08-22', '2025-08-23']
}
},
computed: {
@@ -128,6 +154,9 @@ export default {
}
},
methods: {
setShowAddressForm(show) {
this.showAddressForm = true
},
searchGift() {
this.$yrouter.push('/pages/shop/GoodsList/index?s=' +'送礼' )
},
@@ -167,16 +196,49 @@ export default {
}).finally(() => {
})
},
setAddress(flag) {
getAddressList().then(res => {
if (res.data.length === 0) {
this.$refs.addressDialog.open()
} else {
this.address = res.data
if(flag) return
this.$refs.AddressList.open()
}
})
setAddress() {
this.showAddressForm = true;
},
closeAddressForm() {
this.showAddressForm = false;
},
handleAddressSubmit(formData) {
console.log(formData);
uni.showLoading({
title: '领取中...',
mask: true
});
// code string 礼品卡code
// realName string 真实姓名
// phone string 手机号码
// orderStartDate string 起始日期(yyyy-MM-dd
// orderEndDate string 结束日期(yyyy-MM-dd
// 调用领取礼包API
receiveSojoumGroupBuyGift({
code: this.card.code,
realName: formData.realName,
phone: formData.phone,
orderStartDate: formData.checkInDate,
orderEndDate: formData.checkOutDate
}).then(res => {
this.showAddressForm = false;
this.order = res.data.orderId;
this.$emit('receive', this.card.code);
uni.showToast({
title: '领取成功',
icon: 'success'
});
}).catch(() => {
uni.showToast({
title: '领取失败,请重试',
icon: 'none'
});
}).finally(() => {
uni.hideLoading();
});
},
async showTips() {
// 获取发礼提示
+31 -4
View File
@@ -1,6 +1,11 @@
<template>
<view v-if="!loading">
<GiftCard v-if="!giftCard.isExpire" :card="giftCard" :addr="giftChooseAddress" @receive="getGiftCard($event)" />
<GiftCard
v-if="!giftCard.isExpire"
:card="giftCard"
:isTravelGroup="isTravelGroup"
:addr="giftChooseAddress"
@receive="getGiftCard($event)" />
<view v-else>
<view class="no-img-wrap">
<view class="wrap-box" >
@@ -15,7 +20,7 @@
<script>
import GiftCard from './components/GiftCard.vue'
import { getGiftCardDetail } from '@/api/gift'
import { getGiftCardDetail, fetchSojoumGroupBuyGiftDetail } from '@/api/gift'
export default {
components: {
GiftCard
@@ -25,11 +30,17 @@ export default {
webUrl: this.$VUE_APP_RESOURCES_URL,
giftCard: {},
giftChooseAddress: {},
loading: false
loading: false,
isTravelGroup: false
}
},
onLoad(opts) {
this.getGiftCard(opts.code)
this.isTravelGroup = opts.isTravelGroup === '1'
if(opts.isTravelGroup === '1') {
this.getSojoumGroupBuyGiftDetail(opts.code)
} else {
this.getGiftCard(opts.code)
}
},
onShow() {
@@ -47,6 +58,22 @@ export default {
}
},
methods: {
/**
* 获取旅居团购礼品卡订单详情
*/
getSojoumGroupBuyGiftDetail(code) {
fetchSojoumGroupBuyGiftDetail({
code: code
}).then(res => {
this.giftCard = res.data || {}
})
},
/**
* 跳转首页
*/
toHome() {
uni.switchTab({
url: '/pages/home/index'
+31 -2
View File
@@ -18,6 +18,7 @@
<view v-if="cateIndex === 0" class="list-body">
<block v-if="sendList.length > 0">
<view
v-for="(item, index) in sendList"
:key="index"
class="gift-item"
@@ -50,6 +51,26 @@
</view>
</view>
</view>
<view v-if="item.isTravelGroup === 1" class="gift-body" @click="giftItemClickHanlde(item)">
<view class="gift-img">
<image
:src="item.giftInfoTravelGroup.travelGroupProductInfo.mainImage"
class="img"
mode="widthFix"
/>
</view>
<view class="gift-good-info">
<view class="name more-t">
{{ item.giftInfoTravelGroup.travelGroupProductInfo.name }}
</view>
<view class="price-wrap">
<view class="price">
<text class="prefix"></text>{{ item.giftInfoTravelGroup.travelGroupProductInfo.price }}
</view>
<view class="num">已领取{{item.giftInfoTravelGroup.receiveNum}}/{{ item.giftInfoTravelGroup.totalNum }}</view>
</view>
</view>
</view>
<view class="gift-bottom">
<view class="gift-txt">
<!-- 赠言{{ item.message || '' }} -->
@@ -412,8 +433,16 @@ export default {
this.$refs.giftTips.showTips = true
},
giftItemClickHanlde(item) {
console.log(item);
if (item.isTravelGroup === 1) {
this.$yrouter.push({
path: '/pkg_product/views/sojoumOrderDetails',
query: {
id: item.orderId,
isView: 1
}
})
return
}
// if (this.cateIndex === 0) return
this.$yrouter.push({
path: '/pages/order/OrderDetails/index',