最近做一个酒店小程序日历选择的功能,于是想自己动手撸一个,有app基础所以做起来不算太难再加上参考网上的一些例子。不多说直接上图(gif懒得搞)
给图片说明下,图片是截图微信传过来的所以有点不清楚。这是有点仿途家的效果图,上面数据都是自己造的,变成自己的数据结构自己转一转就可以了。今天以前的日期是划线的状态,然后有个无房的状态(这个数据是自己造的临时数据),图一是连续选了多天的效果图,图二是单选的效果图,图三是点到中间有无房的效果图,图四就是两个连续的效果图。
简单说完后就直接上代码吧。
var utils = require('../utils/util.js')
Page({
data: {
calendar: [],
// 构建顶部日期时使用
date: ['日', '一', '二', '三', '四', '五', '六'],
inTime: '', //入住时间
outTime: '', //离开时间
text_in: '入住',
text_out:'',
old_id:-1,
old_title:''
},
// 日历初始化
dataInit(setYear, setMonth) {
var now_today = utils.year_month_day();
// 当前时间/传入的时间
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;
var month_day = year + '-' + (month < 10 ? '0' + month : month) + '-' + (num < 10 ? '0' + num : num);
obj = {
/*
* 返回值说明
* today : 2018-12-27 当前时间
* dateNum : 27
*/
today: year + '-' + (month < 10 ? '0' + month : month) + '-' + (num < 10 ? '0' + num : num),
dateNum: now_today === month_day ? '今天' : num,
// price: (new Date(now_today) <= new Date(month_day)) ?'¥234':'',
// canclick: (new Date(now_today) <= new Date(month_day)) ? true : false,
price: (new Date(now_today) <= new Date(month_day)) ? num % 3 == 0 ? '' : '¥234':'',
canclick: (new Date(now_today) <= new Date(month_day)) ? num%3==0?1:2 : 0,//0表示今天之前的日期1表示无房2表示有房可点
text_out:'',
wufang: num % 3 == 0 ? (new Date(now_today) <= new Date(month_day))?'无房':'':''
}
} else {
// 填补空缺
// 例如2018-12月第一天是星期6,则需要补6个空格
obj = {};
}
dateArr[i] = obj;
};
return dateArr;
},
// 点击了日期,选择入住时间或者离店时间
dayClick(e) {
var that = this;
var eTime = e.currentTarget.dataset.day;
var canclick = e.currentTarget.dataset.canclick;
var id = e.currentTarget.id;
var title = e.currentTarget.dataset.title;
var inTime = that.data.inTime;
var outTime = that.data.outTime;
if (canclick == 0 || canclick==null)
return;
if (inTime == '' || (new Date(eTime) <= new Date(inTime)) || outTime != '') {
if(canclick==1)
return;
// 如果入住时间为空或选择的时间小于等于入住时间,则选择的时间为入住时间
inTime = eTime;
outTime = '';
if (that.data.old_id == -1) {
} else {
that.data.calendar[that.data.old_title][that.data.old_id]['text_out'] = '';
}
} else {
outTime = eTime;
// console.log(id);
var istrue = that.juge_same_date(that.getAll(inTime, outTime), that.out_canclick());
if (istrue){
wx:wx.showToast({
title: '中间有无房不可选',
icon: 'none',
})
}
if (istrue)
return;
that.data.calendar[title][id]['text_out']='离开';
that.data.old_id = id;
that.data.old_title = title;
}
that.setData({
inTime,
outTime,
old_id: that.data.old_id,
text_out:that.data.text_out,
calendar: that.data.calendar
})
},
// 获取所有包含无房的时间
out_canclick(){
var that = this;
var arry_year=[];
for (var key in that.data.calendar){
// console.log(key);
var arry = that.data.calendar[key];
var size =arry.length;
for (var i = 0; i < size; i++) {
if (arry[i]['canclick']==1){
arry_year.push(arry[i]['today']);
}
}
}
// console.log(arry_year);
return arry_year;
},
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);
},
//获取点击范围内的时间段
getAll: function (begin, end) {
var vm =this;
// 开始日期和结束日期
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; // 返回两个日期之间的所有日期数组。
},
//判断两个时间里面有没有相同的时间
juge_same_date(arry1,arry2){
var size_chouse =arry1.length;
var size_wufang = arry2.length;
// console.log(arry1);
// console.log(arry2);
var have = -2;
var ishave = false;
for(var i=0;i<size_wufang;i++){
for(var j=0;j<size_chouse-1;j++){
if(arry2[i]===arry1[j]){
have = 1;
break;
}
}
if(have==1)
break;
}
if(have==1){
ishave =true;
}
console.log(ishave);
return ishave;
},
onLoad(options) {
var that = this;
// 获取本月时间
var nowTime = new Date();
var year = nowTime.getFullYear();
var month = nowTime.getMonth();
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 = that.dataInit(year, month);
// 接收数据
timeArray[year + '年' + (month < 10 ? '0' + month : month) + '月'] = time;
};
that.setData({
calendar: timeArray
});
},
})
以上是js的代码。
继续
<view class="page">
<view class="reserve-time">
<text class="time_text">入住时间</text>{{inTime}}
<text class="time_text">离店时间</text>{{outTime}}
</view>
<!-- 星期 -->
<view class="line"></view>
<view class='header'>
<!-- <view wx:for='{{date}}' class='{{item == "周六" || item == "周日" ? "weekMark" : ""}}'>{{item}}</view> -->
<view wx:for='{{date}}' wx:key='index'>{{item}}</view>
</view>
<!-- 日期 -->
<view class="date-content">
<view class='date-box' wx:for='{{calendar}}' wx:key='index' wx:for-item='calendarItem' wx:for-index='idx'>
<view class="title">{{idx}}</view>
<view class="content">
<view wx:for='{{calendarItem}}' wx:key='index' class='days {{(item.today > inTime && item.today < outTime) ? "day-select" :item.today == inTime?outTime===""?"day-start-first-select":"day-start-select":item.today == outTime ?"day-end-select":"not-select"}}' id='{{index}}' data-title='{{idx}}' data-canclick='{{item.canclick}}'
data-id='{{item.dateNum}}' data-day='{{item.today}}' bindtap="dayClick">
<view class="show_center">
<!-- <view class="price">{{text_out}}</view> -->
<view class="{{item.canclick!=0?item.canclick==1?'wufang':'':'unclick'}}">{{item.dateNum}}</view>
<view class="price">{{''===item.text_out?item.price:item.text_out}}</view>
<view class="wufang">{{''===item.text_out?''===item.wufang?item.wufang:item.wufang:''}}</view>
</view>
</view>
</view>
</view>
</view>
</view>
以上是页面的代码。
以下是css的样式
.reserve-time {
color: #f40;
line-height: 35px;
font-size: 30rpx;
}
.time_text {
font-size: 30rpx;
}
.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;
padding-top: 10rpx;
padding-bottom: 10rpx;
}
.line {
width: 100%;
background: #f00;
height: 1rpx;
}
.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: #ff3930;
}
.content {
width: 100%;
background: #fff;
}
.date-content {
padding: 0 1%;
box-sizing: border-box;
}
.title {
display: flex;
justify-content: center;
line-height: 35px;
align-items: center;
padding-bottom: 10rpx;
padding-top: 10rpx;
}
.days {
display: inline-block;
width: 14.28%;
height: 100rpx;
vertical-align: middle;
overflow: auto;
}
.day-select {
color: #fff;
background:coral;
box-sizing: border-box;
font-size: 30rpx;
}
.day-start-select {
color: #fff;
background: #ff5128;
border-radius: 10rpx 0rpx 0rpx 10rpx;
box-sizing: border-box;
font-size: 30rpx;
}
.day-start-first-select {
color: #fff;
background: #ff5128;
border-radius: 10rpx 10rpx 10rpx 10rpx;
box-sizing: border-box;
font-size: 30rpx;
}
.day-end-select {
color: #fff;
background: #ff5128;
border-radius: 0rpx 10rpx 10rpx 0rpx;
box-sizing: border-box;
font-size: 30rpx;
}
.not-select {
color: #333;
font-size: 30rpx;
}
.price {
font-size: 25rpx;
}
.unclick {
color: gainsboro;
text-decoration: line-through;
}
.wufang{
color: gainsboro;
font-size: 25rpx;
}
.show_center {
display: flex;
flex-direction: column;
align-items: center;
height: 100rpx;
justify-content: center;
}
以上就是全部了,主要参考以下大神的博客。有啥更好的优化欢迎评论。