效果图
app.vue
onLaunch:function(options){this.defaultcache()}defaultcache(){// 入住信息缓存var arr = this.getDateTime();var ReserVation = {reservType:0,//1 人数 2日期InCheckin:{},//入离日期peopleArr:[{title:'成人',num:2},{title:'儿童',num:0},{title:'宝子',num:1},{title:'房间数',num:1},],//入住人数IntimeCur:[{len:0,str:0},{len:0,str:0}],//选择日期timeDataArr:[],//日期数组}ReserVation.timeDataArr = arr[0]ReserVation.IntimeCur = arr[1]ReserVation.InCheckin = arr[2][0]uni.setStorageSync('ReserVation',ReserVation)},// 获取日期getDateTime(){var that = thisvar showY = 3;//显示几个月var timeData = [];//日期数组var timestamp = Date.parse(new Date());var date = new Date(timestamp);//年var Y = date.getFullYear();//月 var M = date.getMonth() + 1;//日var D = date.getDate();// 周几和月份天数var time = {};var Yday = 0,Mday = 0,data = {},param = {},toDays = 2;//toDays 默认住几天for(let i = 0;i < showY;i++){if(12 < (M + i)){Yday = Y + 1Mday = (M + i) - 12}else{Yday = YMday = M + i}time = that.getDaysInMonth(Yday,Mday)data = {year:Yday,moon:Mday,arr:[],days:time.days,Z:time.Z}for(let k = 0;k < time.Z;k++){data.arr.push({date:''});}for(let j = 0;j < time.days;j++){param = {};param.date = j + 1;param.Z = that.getDaysInMonth(Yday,Mday,param.date)param.price = 0;if(i == 0 && (j + 1) < D){param.status = 1}else if(i == 0 && (j + 1) == D){param.status = 2}data.arr.push(param)}timeData.push(data)}var start = {len:0,str:D};// if(that.timeData[start.len].days < (D + 1)){// start.len = 1// start.str = 0// }var end = {len:0,str:D + toDays - 1}if(timeData[end.len].days < end.str){end.str = end.str - timeData[end.len].daysend.len = 1}start.str = start.str + parseInt(timeData[start.len].Z) - 1end.str = end.str + parseInt(timeData[end.len].Z) - 1var timeCur = [start,end]var Checkin = {start_Y:timeData[timeCur[0].len].year,start_M:timeData[timeCur[0].len].moon,start_D:timeData[timeCur[0].len].arr[timeCur[0].str].date,start_Z:timeData[timeCur[0].len].arr[timeCur[0].str].Z,end_Y:timeData[timeCur[1].len].year,end_M:timeData[timeCur[1].len].moon,end_D:timeData[timeCur[1].len].arr[timeCur[1].str].date,end_Z:timeData[timeCur[1].len].arr[timeCur[1].str].Z,days:toDays,}return [timeData,timeCur,[Checkin]];},// 获取周几和月份天数getDaysInMonth(Y,M,D){if(D){return this.getWeekByDate(`${Y}-${M}-${D}`,true)}//一号周几var Z = this.getWeekByDate(`${Y}-${M}-1`);// 月份天数var days = new Date(Y, M, 0).getDate();return {Z,days}},// 返回周几getWeekByDate(dates,status){let show_day = status?['周日', '周一', '周二', '周三', '周四', '周五', '周六']:['0', '1', '2', '3', '4', '5', '6'];let date = new Date(dates);date.setDate(date.getDate());let day = date.getDay();return show_day[day];},
page-reservation.vue
<template>
<view><view :class="modalName == 'reservation'?'cu-modal bottom-modal show':'cu-modal bottom-modal'" @touchmove.stop="() => false":style="'--CustomBar--:'+CustomBar+'px;z-index:10000;'"><view class="cu-dialog reservation-index"><view class="cu-custom"><view class="cu-bar fixed bg-white dialog-title" :style="'height:'+CustomBar+'px;padding-top:'+StatusBar+'px;'"><view class="action" @click="showModal('')"><text class="cuIcon-close" style="font-size: 42upx;"></text></view><view class="content" :style="'top:'+StatusBar+'px'"><view>选择入住条件</view></view></view></view><!-- 房住 --><view class="reser-room"><view>房住</view><view @click="tabreser(1)"><view v-for="(item,index) in peopleArrCur" :key="index" :class="item.num > 0?'reser-room-cur':''">{{item.num + item.title}}</view><view :class="type == 1?'cuIcon-unfold':'cuIcon-unfold reser-rotate'"></view></view></view><!-- list --><view class="reser-room-list reser-cur" :style="type != 1?'height:0;box-shadow:0;':''"><view v-for="(item,index) in peopleArrCur" :key="index"><view>{{item.title}}</view><view class="room-list-count"><view class="room-list-icon" :class="item.num < 1 || (index == 0 && item.num < 2) || (index == 3 && item.num < 2) || (isType && index == 2)?'list-icon-cur':''"@click="item.num < 1 || (index == 0 && item.num < 2) || (index == 3 && item.num < 2) || (isType && index == 2)?'':countTap(index,1)"><view class="cuIcon-move"></view></view><view>{{item.num}}</view><view class="room-list-icon" :class="item.num > 20 || (isType && index == 2)?'list-icon-cur':''"@click="item.num > 20 || (isType && index == 2)?'':countTap(index,2)"><view class="cuIcon-add"></view></view></view></view></view><!-- 日期 --><view class="reser-room reser-money"><view>入离日期</view><view @click="tabreser(2)"><view><span class="reser-room-cur">{{Checkin.start_M}}月{{Checkin.start_D}}日</span>{{Checkin.start_Z}}</view><view class="reser-room-ing">{{Checkin.days}}晚</view><view v-if="Checkin.days > 1"><span class="reser-room-cur">{{Checkin.end_M}}月{{Checkin.end_D}}日</span>{{Checkin.end_Z}}</view><view :class="type == 2?'cuIcon-unfold':'cuIcon-unfold reser-rotate'"></view></view></view><view class="reser-time" :style="type == 2?'':'height:0;'"><view>*以下价格为单晚入住参考价</view><!-- list --><view class="reser-data"><view v-for="(item,index) in timeTitle" :key="index">{{item}}</view></view><scroll-view scroll-y class="reser-list"@scroll="getScrollTop"><view v-for="(item,index) in timeData" :key="index" class="list-time":id="'Time_'+index"><view><view :class="index == scroll_index && type == 2 && modalName == 'reservation'?'reser-fixed':''">{{item.year}}年{{item.moon}}月</view></view><view><view v-for="(cell,cell_index) in item.arr" :key="cell_index" class="list-date":class="timeCur[1].str != -1 && timeCur[0].len != timeCur[1].len && (index == timeCur[0].len && timeCur[0].str < cell_index || index == timeCur[1].len && timeCur[1].str > cell_index) ? 'list-cur-one':timeCur[1].str != -1 && timeCur[0].len == timeCur[1].len && (index == timeCur[0].len && timeCur[0].str < cell_index && index == timeCur[1].len && timeCur[1].str > cell_index) ? 'list-cur-one':timeCur[1].len - timeCur[0].len > 1 && index == timeCur[1].len - 1?'list-cur-one':(index == timeCur[0].len && cell_index == timeCur[0].str) || (index == timeCur[1].len && cell_index == timeCur[1].str)?'list-cur-two':''" :style="cell.date?'':'visibility: hidden;'"@click="cell.status == 1?'':timetap(index,cell_index)"><view><view :class="cell.status == 1?'reser-hui':cell.status == 2?'reser-chen':''">{{cell.status == 2?'今天':cell.date}}</view><view class="reser-cur-font" v-if="cell.price > 0"><span v-if="((timeCur[1].str != -1 && timeCur[0].len != timeCur[1].len && (index == timeCur[0].len && timeCur[0].str < cell_index || index == timeCur[1].len && timeCur[1].str > cell_index)) ||(timeCur[1].str != -1 && timeCur[0].len == timeCur[1].len && (index == timeCur[0].len && timeCur[0].str < cell_index && index == timeCur[1].len && timeCur[1].str > cell_index)) ||(timeCur[1].len - timeCur[0].len > 1 && index == timeCur[1].len - 1) || ((index == timeCur[0].len && cell_index == timeCur[0].str) || (index == timeCur[1].len && cell_index == timeCur[1].str)))">¥{{cell.price}}</span></view><view class="reser-cur-font" v-if="(index == timeCur[0].len && cell_index == timeCur[0].str) || (index == timeCur[1].len && cell_index == timeCur[1].str)">{{(index == timeCur[0].len && cell_index == timeCur[0].str)?'入住':'离店'}}</view></view></view></view></view><view class="wdh" style="height: 162px;"></view></scroll-view><view class="reser-button"><button class="cu-btn round" @click="btnConfirm">确定</button></view></view></view></view>
</view>
</template>
<script>
export default{data(){return{StatusBar:this.StatusBar,CustomBar: this.CustomBar,type:0,timeTitle:['周日','周一','周二','周三','周四','周五','周六'],timeData:[],timeCur:[{len:0,str:0},{len:0,str:0}],scroll_index:-1,//fiexd日期Checkin:{start_M:'',start_D:'',start_Z:'',end_M:'',end_D:'',end_Z:'',days:'',},//入离日期peopleArrCur:[],}},name: 'page-reservation',props: {modalName: {type: String,default: ''},ReserVation: {type: Object,default: {}},isType: {type: [Boolean, String],default: false},},created(){//默认显示日期或者人数this.type = this.ReserVation.reservType//房住this.peopleArrCur = this.ReserVation.peopleArr//选择的入住时间this.timeCur = this.ReserVation.IntimeCur//日期数组this.timeData = this.ReserVation.timeDataArr//入住时间信息this.Checkin = this.ReserVation.InCheckinthis.list()},methods:{list(){var that = thissetTimeout(() => {that.scroll_index = 0},500)setTimeout(() => {that.getDateHeight();},1000)},timetap(index,cell_index){var that = thisif(that.timeCur[1].str != -1 || (cell_index < that.timeCur[0].str && index == that.timeCur[0].len) || (index < that.timeCur[0].len)){//选择开始that.timeCur[0].len = indexthat.timeCur[0].str = cell_indexthat.timeCur[1].len = indexthat.timeCur[1].str = -1that.Checkin = {start_M:that.timeData[that.timeCur[0].len].moon,start_D:that.timeData[that.timeCur[0].len].arr[that.timeCur[0].str].date,start_Z:that.timeData[that.timeCur[0].len].arr[that.timeCur[0].str].Z,end_M:'',end_D:'',end_Z:'',days:1,}}else{//选择结束var number = 0if(that.timeCur[0].len == index){number = cell_index - that.timeCur[0].str + 1}else{var time = index - that.timeCur[0].len;number += (that.timeData[that.timeCur[0].len].arr.length - that.timeCur[0].str)for(let i = that.timeCur[0].len + 1;i < index;i++){number += that.timeData[i].days}number += (cell_index - parseInt(that.timeData[index].Z)) + 1}if(number > 30){getApp().Tips('最多选择三十天')}else{that.timeCur[1].len = indexthat.timeCur[1].str = cell_indexthat.getCheckinDays(number)}}},// 入离日期getCheckinDays(D){var that = thisthat.Checkin = {start_Y:that.timeData[that.timeCur[0].len].year,start_M:that.timeData[that.timeCur[0].len].moon,start_D:that.timeData[that.timeCur[0].len].arr[that.timeCur[0].str].date,start_Z:that.timeData[that.timeCur[0].len].arr[that.timeCur[0].str].Z,end_Y:that.timeData[that.timeCur[1].len].year,end_M:that.timeData[that.timeCur[1].len].moon,end_D:that.timeData[that.timeCur[1].len].arr[that.timeCur[1].str].date,end_Z:that.timeData[that.timeCur[1].len].arr[that.timeCur[1].str].Z,days:D,}},btnConfirm(){if(this.Checkin.days < 2){return getApp().Tips('请选择离店时间~')}this.$emit('getHotelData', this.peopleArrCur,this.Checkin,this.timeCur);},getDateHeight(){var that = thisvar text = ''for(let i = 0;i < that.timeData.length;i++){text = '#Time_' + iuni.createSelectorQuery().in(that).select(text).boundingClientRect(function (res) {that.timeData[i].TimeHiehgt = res.height + (i == 0?0:that.timeData[i - 1].TimeHiehgt) - 5}).exec();}},getScrollTop(e){var i = this.scroll_index > 0?this.scroll_index - 1:0;for(i;i < this.timeData.length;i++){if(e.detail.scrollTop < this.timeData[i].TimeHiehgt){this.scroll_index = i;break;}}},showModal(target){this.$emit('showModal', target);},countTap(index,type){if(type == 1){this.peopleArrCur[index].num--}else{this.peopleArrCur[index].num++}},tabreser(type){var that = thisif(that.type == type){that.type = 0}else{that.type = typeif(type == 2){that.scroll_index = -1setTimeout(() => {that.scroll_index = 0},500)}}},},
}
</script>
<style>
/* 预定酒店 */
.reservation-index{height: 100vh;}
.dialog-title{position: relative !important;z-index: 0 !important;}
.reser-room{font-size: 26upx;display: flex;align-items: center;justify-content:space-between;color: #666;
height:53px;padding: 0 30upx;background: #fff;width: 100%;float: left;}
.reser-room>view:nth-child(2){display: flex;align-items:center;}
.reser-room>view:nth-child(2)>view{margin-left: 20upx;}
.reser-room>view:nth-child(2)>.cuIcon-unfold{color: #000;}
.reser-cur{box-shadow: inset 0rpx 3rpx 6rpx 1rpx rgba(0,0,0,0.16);}
.reser-room-cur{color: #FC9C39;}
.reser-room-list{width: 100%;float: left;padding: 0 30upx;transition: height 0.3s;background: #fff;height: 200px;overflow: hidden;}
.reser-room-list>view{width: 100%;float: left;height:50px;display:flex;align-items:center;
justify-content:space-between;font-size: 26upx;color: #666;}
.room-list-count{display: flex;align-items: center;}
.room-list-icon{display: flex;align-items: center;justify-content: center;width: 38upx;height: 38upx;border-radius: 50%;color: #fff;
background-color: #FF9800;}
.list-icon-cur{background-color: #939393 !important;}
.room-list-count>view:nth-child(2){margin: 0 10upx;min-width: 34upx;}
.cuIcon-unfold{transform:rotate(0deg);transition: all 0.3s;margin-left: 6upx !important;}
.reser-rotate{transform:rotate(-90deg);}
.reser-room-ing{background-color: #FAFAFA;border-radius: 20upx;padding: 0 20upx;height: 40upx;line-height: 40upx;font-size: 20upx;color: #666;}
/* 日期 */
.reser-money{margin-top: 10px;}
.reser-time{width: 100%;height:calc(100vh - 116px - var(--CustomBar--)) ;background-color: #fff;float: left;transition: height 0.3s;overflow: hidden;}
.reser-time>view{width: 100%;float: left;}
.reser-time>view:nth-child(1){background: #FFE3C6;color: #5F5F5F;height: 31px;display: flex;align-items: center;justify-content: center;}
.reser-data{width: calc(100% - 60upx) !important;float: left;height: 50px;display: flex;align-items: center;font-size: 24upx;
color: #5F5F5F;margin: 0 30upx;}
.reser-data>view{width: calc((100% - 60upx) / 7);margin-left: 10upx;}
.reser-data>view:nth-child(1){margin-left: 0;}
.reser-list{width: 100%;float: left;background: #fff;height:calc(100vh - 197px - var(--CustomBar--));}
.list-time{width: 100%;float: left;position: relative;}
.list-time>view:nth-child(1){padding-bottom:20upx;font-size: 30upx;color: #FC9C39;height: 31px;
width: calc(100% - 56upx);margin: 0 28upx;}
.list-time>view:nth-child(1)>view{height: 31px;border-bottom: 1px solid #F2F4F9;background: #fff;z-index: 1;}
.reser-fixed{position: fixed;top: calc(197px + var(--CustomBar--));width: calc(100% - 56upx);}
.list-time>view:nth-child(2){width: 100%;padding: 20upx 30upx 30upx;float: left;}
.list-date{width: calc((100% - 30px) / 7);height: 58px;border-radius: 10upx;float: left;display: flex;align-items: center;justify-content: center;
margin-left: 5px;margin-top: 5px;}
.list-date{font-size: 30upx;color: #252525;}
.list-time>view:nth-child(2)>view:nth-child(7n+1){margin-left: 0 !important;}
.list-cur-one{background-color: #F8C691;}
.list-cur-two{background-color: #FC9C39;}
.list-cur-two>view>view:nth-child(1){color: #252525 !important;}
.reser-cur-font{font-size: 24upx;color: #FFFFFF;}
.reser-hui{color: #AAAAAA;}
.reser-chen{color: #FC9C39;}
</style>
需要引入的.vue
<template>
<view><view @click="page_showModal('reservation',1)">打开房租</view><view @click="page_showModal('reservation',2)">打开日历</view><page-reservation v-if="page_modalName" :modalName="page_modalName" :ReserVation="ReserVation" @showModal="page_showModal"@getHotelData="getHotelData"></page-reservation>
</view>
</template>
<script>
import PageReservation from '@/colorui/components/page-reservation.vue'
export default {components:{ PageReservation },data() {return {page_modalName:'',ReserVation:uni.getStorageSync('ReserVation'),//入住人数日期}},methods: {// 修改入住信息getHotelData(peopleArr,InCheckin,IntimeCur){this.ReserVation.peopleArr = peopleArrthis.ReserVation.InCheckin = InCheckinthis.ReserVation.IntimeCur = IntimeCuruni.setStorage({key:"ReserVation",data:this.ReserVation})this.page_showModal('')},// 入住信息弹窗page_showModal(target,type){var that = thisif(type){that.ReserVation.reservType = type}that.page_modalName = '1'setTimeout(() => {that.page_modalName = target},target?100:500)},},
</script>
默认选择当天和明天
入住一次性最多选择三十天
默认获取三个月日期数组
存储信息
InCheckin 选择的日期信息
IntimeCur 组件选择的日期
peopleArr 入住人数信息
timeDataArr 显示的日历
引入的组件库ColorUI组件库
用的是uni-app
遇到问题可以看我主页加我Q,很少看博客,对你有帮助别忘记点赞收藏。