Feat:订单预约日期
This commit is contained in:
@@ -0,0 +1,188 @@
|
|||||||
|
<template>
|
||||||
|
<view class="calendar-wrapper">
|
||||||
|
<u-calendar
|
||||||
|
ref="ucalendar"
|
||||||
|
:show="show"
|
||||||
|
:mode="'range'"
|
||||||
|
:maxRange="999"
|
||||||
|
:defaultDate="defaultDate"
|
||||||
|
:minDate="minDate"
|
||||||
|
:disabledDate="disabledDates"
|
||||||
|
color="#C52733"
|
||||||
|
@confirm="handleDateChange"
|
||||||
|
@close="hideCalendar"
|
||||||
|
:monthNum="1"
|
||||||
|
>
|
||||||
|
<view slot="tooltip" class="calendar-tooltip">
|
||||||
|
{{ tooltipText }}
|
||||||
|
</view>
|
||||||
|
</u-calendar>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Calendar',
|
||||||
|
props: {
|
||||||
|
minDay: {
|
||||||
|
type: Number,
|
||||||
|
default: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
show: false,
|
||||||
|
defaultDate: null,
|
||||||
|
minDate: new Date().getTime(),
|
||||||
|
disabledDates: [], // 存储禁用日期
|
||||||
|
tooltipText: '请选择入住日期(最多连续5天)',
|
||||||
|
selectedRange: {
|
||||||
|
startDate: null,
|
||||||
|
endDate: null
|
||||||
|
},
|
||||||
|
dateList: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onReady() {
|
||||||
|
// 如果需要兼容微信小程序的话,需要用此写法
|
||||||
|
this.$refs.ucalendar.setFormatter(this.formatter)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
formatter(day) {
|
||||||
|
// 将day.date转换为yyyy-MM-dd格式,用于与dateList中的日期比较
|
||||||
|
const currentDate = new Date(day.date)
|
||||||
|
const dateStr = `${currentDate.getFullYear()}-${String(currentDate.getMonth() + 1).padStart(2, '0')}-${String(currentDate.getDate()).padStart(2, '0')}`
|
||||||
|
|
||||||
|
// 在dateList中查找匹配的日期
|
||||||
|
const matchedDate = this.dateList.find(item => item.date === dateStr)
|
||||||
|
|
||||||
|
if (matchedDate) {
|
||||||
|
// 根据inventoryStatus设置bottomInfo和disabled状态
|
||||||
|
switch (matchedDate.inventoryStatus) {
|
||||||
|
case -1:
|
||||||
|
day.bottomInfo = '不可预约'
|
||||||
|
day.disabled = true
|
||||||
|
break
|
||||||
|
case 0:
|
||||||
|
day.bottomInfo = '可预约'
|
||||||
|
day.disabled = false
|
||||||
|
break
|
||||||
|
case 1:
|
||||||
|
day.bottomInfo = '已被预约'
|
||||||
|
day.disabled = true
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
day.bottomInfo = '不可预约'
|
||||||
|
day.disabled = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return day
|
||||||
|
},
|
||||||
|
showCalendar(days) {
|
||||||
|
this.show = true
|
||||||
|
this.dateList = days
|
||||||
|
},
|
||||||
|
hideCalendar() {
|
||||||
|
this.show = false
|
||||||
|
},
|
||||||
|
// 处理日期选择变化
|
||||||
|
handleDateChange(e) {
|
||||||
|
// e是选中的日期数组 ["2025-10-21", "2025-10-22", "2025-10-23", "2025-10-24", "2025-10-25"]
|
||||||
|
|
||||||
|
// 检查是否有不可选的日期
|
||||||
|
const hasInvalidDate = e.some(date => {
|
||||||
|
const matchedDate = this.dateList.find(item => item.date === date)
|
||||||
|
return matchedDate && (matchedDate.inventoryStatus === 1 || matchedDate.inventoryStatus === 2 || matchedDate.inventoryStatus === -1)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (hasInvalidDate) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '所选日期包含不可预约日期',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
this.resetSelection()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新选择状态
|
||||||
|
this.selectedRange = {
|
||||||
|
startDate: e[0],
|
||||||
|
endDate: e[e.length - 1]
|
||||||
|
}
|
||||||
|
// 如果选择的天数小于minDay,提示用户选择至少minDay天
|
||||||
|
if (e.length < this.minDay) {
|
||||||
|
uni.showToast({
|
||||||
|
title: `请选择至少${this.minDay}天`,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
this.resetSelection()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 触发父组件事件
|
||||||
|
this.$emit('dateSelected', this.selectedRange)
|
||||||
|
this.hideCalendar()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 检查日期范围内是否有不可预约的日期
|
||||||
|
checkInvalidDatesInRange(start, end) {
|
||||||
|
// 遍历日期范围内的每一天
|
||||||
|
for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) {
|
||||||
|
const dateStr = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
|
||||||
|
const matchedDate = this.dateList.find(item => item.date === dateStr)
|
||||||
|
|
||||||
|
// 如果找到匹配的日期,且状态为已被预约(1)或不可预约(2)
|
||||||
|
if (matchedDate && (matchedDate.inventoryStatus === 1 || matchedDate.inventoryStatus === 2)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
|
||||||
|
// 检查选择范围内是否有禁用日期
|
||||||
|
checkDisabledDatesInRange(start, end) {
|
||||||
|
return this.disabledDates.some(date => {
|
||||||
|
const disabledDate = new Date(date)
|
||||||
|
return disabledDate >= start && disabledDate <= end
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 重置选择
|
||||||
|
resetSelection() {
|
||||||
|
this.selectedRange = {
|
||||||
|
startDate: null,
|
||||||
|
endDate: null
|
||||||
|
}
|
||||||
|
this.defaultDate = null
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理月份切换
|
||||||
|
handleMonthSwitch(e) {
|
||||||
|
// 可以在这里处理月份切换逻辑,例如加载该月的禁用日期
|
||||||
|
this.$emit('monthChange', e)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 设置禁用日期
|
||||||
|
setDisabledDates(dates) {
|
||||||
|
this.disabledDates = dates
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.calendar-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.calendar-tooltip {
|
||||||
|
padding: 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -47,12 +47,12 @@
|
|||||||
<view>预</view>
|
<view>预</view>
|
||||||
<view>约</view>
|
<view>约</view>
|
||||||
</view>
|
</view>
|
||||||
<view v-for="(d) in currentWeek" :key="d.date" class="date-item">
|
<view v-for="(d) in currentWeek" :key="d.date" class="date-item">
|
||||||
<view>{{ d.week }}</view>
|
<view>{{ d.week }}</view>
|
||||||
<view class="v12-my-1 v12-primary-text">{{ d.monthDay }}</view>
|
<view class="v12-my-1 v12-primary-text">{{ d.monthDay }}</view>
|
||||||
<view>不可预约</view>
|
<view>{{ d.status }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="v12-primary-text v12-font-24 date-item v12-white v12-px-1">
|
<view @click="handleDate" class="v12-primary-text v12-font-24 date-item v12-white v12-px-1">
|
||||||
<view>可</view>
|
<view>可</view>
|
||||||
<view>约</view>
|
<view>约</view>
|
||||||
<view>日</view>
|
<view>日</view>
|
||||||
@@ -133,14 +133,22 @@
|
|||||||
<view class="buy-btn" @click="bookNow">立即购买</view>
|
<view class="buy-btn" @click="bookNow">立即购买</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<Calendar ref="calendar"
|
||||||
|
:minDay="detail.minBookingDays"
|
||||||
|
@dateSelected="handleDateSelected"
|
||||||
|
></Calendar>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getJiaLouProductDetail, getJiaLouCalendar,getJiaLouBookingRules } from '@/api/qianxian'
|
import { getJiaLouProductDetail, getJiaLouCalendar,getJiaLouBookingRules } from '@/api/qianxian'
|
||||||
import {getGiftCardSendBackground} from "@/api/gift"
|
import {getGiftCardSendBackground} from "@/api/gift"
|
||||||
|
import Calendar from '../components/Calendar.vue'
|
||||||
export default {
|
export default {
|
||||||
name: 'GroupBuyDetails',
|
name: 'GroupBuyDetails',
|
||||||
|
components: {
|
||||||
|
Calendar
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
webUrl: this.$VUE_APP_RESOURCES_URL,
|
webUrl: this.$VUE_APP_RESOURCES_URL,
|
||||||
@@ -193,7 +201,8 @@ export default {
|
|||||||
},
|
},
|
||||||
calendar: [],
|
calendar: [],
|
||||||
currentWeek: [],
|
currentWeek: [],
|
||||||
rules: ""
|
rules: "",
|
||||||
|
rangeDate: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onShow() {
|
onShow() {
|
||||||
@@ -214,6 +223,14 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
handleDateSelected(dateRange) {
|
||||||
|
console.log(dateRange, 'dateRange');
|
||||||
|
|
||||||
|
this.rangeDate = dateRange
|
||||||
|
},
|
||||||
|
handleDate() {
|
||||||
|
this.$refs.calendar.showCalendar(this.calendar)
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* 获取产品可预约日期
|
* 获取产品可预约日期
|
||||||
*/
|
*/
|
||||||
@@ -245,6 +262,7 @@ export default {
|
|||||||
result.push({
|
result.push({
|
||||||
date: dateStr,
|
date: dateStr,
|
||||||
week: this.getWeekLabel(dateStr),
|
week: this.getWeekLabel(dateStr),
|
||||||
|
status: this.findDateStatus(dateStr),
|
||||||
monthDay: i === 0 ? '今日' : this.getMonthDay(dateStr)
|
monthDay: i === 0 ? '今日' : this.getMonthDay(dateStr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -285,8 +303,100 @@ export default {
|
|||||||
uni.showToast({ title: '已为您接入管家', icon: 'none' })
|
uni.showToast({ title: '已为您接入管家', icon: 'none' })
|
||||||
},
|
},
|
||||||
bookNow() {
|
bookNow() {
|
||||||
uni.navigateTo({ url: '/pkg_product/views/submitOrder?id=' + this.id + '&orderStartDate=' + this.currentWeek[0].date + '&orderEndDate=' + this.currentWeek[4].date })
|
uni.navigateTo({ url: '/pkg_product/views/submitOrder?id=' + this.id + '&orderStartDate=' + this.rangeDate.startDate + '&orderEndDate=' + this.rangeDate.endDate })
|
||||||
}
|
},
|
||||||
|
/**
|
||||||
|
* 查找指定日期的预约状态
|
||||||
|
* @param {string} dateStr YYYY-MM-DD格式的日期字符串
|
||||||
|
* @returns {string} 预约状态文本:可约、已约、不可约
|
||||||
|
*/
|
||||||
|
findDateStatus(dateStr) {
|
||||||
|
// 在calendar数组中查找匹配的日期
|
||||||
|
const matchedDate = this.calendar.find(item => item.date === dateStr)
|
||||||
|
console.log('未找到匹配日期:', matchedDate)
|
||||||
|
// 如果找到匹配的日期,根据inventoryStatus返回对应文本
|
||||||
|
if (matchedDate) {
|
||||||
|
switch (matchedDate.inventoryStatus) {
|
||||||
|
case 0:
|
||||||
|
return '可订'
|
||||||
|
case 1:
|
||||||
|
return '不可订'
|
||||||
|
case 2:
|
||||||
|
return '不可订'
|
||||||
|
default:
|
||||||
|
return '不可订'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有找到匹配的日期,返回不可约
|
||||||
|
return '不可订'
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理日期点击事件
|
||||||
|
* @param {Object} date 日期对象
|
||||||
|
*/
|
||||||
|
handleDateClick(date) {
|
||||||
|
// 如果是不可订的日期,直接返回
|
||||||
|
if (date.status === '不可订') {
|
||||||
|
uni.showToast({
|
||||||
|
title: '该日期不可预订',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否已选中
|
||||||
|
const index = this.rangeDate.indexOf(date.date)
|
||||||
|
if (index > -1) {
|
||||||
|
// 如果已选中,则取消选中
|
||||||
|
this.rangeDate.splice(index, 1)
|
||||||
|
} else {
|
||||||
|
// 如果未选中,则添加到选中列表
|
||||||
|
this.rangeDate.push(date.date)
|
||||||
|
// 对日期进行排序
|
||||||
|
this.rangeDate.sort()
|
||||||
|
|
||||||
|
// 检查日期连续性
|
||||||
|
if (this.rangeDate.length > 1) {
|
||||||
|
const isConsecutive = this.checkConsecutiveDates(this.rangeDate)
|
||||||
|
if (!isConsecutive) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请选择连续的日期',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
// 移除最后添加的日期
|
||||||
|
this.rangeDate.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查日期是否被选中
|
||||||
|
* @param {string} date 日期字符串
|
||||||
|
* @returns {boolean} 是否被选中
|
||||||
|
*/
|
||||||
|
isDateSelected(date) {
|
||||||
|
return this.rangeDate.includes(date)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查日期是否连续
|
||||||
|
* @param {Array} dates 日期数组
|
||||||
|
* @returns {boolean} 是否连续
|
||||||
|
*/
|
||||||
|
checkConsecutiveDates(dates) {
|
||||||
|
for (let i = 1; i < dates.length; i++) {
|
||||||
|
const curr = new Date(dates[i])
|
||||||
|
const prev = new Date(dates[i-1])
|
||||||
|
const diffDays = (curr - prev) / (1000 * 60 * 60 * 24)
|
||||||
|
if (diffDays !== 1) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -383,8 +493,13 @@ export default {
|
|||||||
color: #333;
|
color: #333;
|
||||||
height: 160rpx;
|
height: 160rpx;
|
||||||
padding: 0 4rpx;
|
padding: 0 4rpx;
|
||||||
|
|
||||||
|
.selected-date {
|
||||||
|
background-color: #E9BABA;
|
||||||
|
font-weight: bold;
|
||||||
|
border-radius: 100rpx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.simple-table {
|
.simple-table {
|
||||||
margin-top: 12rpx;
|
margin-top: 12rpx;
|
||||||
border: 1rpx solid #FADE9F;
|
border: 1rpx solid #FADE9F;
|
||||||
|
|||||||
@@ -108,7 +108,6 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 日期选择器(简单占位) -->
|
<!-- 日期选择器(简单占位) -->
|
||||||
<u-calendar v-model="showCalendar" mode="range" :min-date="minDate" @confirm="onDateConfirm" />
|
|
||||||
<passkeyborad
|
<passkeyborad
|
||||||
v-if="isShowPayPwdPop"
|
v-if="isShowPayPwdPop"
|
||||||
ref='payPwdPop'
|
ref='payPwdPop'
|
||||||
@@ -118,6 +117,7 @@
|
|||||||
@close="pwdPopClose"
|
@close="pwdPopClose"
|
||||||
@finish="pwdPopFinish"
|
@finish="pwdPopFinish"
|
||||||
></passkeyborad>
|
></passkeyborad>
|
||||||
|
<Calendar ref="calendar"></Calendar>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user