欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

vue自定义日期选择,类似美团日期选择,日历控件,vue日历区间选择

程序员文章站 2022-05-04 12:02:07
一个日历的控件,基于vue的,可以日历区间选择,可用于酒店日历区间筛选,动手能力强,可以修改成小程序版本的,先上效果图 里面的颜色样式都是可以修改的 选择范围效果 话不多说,直接上干货,代码可以直接复制访问 1 2 3 ......

一个日历的控件,基于vue的,可以日历区间选择,可用于酒店日历区间筛选,动手能力强,可以修改成小程序版本的,先上效果图

vue自定义日期选择,类似美团日期选择,日历控件,vue日历区间选择

 

里面的颜色样式都是可以修改的

vue自定义日期选择,类似美团日期选择,日历控件,vue日历区间选择

 

选择范围效果

 

话不多说,直接上干货,代码可以直接复制访问

  1 <!doctype html>
  2 <html lang="en">
  3 <head>
  4     <meta charset="utf-8">
  5     <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no" />
  6     <meta name="renderer" content="webkit">
  7     <title></title>
  8 </head>
  9 <style>
 10 html,body{padding:0;margin:0;height:100%;}
 11 .header{
 12    width:100%;
 13    height:40px;
 14    text-align: center;
 15    position: relative;
 16    line-height: 40px;
 17 }
 18 .body{
 19    width: 100%;
 20    height:87%;
 21    height: -moz-calc(100% - 80px);
 22    height: -webkit-calc(100% - 80px);
 23    height: calc(100% - 80px);
 24    overflow-y: auto;
 25    position:absolute;
 26 }
 27 .golbal-left{
 28    width: 13px;
 29    height: 13px;
 30    border-top: 2px solid gainsboro;
 31    border-right: 2px solid gainsboro;
 32    transform: rotate(225deg);
 33    -webkit-transform: rotate(225deg);
 34    position: absolute;
 35    left: 16px;
 36    top: 15px;
 37 }
 38 .calendar {
 39   width: 100vw;
 40   text-align: center;
 41 }
 42 .week-title {
 43   overflow: hidden;
 44   position: fixed;
 45   margin-bottom: 1.5rem;
 46   background-color: #f6f6f8;
 47   z-index: 2;
 48 }
 49 .week-title>div {
 50   width: 14.28vw;
 51   height: 2rem;
 52   line-height: 2rem;
 53   float: left;
 54 }
 55 .box {
 56   position: absolute;
 57   top: 2rem;
 58   z-index: 1;
 59 }
 60 .data-title {
 61   height: 2rem;
 62   line-height: 2rem;
 63   border-top: 1px solid #ededed;
 64   border-bottom: 1px solid #ededed;
 65   clear: both;
 66 }
 67 .calendar-data {
 68   width: 100vw;
 69   clear: both;
 70 }
 71 .day {
 72   width: 14.28vw;
 73   height: 3rem;
 74   line-height: 1.6rem;
 75   float: left;
 76   display: flex;
 77   flex-direction: column;
 78 }
 79 .day.disabled{
 80   color:#ddd;
 81 }
 82 .active-start {
 83   color: white;
 84   background-color: #30b6af;
 85 }
 86 .active-start::after {
 87   content: '入住';
 88   font-size: .5rem;
 89 }
 90 .active {
 91   color: white;
 92   background-color: rgba(63,182,175,.5);
 93 }
 94 .active-end {
 95   color: white;
 96   background-color: #30b6af;
 97   position: relative;
 98 }
 99 .active-end::after {
100   content: '离开';
101   font-size: .5rem;
102 }
103 .active-end i{
104     position: absolute;
105     top:-120%;
106     width:100%;
107     height:100%;
108     background:rgba(0,0,0,1);
109     opacity:0.6;
110     border-radius:8px;
111     display: flex;
112     align-items: center;
113     justify-content: center;
114     font-style: normal;
115     font-size: 15px;
116     color:#fff;
117 }
118 .active-end i::after{
119     position: absolute;
120     content: '';
121     float: left;
122     width: 0; 
123     height: 0;
124     border-width: 10px;
125     border-style: solid;
126     border-color:#000 transparent transparent transparent;
127     opacity:1;
128     bottom:-20px;
129     left:50%;
130     margin-left:-10px;
131 }
132 .screenbottom{
133    height:35px;
134    width:100%;
135    display: flex;
136 }
137 .reset{
138    width:50%;
139    height:40px;
140    line-height: 40px;
141    color:#3e3e3e;
142    text-align: center;
143    background: #fff;
144 }
145 .determine{
146    width:50%;
147    height:40px;
148    line-height: 40px;
149    background: #48d8bf;
150    color:#fff;
151    text-align: center;
152 }
153 footer{
154     position: fixed;
155     bottom:0;
156     width:100%;
157 }
158 [v-cloak] 
159 {
160     display: none;
161 }
162 </style>
163 <body>
164     <div id='app' v-cloak>
165         <header class="header">
166           <span>时间范围</span>
167         </header>
168         <div class="body">
169             <div class='calendar'>
170                 <div class='week-title'>
171                     <div>日</div>
172                     <div>一</div>
173                     <div>二</div>
174                     <div>三</div>
175                     <div>四</div>
176                     <div>五</div>
177                     <div>六</div>
178                 </div>
179                 <div class='box'>
180                     <div class='calendar-body'>
181                         <div v-for="(item,index) in calendar">
182                             <!-- 标题 -->
183                             <div class='data-title'>
184                                 {{item.fullyear + '年' + item.fullmonth+'月'}}
185                             </div>
186                             <!-- 日期 -->
187                             <div class='calendar-data'>
188                                 <div class="day"                      
189                                 :class="item2.disabled + ' '+ item2.disabled2 + ' ' +item2.start_date + ' ' + item2.end_date +' ' + item2.active_date"  
190                                 v-for="(item2,index) in item.days" 
191                                 @click="selectdate(item2)">
192                                     {{item2.day}}
193                                 </div>
194                             </div>
195                         </div>
196                     </div>
197                 </div>
198             </div>
199         </div>
200         <footer>
201             <div class="screenbottom">
202                 <div class="reset">取消</div>
203                 <div class="determine">确定</div>
204             </div>
205         </footer>        
206     </div>
207 </body>
208 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
209  <script type="text/javascript">
210     let vm = new vue({
211          el:'#app',
212          data:{
213             start:'',              //开始时间。从当天开始。
214             calendar:[],
215             month_length: 6,       //最长预定多少个月后的房间  读取总店配置。
216             max_reserve_days: 0,   //最长预定天数。,一个月按30天计划
217             max_reserve_date: '',  //最长可预定的日期。例如:2019-09-12
218             select_start_ymd : '', //入住开始提交时间  例如:2019-5-8
219             select_start_show: '', //入住开始显示时间  例如:05月08日
220             select_end_ymd: '',    //离店开始提交时间  例如:2019-5-8
221             select_end_show: '',   //离店开始显示时间  例如:05月08日
222             select_index:'start',  //记录当前点击时间,所对应的时间是开始时间还是结束时间
223             select_all_day:''
224          },
225          methods:{
226            initdate:function(){
227                 var _this = this;
228                 // 创建时间对象
229                 let date = new date();
230                 //如果当前时间为凌晨6点前。则当前日期往前一天
231                 if (date.gethours() < 6) {
232                     date = new date(date.gettime() - 86400 * 1000);
233                 }
234                 // 获取完整年月
235                 let fulldate = [
236                     date.getfullyear(),
237                     date.getmonth() + 1,
238                     date.getdate(),
239                     date.getfullyear() + '-' + (date.getmonth() + 1) + '-' + date.getdate()
240                 ];
241                 /**
242                  * 从缓存拿已经设置的开始和结束日期
243                  * 如果第一次用户是第一次进入。则设置默认值为,并且保存进缓存。
244                  */
245                 var select_start_ymd = '';
246                 var select_start_ymd_show = '';
247                 var select_end_ymd = '';
248                 var select_end_ymd_show = '';
249 
250                 if (select_start_ymd == '' || select_start_ymd == undefined || select_start_ymd == 'undefined' || _this.comparedate(select_start_ymd, fulldate[3]) == 3) {
251                     select_start_ymd = date.getfullyear() + '-' + (date.getmonth() + 1) + '-' + date.getdate();
252                     select_start_ymd_show = _this.parsemonth(date.getmonth() + 1) + '月' + _this.parseday(date.getdate()) + '日';
253                 }
254 
255                 if (select_end_ymd == '' || select_end_ymd == undefined || select_end_ymd == 'undefined' || _this.comparedate(select_end_ymd, fulldate[3]) == 3) {
256                     let temp_date = new date(date.gettime() + 86400 * 1000)
257                     select_end_ymd = temp_date.getfullyear() + '-' + (temp_date.getmonth() + 1) + '-' + temp_date.getdate();
258                     select_end_ymd_show = _this.parsemonth(temp_date.getmonth() + 1) + '月' + _this.parseday(temp_date.getdate()) + '日';
259                 }
260                 //设置数据。并且保存缓存
261                 _this.select_start_ymd = select_start_ymd
262                 _this.select_end_ymd = select_end_ymd
263 
264                 //通过月份。计划最长可预定天数和日期  ,最后一天为离店时间。所以多加一天可选择
265                 let max_reserve_days = _this.month_length * 30 + 1;
266 
267                 //最大天数转换成毫秒数。再转换成时间
268                 let max_date = new date(date.gettime() + max_reserve_days * 24 * 60 * 60 * 1000);
269                 let max_reserve_date = max_date.getfullyear() + '-' + (max_date.getmonth() + 1) + '-' + max_date.getdate() + '';
270                 _this.max_reserve_days = max_reserve_days
271                 _this.max_reserve_date = max_reserve_date
272 
273                 //获取当前月份完整日期天数
274                 let cur_month_date = new date(fulldate[0] + '-' + _this.parsemonth(fulldate[1]) + '-01')
275                 let cur_month = {};
276                 cur_month.fullyear = fulldate[0]; //  年
277                 cur_month.fullmonth = fulldate[1];  //月
278                 cur_month.daylength = _this.getmonthdays(cur_month.fullmonth, cur_month.fullyear);//当前月份总共有多少天
279                 cur_month.firstdayweek = cur_month_date.getday();  //当前月份第一天星期几0~7
280                 cur_month.curday = date.getdate(); //当前天
281                 cur_month.days = [];
282                 //初始化天数
283                 var item = {};
284                 for (let i = 1; i <= cur_month.daylength; i++) {
285                     item = {
286                         ymd: cur_month.fullyear + '-' + cur_month.fullmonth + '-' + i,
287                         ymd_cn: _this.parsemonth(cur_month.fullmonth) + '月' + _this.parseday(i) + '日',
288                         day: i,
289                         disabled: i < cur_month.curday ? 'disabled' : '',
290                     };
291                     //开始时间
292                     item.start_date = _this.comparedate(_this.select_start_ymd, item.ymd) == 2 ? 'active-start' : '';
293                     //中间的日期
294                     item.active_date = (_this.comparedate(_this.select_start_ymd, item.ymd) == 3 && _this.comparedate(_this.select_end_ymd, item.ymd) == 1) ? 'active' : '';
295                     //结束时间
296                     item.end_date = _this.comparedate(_this.select_end_ymd, item.ymd) == 2 ? 'active-end' : '';
297                     //超过设置最长日期。禁止选择
298                     item.disabled2 = _this.comparedate(max_reserve_date, item.ymd) == 3 ? 'disabled' : '';
299                     cur_month['days'].push(item);
300                 }
301 
302                 //前补0
303                 if (cur_month.firstdayweek > 0) {
304                     for (let i = 0; i < cur_month.firstdayweek; i++) {
305                         cur_month['days'].unshift('');
306                     }
307                 }
308 
309                 _this.calendar.push(cur_month)
310 
311                 var next_month_date;
312                 var nextfulldate = [];
313                 for (let i2 = 0; i2 < _this.month_length; i2++) {
314                     //下一个朋的天数信息
315                     next_month_date = new date(fulldate[0], fulldate[1] + i2, '1');
316                     nextfulldate = [
317                         next_month_date.getfullyear(),
318                         next_month_date.getmonth() + 1,
319                     ]
320                     var next_month = {};
321                     next_month.fullyear = nextfulldate[0]; //  年
322                     next_month.fullmonth = nextfulldate[1];  //月
323                     next_month.daylength = _this.getmonthdays(next_month.fullmonth, next_month.fullyear);//当前月份总共有多少天
324                     next_month.firstdayweek = next_month_date.getday();  //当前月份第一天星期几0~6
325                     next_month.days = [];
326                      //初始化天数
327                     for (let i = 1; i <= next_month.daylength; i++) {
328                         item = {
329                             ymd: next_month.fullyear + '-' + next_month.fullmonth + '-' + i,
330                             ymd_cn: _this.parsemonth(next_month.fullmonth) + '月' + _this.parseday(i) + '日',
331                             day: i,
332                             active: '',
333                             disabled: '',
334                         };
335                         //开始时间
336                         item.start_date = _this.comparedate(_this.select_start_ymd, item.ymd) == 2 ? 'active-start' : '';
337                         //中间的日期
338                         item.active_date = (_this.comparedate(_this.select_start_ymd, item.ymd) == 3 && _this.comparedate(_this.select_end_ymd, item.ymd) == 1) ? 'active' : '';
339                         //结束时间
340                         item.end_date = _this.comparedate(_this.select_end_ymd, item.ymd) == 2 ? 'active-end' : '';
341                         //超过设置最长日期。禁止选择
342                         item.disabled2 = _this.comparedate(max_reserve_date, item.ymd) == 3 ? 'disabled' : '';
343                         next_month['days'].push(item);
344                     }
345                     //前补0
346                     if (next_month.firstdayweek > 0) {
347                         for (let i = 0; i < next_month.firstdayweek; i++) {
348                         next_month['days'].unshift('');
349                         }
350                     }
351                     _this.calendar.push(next_month)
352                 }
353                 console.log(_this.calendar);
354             },
355                         //格式月份期
356             parsemonth: function(month){
357                 month = parseint(month);
358                 if(month <10){
359                     month = '0'+month
360                 }
361                 return month;
362             },
363 
364             //格式天
365             parseday: function (day) {
366                 day = parseint(day);
367                 if (day < 10) {
368                 day = '0' + day
369                 }
370                 return day;
371             },
372             // 获取每个月的天数
373             getmonthdays(m, year) {
374                 let days = [0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
375                 if (m != 2) {
376                     return days[m];
377                 }
378                 if ((year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0 && year % 100 === 0)) {
379                     return 29
380                 } else {
381                     return 28
382                 }
383             },
384             comparedate(date1, date2){
385                 var dateone = date1.replace(/-/g,'/');
386                 var datetwo = date2.replace(/-/g,'/');
387                 var odate1 = new date(dateone)
388                 var odate2 = new date(datetwo)
389                 if(odate1.gettime() > odate2.gettime()){
390                     return 1; //大于
391                 } else if (odate1.gettime() == odate2.gettime()) {
392                     return 2; //等于
393                 }else{
394                     return 3; //小于
395                 }
396             },
397             //点击日期按钮
398             selectdate:function(item){
399                 var _this = this;
400                 let select_data = item;
401                 console.log(select_data)
402                 let select_start_ymd = _this.select_start_ymd;
403                 let select_end_ymd = _this.select_end_ymd;
404                 //如果是点击不能用的地址
405                 if (select_data.disabled != ''){
406                     return false;
407                 }
408                 if (_this.select_index == 'start') {
409                     select_start_ymd = select_data.ymd;
410                     //如果选择的日期。是当前日期。或者比当前开始日期还早的。就 要把当前日期变为开始日期
411                    
412                     _this.select_start_ymd = select_start_ymd;
413                     _this.select_start_ymd_show = select_data.ymd_cn;
414                     _this.select_end_ymd = '';
415                     _this.select_end_ymd_show = '';
416 
417                     //将索引改为结束时间
418 
419                     _this.select_index = 'end';
420 
421                 } else if (_this.select_index == 'end'){
422                     let v = _this.comparedate(select_start_ymd, select_data.ymd)
423                     //如果选择的时间大于开始时间。则有效。否则重置开始时间
424                     if(v == 3 ){
425                         _this.select_end_ymd = select_data.ymd;
426                         _this.select_end_ymd_show = select_data.ymd_cn;
427                         //将索引改为结束时间
428                         _this.select_index = 'start';
429                         //保存数据到缓存
430                         _this.savedate();
431                     }else{
432                         _this.select_start_ymd = select_data.ymd;
433                         _this.select_start_ymd_show = select_data.ymd_cn;
434                         _this.select_end_ymd = '';
435                         _this.select_end_ymd_show = '';
436                         //将索引改为结束时间
437                         _this.select_index = 'end';
438                     }
439 
440                 }
441                 _this.resetcalendar();
442             },
443             //重新计算一下日历
444             resetcalendar:function(){
445                 let _this = this;
446                 let calendar = _this.calendar;
447                 if(calendar.length > 0 ){
448                     for (var i in calendar){
449                         if(calendar[i]['days'].length > 0 ){
450                             for (var i2 in calendar[i]['days']) {
451                                 if (calendar[i]['days'][i2] != ''){
452                                     //开始时间
453                                     calendar[i]['days'][i2]['start_date'] = _this.comparedate(_this.select_start_ymd, calendar[i]['days'][i2]['ymd']) == 2 ? 'active-start' : '';
454                                     //中间的日期
455                                     calendar[i]['days'][i2]['active_date'] = (_this.comparedate(_this.select_start_ymd, calendar[i]['days'][i2]['ymd']) == 3 && _this.comparedate(_this.select_end_ymd, calendar[i]['days'][i2]['ymd']) == 1) ? 'active' : '';
456                                     //结束时间
457                                     calendar[i]['days'][i2]['end_date'] = _this.comparedate(_this.select_end_ymd, calendar[i]['days'][i2]['ymd']) == 2 ? 'active-end' : '';
458                                 }
459                             }    
460                         }
461                     }
462                 }
463 
464                 _this.calendar = calendar;
465             },
466             //如果设置结束时间成功。保存一次当前时间。并且计算总天数。到缓存中
467             savedate:function(){
468                 var _this = this;
469                 var date1 = new date(this.select_start_ymd.replace(/-/g,'/'));
470                 var date2 = new date(this.select_end_ymd.replace(/-/g,'/'));
471                 //计算天数
472                 var days = parseint((date2.gettime() - date1.gettime()) / 1000 / 86400);
473                 //保存缓存
474                 _this.select_all_day = days;
475             }
476          },computed:{
477 
478          },mounted(){
479             var _this = this;
480             _this.$nexttick(function () {
481                 _this.initdate()
482             })
483          }
484     })
485  </script>
486 </html>

 

 

 里面的备注很清晰,需要存起来下个页面用可以在savedate这个函数中存进去localstorage中。

案例除了vue不基于任何插件,可以自定义修改,自定义程度高