版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.youkuaiyun.com/u012562411/article/details/85287537
例如 图中18-19是满房那么该日期是就不能被选择 26 27 28都是不能被选中的
需求说明
1.小程序最多选择俩天日期
2.如果已经预定了则为满房
3.不能选择小于当前时间的日期
4.该流程是用户预订房间时必须是vip如果不是vip的话是先购买vip然后在根据选择的房间进行预约,
ps:如果预约的日期为18号19号20号的(选择的为俩天日期:酒店入住是住晚上;那么选择的日期就是18号和19号而选择的20号是木有关系的)那么当前房间的18号19号为满房且用户是不能够点击的20号是可以正常点击的
ps:举个列子 如果20号恰巧已经被预定出去了 (也就是说20是满房状态)那么19号就不能和21号点击了(虽然最多选择俩天但是20号满房状态所以不能够选择) 如果点击20号是可以的虽20号是满房但是 他选择的是19号晚上和20号不牵扯所以20号是可被点击
5.刚刚优化了部分功能 上图中有显示如果当25号还没有被预定出去的时候 26-27号和23-24却被预定了那么点击25号的时候26号还是可以的点击的 但是27号却不能点击 2019-09-18号更新
js源码
var common = require('../../common.js');
var util = require('../../utils/util.js');
var config = common.getconfig();
var vm = null;
const app = getApp()
Page({
data: {
calendar: [],
// 构建顶部日期时使用
date: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
dateList: ['2019-09-18', '2019-09-19', '2019-09-22', '2019-09-23', '2019-09-24', '2019-09-26', '2019-09-27', '2019-09-28'],
inTime: '',
id:'',
outTime: '',
toDay:'', //当前日期
token:'',
type:0, // 1会员 0不是
falg:0,
equitiesList:[],
sort:0,
agree:0
},
// 日历初始化
dataInit(setYear, setMonth) {
// 当前时间/传入的时间
var now = setYear ? new Date(setYear, setMonth) : new Date();
var year = setYear || now.getFullYear();
// 传入的月份已经加1
var month = setMonth || now.getMonth() + 1;
// 构建某日数据时使用
var obj = {};
// 需要遍历的日历数组数据
var dateArr = [];
// 需要的格子数,为当前星期数+当月天数
var arrLen = 0;
// 该月加1的数值,如果大于11,则为下年,月份重置为1
// 目标月1号对应的星期
var startWeek = new Date(year + '-' + (month < 10 ? '0' + month : month) + '-01').getDay();
//获取目标月有多少天
var dayNums = new Date(year, month < 10 ? '0' + month : month, 0).getDate();
var num = 0;
// 计算当月需要的格子数 = 当前星期数+当月天数
arrLen = startWeek * 1 + dayNums * 1;
for (var i = 0; i < arrLen; i++) {
if (i >= startWeek) {
num = i - startWeek + 1;
obj = {
/*
* 返回值说明
* isToday : 2018-12-27
* dateNum : 27
*/
isToday: year + '-' + (month < 10 ? '0' + month : month) + '-' + (num < 10 ? '0' + num : num),
dateNum: num,
is_select:0
}
} else {
// 填补空缺
// 例如2018-12月第一天是星期6,则需要补6个空格
obj = {};
}
dateArr[i] = obj;
};
return dateArr;
},
sub() {
if (vm.data.type==0){
vm.setData({
falg:1
})
}else{
wx.request({
url: config.goods_wx_applet_buy_url,
data: {
token: vm.data.token,
id: vm.data.id,
enter_date: vm.data.inTime,
leave_date: vm.data.outTime
},
header: {
"content-type": "application/x-www-form-urlencoded"
},
method: 'POST',
success: function (ret) {
if (ret.data.status == 1) {
wx.showToast({
title: ret.data.msg,
icon: "none",
duration: 1000,
})
wx.hideLoading()
vm.wxpay(ret);
} else {
wx.hideLoading()
wx.showToast({
title: ret.data.msg,
icon: "none",
duration: 1000,
})
}
}
})
}
},
pay() {
if (vm.data.agree == 0) {
wx.showToast({
title: '请阅读勾选唐宿服务条款',
icon: 'none'
})
return;
}
var id = vm.data.equitiesList[vm.data.sort].id;
if (id == 0) {
wx.showToast({
title: '请选择需购买的会员',
})
return;
}
wx.request({
url: config.buyMember_url,
header: {
'content-type': 'application/json'
},
method: 'get',
data: {
token: vm.data.token,
id: id
},
success: ret => {
console.log(ret)
wx.showToast({
title: ret.data.msg,
icon: "none",
duration: 1000,
})
wx.hideLoading()
vm.wxpays(ret);
}
})
},
wxpay(ret) {
wx.requestPayment({
timeStamp: ret.data.data.sortedMap['timeStamp'],
nonceStr: ret.data.data.sortedMap['nonceStr'],
package: ret.data.data.sortedMap['package'],
signType: ret.data.data.sortedMap['signType'],
paySign: ret.data.data.sortedMap['paySign'],
success: function (res) {
if (res) {
console.log(res);
if (res) {
wx.showModal({
title: '支付成功',
content: '',
})
setTimeout(function () {
wx.reLaunch({
url: '/pages/order/myOrder/myOrder?status=-1',
})
}, 500)
} else {
setTimeout(function () {
wx.reLaunch({
url: '/pages/order/myOrder/myOrder?status=1',
})
}, 500)
}
}
},
fail: function (res) {
console.log(res);
console.log(123213);
wx.reLaunch({
url: '/pages/order/myOrder/myOrder?status=-1',
})
}
})
},
wxpays(ret) {
wx.requestPayment({
timeStamp: ret.data.data.sortedMap['timeStamp'],
nonceStr: ret.data.data.sortedMap['nonceStr'],
package: ret.data.data.sortedMap['package'],
signType: ret.data.data.sortedMap['signType'],
paySign: ret.data.data.sortedMap['paySign'],
success: function (res) {
if (res) {
console.log(res);
if (res) {
wx.showModal({
title: '支付成功',
content: '',
})
setTimeout(function () {
vm.my_index();
}, 500)
} else {
vm.my_index();
}
}
},
fail: function (res) {
console.log(res);
console.log(123213);
vm.my_index();
}
})
},
// 点击了日期,选择入住时间或者离店时间
dayClick(e) {
console.log(e);
var vm = this;
var eTime = e.currentTarget.dataset.day; //当前点击的日期
var inTime = vm.data.inTime; //入驻
var outTime = vm.data.outTime; //离开
if (inTime==''){ //判断入驻日期是否选择 木有选择
if (vm.data.dateList.indexOf(eTime) !== -1) { //点击的日期在数组中
wx.showToast({
title: '当天以为预定了哦~',
icon: 'none'
})
}else{
if (inTime == '' || (new Date(eTime) <= new Date(inTime)) || outTime != '') { //默认入驻日期
// 如果入住时间为空或选择的时间小于等于入住时间,则选择的时间为入住时间
inTime = eTime;
outTime = '';
}else{
//判断点击当前日期 和 入驻日期进行比较
var times = vm.getDateDiff(inTime, eTime, "day");
console.log(times);
if (times > 2) {
wx.showToast({
title: '亲爱的唐宿会员:预定不能超过2晚哦~',
icon: 'none'
})
inTime = eTime;
outTime = ''
}
}
}
}else{
if (inTime && outTime!=''){
if (vm.data.dateList.indexOf(eTime) !== -1) { //点击的日期在数组中
wx.showToast({
title: '当天以预定了哦~',
icon: 'none'
})
return;
}
}
if (inTime == '' || (new Date(eTime) <= new Date(inTime)) || outTime != '') { //默认入驻日期
if (vm.data.dateList.indexOf(eTime) !== -1) { //点击的日期在数组中
wx.showToast({
title: '当天以预定了哦~',
icon: 'none'
})
}else{
// 如果入住时间为空或选择的时间小于等于入住时间,则选择的时间为入住时间
inTime = eTime;
outTime = '';
}
} else {
//判断点击当前日期 和 入驻日期进行比较
var times = vm.getDateDiff(inTime, eTime, "day");
if (times > 2) {
wx.showToast({
title: '亲爱的唐宿会员:预定不能超过2晚哦~',
icon: 'none'
})
if (vm.data.dateList.indexOf(eTime) !== -1){
wx.showToast({
title: '当天以预定了哦~',
icon: 'none'
})
}else{
inTime = eTime;
outTime = ''
}
}
if (times == 2) {
var all_time = vm.getAll(inTime, eTime);
if (vm.data.dateList.indexOf(all_time[1]) !== -1) {
wx.showToast({
title: '预定房源包含满房,请重新选择哦~',
icon: 'none'
})
} else {
outTime = eTime;
console.log(outTime);
}
}
if (times == 1) {
outTime = eTime;
}
}
}
console.log(outTime);
vm.setData({
inTime,
outTime
})
},
getAll:function(begin, end) { // 开始日期和结束日期
if (!begin || !end) { // 去除空的可能性
wx.showToast({
title: '选择的时间不能为空哦~',
icon:'none'
})
return false;
}
// 在时间Date的原型中定义一个format方法
Date.prototype.format = function () {
var s = ""; // 定义一个字符串,目的,要时间格式按照我们的要求拼接
var month = vm.getMonth() + 1;
var day = vm.getDate();
s += vm.getFullYear() + "-";
s += '0'+month + "-";
s += day;
return s; // 得到的格式如 "2018-11-20"
}
var ab = begin.split('-'); // 把日期参数分割,注意,如果以'/'连接,则分割'/'
var ae = end.split('-');
var db = new Date();
db.setUTCFullYear(ab[0], ab[1] - 1, ab[2]); // 返回符合UTC的时间格式
var de = new Date();
de.setUTCFullYear(ae[0], ae[1] - 1, ae[2]);
var unixDb = db.getTime();
var unixDe = de.getTime();
console.log(unixDb);
var arr = [];
for (var k = unixDb; k <= unixDe;) {
arr.push(vm.getTimes(parseInt(k)));
k = k + 24 * 60 * 60 * 1000;
}
return arr; // 返回两个日期之间的所有日期数组。
},
getTimes:function(nS) {
var date = new Date(parseInt(nS));
var year = date.getFullYear();
var mon = date.getMonth() + 1;
var day = date.getDate();
var hours = date.getHours();
var minu = date.getMinutes();
var sec = date.getSeconds();
return year + '-' + (mon < 10 ? '0' + mon : mon) + '-' + (day < 10 ? '0' + day : day) ;
},
getDateDiff:function (startTime, endTime, diffType) {
//将xxxx-xx-xx的时间格式,转换为 xxxx/xx/xx的格式
startTime = startTime.replace(/\-/g, "/");
endTime = endTime.replace(/\-/g, "/");
//将计算间隔类性字符转换为小写
diffType = diffType.toLowerCase();
var sTime =new Date(startTime); //开始时间
var eTime =new Date(endTime); //结束时间
//作为除数的数字
var timeType =1;
switch (diffType) {
case"second":
timeType =1000;
break;
case"minute":
timeType =1000*60;
break;
case"hour":
timeType =1000*3600;
break;
case"day":
timeType =1000*3600*24;
break;
default:
break;
}
return parseInt((eTime.getTime() - sTime.getTime()) / parseInt(timeType));
},
//排序选择
radioChange: function (e) {
console.log(e);
vm.setData({
sort: e.detail.value
})
},
changese: function (e) {
if (vm.data.agree == 1) {
vm.setData({
agree: 0
})
} else {
vm.setData({
agree: 1
})
}
},
init(){
wx.request({
url: config.checkHousingRecord_url,
header: {
'content-type': 'application/json'
},
data: {
id: vm.data.id
},
method: 'get',
success: ret => {
console.log(ret)
vm.setData({
dateList: ret.data.data.dateList
})
}
})
},
close() {
vm.setData({
falg: 0
})
},
tk() {
wx.navigateTo({
url: '/pages/tk/tk',
})
},
xy(e) {
wx.navigateTo({
url: '/pages/xy/xy?id=' + e.currentTarget.dataset.id,
})
},
my_index(){
wx.request({
url: config.equitiesList_url,
header: {
'content-type': 'application/json'
},
methods: 'get',
success: ret => {
console.log(ret)
vm.setData({
equitiesList: ret.data.data.equitiesList
})
}
})
wx.request({
url: config.my_index_url,
method: 'get',
header: {
'content-type': 'application/json'
},
data: {
token: vm.data.token
},
success: ret => {
console.log(ret);
if (ret) {
if (ret.data.status) {
vm.setData({
type: ret.data.data.account.type
})
} else {
wx.showToast({
title: ret.data.msg,
icon: 'none'
})
}
}
}
})
},
onLoad(options) {
vm = this;
vm.setData({
id: options.id,
token: wx.getStorageSync('token')
})
//vm.init();
setTimeout(function(){
// 获取本月时间
var nowTime = new Date();
var year = nowTime.getFullYear();
var month = nowTime.getMonth();
var months = month + 1 > 12 ? 1 : month + 1;
var toDay = nowTime.getFullYear() + '-' + (months < 10 ? '0' + months : months) + '-' + nowTime.getDate();
var time = [];
var timeArray = {};
// 循环6个月的数据
for (var i = 0; i < 6; i++) {
year = month + 1 > 12 ? year + 1 : year;
month = month + 1 > 12 ? 1 : month + 1;
// 每个月的数据
time = vm.dataInit(year, month);
// 接收数据
timeArray[year + '年' + (month < 10 ? '0' + month : month) + '月'] = time;
};
var arr = [];
for (let z in timeArray) {
arr.push(timeArray[z]); //属性
}
for (var j = 0; j < arr.length; j++) {
for (var k = 0; k < arr[j].length; k++) {
arr[j][k].is_select = 0;
if (vm.data.dateList.indexOf(arr[j][k].isToday) !== -1) {
arr[j][k].is_select = 1;
} else {
arr[j][k].is_select = 0
}
}
}
console.log(arr);
console.log(timeArray);
vm.setData({
calendar: timeArray,
toDay: toDay,
id: options.id,
token: wx.getStorageSync('token')
});
},500)
vm.my_index();
},
})
html代码
<view class="page">
<view class="top">
<view class="reserve-time">
<text>入住时间</text>{{inTime}}
<text>离店时间</text>{{outTime}}
</view>
<!-- 星期 -->
<view class='header'>
<block wx:for='{{date}}' wx:key="this*">
<view class='{{item == "周六" || item == "周日" ? "weekMark" : ""}}'>{{item}}</view>
</block>
</view>
</view>
<!-- 日期 -->
<view class="date-content">
<block wx:for='{{calendar}}' wx:for-item='calendarItem' wx:for-index='idx' wx:key="ids">
<view class='date-box'>
<view class="title aui-text-center">{{idx}}</view>
<view class="content aui-font-size-26">
<block wx:for='{{calendarItem}}' wx:key="index">
<view wx:if="{{item.isToday < toDay}}" class='days not-select'>
<view>{{item.dateNum}}</view>
</view>
<view wx:else class='days {{(item.isToday > inTime && item.isToday < outTime) || item.isToday == inTime || item.isToday == outTime ? "day-select" : ""}} {{item.is_select ==1 ? "not-select" : ""}}' data-id='{{item.dateNum}}' data-day='{{item.isToday}}' bindtap="dayClick">
<view class='{{item.isToday == outTime ? "day-select" : ""}}'>{{item.dateNum}}</view>
<view wx:if="{{item.dateNum!=undefined}}">
<view class='manfang aui-font-size-20 {{(item.isToday > inTime && item.isToday < outTime) || item.isToday == inTime || item.isToday == outTime ? "day-select" : ""}}' >
<block wx:if="{{item.is_select==1}}">
<view class=' aui-font-size-20' style="color:#fff" wx:if="{{item.isToday == outTime}}">
离开
</view>
<view class=' aui-font-size-20' wx:else>
满房
</view>
</block>
<block wx:else>
<view class=' aui-font-size-20' style="color:#fff" wx:if="{{item.isToday == inTime}}">
入住
</view>
<view class=' aui-font-size-20' style="color:#fff" wx:if="{{item.isToday == outTime}}">
离开
</view>
</block>
</view>
</view>
<!-- <view class='manfang aui-font-size-20' style="color:#fff" wx:if="{{item.isToday == inTime}}">
入住
</view>
<view class='manfang aui-font-size-20' style="color:#fff" wx:if="{{item.isToday == outTime}}">
离开
</view> -->
</view>
</block>
</view>
</view>
</block>
</view>
<view class="aui-bar aui-bar-tab aui-padded-15 footer" id="footer" wx:if="{{inTime!='' && outTime!=''}}" bindtap="sub">
<view class="aui-btn aui-btn-block aui-btn-theme aui-font-size-14">确定</view>
</view>
<view class="aui-bar aui-bar-tab aui-padded-15 footer" id="footer" wx:else>
<view class="aui-btn aui-btn-block aui-font-size-14" style="color:#fff">确定</view>
</view>
</view>
<view class="popup" wx:if="{{falg==1}}">
<view class="inner aui-padded-b-5">
<view class="aui-bar aui-bar-nav aui-bar-light aui-padded-r-5">
<view class="aui-pull-right aui-btn" bindtap="close">
<image src="/images/close2.png" mode="widthFix" style="width:40rpx;"></image>
</view>
</view>
<view class="aui-padded-15">
<view class="aui-text-center aui-text-gray aui-padded-b-15">您还不是唐宿的会员,立即开通会员资格?</view>
<radio-group class="radio-group" bindchange="radioChange">
<view class="aui-text-left aui-padded-t-5 aui-padded-b-5 aui-font-size-36 list">
<block wx:for="{{equitiesList}}" wx:key="kei">
<view class="aui-padded-b-10 aui-padded-t-10 nr">
{{item.name}}
<radio color="#FA8B1D" class="aui-pull-right" value="{{index}}" checked="{{sort==index?true:false}}"/>
<view class="aui-text-grayer aui-font-size-24 aui-padded-t-5" bindtap="xy" data-id="{{item.id}}">《{{item.name}}唐宿享有权益》</view>
</view>
</block>
</view>
</radio-group>
</view>
<view class="aui-text-gray aui-padded-l-15 aui-padded-b-10">
<checkbox-group bindchange="changese" >
<checkbox color="#FA8B1D" name="text" value="1" checked="{{agree==1?true:false}}" />
<text class="aui-font-size-24" bindtap="tk">同意《唐宿服务条款》</text>
</checkbox-group>
</view>
<view class="aui-padded-15" bindtap="pay">
<view class="aui-btn aui-btn-block aui-font-size-14 aui-btn-danger btn" style="background-color:#FA8B1D !important">确认支付</view>
</view>
</view>
</view>
css代码
@import '../aui.wxss';
@import '../common.wxss';
@import '../global.wxss';
page{
background-color: #fff;
margin-bottom: 180rpx;
}
.top{
position: fixed;
z-index: 9;
top: 0;
left: 0;
width: 100%;
background-color: #fff;
border-bottom: solid 1px #f5f5f5;
}
.reserve-time {
color: #cc4c2e;
line-height: 45px;
}
.reserve-time text {
color: #666;
margin: 0 10px 0 20px;
}
.page, .date-content {
width: 100vw;
/* background: #f4f4f4; */
}
.header{
font-size: 0;
padding: 0 24rpx;
background: #fff;
margin-top: 10rpx
}
.header>view{
display: inline-block;
width: 14.285%;
color: #333;
font-size: 12px;
text-align: center;
line-height: 30px;
}
.yearMonth {
font-size: 14px;
line-height: 35px;
color: #333;
padding-left: 10px;
box-sizing: border-box;
}
.header .weekMark{
color: #cc4c2e;
}
.content {
width: 100%;
background: #fff;
}
.date-content {
padding: 0 1%;
box-sizing: border-box;
margin-top: 180rpx;
}
.title {
line-height: 35px;
margin: 30rpx auto;
}
.days {
width: 14.28%;
text-align: center;
display: inline-block;
line-height: 50rpx;
height: 80rpx;
position: relative;
}
.days .manfang{
position: absolute;
top: 50rpx;
left: 0;
width: 100%;
text-align: center;
color: #AAAAAA;
line-height:20rpx;
height: 20rpx;
}
.day-select {
color: #fff;
background: #cc4c2e;
}
.not-select {
color: #999 !important;
}
.aui-btn-block{
height: 80rpx;
line-height: 80rpx;
}
.popup{
position: fixed;
background-color: rgb(0,0,0,0.5);
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 9999;
}
.popup .inner{
position: absolute;
top: 35%;
left: 50%;
width: 90%;
margin-left: -45%;
margin-top: -180rpx;
background-color: #fff;
}
radio {
transform:scale(0.8);
}
原文链接:原文链接
主要代码来自 逍遥生-前端 这位大神提供,我只是在原作者提供的源码的基础上再次根据需求更改了部分需求.