| <template> | 
|     <view class="date-time-picker" v-if="visible"> | 
|         <view class="date-time-mask" @click.stop="hide"></view> | 
|         <view class="date-time-container" @click.stop="handleEvent"> | 
|             <view class="time-picker-tool" v-if='isShowToolBar'> | 
|                 <view :class="[cancelButtonClass]" @click.stop="cancel"> | 
|                     <text>{{cancelButtonText}}</text> | 
|                 </view> | 
|                 <view :class="[toolBarTitleClass]"> | 
|                     <text>{{toolBarTitle}}</text> | 
|                 </view> | 
|                 <view :class="[confirmButtonClass]" @click.stop="confirm"> | 
|                     <text>{{confirmButtonText}}</text> | 
|                 </view> | 
|             </view> | 
|             <picker-view class="picker-view" :indicator-style="indicatorStyleString" :value="dateTime" @change="dateTimePickerChange"> | 
|                 <picker-view-column data-id='year' v-if='isShowYear'> | 
|                     <view class="item" v-for="(item,index) in years" :key="index">{{item}}年</view> | 
|                 </picker-view-column> | 
|                 <picker-view-column data-id='month' v-if='isShowMonth'> | 
|                     <view class="item" v-for="(item,index) in months" :key="index">{{item}}月</view> | 
|                 </picker-view-column> | 
|                 <picker-view-column data-id='day' v-if='isShowDay'> | 
|                     <view class="item" v-for="(item,index) in days" :key="index">{{item}}日</view> | 
|                 </picker-view-column> | 
|                 <picker-view-column data-id='hour' v-if='isShowHour'> | 
|                     <view class="item" v-for="(item,index) in hours" :key="index">{{item}}时</view> | 
|                 </picker-view-column> | 
|                 <picker-view-column data-id='minute' v-if='isShowMinute'> | 
|                     <view class="item" v-for="(item,index) in minutes" :key="index">{{item}}分</view> | 
|                 </picker-view-column> | 
|                 <picker-view-column data-id='second' v-if='isShowSecond'> | 
|                     <view class="item" v-for="(item,index) in seconds" :key="index">{{item}}秒</view> | 
|                 </picker-view-column> | 
|             </picker-view> | 
|         </view> | 
|     </view> | 
| </template> | 
|   | 
| <script> | 
|     import { | 
|         getOneMonthDays, | 
|         getTimeArray, | 
|         addZero, | 
|         getIndexOfArray | 
|     } from './uitls/util.js' | 
|     export default { | 
|         name: 'DateTimePicker', | 
|         props: { | 
|             startYear: { | 
|                 type: Number, | 
|                 default: 1900 | 
|             }, | 
|             endYear: { | 
|                 type: Number, | 
|                 default: new Date().getFullYear() | 
|             }, | 
|             isShowToolBar: { | 
|                 type: Boolean, | 
|                 default: true | 
|             }, | 
|             cancelButtonText: { | 
|                 type: String, | 
|                 default: '取消' | 
|             }, | 
|             cancelButtonClass: { | 
|                 type: String, | 
|                 default: 'cancel-btn' | 
|             }, | 
|             toolBarTitle: { | 
|                 type: String, | 
|                 default: '请选择' | 
|             }, | 
|             toolBarTitleClass: { | 
|                 type: String, | 
|                 default: 'tool-title' | 
|             }, | 
|             confirmButtonText: { | 
|                 type: String, | 
|                 default: '确定' | 
|             }, | 
|             confirmButtonClass: { | 
|                 type: String, | 
|                 default: 'confirm-btn' | 
|             }, | 
|             datestring: { | 
|                 type: String, | 
|                 default: '' | 
|             }, | 
|             type: { | 
|                 /** | 
|                  * date 年月日 | 
|                  * year-month 年月 | 
|                  * year 年 | 
|                  * datetime 年月日 时分 | 
|                  * datetime-all 年月日 时分秒 | 
|                  * time 时分秒 | 
|                  * hour-minute 时分 | 
|                  */ | 
|                 type: String, | 
|                 default: 'date' | 
|             }, | 
|             indicatorStyle: { | 
|                 type: Object, | 
|                 default: null | 
|             }, | 
|             startDate: { | 
|                 type: String, | 
|                 default: '' | 
|             }, | 
|             endDate: { | 
|                 type: String, | 
|                 default: '' | 
|             }, | 
|         }, | 
|         data() { | 
|             return { | 
|                 visible: false, | 
|                 dateTime: [], | 
|                 days: [], | 
|                 indicatorStyleString: '' | 
|             } | 
|         }, | 
|         watch: { | 
|             indicatorStyle(val){ | 
|                 this.getIndicatorStyle(); | 
|             }, | 
|             type() { | 
|                 this.initDateTime() | 
|             }, | 
|             datestring(){ | 
|                 this.initDateTime() | 
|             } | 
|         }, | 
|         computed: { | 
|             years() { | 
|                 let startYear = this.startYear; | 
|                 let endYear = this.endYear; | 
|                 if(this.startDate){ | 
|                     if(this.startDate.indexOf('-')>-1){ | 
|                         startYear = this.startDate.split('-')[0] | 
|                     }else{ | 
|                         startYear = this.startDate | 
|                     } | 
|                 } | 
|                 return this.initTimeData(endYear, startYear); | 
|             }, | 
|             isShowYear() { | 
|                 return this.type !== 'time' && this.type !== 'hour-minute'; | 
|             }, | 
|             months() { | 
|                 let startMonth = 1; | 
|                 let endMonth = 12; | 
|                 if(this.isShowMonth && this.startDate){ | 
|                     let arr = this.startDate.split('-'); | 
|                     if(arr.length>1 && arr[0] <= this.years[this.years.length-1]){ | 
|                         startMonth = Number(arr[1]) | 
|                     } | 
|                 } | 
|                 return this.initTimeData(endMonth, startMonth); | 
|             }, | 
|             isShowMonth() { | 
|                 return this.type !== 'year' && this.type !== 'time' && this.type !== 'hour-minute'; | 
|             }, | 
|             isShowDay() { | 
|                 return this.type === 'date' || this.type === 'datetime' || this.type === 'datetime-all'; | 
|             }, | 
|             hours() { | 
|                 return this.initTimeData(23, 0); | 
|             }, | 
|             isShowHour() { | 
|                 return this.type !== 'date' && this.type !== 'year-month' && this.type !== 'year'; | 
|             }, | 
|             minutes() { | 
|                 return this.initTimeData(59, 0); | 
|             }, | 
|             isShowMinute() { | 
|                 return this.type !== 'date' && this.type !== 'year-month' && this.type !== 'year'; | 
|             }, | 
|             seconds() { | 
|                 return this.initTimeData(59, 0); | 
|             }, | 
|             isShowSecond() { | 
|                 return this.type === 'datetime-all' || this.type === 'time'; | 
|             } | 
|         }, | 
|         methods: { | 
|             getIndicatorStyle(){ | 
|                 if(this.indicatorStyle){ | 
|                     for(let key in this.indicatorStyle){ | 
|                         this.indicatorStyleString += `${key}:${this.indicatorStyle[key]};` | 
|                     } | 
|                 } | 
|             }, | 
|             handleEvent() { | 
|                 return; | 
|             }, | 
|             cancel() { | 
|                 this.hide(); | 
|             }, | 
|             confirm() { | 
|                 this.formatDate(); | 
|                 this.hide(); | 
|             }, | 
|             show() { | 
|                 this.visible = true; | 
|             }, | 
|             hide() { | 
|                 this.visible = false; | 
|             }, | 
|             initDateTime() { | 
|                 let value; | 
|                 if (this.datestring.length > 0) { | 
|                     if (this.type === 'year') { | 
|                         value = new Date(this.datestring, 0); | 
|                     } else if (this.type === 'time' || this.type === 'hour-minute') { | 
|                         let date = new Date(); | 
|                         let ary = this.datestring.split(':'); | 
|                         ary.forEach((item, index) => { | 
|                             if (index == 0) { | 
|                                 date.setHours(item) | 
|                             } else if (index == 1) { | 
|                                 date.setMinutes(item) | 
|                             } else if (index == 2) { | 
|                                 date.setSeconds(item) | 
|                             } | 
|                         }) | 
|                         value = date; | 
|                     } else { | 
|                         value = new Date(this.datestring.replace(/-/g, '/')); | 
|                     } | 
|   | 
|                 } else { | 
|                     value = new Date(); | 
|                 } | 
|                 let len, timeArray, index; | 
|                 let array = getTimeArray(value); | 
|                 let [year, month, day, hour, minute, second] = array; | 
|                 this.days = this.initTimeData(getOneMonthDays(year, month-1), 1); | 
|                 let names = ['year', 'month', 'day', 'hour', 'minute', 'second']; | 
|                 switch (this.type) { | 
|                     case "date": | 
|                         len = 3; | 
|                         break; | 
|                     case "year-month": | 
|                         len = 2; | 
|                         break; | 
|                     case "year": | 
|                         len = 1; | 
|                         break; | 
|                     case "datetime": | 
|                         len = 5; | 
|                         break; | 
|                     case "datetime-all": | 
|                         len = 6; | 
|                         break; | 
|                     case "time": | 
|                         len = 3; | 
|                         break; | 
|                     case "hour-minute": | 
|                         len = 2; | 
|                         break; | 
|                 } | 
|                 timeArray = new Array(len).fill(0); | 
|                 if (this.type === 'time' || this.type === 'hour-minute') { | 
|                     names = names.slice(3); | 
|                     array = array.slice(3); | 
|                 } | 
|                 timeArray = timeArray.map((item, index) => { | 
|                     const name = names[index]; | 
|                     return getIndexOfArray(array[index], this[name + 's']) | 
|                 }) | 
|                 this.dateTime = timeArray; | 
|             }, | 
|             initTimeData(end, start) { | 
|                 let timeArray = []; | 
|                 while (start <= end) { | 
|                     timeArray.push(start); | 
|                     start++; | 
|                 } | 
|                 return timeArray; | 
|             }, | 
|             formatDate() { | 
|                 let names = ['year', 'month', 'day', 'hour', 'minute', 'second']; | 
|                 let dateString, formatDateArray = []; | 
|                 if (this.type === 'date' || this.type === 'year-month' || this.type === 'year') { | 
|                     formatDateArray = this.dateTime.map((item, index) => { | 
|                         return this[names[index] + 's'][item] < 10 ? addZero(this[names[index] + 's'][item]) : this[names[index] + 's'][item]; | 
|                     }) | 
|                     dateString = formatDateArray.join('-'); | 
|                 } else if (this.type === 'time' || this.type === 'hour-minute') { | 
|                     names = names.splice(3); | 
|                     formatDateArray = this.dateTime.map((item, index) => { | 
|                         return this[names[index] + 's'][item] < 10 ? addZero(this[names[index] + 's'][item]) : this[names[index] + 's'][item]; | 
|                     }) | 
|                     dateString = formatDateArray.join(':'); | 
|                 } else { | 
|                     let name1 = names.splice(0, 3); | 
|                     formatDateArray = this.dateTime.map((item, index) => { | 
|                         if (index > 2) { | 
|                             return this[names[index - 3] + 's'][item] < 10 ? addZero(this[names[index - 3] + 's'][item]) : this[names[index - 3] + 's'][item]; | 
|                         } else { | 
|                             return this[name1[index] + 's'][item] < 10 ? addZero(this[name1[index] + 's'][item]) : this[name1[index] + 's'][item]; | 
|                         } | 
|                     }) | 
|                     dateString = formatDateArray.splice(0, 3).join('-') + ' ' + formatDateArray.join(':'); | 
|                 } | 
|                 this.$emit('change', dateString) | 
|             }, | 
|             dateTimePickerChange(e) { | 
|                 let columns = e.target.value; | 
|                 if (this.type === 'date' || this.type === 'datetime' || this.type === 'datetime-all') { | 
|                     this.dateTime.splice(0, 1, columns[0]); | 
|                     if (columns[0] != this.dateTime[0]) { | 
|                         this.days = this.initTimeData(getOneMonthDays(this.years[this.dateTime[0]], this.months[this.dateTime[1]]), 1); | 
|                         if (this.dateTime[1] == 1) { | 
|                             if (this.dateTime[2] === this.days.length - 1) { | 
|                                 if (getOneMonthDays(this.years[columns[0]], this.dateTime[1]) < getOneMonthDays(this.years[this.dateTime[0]],this.dateTime[1])) { | 
|                                     this.dateTime.splice(2, 1, this.days.length - 1) | 
|                                 } | 
|                             } | 
|                         } | 
|                     } else { | 
|                         this.dateTime.splice(1, 1, columns[1]); | 
|                         this.days = this.initTimeData(getOneMonthDays(this.years[this.dateTime[0]], this.dateTime[1]), 1); | 
|                         if (columns[1] != this.dateTime[1]) { | 
|                             if (this.dateTime[1] == 1) { | 
|                                 if (this.dateTime[2] === this.days.length - 1) { | 
|                                     if (getOneMonthDays(this.years[columns[0]], this.dateTime[1]) < getOneMonthDays(this.years[this.dateTime[0]], | 
|                                             this.dateTime[1])) { | 
|                                         this.dateTime.splice(2, 1, this.days.length - 1) | 
|                                     } | 
|                                 } | 
|                             } else { | 
|                                 if (this.dateTime[2] > this.days.length - 1) { | 
|                                     this.dateTime.splice(2, 1, this.days.length - 1) | 
|                                 } else { | 
|                                     this.dateTime.splice(2, 1, columns[2]) | 
|                                 } | 
|                             } | 
|                         } else { | 
|                             this.dateTime.splice(2, 1, columns[2]) | 
|                         } | 
|                     } | 
|                     if (columns.length > 2) { | 
|                         columns.splice(3).forEach((column, index) => { | 
|                             this.dateTime.splice(index + 3, 1, column); | 
|                         }) | 
|                     } | 
|                 } else { | 
|                     columns.forEach((column, index) => { | 
|                         this.dateTime.splice(index, 1, column); | 
|                     }) | 
|                 } | 
|                 if (!this.isShowToolBar) { | 
|                     this.formatDate(); | 
|                 } | 
|             }, | 
|         }, | 
|         mounted() { | 
|             this.getIndicatorStyle(); | 
|             this.initDateTime(); | 
|         } | 
|     } | 
| </script> | 
|   | 
| <style lang='scss' scoped> | 
|     .date-time-picker { | 
|         .date-time-mask { | 
|             position: fixed; | 
|             top: 0; | 
|             bottom: 0; | 
|             left: 0; | 
|             right: 0; | 
|             background-color: rgba($color: #000000, $alpha: .5); | 
|             z-index: 998; | 
|         } | 
|   | 
|         .date-time-container { | 
|             position: fixed; | 
|             height: 50%; | 
|             bottom: 0; | 
|             right: 0; | 
|             left: 0; | 
|             background-color: #f6f6f6; | 
|             z-index: 1000; | 
|             display: flex; | 
|             flex-direction: column; | 
|   | 
|             .time-picker-tool { | 
|                 height: 80rpx; | 
|                 display: flex; | 
|                 align-items: center; | 
|                 justify-content: space-between; | 
|                 font-size: 14px; | 
|   | 
|                 .cancel-btn { | 
|                     padding: 0 28rpx; | 
|                     box-sizing: border-box; | 
|                     color: #969799; | 
|                 } | 
|   | 
|                 .tool-title { | 
|                     font-weight: 500; | 
|                     font-size: 15px; | 
|                     max-width: 50%; | 
|                     overflow: hidden; | 
|                     white-space: nowrap; | 
|                     text-overflow: ellipsis; | 
|                 } | 
|   | 
|                 .confirm-btn { | 
|                     padding: 0 28rpx; | 
|                     box-sizing: border-box; | 
|                     color: #576b95; | 
|                 } | 
|             } | 
|   | 
|             .picker-view { | 
|                 width: 100%; | 
|                 flex: 1; | 
|   | 
|                 .item { | 
|                     font-size: 14px; | 
|                     display: flex; | 
|                     align-items: center; | 
|                     justify-content: center; | 
|                 } | 
|             } | 
|         } | 
|     } | 
| </style> |