最近由于小程序开发需要用到一个日历类似Airbnb日期选择的日历控件,由于在网上没找到合适的,于是干脆自己写一个,其实并不复杂,下面展示一下效果

其实这样的效果又一个缺陷,就是由于没有分页的效果,所以一次不能展示无限长时间,我这里展示的是最近一年的所有天数,废话不多说,贴代码了。
wxml代码:
<!--index.wxml-->
<view class="container">
<view class='content'>
<view class='top_week'>
<view class='week_text' wx:for='{{weeks_ch}}' wx:key='key' wx:item='{{item}}'>{{item}}</view>
</view>
<scroll-view scroll-y class='scrollview'>
<block wx:for='{{dataList}}' wx:key='key' wx:item='{{item}}'>
<view class='item_title'>
<view class='item_title_text'>{{item.year}}年{{item.month}}月</view>
</view>
<view class='item_data'>
<block wx:for='{{item.days}}' wx:key='sub_key' wx:for-item='sub_day'>
<view class="day_item {{sub_day.status==2?'enable_no':''}} {{sub_day.status==1?'cur_data':''}} {{sub_day.select==0?'start_time':''}} {{sub_day.select==2?'center_time':''}} {{sub_day.select==1?'end_time':''}} {{sub_day.select==4?'only_start_time':''}}" data-year="{{item.year}}" data-month="{{item.month}}" data-day="{{sub_day.day}}" data-select="{{sub_day.select}}" data-status="{{sub_day.status}}" bindtap="{{(sub_day.status!=3&&sub_day.status!=2)?'day_click':''}}">{{sub_day.day}}</view>
</block>
</view>
</block>
</scroll-view>
</view>
</view>
wcss代码如下:
.content{
display: flex;
flex-direction: column;
margin-left: 30px;
margin-right: 30px;
}
.filter_content{
display: flex;
flex-direction: column;
justify-content: center;
}
.barview{
display: flex;
height: 30px;
justify-content: center;
}
.bar{
position: relative;
width: 100%;
height: 30px;
}
.btn1{
position: absolute;
}
.person{
display: flex;
height: 30px;
justify-content: center;
}
.line-img{
background: gray;
width: 100%;
height: 1px;
}
.line{
display: flex;
justify-content: center;
}
.kedus{
width: 24px;
line-height: 50rpx;
text-align: center;
background-size: 24px 30px;
padding-top: 5rpx;
}
.no_sel_text{
color: gray;
font-size: 12px;
}
.sel_text{
color: #fff;
font-size: 9px;
}
.kedu{
display: flex;
width: 100%;
justify-content: space-between;
position: relative;
}
.kedu_img{
width: 24px;
height: 50rpx;
}
.showview{
display: flex;
justify-content: center;
}
.showtext{
color: #ff0000;
}
.space_type_view{
display: flex;
flex-direction: row;
flex-flow: wrap;
}
.space_type_item{
width: 30%;
height: 60rpx;
border-radius: 30rpx;
margin-top: 20rpx;
font-size: 30rpx;
line-height: 60rpx;
display:flex;
justify-content: center;
text-align: center;
}
.center_item{
margin-left: auto;
margin-right: auto;
}
.enable_no{
border: 1rpx solid #6D7C8D;
color: black;
}
.enable_yes{
border: 1rpx solid #E3E3E3;
color: gray;
}
.checked_yes{
background: #6EBB59;
border: 0rpx;
color: #fff;
}
.checked_no{
border: 1rpx solid #E3E3E3;
}
.submit{
position: fixed;
height:120rpx;
width: 100%;
bottom: 0rpx;
}
.result_view{
width: 650rpx;
height: 90rpx;
margin-left: auto;
margin-right: auto;
margin-top: 15rpx;
margin-bottom: 15rpx;
background: #49ae35;
color: #fff;
line-height: 90rpx;
font-size: 32rpx;
text-align: center;
}
.title_view{
margin-top: 30rpx;
color: #333333;
font-weight: bold;
}
js代码如下:
//index.js
var data_cal = require("../../utils/data_cal.js");
const app = getApp();
var cur_data = new Date();
Page({
data: {
weeks_ch:['日', '一', '二', '三', '四', '五', '六'],
dataList:null,
start_data:null,
end_data:null
},
onLoad: function () {
var year = cur_data.getFullYear();
var month = cur_data.getMonth()+1;
var day = cur_data.getDate();
this.initData(year,month-1);
},
//初始化日期数据
initData: function (cur_year, cur_month) {
var a = [];
for (var i = 0; i < 12; i++) {
if (cur_month + 1 > 12) {
cur_year = cur_year + 1;
cur_month = 1;
} else {
cur_month = cur_month + 1;
}
var mObject1 = this.calculateDays(cur_year, cur_month);
a[i] = mObject1;
}
this.setData({
dataList:a
});
},
// 获取当月有多少天(下个月月初是多少)
getThisMonthDays: function (year, month) {
return new Date(year, month, 0).getDate();
},
// 获取当月第一周第一天是周几
getFirstDayOfWeek: function (year, month) {
return new Date(Date.UTC(year, month - 1, 1)).getDay();
},
// 计算当前年月空的几天
calculateEmptyGrids: function (year, month) {
const firstDayOfWeek = this.getFirstDayOfWeek(year, month);
let empytGrids = [];
if (firstDayOfWeek > 0) {
for (let i = 0; i < firstDayOfWeek; i++) {
empytGrids.push(i);
}
}
return empytGrids;
},
calculateDays: function (year, month) {
var mObject = {}; //存入单月对象
mObject["year"] = year;
mObject["month"] = month;
var days = [];
var empytGrids = this.calculateEmptyGrids(year, month);
for (let i = 0; i < empytGrids.length; i++) { //把由于星期导致的空白的格子数添加进去
var day = {};
day["day"] = "";
day["status"] = 3;
day["select"] = 3;
days.push(day);
}
var thisMonthDays = this.getThisMonthDays(year, month);//这个月有多少天
//当前的时间
var cusDate = new Date(cur_data.getFullYear(), cur_data.getMonth(),cur_data.getDate());
for (let i = 1; i <= thisMonthDays; i++) {
var day = {};
//加入的时间
var date = new Date(year, month - 1, i);
//status 0-可选择(今后时间) 1-当前时间(今天) 2-不可被选择(过去时间) 3-空白格
//select 0-开头 1-结尾 2-中间 3-正常 4-只选择一个开始日期
day["day"] = i;
day["select"] = 3;
var time = parseInt(data_cal.calculateTime(date, cusDate));
if (time < 0) { //比现在的时间比较是大于还是小于,小于则不可点击
day["status"] = 0;
} else if (time == 0) {
day["status"] = 1;
} else {
day["status"] = 2;
}
days.push(day);
}
mObject["days"] = days;
return mObject;
},
//日期点击事件
day_click:function(e){
var obj = {};
obj.year = e.currentTarget.dataset.year;
obj.month = e.currentTarget.dataset.month;
obj.day = e.currentTarget.dataset.day;
obj.select = e.currentTarget.dataset.select;
obj.status = e.currentTarget.dataset.status;
if (this.data.start_data == null && this.data.end_data==null){ //开始时间
this.resetData(obj, null, this.data.dataList,0);
} else if (this.data.end_data == null && this.data.start_data != null){ //结束时间
var start = new Date(this.data.start_data).getTime();
var end_str = obj.year + "-" + obj.month + "-" + obj.day
var end = new Date(end_str).getTime();
if (end == start) {
this.resetData(null, obj, this.data.dataList, 1);
}else if(end<=start){
this.clearData(this.data.dataList);
this.resetData(obj, null, this.data.dataList,0);
}else{
this.resetData(null, obj, this.data.dataList,0);
}
} else if (this.data.end_data != null && this.data.start_data != null){ //重复开始
this.clearData(this.data.dataList);
this.resetData(obj, null, this.data.dataList,0);
}
},
//清除日期格式
clearData: function (data){
this.setData({
end_data: null,
start_data:null
});
for (var i = 0; i < data.length; i++) {
var d = data[i];
var days = d.days;
for (var j = 0; j < days.length; j++) {
var day = days[j];
day.select = 3;
}
}
this.setData({
dataList: data
});
},
//传入开始时间和结束时间和日期数组
resetData:function(startData,endData,data,types){
if(types == 1){
this.setData({
end_data: endData.year + "-" + endData.month + "-" + endData.day
});
}else{
if (startData == null && endData != null){
this.setData({
end_data: endData.year + "-" + endData.month + "-" + endData.day
});
var start = new Date(this.data.start_data).getTime();
var end = new Date(this.data.end_data).getTime();
for (var i = 0; i < data.length; i++) {
var d = data[i];
var days = d.days;
for (var j = 0; j < days.length; j++) {
var day = days[j];
var timeStr = d.year + "-" + d.month + "-" + day.day;
var time = new Date(timeStr).getTime();
if (time == start) {
if(day.status!=3){
day.select = 0;
}
}else if (time > start && time < end) {
day.select = 2;
} else if (time == end && day.day=="") {
day.select = 2;
} else if (time == end){
day.select = 1;
break;
}
}
}
} else if (startData != null && endData == null){
this.setData({
start_data: startData.year + "-" + startData.month + "-" + startData.day
});
for (var i = 0; i < data.length; i++) {
var d = data[i];
if (d.year == startData.year && d.month == startData.month){
var days = d.days;
for(var j=0;j<days.length;j++){
var day = days[j];
if (day.day == startData.day){
day.select = 4;
break;
}
}
}
}
}
this.setData({
dataList: data,
});
}
}
})
简单的日历选择控件就写出来了,很多时候看起来复杂,其实写得时候发现很简单,只要写出第一行代码就可以。
网友评论