最近做一個酒店小程序日曆選擇的功能,於是想自己動手擼一個,有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;
}
以上就是全部了,主要參考以下大神的博客。有啥更好的優化歡迎評論。