REFACTOR:礼品功能重构
This commit is contained in:
+22
@@ -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>
|
||||
@@ -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 ? "待使用" : "待收货"
|
||||
|
||||
@@ -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>]]>
|
||||
@@ -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() {
|
||||
// 获取发礼提示
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user