微信小程序开发现在很火,在日益增长的需求上,也衍生了很多实用插件,本文介绍一个我自己写的日期多选插件,实现后的效果如下图:

实现方式如下:
一、wxml文件:
<scroll-view class="container" >
<!--------周列表---------->
<view class="week-list">
<view wx:for="{{week}}" wx:key="fweek" class="week">
{{item}}
</view>
<view class="clear"></view>
</view>
<view style="height: 2.4rem;"></view>
<!--------月列表---------->
<view wx:for="{{showYear}}" wx:key="fyear" wx:for-index="mk" wx:for-item="ylist" class="month-list">
<view class="year-month">
{{showYear[mk]}}年{{showMonth[mk]}}月
</view>
<view class="month-daybox">
<view wx:for="{{firstWeek[mk]}}" wx:key="ffk" wx:for-index="ffk" wx:for-item="fflist" class="month-day"></view>
<view wx:for="{{showMonthDays[mk]}}" wx:key="fmd" wx:for-index="mdk" wx:for-item="daylist" class="month-day {{mk == 0 && today > daylist?'disabled':(canChooseNum>1?(canChooseTimes[showMonthDaysTimestamp[mk][mdk]] == 1?'':'disabled'):'')}} {{continuityChoose[0] == showMonthDaysTimestamp[mk][mdk]||continuityChoose[1] == showMonthDaysTimestamp[mk][mdk]?'act':''}} {{continuityChoose.length >= 2&§ionDays[showMonthDaysTimestamp[mk][mdk]] == 1?'act-ctniu':''}}" bindtap="{{mk == 0 && today > daylist?'':(canChooseNum>1?(canChooseTimes[showMonthDaysTimestamp[mk][mdk]] == 1?'clickDays':''):'clickDays')}}" data-date="{{showYear[mk]}}-{{showMonth[mk]}}-{{daylist}}">
<view class="tip-box" style="{{tipPosition}}{{clickThat == showMonthDaysTimestamp[mk][mdk]&&continuityChoose.length==1?'display: block;':''}}">
<view>请选择离店日期</view>
<view>如需当日离店,请再次点击入住日期</view>
</view>
<view class="tip-triangle" style="{{clickThat == showMonthDaysTimestamp[mk][mdk]&&continuityChoose.length==1?'display: block;':''}}"></view>
<view wx:if="{{mk == 0 && today == daylist}}" class="today-sign">今天</view>
<view wx:else class="today-sign"></view>
<view>{{daylist}}</view>
<view wx:if="{{continuityChoose[0] == showMonthDaysTimestamp[mk][mdk]&&continuityChoose[1] != showMonthDaysTimestamp[mk][mdk]}}" class="today-sign">入住</view>
<view wx:elif="{{continuityChoose[1] == showMonthDaysTimestamp[mk][mdk]&&continuityChoose[0] != showMonthDaysTimestamp[mk][mdk]}}" class="today-sign">离店</view>
<view wx:elif="{{continuityChoose[0] == showMonthDaysTimestamp[mk][mdk]&&continuityChoose[1] == showMonthDaysTimestamp[mk][mdk]}}" class="today-sign">住/离</view>
<view wx:else class="today-sign"></view>
</view>
<view class="clear"></view>
</view>
</view>
</scroll-view>
二、js文件:
//index.js
//获取应用实例
const App = getApp()
Page({
data: {
week : ['日','一','二','三','四','五','六'],
showYear : [],
showMonth : [],
showMonthDays : [],
showMonthDaysTimestamp : [],
firstWeek : [],
today : 0,
//连续选择
continuityChoose : [],
//连续选择区间时间戳
sectionDays : {},
winWidth : 0,
tipPosition : '',
clickThat : '',
//一选择天数
chooseDays : 0,
currentPages : [],
//限制选择天数(为0时不限制)
initChooseNum : 10,
canChooseNum : 0,
canChooseTimes : {}
},
onLoad: function () {
let that = this
that.dateInit(2);
wx.getSystemInfo({
success(res) {
that.setData({
winWidth: res.windowWidth
})
}
})
let pages = getCurrentPages();
that.setData({
currentPages : pages
})
//初始化日期选项
let chooseDateObj = wx.getStorageSync(App.ccId+'_chooseDateObj')
if(chooseDateObj){
that.setData(chooseDateObj)
}
},
/**
* 初始化日历数据
* @param {number} showNum - 显示月份数
*/
dateInit: function (showNum) {
const date = new Date();
var showNum = showNum?showNum:1
var year = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate()
var showYear = [],showMonth = [],showMonthDays = [],showMonthDaysTimestamp = [],firstWeek = [];
for(var i = 0;i<showNum;i++){
if(month+1>12){
//目标月天数
var dayNums = new Date(year, month-1, 0).getDate();
//目标月第一天周几
var firstDayWeek = new Date(year, month-1, 1).getDay();
showYear.push(year);
showMonth.push(month);
var monthDays = [];
var monthDaysTimestamp = [];
for(var j = 1;j <= dayNums; j++){
monthDays.push(j)
monthDaysTimestamp.push(new Date(year+'/'+month+'/'+j).getTime()/1000)
}
showMonthDays.push(monthDays);
showMonthDaysTimestamp.push(monthDaysTimestamp);
var fdweekArr = [];
for(var k = 0;k<firstDayWeek;k++){
fdweekArr.push('');
}
firstWeek.push(fdweekArr);
month = 1;
year++;
}else{
//目标月天数
var dayNums = new Date(year, month, 0).getDate();
//目标月第一天周几
var firstDayWeek = new Date(year, month-1, 1).getDay();
showYear.push(year);
showMonth.push(month);
var monthDays = [];
var monthDaysTimestamp = [];
for(var j = 1;j <= dayNums; j++){
monthDays.push(j)
monthDaysTimestamp.push(Number(new Date(year+'/'+month+'/'+j).getTime())/1000)
}
showMonthDays.push(monthDays);
showMonthDaysTimestamp.push(monthDaysTimestamp);
var fdweekArr = [];
for(var k = 0;k<firstDayWeek;k++){
fdweekArr.push('');
}
firstWeek.push(fdweekArr);
month++;
}
}
this.setData({
showYear : showYear,
showMonth : showMonth,
showMonthDays : showMonthDays,
showMonthDaysTimestamp : showMonthDaysTimestamp,
firstWeek : firstWeek,
today : day
})
// console.log(showYear);
// console.log(showMonth);
// console.log(showMonthDays);
// console.log(firstWeek);
//console.log(showMonthDaysTimestamp);
},
//日期点击事件
clickDays : function(e){
let that = this
let nowDate = e.currentTarget.dataset.date
let continuityChoose = that.data.continuityChoose
let continuityChooseVal = []
let tipPosition = '';
let nowTimestamp = new Date(nowDate.replace(/-/g, '/')).getTime()/1000
let chooseDays = 0;
let sectionDays = {};
let offsetLeft = e.currentTarget.offsetLeft
let winWidth = that.data.winWidth
if(continuityChoose.length == 0 || continuityChoose.length >= 2){
tipPosition = that.setTipPosition(offsetLeft,winWidth);
continuityChooseVal = [nowTimestamp];
that.limitSelectionDays(nowTimestamp)
}else if(continuityChoose.length == 1){
continuityChooseVal = continuityChoose
//判断当前已选日期是否早于当前点击日期
let hasTimestamp = continuityChoose[0]
if(nowTimestamp<hasTimestamp){
tipPosition = that.setTipPosition(offsetLeft,winWidth);
continuityChooseVal = [nowTimestamp]
that.limitSelectionDays(nowTimestamp)
}else{
continuityChooseVal.push(nowTimestamp);
chooseDays = nowTimestamp-continuityChooseVal[0]
if(chooseDays > 0){
chooseDays = Math.ceil(chooseDays/(24*3600))+1
if(chooseDays > 2){
let startSectionTime = continuityChooseVal[0]
for(let i = 0;i < chooseDays-2; i++){
startSectionTime+=(24*3600)
sectionDays[startSectionTime] = 1
}
}
}else{
chooseDays+=1;
}
that.setData({
canChooseTimes : {},
canChooseNum : 0
})
}
}
that.setData({
continuityChoose : continuityChooseVal,
tipPosition : tipPosition,
clickThat : nowTimestamp,
sectionDays : sectionDays,
chooseDays : chooseDays
})
if(continuityChooseVal.length>=2){
setTimeout(function(){
if(that.data.currentPages.length<=1){
return false;
}
wx.setStorageSync(App.ccId+'_chooseDateObj', {
continuityChoose : continuityChooseVal,
sectionDays : sectionDays,
chooseDays : chooseDays
})
let url = '/'+that.data.currentPages[0].route;
wx.reLaunch({
url: url
})
},1000)
}
},
//设置tip位置
setTipPosition : function(offsetLeft,winWidth){
let tipPosition = '';
if(offsetLeft>winWidth/2){
if((winWidth-offsetLeft)/2 < 63){
tipPosition = 'right: 0;';
}else{
tipPosition = 'left: 50%;transform: translateX(-50%);';
}
}else{
if(offsetLeft < 63){
tipPosition = 'left: 0;';
}else{
tipPosition = 'left: 50%;transform: translateX(-50%);';
}
}
return tipPosition;
},
//将限制选择的天数之后全部设置为不可点状态(及列出可选日期时间戳)
limitSelectionDays : function(ntime){
let canChooseNum = this.data.initChooseNum
let canChooseTimes = {}
if(canChooseNum>=2){
for(let i=0;i<canChooseNum;i++){
canChooseTimes[ntime] = 1;
ntime=ntime+(24*3600)
}
}
this.setData({
canChooseTimes : canChooseTimes,
canChooseNum : canChooseNum
});
}
})
三、wxss文件:
.week-list{
position: fixed;
z-index: 3;
top: 0;
left: 0;
right: 0;
height: 2.4rem;
line-height: 2.4rem;
background-color: #ffffff;
}
.week-list .week{
float: left;
width: 14.2%;
text-align: center;
}
.month-list{
padding: 1rem;
padding-top: 0;
background-color: #ffffff;
}
.month-list .month-day{
position: relative;
float: left;
width: 14.2%;
height: 2.6rem;
padding: 0.2rem 0;
}
.month-list .month-day.act{
background-color: #FFD428;
}
.month-list .month-day.act-ctniu{
background-color: #f9e4ab;
}
.month-list .month-day .tip-box{
display: none;
position: absolute;
white-space: nowrap;
top: -2.6rem;
background-color: rgba(0,0,0,.5);
padding: 0.2rem 0;
width: 10.4rem;
border-radius: 0.3rem;
z-index: 2;
height: 1.6rem;
pointer-events:none;
font-weight: 400;
}
.tip-triangle{
display: none;
position: absolute;
left: 50%;
transform: translateX(-50%);
z-index: 2;
top: -0.6rem;
width: 0px; /* 宽高设置为0,很重要,否则达不到效果 */
height: 0px;
border: 0.3rem solid rgba(0,0,0,.5);
border-bottom-color: transparent; /* 设置透明背景色 */
border-left-color: transparent;
border-right-color: transparent;
}
.month-list .month-day .tip-box view{
font-size: 0.6rem;
height: 0.8rem;
line-height: 0.8rem;
color: #ffffff;
}
.month-list .month-day.disabled view{
color: #999999;
}
.month-list .month-day view{
text-align: center;
font-weight: 500;
height: 1rem;
line-height: 1rem;
}
.month-list .month-day .today-sign{
font-size: 0.6rem;
font-weight: 400;
height: 0.8rem;
line-height: 0.8rem;
}
.month-list .year-month{
text-align: center;
line-height: 2rem;
}
以上代码实现功能可能会和你想要的结果有出入,但可以进行修改后达到您想要的需求,其实不难。