• VUE自定义(有限)库存日历插件


    开发过程中遇到一个令人发指的,一个element-ui无法满足的日历需求, 改造其日历插件的代价太大,于是索性自己手写一个,需求如下:

    1. 根据开始、结束时间计算时间覆盖的月份,渲染有限的可选择日期 

    2. 日期下显示每日库存,库存为0的日期不可选择,同时不可作为中间日期被包含选择

    3. 根据传入的默认选择日期初始化选择状态,若没有传入默认选择日期,初始化选择开始与结束时间

    3. 其余功能与正常日历插件相同

    基本思路: 1. 根据传入日期列表的开始与结束时间计算一共有几个月份,根据月份生成数组,数组内存放每月的覆盖天数,

                       2. 遍历月份数组 ,计算当前月份的一号是周几,根据这个补全当月时间,设置每天的选择状态(0:未选择,1:连带选择,2:被点击选择)为0,并初始化每个覆盖天数的库存,补全的其余天数库存设为0

                       3. 将每月补全的数据放入新数组,作为渲染每月Tab页的数据源

          4. 设置全局的开始与结束日期的选择状态,点击日期,判断设置开始日期选择状态为false,则记录开始时间并将状态设置为true,若开始日期状态为true则记录结束日期并设置结束日期选择状态为true,若结束日期状态为true则关闭选择框,并为父组件的开始与结束时间重新赋值

          5. 每次开启选择框则设置开始与结束日期选择状态为false

    插件使用:

    <data-picker :datedata="planDateList" :initstartdate='initstartdate' :initenddate='initenddate' :startdate='saleDate[0]' :enddate='saleDate[1]' :planid='resSalePlanId'></data-picker>

     效果图  :

    插件代码如下:

      1  Vue.component('data-picker', {
      2         props: [
      3             'datedata',
      4             'startdate',
      5             'enddate',
      6             'planid',
      7             'initstartdate',
      8             'initenddate'
      9         ],
     10         data: function () {
     11             return {
     12                 currentDay: 1,
     13                 currentMonth: 1,
     14                 premonthDays: 0,
     15                 currentYear: 2002,
     16                 currentWeek: 1,
     17                 days: [],
     18                 daysTemplate: [01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31],
     19                 monthCountArr: [31,29,31,30,31,30,31,31,30,31,30,31],
     20                 index: 0,
     21                 startWeekNum: 1,
     22                 monthArr: [],
     23                 monthDataArr:[],//整月数据
     24                 startDate: '',
     25                 startDateFlag: false,
     26                 startIndex: 0,
     27                 endDate: '',
     28                 endDateFlag: false,
     29                 endIndex: 0,
     30                 selStartMonthIndex: 0,
     31                 selEndMonthIndex: 0,
     32                 show: false,
     33                 errorFlag: true,//选择库存错误标志
     34                 allMonthData:[],//存放所有月份处理过后的数据
     35                 allMonthData:[],//存放所有月份处理过后的数据
     36                 
     37             }
     38         },
     39         mounted: function() {  //在vue初始化时调用
     40             this.initData();
     41         },
     42         component:{},
     43         methods: {
     44             initData: function(){
     45                 this.monthArr = []
     46 
     47                 this.startDate = this.startdate;
     48                 this.endDate = this.enddate;
     49                 //计算出有几个月  [{11:'11',days:['2-18-10-22']},{}]
     50                 var dateArr = this.datedata,
     51                     obj = {},
     52                     count = 0;
     53                 //按月份分组放数据 
     54                 for(var i=0; i<dateArr.length;i++){
     55                     var month = dateArr[i].startDate.split("-")[1];
     56                     if(!obj[month]){
     57                         count++;
     58                         obj[month] = month;
     59                         var dateObj = {};
     60                         //dateObj.leftAmount = dateArr[i].leftAmount;
     61                         dateObj.days = [];
     62                         dateObj.days.push({date:dateArr[i].startDate, leftAmount:dateArr[i].leftAmount, hasAmount: true});
     63                         dateObj[month] = month;
     64                         this.monthArr.push(dateObj);
     65                     }else{
     66                         this.monthArr[count-1].days.push({date:dateArr[i].startDate, leftAmount:dateArr[i].leftAmount, hasAmount: true})
     67                     }
     68                 }
     69                 //console.log(this.monthArr);
     70 
     71                 //初始化所有月数据
     72                 for(var m=0; m<this.monthArr.length;m++){
     73                     this.getCurMonthData(m);
     74                 }
     75 
     76                 //this.getCurMonthData(this.index);
     77 
     78                 //初始化选择
     79                 var start='',end='';
     80                 this.startDateFlag = false;
     81                 this.endDateFlag = false;
     82                 if(this.initstartdate && this.initenddate ){//有初始值
     83                     start = this.initstartdate;
     84                     end = this.initenddate;
     85                 }else{
     86                     start = this.startDate;
     87                     end = this.endDate;
     88                 }
     89                 for(var j=0; j<this.allMonthData.length; j++){
     90                     for(var k=0; k<this.allMonthData[j].length; k++){
     91 
     92                         if(this.allMonthData[j][k].date == start){
     93                             this.index = j;
     94                             this.monthDataArr = this.allMonthData[j];
     95                             this.selectDay(k, this.allMonthData[j][k]);
     96                         }
     97                         if(this.allMonthData[j][k].date == end){
     98                             this.index = j;
     99                             this.monthDataArr = this.allMonthData[j];
    100                             this.selectDay(k, this.allMonthData[j][k]);
    101                             break;
    102                         }
    103                     }
    104                     
    105                 }
    106 
    107                  //初始化第一页
    108                  this.index = 0;
    109                  this.currentMonth = this.monthArr[0].days[0].date.split("-")[1];
    110                  this.currentYear = this.monthArr[0].days[0].date.split("-")[0];
    111                  this.monthDataArr = this.allMonthData[0];
    112                  this.show = false;
    113             },
    114             pickPre: function(currentYear,currentMonth,index){
    115                 if(this.index >0){
    116                     this.index--;
    117                     if(!this.allMonthData[this.index]){//allMonthData
    118                         //更新数据
    119                         this.getCurMonthData(this.index);
    120                     }else{
    121                         this.currentMonth = this.monthArr[this.index].days[0].date.split("-")[1];
    122                         this.currentYear = this.monthArr[this.index].days[0].date.split("-")[0];
    123                         this.monthDataArr = this.allMonthData[this.index];
    124                         //重置其他月份的选择状态
    125                         //this.clearSelect(this.index);
    126                     }
    127                 }else{
    128                     return;
    129                 }
    130             },
    131             pickNext: function(currentYear,currentMonth,index){
    132                 if(this.index < this.monthArr.length-1){
    133                     this.index++;
    134                     if(!this.allMonthData[this.index]){//allMonthData
    135                         //更新数据
    136                         this.getCurMonthData(this.index);
    137                     }else{
    138                         this.currentMonth = this.monthArr[this.index].days[0].date.split("-")[1];
    139                         this.currentYear = this.monthArr[this.index].days[0].date.split("-")[0];
    140                         this.monthDataArr = this.allMonthData[this.index];
    141                         //重置其他月份的选择状态
    142                         //this.clearSelect(this.index);
    143                     }
    144                 }else{
    145                     return;
    146                 }
    147             },
    148             //重置其他月份的选择状态
    149             clearSelect: function(curIndex){
    150                 for(var i=0; i<this.allMonthData.length; i++){
    151                     if(i !== curIndex){
    152                         for(var j=0; j<this.allMonthData[i].length; j++){
    153                             this.allMonthData[i][j].selectStatus = 0;
    154                         }
    155                     }
    156                 }
    157             },
    158             //根据当前选择月份整理数据 index
    159             getCurMonthData: function(index){
    160                 this.currentMonth = this.monthArr[index].days[0].date.split("-")[1];
    161                 this.currentYear = this.monthArr[index].days[0].date.split("-")[0];
    162 
    163                 //判断是否是闰年
    164                 if(this.isLeapYear(this.currentYear)){
    165                     this.monthCountArr = [31,28,31,30,31,30,31,31,30,31,30,31];
    166                 }else{
    167                     this.monthCountArr = [31,29,31,30,31,30,31,31,30,31,30,31];
    168                 }
    169 
    170                 //计算当前月的第一天是周几 dateArr[0].startDate
    171                 this.startWeekNum = this.getStartWeekNum(this.monthArr[index].days[0].date);
    172                 
    173                 //初始化当前默认月的天数
    174                 var monthDays = this.monthCountArr[parseInt(this.currentMonth)-1];
    175                 this.days = this.daysTemplate.slice(0,monthDays);
    176                 //获取前一个月有多少天
    177                 this.premonthDays=0;
    178                 if(this.currentMonth == 1){
    179                     this.premonthDays = 31;
    180                 }else{
    181                     this.premonthDays = this.monthCountArr[parseInt(this.currentMonth)-2];
    182                 }
    183 
    184                 //处理整月数据并格式化当前月的日期 31 -- 2018-10-31
    185                 for(var n=0;n<this.days.length; n++){
    186                     this.days[n] = this.currentYear + '-' + this.currentMonth + '-' + (this.days[n] > 9 ? this.days[n] : '0'+ this.days[n]);
    187                 }
    188                 //初始化当前框的日期数组 比如: 一号在周四 则数组前加入 28,29,30,31 或 27,28,29,30 或,26,27,28,29 或25,26,27,28
    189                 for(var k=parseInt(this.startWeekNum); k>0; k--){
    190                     this.days.unshift( (this.currentMonth == 1 ? this.currentYear-1 : this.currentYear) + '-' + (this.currentMonth == 1 ? 12 : this.currentMonth-1) + '-' + (this.daysTemplate[this.premonthDays-k] > 9 ? this.daysTemplate[this.premonthDays-k] : '0'+this.daysTemplate[this.premonthDays-k]) )
    191                 }
    192                 //console.log(this.days);
    193                 //处理形成整月数据
    194                 this.handelTheMonthData(this.days,this.monthArr,index);
    195             },
    196             //处理形成整月数据 monthDataArr
    197             handelTheMonthData: function(days,monthArr,index){
    198                 
    199                     this.monthDataArr = [];
    200                     var curMonthData = this.monthArr[index].days;
    201                     for(var n=0;n<days.length; n++){
    202                         var obj={},flag = false,leftAmount=0;
    203                         for(var m=0; m<curMonthData.length; m++){
    204                             if(new Date(curMonthData[m].date).getTime() == new Date(days[n]).getTime() ){//当前日期存在库存
    205                                 flag = true;
    206                                 leftAmount = curMonthData[m].leftAmount;
    207                             }
    208                         }
    209                         if(flag){
    210                             obj.date = days[n];
    211                             obj.leftAmount = leftAmount;
    212                             obj.selectStatus = 0; //0:未选择 1:连带选择 2:被选中
    213                             this.monthDataArr.push(obj);
    214                         }else{
    215                             obj.date = days[n];
    216                             obj.leftAmount = 0;
    217                             obj.selectStatus = 0; //0:未选择 1:连带选择 2:被选中
    218                             this.monthDataArr.push(obj);
    219                         }
    220                     }
    221                     this.allMonthData[index] = this.monthDataArr;
    222                     //console.log(this.allMonthData);
    223                     return this.monthDataArr;
    224                
    225             },
    226             //计算当前月的第一天是周几
    227             getStartWeekNum: function(date){
    228                 var date = new Date(date);
    229                 date.setDate(1);
    230                 //console.log(date.getDay())
    231                 return date.getDay();
    232             },
    233             //判断是否是闰年
    234             isLeapYear: function(year){
    235                 if((year%4==0 && year%100!=0) || year%400==0){
    236                     return true;
    237                 }else{
    238                     return false;
    239                 }
    240             },
    241             pickUp: function(){
    242                 this.show = !this.show;
    243                 this.startDateFlag = false;
    244                 this.endDateFlag = false;
    245             },
    246             selectDay: function(index,dayobject){//this.startDate  this.endDate
    247                 //判断当前是否可点击
    248                 if(dayobject.leftAmount == 0){
    249                     return;
    250                 }
    251                 //console.log(dayobject);
    252 
    253                 self.errorFlag = true;
    254                 //初始化各日期selectStatus值
    255                 for(var i=0; i<this.monthDataArr.length; i++){
    256                     this.monthDataArr[i].selectStatus = 0;
    257                 }
    258 
    259                 if(this.startDateFlag){
    260                     this.endDate = dayobject.date;
    261                     this.endDateFlag = true;
    262                     this.endIndex = index;
    263                     this.selEndMonthIndex = this.index;
    264                 }else{
    265                     this.startDate = dayobject.date;
    266                     this.startDateFlag = true;
    267                     this.startIndex = index;
    268                     this.selStartMonthIndex = this.index;
    269                     //重置其他月份的选择状态
    270                     this.clearSelect(this.index);
    271                 }
    272                 //设置selectStatus值  :class="{{"select":(dayobject.selectStatus == 2),"subSelect":(dayobject.selectStatus == 1) }}" 
    273                 this.monthDataArr[index].selectStatus = 2;
    274 
    275                 if(this.endDateFlag){//判断是否可连续选择 计算连续时间 若可连续设置selectStatus值 关闭弹窗 
    276                     //判断大小是否颠倒
    277                     if(this.selStartMonthIndex > this.selEndMonthIndex || (this.selStartMonthIndex==this.selEndMonthIndex && this.startIndex>this.endIndex) ){
    278                         var box,dateBox,indexBox;
    279                         box = this.selStartMonthIndex;
    280                         this.selStartMonthIndex = this.selEndMonthIndex;
    281                         this.selEndMonthIndex = box;
    282 
    283                         indexBox = this.startIndex;
    284                         this.startIndex = this.endIndex;
    285                         this.endIndex = indexBox;
    286 
    287                         dateBox = this.startDate;
    288                         this.startDate = this.endDate;
    289                         this.endDate = dateBox;
    290                     }
    291 
    292                     //判断是否跨月
    293                     var startMonth = this.startDate.split("-")[1];
    294                     if(this.selEndMonthIndex !== this.selStartMonthIndex){//不同月 startMonth !== this.currentMont
    295                         //获取开始月的index 开始月到月尾 开始月到结束月的中间月的全部 以及结束月到点击时间 selectStatus变为1
    296                         for(var i=this.selStartMonthIndex; i<this.selEndMonthIndex+1; i++){
    297                             for(var j=0; j<this.allMonthData[i].length; j++){
    298 
    299                                 // if(this.allMonthData[i][j].leftAmount == 0){//
    300                                 //     self.errorFlag = false;
    301                                 //     return;
    302                                 // }
    303                                 
    304                                 if(i==this.selStartMonthIndex && j == this.startIndex && this.allMonthData[i][j].leftAmount !==0){//开始月点击的第一天
    305                                     this.allMonthData[i][j].selectStatus = 2;
    306                                 }else if(i==this.selStartMonthIndex && j > this.startIndex && this.allMonthData[i][j].leftAmount !==0){//开始月其它天
    307                                     this.allMonthData[i][j].selectStatus = 1;
    308                                 }else if(i==this.selEndMonthIndex && j == this.endIndex && this.allMonthData[i][j].leftAmount !==0){//结束月电机的最后一天
    309                                     this.allMonthData[i][j].selectStatus = 2;
    310                                 }else if(i==this.selEndMonthIndex && j < this.endIndex && this.allMonthData[i][j].leftAmount !==0){
    311                                     this.allMonthData[i][j].selectStatus = 1;
    312                                 }else if(i<this.selEndMonthIndex && i>this.selStartMonthIndex && this.allMonthData[i][j].leftAmount !==0){//中间月
    313                                     this.allMonthData[i][j].selectStatus = 1;
    314                                 }
    315                             }
    316                         }
    317                     }else{//同一月
    318                         for(var i=this.startIndex; i<this.endIndex+1; i++){
    319                             if(this.monthDataArr[i].leftAmount !== 0){
    320                                 if(i == this.startIndex || i == this.endIndex){
    321                                     this.monthDataArr[i].selectStatus = 2;
    322                                 }
    323                                 // if(i == this.endIndex){
    324                                 //     this.monthDataArr[i].selectStatus = 2;
    325                                 // }
    326                                 else {
    327                                     this.monthDataArr[i].selectStatus = 1;
    328                                 }
    329                             }else{
    330                                 self.errorFlag = false;
    331                                 return;
    332                             }
    333                             
    334                         }
    335                     }
    336                     //设置值
    337                     this.$parent.$parent.$parent.$parent.curEditData.saleDate=[];
    338                     this.$parent.$parent.$parent.$parent.curEditData.saleDate.push(this.startDate);
    339                     this.$parent.$parent.$parent.$parent.curEditData.saleDate.push(this.endDate);
    340 
    341                     //console.log('111111111~~~');
    342                     //console.log(this.allMonthData)
    343                     
    344                     this.pickUp();
    345                 }
    346                 
    347             }
    348         },
    349         watch: {
    350             'planid': function(){
    351                 this.clearSelect(-1);
    352                 this.allMonthData = [];
    353                 this.initData(true);
    354             }
    355         },
    356         template: 
    357             '<div class="calendarBox">'+
    358                 '<div id="calendarDate" class="calendarInput" @click="pickUp()">'+
    359                     '<span>{{startDate}}</span> <span> ~ </span> <span>{{endDate}} <i slot="suffix" class="el-input__icon el-icon-date"></i></span>'+
    360                 '</div> '+
    361                 '<div class="calendar" v-show="show">'+
    362                     '<div class="month">'+
    363                         '<ul class="clearfix">'+
    364                             '<li v-if="index >= 1" class="arrow" @click="pickPre(currentYear,currentMonth,index)"> ❮ </li>'+
    365                             '<li v-if="index < 1" class="disabledArrow" @click="pickPre(currentYear,currentMonth,index)"> ❮ </li>'+
    366                             '<li class="year-month" @click="pickYear(currentYear,currentMonth)">'+
    367                                 '<span class="choose-year">{{ currentYear }} 年 </span>'+
    368                                 '<span class="choose-month">{{ currentMonth }} 月</span>'+
    369                             '</li>'+
    370                             '<li v-if="index < monthArr.length-1" class="arrow" style="text-align:right;" @click="pickNext(currentYear,currentMonth,index)"> ❯ </li>'+
    371                             '<li v-if="index >= monthArr.length-1" class="disabledArrow" style="text-align:right;" @click="pickNext(currentYear,currentMonth,index)"> ❯ </li>'+
    372                        '</ul>'+
    373                     '</div>'+
    374                     '<ul class="weekdays clearfix">'+
    375                         '<li>日</li>'+
    376                         '<li>一</li>'+
    377                         '<li>二</li>'+
    378                         '<li>三</li>'+
    379                         '<li>四</li>'+
    380                         '<li>五</li>'+
    381                         '<li>六</li>'+  
    382                         '<p v-show="!errorFlag">不可选择库存为0的连续时间段</p>'+
    383                     '</ul>'+
    384                     '<ul class="days clearfix">'+  
    385                         '<li v-for="(dayobject,index) in monthDataArr" @click="selectDay(index,dayobject)">'+
    386                             '<template v-if="dayobject.selectStatus == 0">'+ 
    387                                 '<span v-if="dayobject.leftAmount == 0" class="other-month">{{ new Date(dayobject.date).getDate() }}</span>'+
    388                                 '<span v-else >'+
    389                                     '<span v-if="new Date(dayobject.date).getFullYear() == new Date().getFullYear() && new Date(dayobject.date).getMonth() == new Date().getMonth() && new Date(dayobject.date).getDate() == new Date().getDate()" class="active">'+
    390                                         '{{ new Date(dayobject.date).getDate() }}'+
    391                                         '<span style="color:#409EFF">库存:{{ dayobject.leftAmount }}</span>'+
    392                                     '</span>'+
    393                                     '<span v-else>{{ new Date(dayobject.date).getDate() }}</br><span style="color:#409EFF">库存:{{ dayobject.leftAmount }}</span></span>'+
    394                                 '</span>'+
    395                             '</template>'+
    396                             '<template v-if="dayobject.selectStatus == 1">'+ 
    397                                 '<span v-if="dayobject.leftAmount == 0" class="other-month subSelect">{{ new Date(dayobject.date).getDate() }}</span>'+
    398                                 '<span class="subSelect" v-else >'+
    399                                     '<span v-if="new Date(dayobject.date).getFullYear() == new Date().getFullYear() && new Date(dayobject.date).getMonth() == new Date().getMonth() && new Date(dayobject.date).getDate() == new Date().getDate()" class="active">'+
    400                                         '{{ new Date(dayobject.date).getDate() }}'+
    401                                         '<span class="inventory">库存:{{ dayobject.leftAmount }}</span>'+
    402                                     '</span>'+
    403                                     '<span v-else>{{ new Date(dayobject.date).getDate() }}</br><span class="inventory">库存:{{ dayobject.leftAmount }}</span></span>'+
    404                                 '</span>'+
    405                             '</template>'+
    406                             '<template v-if="dayobject.selectStatus == 2">'+ 
    407                                 '<span v-if="dayobject.leftAmount == 0" class="other-month select">{{ new Date(dayobject.date).getDate() }}</span>'+
    408                                 '<span class="select" v-else >'+
    409                                     // '<span class="selectFlag" v-if="dayobject.selectStatus == 1">开始</span>'+
    410                                     // '<span class="selectFlag" v-if="dayobject.selectStatus == 2">结束</span>'+
    411                                     '<span v-if="new Date(dayobject.date).getFullYear() == new Date().getFullYear() && new Date(dayobject.date).getMonth() == new Date().getMonth() && new Date(dayobject.date).getDate() == new Date().getDate()" class="active">'+
    412                                         '{{ new Date(dayobject.date).getDate() }}'+
    413                                         '<span class="inventory">库存:{{ dayobject.leftAmount }}</span>'+
    414                                     '</span>'+
    415                                     '<span v-else>{{ new Date(dayobject.date).getDate() }}</br><span class="inventory">库存:{{ dayobject.leftAmount }}</span></span>'+
    416                                 '</span>'+
    417                             '</template>'+
    418                         '</li>'+
    419                     '</ul>'+
    420                 '</div> '+
    421             '</div> '
    422     })
  • 相关阅读:
    关于时间的一些总结和全屏的一个知识点和百度的一道算法题
    关于超高频的一些研究
    Windows程序设计小结1
    windows系统Java环境配置
    第六章 事务与并发控制
    第五章 存储过程&触发器
    第四章 T-SQL编程
    第三章 数据库查询
    第二章 表的操作
    第一章 数据库的创建
  • 原文地址:https://www.cnblogs.com/jlliu/p/9854918.html
Copyright © 2020-2023  润新知