| class Calendar { | 
|     constructor({ | 
|         selected, | 
|         startDate, | 
|         endDate, | 
|         range, | 
|     } = {}) { | 
|         // 当前日期 | 
|         this.date = this.getDateObj(new Date()) // 当前初入日期 | 
|         // 打点信息 | 
|         this.selected = selected || []; | 
|         // 起始时间 | 
|         this.startDate = startDate | 
|         // 终止时间 | 
|         this.endDate = endDate | 
|     // 是否范围选择 | 
|         this.range = range | 
|         // 多选状态 | 
|         this.cleanMultipleStatus() | 
|         // 每周日期 | 
|         this.weeks = {} | 
|         this.lastHover = false | 
|     } | 
|     /** | 
|      * 设置日期 | 
|      * @param {Object} date | 
|      */ | 
|     setDate(date) { | 
|         const selectDate = this.getDateObj(date) | 
|         this.getWeeks(selectDate.fullDate) | 
|     } | 
|   | 
|     /** | 
|      * 清理多选状态 | 
|      */ | 
|     cleanMultipleStatus() { | 
|         this.multipleStatus = { | 
|             before: '', | 
|             after: '', | 
|             data: [] | 
|         } | 
|     } | 
|   | 
|     setStartDate(startDate) { | 
|         this.startDate = startDate | 
|     } | 
|   | 
|     setEndDate(endDate) { | 
|         this.endDate = endDate | 
|     } | 
|   | 
|   getPreMonthObj(date){ | 
|     date = fixIosDateFormat(date) | 
|     date = new Date(date) | 
|   | 
|     const oldMonth = date.getMonth() | 
|     date.setMonth(oldMonth - 1) | 
|     const newMonth = date.getMonth() | 
|     if(oldMonth !== 0 && newMonth - oldMonth === 0){ | 
|       date.setMonth(newMonth - 1) | 
|     } | 
|     return this.getDateObj(date) | 
|   } | 
|   getNextMonthObj(date){ | 
|     date = fixIosDateFormat(date) | 
|     date = new Date(date) | 
|   | 
|     const oldMonth = date.getMonth() | 
|     date.setMonth(oldMonth + 1) | 
|     const newMonth = date.getMonth() | 
|     if(newMonth - oldMonth > 1){ | 
|       date.setMonth(newMonth - 1) | 
|     } | 
|     return this.getDateObj(date) | 
|   } | 
|   | 
|     /** | 
|      * 获取指定格式Date对象 | 
|      */ | 
|     getDateObj(date) { | 
|     date = fixIosDateFormat(date) | 
|     date = new Date(date) | 
|   | 
|         return { | 
|             fullDate: getDate(date), | 
|       year: date.getFullYear(), | 
|       month: addZero(date.getMonth() + 1), | 
|       date: addZero(date.getDate()), | 
|       day: date.getDay() | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * 获取上一个月日期集合 | 
|      */ | 
|     getPreMonthDays(amount, dateObj) { | 
|         const result = [] | 
|         for (let i = amount - 1; i >= 0; i--) { | 
|       const month = dateObj.month - 1 | 
|             result.push({ | 
|                 date: new Date(dateObj.year, month, -i).getDate(), | 
|                 month, | 
|                 disable: true | 
|             }) | 
|         } | 
|         return result | 
|     } | 
|     /** | 
|      * 获取本月日期集合 | 
|      */ | 
|     getCurrentMonthDays(amount, dateObj) { | 
|         const result = [] | 
|         const fullDate = this.date.fullDate | 
|         for (let i = 1; i <= amount; i++) { | 
|             const currentDate = `${dateObj.year}-${dateObj.month}-${addZero(i)}` | 
|             const isToday = fullDate === currentDate | 
|             // 获取打点信息 | 
|             const info = this.selected && this.selected.find((item) => { | 
|                 if (this.dateEqual(currentDate, item.date)) { | 
|                     return item | 
|                 } | 
|             }) | 
|   | 
|             // 日期禁用 | 
|             let disableBefore = true | 
|             let disableAfter = true | 
|             if (this.startDate) { | 
|                 disableBefore = dateCompare(this.startDate, currentDate) | 
|             } | 
|   | 
|             if (this.endDate) { | 
|                 disableAfter = dateCompare(currentDate, this.endDate) | 
|             } | 
|   | 
|             let multiples = this.multipleStatus.data | 
|             let multiplesStatus = -1 | 
|             if (this.range && multiples) { | 
|         multiplesStatus = multiples.findIndex((item) => { | 
|           return this.dateEqual(item, currentDate) | 
|         }) | 
|             } | 
|       const checked = multiplesStatus !== -1 | 
|   | 
|             result.push({ | 
|                 fullDate: currentDate, | 
|                 year: dateObj.year, | 
|                 date: i, | 
|                 multiple: this.range ? checked : false, | 
|                 beforeMultiple: this.isLogicBefore(currentDate, this.multipleStatus.before, this.multipleStatus.after), | 
|                 afterMultiple: this.isLogicAfter(currentDate, this.multipleStatus.before, this.multipleStatus.after), | 
|                 month: dateObj.month, | 
|                 disable: (this.startDate && !dateCompare(this.startDate, currentDate)) || (this.endDate && !dateCompare(currentDate,this.endDate)), | 
|                 isToday, | 
|                 userChecked: false, | 
|         extraInfo: info | 
|             }) | 
|         } | 
|         return result | 
|     } | 
|     /** | 
|      * 获取下一个月日期集合 | 
|      */ | 
|     _getNextMonthDays(amount, dateObj) { | 
|         const result = [] | 
|     const month = dateObj.month + 1 | 
|         for (let i = 1; i <= amount; i++) { | 
|             result.push({ | 
|                 date: i, | 
|                 month, | 
|                 disable: true | 
|             }) | 
|         } | 
|         return result | 
|     } | 
|   | 
|     /** | 
|      * 获取当前日期详情 | 
|      * @param {Object} date | 
|      */ | 
|     getInfo(date) { | 
|         if (!date) { | 
|             date = new Date() | 
|         } | 
|   | 
|         return this.calendar.find(item => item.fullDate === this.getDateObj(date).fullDate) | 
|     } | 
|   | 
|     /** | 
|      * 比较时间是否相等 | 
|      */ | 
|     dateEqual(before, after) { | 
|         before = new Date(fixIosDateFormat(before)) | 
|         after = new Date(fixIosDateFormat(after)) | 
|         return before.valueOf() === after.valueOf() | 
|     } | 
|   | 
|     /** | 
|      *  比较真实起始日期 | 
|      */ | 
|   | 
|     isLogicBefore(currentDate, before, after) { | 
|         let logicBefore = before | 
|         if (before && after) { | 
|             logicBefore = dateCompare(before, after) ? before : after | 
|         } | 
|         return this.dateEqual(logicBefore, currentDate) | 
|     } | 
|   | 
|     isLogicAfter(currentDate, before, after) { | 
|         let logicAfter = after | 
|         if (before && after) { | 
|             logicAfter = dateCompare(before, after) ? after : before | 
|         } | 
|         return this.dateEqual(logicAfter, currentDate) | 
|     } | 
|   | 
|     /** | 
|      * 获取日期范围内所有日期 | 
|      * @param {Object} begin | 
|      * @param {Object} end | 
|      */ | 
|     geDateAll(begin, end) { | 
|         var arr = [] | 
|         var ab = begin.split('-') | 
|         var ae = end.split('-') | 
|         var db = new Date() | 
|         db.setFullYear(ab[0], ab[1] - 1, ab[2]) | 
|         var de = new Date() | 
|         de.setFullYear(ae[0], ae[1] - 1, ae[2]) | 
|         var unixDb = db.getTime() - 24 * 60 * 60 * 1000 | 
|         var unixDe = de.getTime() - 24 * 60 * 60 * 1000 | 
|         for (var k = unixDb; k <= unixDe;) { | 
|             k = k + 24 * 60 * 60 * 1000 | 
|             arr.push(this.getDateObj(new Date(parseInt(k))).fullDate) | 
|         } | 
|         return arr | 
|     } | 
|   | 
|     /** | 
|      *  获取多选状态 | 
|      */ | 
|     setMultiple(fullDate) { | 
|     if (!this.range) return | 
|   | 
|         let { | 
|             before, | 
|             after | 
|         } = this.multipleStatus | 
|         if (before && after) { | 
|             if (!this.lastHover) { | 
|                 this.lastHover = true | 
|                 return | 
|             } | 
|             this.multipleStatus.before = fullDate | 
|             this.multipleStatus.after = '' | 
|             this.multipleStatus.data = [] | 
|             this.multipleStatus.fulldate = '' | 
|             this.lastHover = false | 
|         } else { | 
|             if (!before) { | 
|                 this.multipleStatus.before = fullDate | 
|                 this.lastHover = false | 
|             } else { | 
|                 this.multipleStatus.after = fullDate | 
|                 if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) { | 
|                     this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus | 
|                         .after); | 
|                 } else { | 
|                     this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus | 
|                         .before); | 
|                 } | 
|                 this.lastHover = true | 
|             } | 
|         } | 
|         this.getWeeks(fullDate) | 
|     } | 
|   | 
|     /** | 
|      *  鼠标 hover 更新多选状态 | 
|      */ | 
|     setHoverMultiple(fullDate) { | 
|     if (!this.range || this.lastHover) return | 
|   | 
|         const { before } = this.multipleStatus | 
|   | 
|         if (!before) { | 
|             this.multipleStatus.before = fullDate | 
|         } else { | 
|             this.multipleStatus.after = fullDate | 
|             if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) { | 
|                 this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after); | 
|             } else { | 
|                 this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before); | 
|             } | 
|         } | 
|         this.getWeeks(fullDate) | 
|     } | 
|   | 
|     /** | 
|      * 更新默认值多选状态 | 
|      */ | 
|     setDefaultMultiple(before, after) { | 
|         this.multipleStatus.before = before | 
|         this.multipleStatus.after = after | 
|         if (before && after) { | 
|             if (dateCompare(before, after)) { | 
|                 this.multipleStatus.data = this.geDateAll(before, after); | 
|                 this.getWeeks(after) | 
|             } else { | 
|                 this.multipleStatus.data = this.geDateAll(after, before); | 
|                 this.getWeeks(before) | 
|             } | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * 获取每周数据 | 
|      * @param {Object} dateData | 
|      */ | 
|     getWeeks(dateData) { | 
|         const { | 
|             year, | 
|             month, | 
|         } = this.getDateObj(dateData) | 
|   | 
|         const preMonthDayAmount = new Date(year, month - 1, 1).getDay() | 
|     const preMonthDays = this.getPreMonthDays(preMonthDayAmount, this.getDateObj(dateData)) | 
|   | 
|         const currentMonthDayAmount = new Date(year, month, 0).getDate() | 
|     const currentMonthDays = this.getCurrentMonthDays(currentMonthDayAmount, this.getDateObj(dateData)) | 
|   | 
|     const nextMonthDayAmount = 42 - preMonthDayAmount - currentMonthDayAmount | 
|     const nextMonthDays = this._getNextMonthDays(nextMonthDayAmount, this.getDateObj(dateData)) | 
|   | 
|         const calendarDays = [...preMonthDays, ...currentMonthDays, ...nextMonthDays] | 
|   | 
|         const weeks = new Array(6) | 
|         for (let i = 0; i < calendarDays.length; i++) { | 
|       const index = Math.floor(i / 7) | 
|       if(!weeks[index]){ | 
|         weeks[index] = new Array(7) | 
|       } | 
|             weeks[index][i % 7] = calendarDays[i] | 
|         } | 
|   | 
|         this.calendar = calendarDays | 
|         this.weeks = weeks | 
|     } | 
| } | 
|   | 
| function getDateTime(date, hideSecond){ | 
|   return `${getDate(date)} ${getTime(date, hideSecond)}` | 
| } | 
|   | 
| function getDate(date) { | 
|   date = fixIosDateFormat(date) | 
|   date = new Date(date) | 
|   const year = date.getFullYear() | 
|   const month = date.getMonth()+1 | 
|   const day = date.getDate() | 
|   return `${year}-${addZero(month)}-${addZero(day)}` | 
| } | 
|   | 
| function getTime(date, hideSecond){ | 
|   date = fixIosDateFormat(date) | 
|   date = new Date(date) | 
|   const hour = date.getHours() | 
|   const minute = date.getMinutes() | 
|   const second = date.getSeconds() | 
|   return hideSecond ? `${addZero(hour)}:${addZero(minute)}` : `${addZero(hour)}:${addZero(minute)}:${addZero(second)}` | 
| } | 
|   | 
| function addZero(num) { | 
|   if(num < 10){ | 
|     num = `0${num}` | 
|   } | 
|   return num | 
| } | 
|   | 
| function getDefaultSecond(hideSecond) { | 
|   return hideSecond ? '00:00' : '00:00:00' | 
| } | 
|   | 
| function dateCompare(startDate, endDate) { | 
|   startDate = new Date(fixIosDateFormat(startDate)) | 
|   endDate = new Date(fixIosDateFormat(endDate)) | 
|   return startDate <= endDate | 
| } | 
|   | 
| function checkDate(date){ | 
|   const dateReg = /((19|20)\d{2})(-|\/)\d{1,2}(-|\/)\d{1,2}/g | 
|   return date.match(dateReg) | 
| } | 
|   | 
| const dateTimeReg = /^\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])( [0-5][0-9]:[0-5][0-9]:[0-5][0-9])?$/ | 
| function fixIosDateFormat(value) { | 
|   if (typeof value === 'string' && dateTimeReg.test(value)) { | 
|     value = value.replace(/-/g, '/') | 
|   } | 
|   return value | 
| } | 
|   | 
| export {Calendar, getDateTime, getDate, getTime, addZero, getDefaultSecond, dateCompare, checkDate, fixIosDateFormat} |