• 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不基于任何插件,可以自定义修改,自定义程度高

  • 相关阅读:
    Python实现常用的数据结构
    Python实现一些常用排序算法
    python实现简单排序算法
    Django学习-25-图片验证码实例
    Django学习-24-Ajax
    Django学习-23-ModelForm
    Django学习-22-Form
    Django学习-21-表关系参数
    Django学习-20-信号
    用"再生龙"Clonezilla 来克隆Linux系统
  • 原文地址:https://www.cnblogs.com/taihe/p/12180354.html
Copyright © 2020-2023  润新知