| <template> | 
|     <view class="uni-date"> | 
|         <view class="uni-date-editor" @click="show"> | 
|             <slot> | 
|                 <view | 
|           class="uni-date-editor--x" | 
|           :class="{'uni-date-editor--x__disabled': disabled,'uni-date-x--border': border}" | 
|         > | 
|                     <view v-if="!isRange" class="uni-date-x uni-date-single"> | 
|                         <uni-icons class="icon-calendar" type="calendar" color="#c0c4cc" size="22"></uni-icons> | 
|                         <view class="uni-date__x-input">{{ displayValue || singlePlaceholderText }}</view> | 
|                     </view> | 
|   | 
|                     <view v-else class="uni-date-x uni-date-range"> | 
|             <uni-icons class="icon-calendar" type="calendar" color="#c0c4cc" size="22"></uni-icons> | 
|             <view class="uni-date__x-input text-center">{{ displayRangeValue.startDate || startPlaceholderText }}</view> | 
|   | 
|             <view class="range-separator">{{rangeSeparator}}</view> | 
|   | 
|             <view class="uni-date__x-input text-center">{{ displayRangeValue.endDate || endPlaceholderText }}</view> | 
|                     </view> | 
|   | 
|                     <view v-if="showClearIcon" class="uni-date__icon-clear" @click.stop="clear"> | 
|                         <uni-icons type="clear" color="#c0c4cc" size="22"></uni-icons> | 
|                     </view> | 
|                 </view> | 
|             </slot> | 
|         </view> | 
|   | 
|         <view v-show="pickerVisible" class="uni-date-mask--pc" @click="close"></view> | 
|   | 
|         <view v-if="!isPhone" v-show="pickerVisible" ref="datePicker" class="uni-date-picker__container"> | 
|             <view v-if="!isRange" class="uni-date-single--x" :style="pickerPositionStyle"> | 
|                 <view class="uni-popper__arrow"></view> | 
|   | 
|                 <view v-if="hasTime" class="uni-date-changed popup-x-header"> | 
|                     <input class="uni-date__input text-center" type="text" v-model="inputDate" | 
|                         :placeholder="selectDateText" /> | 
|   | 
|                     <time-picker type="time" v-model="pickerTime" :border="false" :disabled="!inputDate" | 
|                         :start="timepickerStartTime" :end="timepickerEndTime" :hideSecond="hideSecond" style="width: 100%;"> | 
|                         <input class="uni-date__input text-center" type="text" v-model="pickerTime" :placeholder="selectTimeText" | 
|                             :disabled="!inputDate" /> | 
|                     </time-picker> | 
|                 </view> | 
|   | 
|                 <Calendar ref="pcSingle" :showMonth="false" :start-date="calendarRange.startDate" | 
|                     :end-date="calendarRange.endDate" :date="calendarDate" @change="singleChange" | 
|           :default-value="defaultValue" | 
|                     style="padding: 0 8px;" /> | 
|   | 
|                 <view v-if="hasTime" class="popup-x-footer"> | 
|                     <text class="confirm-text" @click="confirmSingleChange">{{okText}}</text> | 
|                 </view> | 
|             </view> | 
|   | 
|             <view v-else class="uni-date-range--x" :style="pickerPositionStyle"> | 
|                 <view class="uni-popper__arrow"></view> | 
|                 <view v-if="hasTime" class="popup-x-header uni-date-changed"> | 
|                     <view class="popup-x-header--datetime"> | 
|             <input class="uni-date__input uni-date-range__input" type="text" v-model="tempRange.startDate" | 
|             :placeholder="startDateText" /> | 
|   | 
|                         <time-picker type="time" v-model="tempRange.startTime" :start="timepickerStartTime" :border="false" | 
|             :disabled="!tempRange.startDate" :hideSecond="hideSecond"> | 
|             <input class="uni-date__input uni-date-range__input" type="text" | 
|             v-model="tempRange.startTime" :placeholder="startTimeText" | 
|             :disabled="!tempRange.startDate" /> | 
|           </time-picker> | 
|         </view> | 
|   | 
|         <uni-icons type="arrowthinright" color="#999" style="line-height: 40px;"></uni-icons> | 
|   | 
|                     <view class="popup-x-header--datetime"> | 
|                         <input class="uni-date__input uni-date-range__input" type="text" v-model="tempRange.endDate" | 
|                             :placeholder="endDateText" /> | 
|   | 
|                         <time-picker type="time" v-model="tempRange.endTime" :end="timepickerEndTime" :border="false" | 
|                             :disabled="!tempRange.endDate" :hideSecond="hideSecond"> | 
|                             <input class="uni-date__input uni-date-range__input" type="text" v-model="tempRange.endTime" | 
|                                 :placeholder="endTimeText" :disabled="!tempRange.endDate" /> | 
|                         </time-picker> | 
|                     </view> | 
|                 </view> | 
|   | 
|                 <view class="popup-x-body"> | 
|                     <Calendar ref="left" :showMonth="false" :start-date="calendarRange.startDate" | 
|             :end-date="calendarRange.endDate" :range="true" :pleStatus="endMultipleStatus" | 
|             @change="leftChange" @firstEnterCale="updateRightCale" style="padding: 0 8px;" /> | 
|                     <Calendar ref="right" :showMonth="false" :start-date="calendarRange.startDate" | 
|                         :end-date="calendarRange.endDate" :range="true" @change="rightChange" | 
|                         :pleStatus="startMultipleStatus" @firstEnterCale="updateLeftCale" | 
|                         style="padding: 0 8px;border-left: 1px solid #F1F1F1;" /> | 
|                 </view> | 
|   | 
|                 <view v-if="hasTime" class="popup-x-footer"> | 
|                     <text @click="clear">{{clearText}}</text> | 
|                     <text class="confirm-text" @click="confirmRangeChange">{{okText}}</text> | 
|                 </view> | 
|             </view> | 
|         </view> | 
|   | 
|         <Calendar v-if="isPhone" ref="mobile" :clearDate="false" :date="calendarDate" :defTime="mobileCalendarTime" | 
|             :start-date="calendarRange.startDate" :end-date="calendarRange.endDate" :selectableTimes="mobSelectableTime" | 
|       :startPlaceholder="startPlaceholder" :endPlaceholder="endPlaceholder" | 
|       :default-value="defaultValue" | 
|             :pleStatus="endMultipleStatus" :showMonth="false" :range="isRange" :hasTime="hasTime" :insert="false" | 
|             :hideSecond="hideSecond" @confirm="mobileChange" @maskClose="close" /> | 
|     </view> | 
| </template> | 
| <script> | 
|     /** | 
|      * DatetimePicker 时间选择器 | 
|      * @description 同时支持 PC 和移动端使用日历选择日期和日期范围 | 
|      * @tutorial https://ext.dcloud.net.cn/plugin?id=3962 | 
|      * @property {String} type 选择器类型 | 
|      * @property {String|Number|Array|Date} value 绑定值 | 
|      * @property {String} placeholder 单选择时的占位内容 | 
|      * @property {String} start 起始时间 | 
|      * @property {String} end 终止时间 | 
|      * @property {String} start-placeholder 范围选择时开始日期的占位内容 | 
|      * @property {String} end-placeholder 范围选择时结束日期的占位内容 | 
|      * @property {String} range-separator 选择范围时的分隔符 | 
|      * @property {Boolean} border = [true|false] 是否有边框 | 
|      * @property {Boolean} disabled = [true|false] 是否禁用 | 
|      * @property {Boolean} clearIcon = [true|false] 是否显示清除按钮(仅PC端适用) | 
|      * @property {[String} defaultValue 选择器打开时默认显示的时间 | 
|      * @event {Function} change 确定日期时触发的事件 | 
|      * @event {Function} maskClick 点击遮罩层触发的事件 | 
|      * @event {Function} show 打开弹出层 | 
|      * @event {Function} close 关闭弹出层 | 
|      * @event {Function} clear 清除上次选中的状态和值 | 
|      **/ | 
|     import Calendar from './calendar.vue' | 
|     import TimePicker from './time-picker.vue' | 
|     import { initVueI18n } from '@dcloudio/uni-i18n' | 
|     import i18nMessages from './i18n/index.js' | 
|   import { getDateTime, getDate, getTime, getDefaultSecond, dateCompare, checkDate, fixIosDateFormat } from './util' | 
|   | 
|     export default { | 
|         name: 'UniDatetimePicker', | 
|         options: { | 
|             virtualHost: true | 
|         }, | 
|         components: { | 
|             Calendar, | 
|             TimePicker | 
|         }, | 
|         data() { | 
|             return { | 
|                 isRange: false, | 
|                 hasTime: false, | 
|                 displayValue: '', | 
|                 inputDate: '', | 
|                 calendarDate: '', | 
|                 pickerTime: '', | 
|                 calendarRange: { | 
|                     startDate: '', | 
|                     startTime: '', | 
|                     endDate: '', | 
|                     endTime: '' | 
|                 }, | 
|                 displayRangeValue: { | 
|                     startDate: '', | 
|                     endDate: '', | 
|                 }, | 
|                 tempRange: { | 
|                     startDate: '', | 
|                     startTime: '', | 
|                     endDate: '', | 
|                     endTime: '' | 
|                 }, | 
|                 // 左右日历同步数据 | 
|                 startMultipleStatus: { | 
|                     before: '', | 
|                     after: '', | 
|                     data: [], | 
|                     fulldate: '' | 
|                 }, | 
|                 endMultipleStatus: { | 
|                     before: '', | 
|                     after: '', | 
|                     data: [], | 
|                     fulldate: '' | 
|                 }, | 
|                 pickerVisible: false, | 
|                 pickerPositionStyle: null, | 
|                 isEmitValue: false, | 
|                 isPhone: false, | 
|                 isFirstShow: true, | 
|         i18nT: () => {} | 
|             } | 
|         }, | 
|         props: { | 
|             type: { | 
|                 type: String, | 
|                 default: 'datetime' | 
|             }, | 
|             value: { | 
|                 type: [String, Number, Array, Date], | 
|                 default: '' | 
|             }, | 
|             modelValue: { | 
|                 type: [String, Number, Array, Date], | 
|                 default: '' | 
|             }, | 
|             start: { | 
|                 type: [Number, String], | 
|                 default: '' | 
|             }, | 
|             end: { | 
|                 type: [Number, String], | 
|                 default: '' | 
|             }, | 
|             returnType: { | 
|                 type: String, | 
|                 default: 'string' | 
|             }, | 
|             placeholder: { | 
|                 type: String, | 
|                 default: '' | 
|             }, | 
|             startPlaceholder: { | 
|         type: String, | 
|                 default: '' | 
|             }, | 
|             endPlaceholder: { | 
|                 type: String, | 
|                 default: '' | 
|             }, | 
|             rangeSeparator: { | 
|                 type: String, | 
|                 default: '-' | 
|             }, | 
|             border: { | 
|                 type: [Boolean], | 
|                 default: true | 
|             }, | 
|             disabled: { | 
|                 type: [Boolean], | 
|                 default: false | 
|             }, | 
|             clearIcon: { | 
|                 type: [Boolean], | 
|                 default: true | 
|             }, | 
|             hideSecond: { | 
|                 type: [Boolean], | 
|                 default: false | 
|             }, | 
|       defaultValue: { | 
|         type: [String, Object, Array], | 
|         default: '' | 
|       } | 
|         }, | 
|         watch: { | 
|             type: { | 
|                 immediate: true, | 
|                 handler(newVal) { | 
|           this.hasTime = newVal.indexOf('time') !== -1 | 
|                     this.isRange = newVal.indexOf('range') !== -1 | 
|                 } | 
|             }, | 
|             // #ifndef VUE3 | 
|             value: { | 
|                 immediate: true, | 
|                 handler(newVal) { | 
|                     if (this.isEmitValue) { | 
|                         this.isEmitValue = false | 
|                         return | 
|                     } | 
|                     this.initPicker(newVal) | 
|                 } | 
|             }, | 
|             // #endif | 
|             // #ifdef VUE3 | 
|             modelValue: { | 
|                 immediate: true, | 
|                 handler(newVal) { | 
|                     if (this.isEmitValue) { | 
|                         this.isEmitValue = false | 
|                         return | 
|                     } | 
|                     this.initPicker(newVal) | 
|                 } | 
|             }, | 
|             // #endif | 
|             start: { | 
|                 immediate: true, | 
|                 handler(newVal) { | 
|                     if (!newVal) return | 
|                     this.calendarRange.startDate = getDate(newVal) | 
|                     if (this.hasTime) { | 
|                         this.calendarRange.startTime = getTime(newVal) | 
|                     } | 
|                 } | 
|             }, | 
|             end: { | 
|                 immediate: true, | 
|                 handler(newVal) { | 
|                     if (!newVal) return | 
|                     this.calendarRange.endDate = getDate(newVal) | 
|                     if (this.hasTime) { | 
|                         this.calendarRange.endTime = getTime(newVal, this.hideSecond) | 
|                     } | 
|                 } | 
|             }, | 
|         }, | 
|         computed: { | 
|             timepickerStartTime() { | 
|                 const activeDate = this.isRange ? this.tempRange.startDate : this.inputDate | 
|                 return activeDate === this.calendarRange.startDate ? this.calendarRange.startTime : '' | 
|             }, | 
|             timepickerEndTime() { | 
|                 const activeDate = this.isRange ? this.tempRange.endDate : this.inputDate | 
|                 return activeDate === this.calendarRange.endDate ? this.calendarRange.endTime : '' | 
|             }, | 
|             mobileCalendarTime() { | 
|                 const timeRange = { | 
|                     start: this.tempRange.startTime, | 
|                     end: this.tempRange.endTime | 
|                 } | 
|                 return this.isRange ? timeRange : this.pickerTime | 
|             }, | 
|             mobSelectableTime() { | 
|                 return { | 
|                     start: this.calendarRange.startTime, | 
|                     end: this.calendarRange.endTime | 
|                 } | 
|             }, | 
|             datePopupWidth() { | 
|                 // todo | 
|                 return this.isRange ? 653 : 301 | 
|             }, | 
|   | 
|             /** | 
|              * for i18n | 
|              */ | 
|             singlePlaceholderText() { | 
|                 return this.placeholder || (this.type === 'date' ? this.selectDateText : this.selectDateTimeText) | 
|             }, | 
|             startPlaceholderText() { | 
|                 return this.startPlaceholder || this.startDateText | 
|             }, | 
|             endPlaceholderText() { | 
|                 return this.endPlaceholder || this.endDateText | 
|             }, | 
|             selectDateText() { | 
|                 return this.i18nT("uni-datetime-picker.selectDate") | 
|             }, | 
|       selectDateTimeText() { | 
|         return this.i18nT("uni-datetime-picker.selectDateTime") | 
|       }, | 
|             selectTimeText() { | 
|                 return this.i18nT("uni-datetime-picker.selectTime") | 
|             }, | 
|             startDateText() { | 
|                 return this.startPlaceholder || this.i18nT("uni-datetime-picker.startDate") | 
|             }, | 
|             startTimeText() { | 
|                 return this.i18nT("uni-datetime-picker.startTime") | 
|             }, | 
|             endDateText() { | 
|                 return this.endPlaceholder || this.i18nT("uni-datetime-picker.endDate") | 
|             }, | 
|             endTimeText() { | 
|                 return this.i18nT("uni-datetime-picker.endTime") | 
|             }, | 
|             okText() { | 
|                 return this.i18nT("uni-datetime-picker.ok") | 
|             }, | 
|             clearText() { | 
|                 return this.i18nT("uni-datetime-picker.clear") | 
|             }, | 
|             showClearIcon() { | 
|                 return this.clearIcon && !this.disabled && (this.displayValue || (this.displayRangeValue.startDate && this.displayRangeValue.endDate)) | 
|             } | 
|         }, | 
|         created() { | 
|             this.initI18nT() | 
|       this.platform() | 
|         }, | 
|         methods: { | 
|       initI18nT() { | 
|         const vueI18n = initVueI18n(i18nMessages) | 
|         this.i18nT = vueI18n.t | 
|       }, | 
|             initPicker(newVal) { | 
|                 if ((!newVal && !this.defaultValue) || Array.isArray(newVal) && !newVal.length) { | 
|                     this.$nextTick(() => { | 
|                         this.clear(false) | 
|                     }) | 
|                     return | 
|                 } | 
|   | 
|                 if (!Array.isArray(newVal) && !this.isRange) { | 
|           if(newVal){ | 
|             this.displayValue = this.inputDate = this.calendarDate = getDate(newVal) | 
|             if (this.hasTime) { | 
|               this.pickerTime = getTime(newVal, this.hideSecond) | 
|               this.displayValue = `${this.displayValue} ${this.pickerTime}` | 
|             } | 
|           }else if(this.defaultValue){ | 
|             this.inputDate = this.calendarDate = getDate(this.defaultValue) | 
|             if(this.hasTime){ | 
|               this.pickerTime = getTime(this.defaultValue, this.hideSecond) | 
|             } | 
|           } | 
|                 } else { | 
|                     const [before, after] = newVal | 
|                     if (!before && !after) return | 
|           const beforeDate = getDate(before) | 
|           const beforeTime = getTime(before, this.hideSecond) | 
|   | 
|           const afterDate = getDate(after) | 
|           const afterTime = getTime(after, this.hideSecond) | 
|                     const startDate = beforeDate | 
|                     const endDate = afterDate | 
|                     this.displayRangeValue.startDate = this.tempRange.startDate = startDate | 
|                     this.displayRangeValue.endDate = this.tempRange.endDate = endDate | 
|   | 
|                     if (this.hasTime) { | 
|                         this.displayRangeValue.startDate = `${beforeDate} ${beforeTime}` | 
|                         this.displayRangeValue.endDate = `${afterDate} ${afterTime}` | 
|                         this.tempRange.startTime = beforeTime | 
|                         this.tempRange.endTime = afterTime | 
|                     } | 
|                     const defaultRange = { | 
|                         before: beforeDate, | 
|                         after: afterDate | 
|                     } | 
|                     this.startMultipleStatus = Object.assign({}, this.startMultipleStatus, defaultRange, { | 
|                         which: 'right' | 
|                     }) | 
|                     this.endMultipleStatus = Object.assign({}, this.endMultipleStatus, defaultRange, { | 
|                         which: 'left' | 
|                     }) | 
|                 } | 
|             }, | 
|             updateLeftCale(e) { | 
|                 const left = this.$refs.left | 
|                 // 设置范围选 | 
|                 left.cale.setHoverMultiple(e.after) | 
|                 left.setDate(this.$refs.left.nowDate.fullDate) | 
|             }, | 
|             updateRightCale(e) { | 
|                 const right = this.$refs.right | 
|                 // 设置范围选 | 
|                 right.cale.setHoverMultiple(e.after) | 
|                 right.setDate(this.$refs.right.nowDate.fullDate) | 
|             }, | 
|             platform() { | 
|                 const { windowWidth } = uni.getSystemInfoSync() | 
|                 this.isPhone = windowWidth <= 500 | 
|                 this.windowWidth = windowWidth | 
|             }, | 
|             show() { | 
|                 if (this.disabled) { | 
|                     return | 
|                 } | 
|                 this.platform() | 
|                 if (this.isPhone) { | 
|                     this.$refs.mobile.open() | 
|                     return | 
|                 } | 
|                 this.pickerPositionStyle = { | 
|                     top: '10px' | 
|                 } | 
|                 const dateEditor = uni.createSelectorQuery().in(this).select(".uni-date-editor") | 
|                 dateEditor.boundingClientRect(rect => { | 
|                     if (this.windowWidth - rect.left < this.datePopupWidth) { | 
|                         this.pickerPositionStyle.right = 0 | 
|                     } | 
|                 }).exec() | 
|                 setTimeout(() => { | 
|                     this.pickerVisible = !this.pickerVisible | 
|                     if (!this.isPhone && this.isRange && this.isFirstShow) { | 
|                         this.isFirstShow = false | 
|                         const { | 
|                             startDate, | 
|                             endDate | 
|                         } = this.calendarRange | 
|                         if (startDate && endDate) { | 
|                             if (this.diffDate(startDate, endDate) < 30) { | 
|                                 this.$refs.right.changeMonth('pre') | 
|                             } | 
|                         } else { | 
|                             this.$refs.right.changeMonth('next') | 
|                             this.$refs.right.cale.lastHover = false | 
|                         } | 
|                     } | 
|   | 
|                 }, 50) | 
|             }, | 
|             close() { | 
|                 setTimeout(() => { | 
|                     this.pickerVisible = false | 
|                     this.$emit('maskClick', this.value) | 
|                     this.$refs.mobile && this.$refs.mobile.close() | 
|                 }, 20) | 
|             }, | 
|             setEmit(value) { | 
|                 if (this.returnType === "timestamp" || this.returnType === "date") { | 
|                     if (!Array.isArray(value)) { | 
|                         if (!this.hasTime) { | 
|                             value = value + ' ' + '00:00:00' | 
|                         } | 
|                         value = this.createTimestamp(value) | 
|                         if (this.returnType === "date") { | 
|                             value = new Date(value) | 
|                         } | 
|                     } else { | 
|                         if (!this.hasTime) { | 
|                             value[0] = value[0] + ' ' + '00:00:00' | 
|                             value[1] = value[1] + ' ' + '00:00:00' | 
|                         } | 
|                         value[0] = this.createTimestamp(value[0]) | 
|                         value[1] = this.createTimestamp(value[1]) | 
|                         if (this.returnType === "date") { | 
|                             value[0] = new Date(value[0]) | 
|                             value[1] = new Date(value[1]) | 
|                         } | 
|                     } | 
|                 } | 
|   | 
|                 this.$emit('update:modelValue', value) | 
|                 this.$emit('input', value) | 
|                 this.$emit('change', value) | 
|                 this.isEmitValue = true | 
|             }, | 
|             createTimestamp(date) { | 
|                 date = fixIosDateFormat(date) | 
|                 return Date.parse(new Date(date)) | 
|             }, | 
|             singleChange(e) { | 
|                 this.calendarDate = this.inputDate = e.fulldate | 
|                 if (this.hasTime) return | 
|                 this.confirmSingleChange() | 
|             }, | 
|             confirmSingleChange() { | 
|         if(!checkDate(this.inputDate)){ | 
|                     const now = new Date() | 
|           this.calendarDate = this.inputDate = getDate(now) | 
|                     this.pickerTime = getTime(now, this.hideSecond) | 
|         } | 
|   | 
|         let startLaterInputDate = false | 
|         let startDate, startTime | 
|         if(this.start) { | 
|           let startString = this.start | 
|           if(typeof this.start === 'number'){ | 
|             startString = getDateTime(this.start, this.hideSecond) | 
|           } | 
|           [startDate, startTime] = startString.split(' ') | 
|           if(this.start && !dateCompare(startDate, this.inputDate)) { | 
|             startLaterInputDate = true | 
|             this.inputDate = startDate | 
|           } | 
|         } | 
|   | 
|         let endEarlierInputDate = false | 
|         let endDate, endTime | 
|         if(this.end) { | 
|           let endString = this.end | 
|           if(typeof this.end === 'number'){ | 
|             endString = getDateTime(this.end, this.hideSecond) | 
|           } | 
|           [endDate, endTime] = endString.split(' ') | 
|           if(this.end && !dateCompare(this.inputDate, endDate)) { | 
|             endEarlierInputDate = true | 
|             this.inputDate = endDate | 
|           } | 
|         } | 
|                 if (this.hasTime) { | 
|           if(startLaterInputDate){ | 
|             this.pickerTime = startTime || getDefaultSecond(this.hideSecond) | 
|           } | 
|           if(endEarlierInputDate){ | 
|             this.pickerTime = endTime || getDefaultSecond(this.hideSecond) | 
|           } | 
|           if(!this.pickerTime){ | 
|             this.pickerTime = getTime(Date.now(), this.hideSecond) | 
|           } | 
|                     this.displayValue = `${this.inputDate} ${this.pickerTime}` | 
|                 } else { | 
|           this.displayValue = this.inputDate | 
|                 } | 
|                 this.setEmit(this.displayValue) | 
|                 this.pickerVisible = false | 
|             }, | 
|             leftChange(e) { | 
|                 const { | 
|                     before, | 
|                     after | 
|                 } = e.range | 
|                 this.rangeChange(before, after) | 
|                 const obj = { | 
|                     before: e.range.before, | 
|                     after: e.range.after, | 
|                     data: e.range.data, | 
|                     fulldate: e.fulldate | 
|                 } | 
|                 this.startMultipleStatus = Object.assign({}, this.startMultipleStatus, obj) | 
|             }, | 
|             rightChange(e) { | 
|                 const { | 
|                     before, | 
|                     after | 
|                 } = e.range | 
|                 this.rangeChange(before, after) | 
|                 const obj = { | 
|                     before: e.range.before, | 
|                     after: e.range.after, | 
|                     data: e.range.data, | 
|                     fulldate: e.fulldate | 
|                 } | 
|                 this.endMultipleStatus = Object.assign({}, this.endMultipleStatus, obj) | 
|             }, | 
|             mobileChange(e) { | 
|                 if (this.isRange) { | 
|                     const {before, after} = e.range | 
|   | 
|           if(!before || !after){ | 
|             return | 
|           } | 
|   | 
|                     this.handleStartAndEnd(before, after, true) | 
|                     if (this.hasTime) { | 
|                         const { | 
|                             startTime, | 
|                             endTime | 
|                         } = e.timeRange | 
|                         this.tempRange.startTime = startTime | 
|                         this.tempRange.endTime = endTime | 
|                     } | 
|                     this.confirmRangeChange() | 
|                 } else { | 
|                     if (this.hasTime) { | 
|                         this.displayValue = e.fulldate + ' ' + e.time | 
|                     } else { | 
|                         this.displayValue = e.fulldate | 
|                     } | 
|                     this.setEmit(this.displayValue) | 
|                 } | 
|                 this.$refs.mobile.close() | 
|             }, | 
|             rangeChange(before, after) { | 
|                 if (!(before && after)) return | 
|                 this.handleStartAndEnd(before, after, true) | 
|                 if (this.hasTime) return | 
|                 this.confirmRangeChange() | 
|             }, | 
|             confirmRangeChange() { | 
|                 if (!this.tempRange.startDate || !this.tempRange.endDate) { | 
|                     this.pickerVisible = false | 
|                     return | 
|                 } | 
|         if(!checkDate(this.tempRange.startDate)){ | 
|           this.tempRange.startDate = getDate(Date.now()) | 
|         } | 
|         if(!checkDate(this.tempRange.endDate)){ | 
|           this.tempRange.endDate = getDate(Date.now()) | 
|         } | 
|   | 
|                 let start, end | 
|   | 
|         let startDateLaterRangeStartDate = false | 
|         let startDateLaterRangeEndDate = false | 
|         let startDate, startTime | 
|         if(this.start) { | 
|           let startString = this.start | 
|           if(typeof this.start === 'number'){ | 
|             startString = getDateTime(this.start, this.hideSecond) | 
|           } | 
|           [startDate,startTime] = startString.split(' ') | 
|           if(this.start && !dateCompare(this.start, this.tempRange.startDate)) { | 
|             startDateLaterRangeStartDate = true | 
|             this.tempRange.startDate = startDate | 
|           } | 
|           if(this.start && !dateCompare(this.start, this.tempRange.endDate)) { | 
|             startDateLaterRangeEndDate = true | 
|             this.tempRange.endDate = startDate | 
|           } | 
|         } | 
|         let endDateEarlierRangeStartDate = false | 
|         let endDateEarlierRangeEndDate = false | 
|         let endDate, endTime | 
|         if(this.end) { | 
|           let endString = this.end | 
|           if(typeof this.end === 'number'){ | 
|             endString = getDateTime(this.end, this.hideSecond) | 
|           } | 
|           [endDate,endTime] = endString.split(' ') | 
|   | 
|           if(this.end && !dateCompare(this.tempRange.startDate, this.end)) { | 
|             endDateEarlierRangeStartDate = true | 
|             this.tempRange.startDate = endDate | 
|           } | 
|           if(this.end && !dateCompare(this.tempRange.endDate, this.end)) { | 
|             endDateEarlierRangeEndDate = true | 
|             this.tempRange.endDate = endDate | 
|           } | 
|         } | 
|                 if (!this.hasTime) { | 
|           start = this.displayRangeValue.startDate = this.tempRange.startDate | 
|                     end = this.displayRangeValue.endDate = this.tempRange.endDate | 
|                 } else { | 
|           if(startDateLaterRangeStartDate){ | 
|             this.tempRange.startTime = startTime || getDefaultSecond(this.hideSecond) | 
|           }else if(endDateEarlierRangeStartDate){ | 
|             this.tempRange.startTime = endTime || getDefaultSecond(this.hideSecond) | 
|           } | 
|           if(!this.tempRange.startTime){ | 
|             this.tempRange.startTime = getTime(Date.now(), this.hideSecond) | 
|           } | 
|   | 
|           if(startDateLaterRangeEndDate){ | 
|             this.tempRange.endTime = startTime || getDefaultSecond(this.hideSecond) | 
|           }else if(endDateEarlierRangeEndDate){ | 
|             this.tempRange.endTime = endTime || getDefaultSecond(this.hideSecond) | 
|           } | 
|           if(!this.tempRange.endTime){ | 
|             this.tempRange.endTime = getTime(Date.now(), this.hideSecond) | 
|           } | 
|                     start = this.displayRangeValue.startDate = `${this.tempRange.startDate} ${this.tempRange.startTime}` | 
|                     end = this.displayRangeValue.endDate = `${this.tempRange.endDate} ${this.tempRange.endTime}` | 
|                 } | 
|         if(!dateCompare(start,end)){ | 
|           [start, end] = [end, start] | 
|         } | 
|                 this.displayRangeValue.startDate = start | 
|                 this.displayRangeValue.endDate = end | 
|                 const displayRange = [start, end] | 
|                 this.setEmit(displayRange) | 
|                 this.pickerVisible = false | 
|             }, | 
|             handleStartAndEnd(before, after, temp = false) { | 
|                 if (!(before && after)) return | 
|   | 
|                 const type = temp ? 'tempRange' : 'range' | 
|         const isStartEarlierEnd = dateCompare(before, after) | 
|         this[type].startDate = isStartEarlierEnd ? before : after | 
|         this[type].endDate = isStartEarlierEnd ? after : before | 
|     }, | 
|             /** | 
|              * 比较时间大小 | 
|              */ | 
|             dateCompare(startDate, endDate) { | 
|                 // 计算截止时间 | 
|                 startDate = new Date(startDate.replace('-', '/').replace('-', '/')) | 
|                 // 计算详细项的截止时间 | 
|                 endDate = new Date(endDate.replace('-', '/').replace('-', '/')) | 
|                 return startDate <= endDate | 
|             }, | 
|   | 
|             /** | 
|              * 比较时间差 | 
|              */ | 
|             diffDate(startDate, endDate) { | 
|                 // 计算截止时间 | 
|                 startDate = new Date(startDate.replace('-', '/').replace('-', '/')) | 
|                 // 计算详细项的截止时间 | 
|                 endDate = new Date(endDate.replace('-', '/').replace('-', '/')) | 
|                 const diff = (endDate - startDate) / (24 * 60 * 60 * 1000) | 
|                 return Math.abs(diff) | 
|             }, | 
|   | 
|             clear(needEmit = true) { | 
|                 if (!this.isRange) { | 
|                     this.displayValue = '' | 
|                     this.inputDate = '' | 
|                     this.pickerTime = '' | 
|                     if (this.isPhone) { | 
|                         this.$refs.mobile && this.$refs.mobile.clearCalender() | 
|                     } else { | 
|                         this.$refs.pcSingle && this.$refs.pcSingle.clearCalender() | 
|                     } | 
|                     if (needEmit) { | 
|                         this.$emit('change', '') | 
|                         this.$emit('input', '') | 
|                         this.$emit('update:modelValue', '') | 
|                     } | 
|                 } else { | 
|                     this.displayRangeValue.startDate = '' | 
|                     this.displayRangeValue.endDate = '' | 
|                     this.tempRange.startDate = '' | 
|                     this.tempRange.startTime = '' | 
|                     this.tempRange.endDate = '' | 
|                     this.tempRange.endTime = '' | 
|                     if (this.isPhone) { | 
|                         this.$refs.mobile && this.$refs.mobile.clearCalender() | 
|                     } else { | 
|                         this.$refs.left && this.$refs.left.clearCalender() | 
|                         this.$refs.right && this.$refs.right.clearCalender() | 
|                         this.$refs.right && this.$refs.right.changeMonth('next') | 
|                     } | 
|                     if (needEmit) { | 
|                         this.$emit('change', []) | 
|                         this.$emit('input', []) | 
|                         this.$emit('update:modelValue', []) | 
|                     } | 
|                 } | 
|             } | 
|         } | 
|     } | 
| </script> | 
|   | 
| <style lang="scss"> | 
|     $uni-primary: #007aff !default; | 
|   | 
|     .uni-date { | 
|         width: 100%; | 
|         flex: 1; | 
|     } | 
|     .uni-date-x { | 
|         display: flex; | 
|         flex-direction: row; | 
|         align-items: center; | 
|         justify-content: center; | 
|         border-radius: 4px; | 
|         background-color: #fff; | 
|         color: #666; | 
|         font-size: 14px; | 
|         flex: 1; | 
|   | 
|     .icon-calendar{ | 
|       padding-left: 3px; | 
|     } | 
|     .range-separator{ | 
|       height: 35px; | 
|       /* #ifndef MP */ | 
|       padding: 0 2px; | 
|       /* #endif */ | 
|             line-height: 35px; | 
|     } | 
|     } | 
|   | 
|     .uni-date-x--border { | 
|         box-sizing: border-box; | 
|         border-radius: 4px; | 
|         border: 1px solid #e5e5e5; | 
|     } | 
|   | 
|     .uni-date-editor--x { | 
|         display: flex; | 
|         align-items: center; | 
|         position: relative; | 
|     } | 
|   | 
|     .uni-date-editor--x .uni-date__icon-clear { | 
|         padding-right: 3px; | 
|         display: flex; | 
|         align-items: center; | 
|         /* #ifdef H5 */ | 
|         cursor: pointer; | 
|         /* #endif */ | 
|     } | 
|   | 
|     .uni-date__x-input { | 
|         width: auto; | 
|         height: 35px; | 
|     /* #ifndef MP */ | 
|     padding-left: 5px; | 
|     /* #endif */ | 
|         position: relative; | 
|         flex: 1; | 
|         line-height: 35px; | 
|         font-size: 14px; | 
|         overflow: hidden; | 
|     } | 
|   | 
|     .text-center { | 
|         text-align: center; | 
|     } | 
|   | 
|     .uni-date__input { | 
|         height: 40px; | 
|         width: 100%; | 
|         line-height: 40px; | 
|         font-size: 14px; | 
|     } | 
|   | 
|     .uni-date-range__input { | 
|         text-align: center; | 
|         max-width: 142px; | 
|     } | 
|   | 
|     .uni-date-picker__container { | 
|         position: relative; | 
|     } | 
|   | 
|     .uni-date-mask--pc { | 
|         position: fixed; | 
|         bottom: 0px; | 
|         top: 0px; | 
|         left: 0px; | 
|         right: 0px; | 
|         background-color: rgba(0, 0, 0, 0); | 
|         transition-duration: 0.3s; | 
|         z-index: 996; | 
|     } | 
|   | 
|     .uni-date-single--x { | 
|         background-color: #fff; | 
|         position: absolute; | 
|         top: 0; | 
|         z-index: 999; | 
|         border: 1px solid #EBEEF5; | 
|         box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); | 
|         border-radius: 4px; | 
|     } | 
|   | 
|     .uni-date-range--x { | 
|         background-color: #fff; | 
|         position: absolute; | 
|         top: 0; | 
|         z-index: 999; | 
|         border: 1px solid #EBEEF5; | 
|         box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); | 
|         border-radius: 4px; | 
|     } | 
|   | 
|     .uni-date-editor--x__disabled { | 
|         opacity: 0.4; | 
|         cursor: default; | 
|     } | 
|   | 
|     .uni-date-editor--logo { | 
|         width: 16px; | 
|         height: 16px; | 
|         vertical-align: middle; | 
|     } | 
|   | 
|     /* 添加时间 */ | 
|     .popup-x-header { | 
|         /* #ifndef APP-NVUE */ | 
|         display: flex; | 
|         /* #endif */ | 
|         flex-direction: row; | 
|     } | 
|   | 
|     .popup-x-header--datetime { | 
|         /* #ifndef APP-NVUE */ | 
|         display: flex; | 
|         /* #endif */ | 
|         flex-direction: row; | 
|         flex: 1; | 
|     } | 
|   | 
|     .popup-x-body { | 
|         display: flex; | 
|     } | 
|   | 
|     .popup-x-footer { | 
|         padding: 0 15px; | 
|         border-top-color: #F1F1F1; | 
|         border-top-style: solid; | 
|         border-top-width: 1px; | 
|         line-height: 40px; | 
|         text-align: right; | 
|         color: #666; | 
|     } | 
|   | 
|     .popup-x-footer text:hover { | 
|         color: $uni-primary; | 
|         cursor: pointer; | 
|         opacity: 0.8; | 
|     } | 
|   | 
|     .popup-x-footer .confirm-text { | 
|         margin-left: 20px; | 
|         color: $uni-primary; | 
|     } | 
|   | 
|     .uni-date-changed { | 
|         text-align: center; | 
|         color: #333; | 
|         border-bottom-color: #F1F1F1; | 
|         border-bottom-style: solid; | 
|         border-bottom-width: 1px; | 
|     } | 
|   | 
|     .uni-date-changed--time text { | 
|         height: 50px; | 
|         line-height: 50px; | 
|     } | 
|   | 
|     .uni-date-changed .uni-date-changed--time { | 
|         flex: 1; | 
|     } | 
|   | 
|     .uni-date-changed--time-date { | 
|         color: #333; | 
|         opacity: 0.6; | 
|     } | 
|   | 
|     .mr-50 { | 
|         margin-right: 50px; | 
|     } | 
|   | 
|     /* picker 弹出层通用的指示小三角, todo:扩展至上下左右方向定位 */ | 
|     .uni-popper__arrow, | 
|     .uni-popper__arrow::after { | 
|         position: absolute; | 
|         display: block; | 
|         width: 0; | 
|         height: 0; | 
|         border: 6px solid transparent; | 
|         border-top-width: 0; | 
|     } | 
|   | 
|     .uni-popper__arrow { | 
|         filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03)); | 
|         top: -6px; | 
|         left: 10%; | 
|         margin-right: 3px; | 
|         border-bottom-color: #EBEEF5; | 
|     } | 
|   | 
|     .uni-popper__arrow::after { | 
|         content: " "; | 
|         top: 1px; | 
|         margin-left: -6px; | 
|         border-bottom-color: #fff; | 
|     } | 
| </style> |