Feat:旅居选择日期这里需要加个左右滑动翻页的功能
This commit is contained in:
@@ -28,27 +28,52 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="days">
|
<view class="calendar-body">
|
||||||
<view
|
<view class="days" :class="[isAnimating ? 'absolute ' + transitionMode + '-enter' : '']">
|
||||||
v-for="(day, index) in calendarDays"
|
<view
|
||||||
:key="index"
|
v-for="(day, index) in calendarDays"
|
||||||
class="day"
|
:key="index"
|
||||||
:class="{
|
class="day"
|
||||||
'empty': !day,
|
:class="{
|
||||||
'selected': isSelected(day),
|
'empty': !day,
|
||||||
'in-range': isInRange(day),
|
'selected': isSelected(day),
|
||||||
'start-date': isStartDate(day),
|
'in-range': isInRange(day),
|
||||||
'end-date': isEndDate(day),
|
'start-date': isStartDate(day),
|
||||||
'selecting-start': isSelectingStart(day),
|
'end-date': isEndDate(day),
|
||||||
'disabled': isDisabled(day),
|
'selecting-start': isSelectingStart(day),
|
||||||
'booked': getDateStatus(day) === 1,
|
'disabled': isDisabled(day),
|
||||||
'unavailable': getDateStatus(day) === 2,
|
'booked': getDateStatus(day) === '已被预约',
|
||||||
'available': getDateStatus(day) === 0
|
'unavailable': getDateStatus(day) === '不可预约',
|
||||||
}"
|
'available': getDateStatus(day) === '可预约'
|
||||||
@click="selectDate(day)"
|
}"
|
||||||
>
|
@click="selectDate(day)"
|
||||||
<text>{{ day || '' }}</text>
|
>
|
||||||
<view class="v12-font-20" v-if="day && getDateStatus(day) !== null">{{ getDateStatus(day) }}</view>
|
<text>{{ day || '' }}</text>
|
||||||
|
<view class="v12-font-20" v-if="day && getDateStatus(day) !== null">{{ getDateStatus(day) }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="days absolute" v-if="isAnimating" :class="[transitionMode + '-leave']">
|
||||||
|
<view
|
||||||
|
v-for="(day, index) in prevMonthDays"
|
||||||
|
:key="'prev-' + index"
|
||||||
|
class="day"
|
||||||
|
:class="{
|
||||||
|
'empty': !day,
|
||||||
|
'selected': isSelected(day, prevYear, prevMonth),
|
||||||
|
'in-range': isInRange(day, prevYear, prevMonth),
|
||||||
|
'start-date': isStartDate(day, prevYear, prevMonth),
|
||||||
|
'end-date': isEndDate(day, prevYear, prevMonth),
|
||||||
|
'selecting-start': isSelectingStart(day, prevYear, prevMonth),
|
||||||
|
'disabled': isDisabled(day, prevYear, prevMonth),
|
||||||
|
'booked': getDateStatus(day, prevYear, prevMonth) === '已被预约',
|
||||||
|
'unavailable': getDateStatus(day, prevYear, prevMonth) === '不可预约',
|
||||||
|
'available': getDateStatus(day, prevYear, prevMonth) === '可预约'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<text>{{ day || '' }}</text>
|
||||||
|
<view class="v12-font-20" v-if="day && getDateStatus(day, prevYear, prevMonth) !== null">{{ getDateStatus(day, prevYear, prevMonth) }}</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -113,7 +138,13 @@ export default {
|
|||||||
dateStatusMap: {}, // 存储日期状态
|
dateStatusMap: {}, // 存储日期状态
|
||||||
selectionState: 'initial', // 'initial' | 'selecting' | 'completed'
|
selectionState: 'initial', // 'initial' | 'selecting' | 'completed'
|
||||||
touchStartX: 0,
|
touchStartX: 0,
|
||||||
touchStartY: 0
|
touchStartY: 0,
|
||||||
|
// 动画相关状态
|
||||||
|
isAnimating: false,
|
||||||
|
transitionMode: '', // 'next' or 'prev'
|
||||||
|
prevYear: null,
|
||||||
|
prevMonth: null,
|
||||||
|
prevMonthDays: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -171,37 +202,38 @@ export default {
|
|||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
getDays(){
|
getDays(){
|
||||||
uni.showLoading({
|
// uni.showLoading({
|
||||||
title: '加载中...',
|
// title: '加载中...',
|
||||||
mask: true,
|
// mask: true,
|
||||||
})
|
// })
|
||||||
sojoumOrderCalendar({
|
sojoumOrderCalendar({
|
||||||
travelGroupProductId: this.travelGroupProductId,
|
travelGroupProductId: this.travelGroupProductId,
|
||||||
month: `${this.currentYear}-${String(this.currentMonth + 1).padStart(2, '0')}`
|
month: `${this.currentYear}-${String(this.currentMonth + 1).padStart(2, '0')}`
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
// 更新日期状态映射
|
// 更新日期状态映射,使用合并而不是覆盖,以支持动画时的旧数据显示
|
||||||
this.dateStatusMap = {}
|
const newStatusMap = {}
|
||||||
res.data.forEach(day => {
|
res.data.forEach(day => {
|
||||||
// inventoryStatus int 状态 (0:可预约, 1:已被预约, 2:不可预约)
|
// inventoryStatus int 状态 (0:可预约, 1:已被预约, 2:不可预约)
|
||||||
this.dateStatusMap[day.date] = day.inventoryStatus === 0 ? '可预约' : day.inventoryStatus === 1 ? '已被预约' : '不可预约'
|
newStatusMap[day.date] = day.inventoryStatus === 0 ? '可预约' : day.inventoryStatus === 1 ? '已被预约' : '不可预约'
|
||||||
})
|
})
|
||||||
|
this.dateStatusMap = { ...this.dateStatusMap, ...newStatusMap }
|
||||||
}
|
}
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
uni.hideLoading()
|
uni.hideLoading()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
getDateStatus(day) {
|
getDateStatus(day, year, month) {
|
||||||
if (!day) return null
|
if (!day) return null
|
||||||
const date = this.formatDate(this.getDateFromDay(day))
|
const date = this.formatDate(this.getDateFromDay(day, year, month))
|
||||||
return this.dateStatusMap[date]
|
return this.dateStatusMap[date]
|
||||||
},
|
},
|
||||||
|
|
||||||
isDisabled(day) {
|
isDisabled(day, year, month) {
|
||||||
|
|
||||||
if (!day) return true
|
if (!day) return true
|
||||||
const date = this.getDateFromDay(day)
|
const date = this.getDateFromDay(day, year, month)
|
||||||
// 禁用过去的日期(今天之前的日期)
|
// 禁用过去的日期(今天之前的日期)
|
||||||
const today = new Date()
|
const today = new Date()
|
||||||
today.setHours(0, 0, 0, 0)
|
today.setHours(0, 0, 0, 0)
|
||||||
@@ -212,7 +244,7 @@ export default {
|
|||||||
if (this.maxDate && date > new Date(this.maxDate)) return true
|
if (this.maxDate && date > new Date(this.maxDate)) return true
|
||||||
|
|
||||||
// 检查预约状态
|
// 检查预约状态
|
||||||
const status = this.getDateStatus(day)
|
const status = this.getDateStatus(day, year, month)
|
||||||
// 只允许选择可预约的日期(状态为"可预约"),其他状态都禁用
|
// 只允许选择可预约的日期(状态为"可预约"),其他状态都禁用
|
||||||
|
|
||||||
return status !== '可预约'
|
return status !== '可预约'
|
||||||
@@ -244,6 +276,15 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
changeMonth(delta) {
|
changeMonth(delta) {
|
||||||
|
if (this.isAnimating) return
|
||||||
|
|
||||||
|
// Setup animation state
|
||||||
|
this.prevYear = this.currentYear
|
||||||
|
this.prevMonth = this.currentMonth
|
||||||
|
this.prevMonthDays = [...this.calendarDays]
|
||||||
|
this.transitionMode = delta > 0 ? 'next' : 'prev'
|
||||||
|
this.isAnimating = true
|
||||||
|
|
||||||
let newMonth = this.currentMonth + delta
|
let newMonth = this.currentMonth + delta
|
||||||
if (newMonth < 0) {
|
if (newMonth < 0) {
|
||||||
this.currentYear--
|
this.currentYear--
|
||||||
@@ -253,6 +294,12 @@ export default {
|
|||||||
newMonth = 0
|
newMonth = 0
|
||||||
}
|
}
|
||||||
this.currentMonth = newMonth
|
this.currentMonth = newMonth
|
||||||
|
|
||||||
|
// Reset animation state after transition
|
||||||
|
setTimeout(() => {
|
||||||
|
this.isAnimating = false
|
||||||
|
this.prevMonthDays = []
|
||||||
|
}, 300)
|
||||||
},
|
},
|
||||||
|
|
||||||
onTouchStart(e) {
|
onTouchStart(e) {
|
||||||
@@ -285,8 +332,10 @@ export default {
|
|||||||
return `${year}-${month}-${day}`
|
return `${year}-${month}-${day}`
|
||||||
},
|
},
|
||||||
|
|
||||||
getDateFromDay(day) {
|
getDateFromDay(day, year, month) {
|
||||||
return day ? new Date(this.currentYear, this.currentMonth, day) : null
|
const y = year !== undefined ? year : this.currentYear
|
||||||
|
const m = month !== undefined ? month : this.currentMonth
|
||||||
|
return day ? new Date(y, m, day) : null
|
||||||
},
|
},
|
||||||
|
|
||||||
// isDisabled(day) {
|
// isDisabled(day) {
|
||||||
@@ -305,42 +354,42 @@ export default {
|
|||||||
// return false
|
// return false
|
||||||
// },
|
// },
|
||||||
|
|
||||||
isSelected(day) {
|
isSelected(day, year, month) {
|
||||||
if (!day) return false
|
if (!day) return false
|
||||||
const date = this.getDateFromDay(day)
|
// const date = this.getDateFromDay(day, year, month) // Unused?
|
||||||
return this.isStartDate(day) || this.isEndDate(day)
|
return this.isStartDate(day, year, month) || this.isEndDate(day, year, month)
|
||||||
},
|
},
|
||||||
|
|
||||||
isStartDate(day) {
|
isStartDate(day, year, month) {
|
||||||
if (!day || !this.tempStartDate) return false
|
if (!day || !this.tempStartDate) return false
|
||||||
const date = this.getDateFromDay(day)
|
const date = this.getDateFromDay(day, year, month)
|
||||||
return date.getTime() === this.tempStartDate.getTime()
|
return date.getTime() === this.tempStartDate.getTime()
|
||||||
},
|
},
|
||||||
|
|
||||||
isEndDate(day) {
|
isEndDate(day, year, month) {
|
||||||
if (!day || !this.tempEndDate) return false
|
if (!day || !this.tempEndDate) return false
|
||||||
const date = this.getDateFromDay(day)
|
const date = this.getDateFromDay(day, year, month)
|
||||||
return date.getTime() === this.tempEndDate.getTime()
|
return date.getTime() === this.tempEndDate.getTime()
|
||||||
},
|
},
|
||||||
|
|
||||||
isInRange(day) {
|
isInRange(day, year, month) {
|
||||||
if (!day || !this.tempStartDate || !this.tempEndDate) return false
|
if (!day || !this.tempStartDate || !this.tempEndDate) return false
|
||||||
const date = this.getDateFromDay(day)
|
const date = this.getDateFromDay(day, year, month)
|
||||||
return date > this.tempStartDate && date < this.tempEndDate
|
return date > this.tempStartDate && date < this.tempEndDate
|
||||||
},
|
},
|
||||||
|
|
||||||
isSelectingStart(day) {
|
isSelectingStart(day, year, month) {
|
||||||
if (!day || !this.tempStartDate || this.tempEndDate) return false
|
if (!day || !this.tempStartDate || this.tempEndDate) return false
|
||||||
// 只有在选择状态且只有开始日期时才显示特殊样式
|
// 只有在选择状态且只有开始日期时才显示特殊样式
|
||||||
if (this.selectionState !== 'selecting') return false
|
if (this.selectionState !== 'selecting') return false
|
||||||
const date = this.getDateFromDay(day)
|
const date = this.getDateFromDay(day, year, month)
|
||||||
return date.getTime() === this.tempStartDate.getTime()
|
return date.getTime() === this.tempStartDate.getTime()
|
||||||
},
|
},
|
||||||
|
|
||||||
selectDate(day) {
|
selectDate(day, year, month) {
|
||||||
if (!day || this.isDisabled(day)) return
|
if (!day || this.isDisabled(day, year, month)) return
|
||||||
|
|
||||||
const selectedDate = this.getDateFromDay(day)
|
const selectedDate = this.getDateFromDay(day, year, month)
|
||||||
|
|
||||||
// 如果设置了最小预订天数,则自动计算结束日期
|
// 如果设置了最小预订天数,则自动计算结束日期
|
||||||
if (this.minBookingDays > 0) {
|
if (this.minBookingDays > 0) {
|
||||||
@@ -708,17 +757,57 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
0% {
|
0% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.7;
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
50% {
|
|
||||||
opacity: 0.7;
|
// Animation Styles
|
||||||
transform: scale(1.05);
|
.calendar-body {
|
||||||
|
position: relative;
|
||||||
|
height: 480rpx; // 6 rows * 80rpx
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
100% {
|
|
||||||
opacity: 1;
|
.days.absolute {
|
||||||
transform: scale(1);
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
// height: 100%;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// Keyframes for sliding
|
||||||
|
@keyframes slide-next-enter {
|
||||||
|
from { transform: translateX(100%); }
|
||||||
|
to { transform: translateX(0); }
|
||||||
|
}
|
||||||
|
@keyframes slide-next-leave {
|
||||||
|
from { transform: translateX(0); }
|
||||||
|
to { transform: translateX(-100%); }
|
||||||
|
}
|
||||||
|
@keyframes slide-prev-enter {
|
||||||
|
from { transform: translateX(-100%); }
|
||||||
|
to { transform: translateX(0); }
|
||||||
|
}
|
||||||
|
@keyframes slide-prev-leave {
|
||||||
|
from { transform: translateX(0); }
|
||||||
|
to { transform: translateX(100%); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.next-enter { animation: slide-next-enter 0.3s forwards; }
|
||||||
|
.next-leave { animation: slide-next-leave 0.3s forwards; }
|
||||||
|
.prev-enter { animation: slide-prev-enter 0.3s forwards; }
|
||||||
|
.prev-leave { animation: slide-prev-leave 0.3s forwards; }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user