ng-devui
Version:
DevUI components based on Angular
1 lines • 327 kB
Source Map (JSON)
{"version":3,"file":"ng-devui-datepicker.mjs","sources":["../../devui/datepicker/date-change-event-args.model.ts","../../devui/datepicker/date-picker.config.service.ts","../../devui/datepicker/date-range-change-event-args.model.ts","../../devui/datepicker/datepicker.component.ts","../../devui/datepicker/datepicker.component.html","../../devui/datepicker/single-date-range-picker.component.ts","../../devui/datepicker/single-date-range-picker.component.html","../../devui/datepicker/date-range-picker.component.ts","../../devui/datepicker/date-range-picker.component.html","../../devui/datepicker/date-range-picker.directive.ts","../../devui/datepicker/date-range-picker.directive.html","../../devui/datepicker/datepicker-cdk-overlay.component.ts","../../devui/datepicker/datepicker.directive.ts","../../devui/datepicker/two-datepicker/two-datepicker-single.component.ts","../../devui/datepicker/two-datepicker/two-datepicker.component.ts","../../devui/datepicker/two-datepicker/two-datepicker.component.html","../../devui/datepicker/two-datepicker/two-datepicker-end.directive.ts","../../devui/datepicker/two-datepicker/two-datepicker-start.directive.ts","../../devui/datepicker/datepicker.module.ts","../../devui/datepicker/ng-devui-datepicker.ts"],"sourcesContent":["export enum SelectDateChangeReason {\r\n date = 0,\r\n time = 1,\r\n button = 2,\r\n format = 3,\r\n custom = 4,\r\n}\r\n\r\nexport interface SelectDateChangeEventArgs {\r\n reason: SelectDateChangeReason;\r\n selectedDate: Date;\r\n}\r\n","import { Injectable } from '@angular/core';\n\n@Injectable()\nexport class DatePickerConfigService {\n dateConfig = {\n timePicker: false,\n dateConverter: null,\n min: 1900,\n max: 2099,\n format: {\n date: 'y/MM/dd',\n time: 'y/MM/dd HH:mm:ss'\n }\n };\n\n defaultFormat = 'y/MM/dd';\n}\n","export enum SelectDateRangeChangeReason {\r\n date = 0,\r\n time = 1,\r\n button = 2,\r\n format = 3,\r\n custom = 4,\r\n}\r\n\r\nexport interface SelectDateRangeChangeEventArgs {\r\n reason: SelectDateRangeChangeReason;\r\n selectedRange: Date[];\r\n}\r\n","import {\r\n ChangeDetectorRef,\r\n Component,\r\n ElementRef,\r\n EventEmitter,\r\n forwardRef,\r\n HostListener,\r\n Input,\r\n OnChanges,\r\n OnDestroy,\r\n OnInit,\r\n Output,\r\n Renderer2,\r\n SimpleChanges,\r\n TemplateRef,\r\n} from '@angular/core';\r\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\r\nimport { I18nInterface, I18nService } from 'ng-devui/i18n';\r\nimport { DateConverter, DefaultDateConverter, unshiftString } from 'ng-devui/utils';\r\nimport { Subscription } from 'rxjs';\r\nimport { SelectDateChangeEventArgs, SelectDateChangeReason } from './date-change-event-args.model';\r\nimport { DatePickerConfigService as DatePickerConfig } from './date-picker.config.service';\r\n\r\n@Component({\r\n selector: 'd-datepicker',\r\n templateUrl: './datepicker.component.html',\r\n styleUrls: ['./datepicker.component.scss'],\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => DatepickerComponent),\r\n multi: true,\r\n },\r\n ],\r\n preserveWhitespaces: false,\r\n})\r\nexport class DatepickerComponent implements OnInit, OnChanges, OnDestroy, ControlValueAccessor {\r\n static DAY_DURATION = 24 * 60 * 60 * 1000;\r\n protected _maxDate: Date;\r\n protected _minDate: Date;\r\n protected nowMinYear: number;\r\n protected nowMaxYear: number;\r\n @Input() cssClass: string;\r\n @Input() dateConverter: DateConverter;\r\n @Input() locale: string;\r\n @Output() selectedDateChange = new EventEmitter<SelectDateChangeEventArgs>();\r\n @Input() disabled = false;\r\n @Input() customViewTemplate: TemplateRef<any>;\r\n @Input() selectedDate: Date;\r\n @Input() mode: 'year' | 'month' | 'date' = 'date';\r\n @Input() dateFormat: string;\r\n yearNumber = 12;\r\n _yearNumber = 12;\r\n _dateConfig: any;\r\n currentYear: number;\r\n currentMonthIndex: number;\r\n _currentHour: number | string;\r\n _currentMinute: number | string;\r\n _currentSecond: number | string;\r\n _showTime: boolean;\r\n hourOptions: string[];\r\n minuteOptions: string[];\r\n displayWeeks: any[];\r\n yearOptions: any[];\r\n openChooseYear: boolean;\r\n openChooseMonth: boolean;\r\n availableMonths: any[];\r\n i18nText: I18nInterface['datePicker'];\r\n i18nLocale: I18nInterface['locale'];\r\n i18nCommonText: I18nInterface['common'];\r\n i18nSubscription: Subscription;\r\n\r\n protected onChange = (_: any) => null;\r\n protected onTouched = () => null;\r\n\r\n constructor(\r\n protected elementRef: ElementRef,\r\n protected renderer2: Renderer2,\r\n protected datePickerConfig: DatePickerConfig,\r\n protected changeDetectorRef: ChangeDetectorRef,\r\n protected i18n: I18nService\r\n ) {\r\n this._dateConfig = datePickerConfig.dateConfig;\r\n this.dateConverter = datePickerConfig.dateConfig.dateConverter || new DefaultDateConverter();\r\n this.renderer2.setStyle(this.elementRef.nativeElement, 'display', 'inline-block');\r\n this.setI18nText();\r\n }\r\n\r\n ngOnInit() {\r\n this._minDate = this.minDate ? new Date(this.minDate) : new Date(this.dateConfig.min, 0, 1, 0, 0, 0);\r\n this._maxDate = this.maxDate ? new Date(this.maxDate) : new Date(this.dateConfig.max, 11, 31, 23, 59, 59);\r\n\r\n this.hourOptions = new Array(24).fill(0).map((value, index) => this.fillLeft(index));\r\n this.minuteOptions = new Array(60).fill(0).map((value, index) => this.fillLeft(index));\r\n const nowDate = this.selectedDate || new Date();\r\n this.nowMinYear =\r\n nowDate.getFullYear() - Math.floor(this._yearNumber / 2) < this.minDate.getFullYear()\r\n ? this.minDate.getFullYear()\r\n : nowDate.getFullYear() - Math.floor(this._yearNumber / 2);\r\n this.nowMaxYear =\r\n nowDate.getFullYear() + Math.floor(this._yearNumber / 2) > this.maxDate.getFullYear()\r\n ? this.maxDate.getFullYear()\r\n : nowDate.getFullYear() + Math.floor(this._yearNumber / 2);\r\n this.initMode();\r\n this.onSelectDateChanged();\r\n this.onDisplayWeeksChange();\r\n this.onYearRangeChange();\r\n this.initDatePicker();\r\n }\r\n\r\n initMode() {\r\n if (this.mode === 'year') {\r\n this.openChooseYear = true;\r\n this.openChooseMonth = false;\r\n if (!this.selectedDate) {\r\n this.selectedDate = new Date();\r\n }\r\n if (this.maxDate.getTime() < this.selectedDate.getTime()) {\r\n this.selectedDate = new Date(this.maxDate);\r\n }\r\n if (this.minDate.getTime() > this.selectedDate.getTime()) {\r\n this.selectedDate = new Date(this.minDate);\r\n }\r\n } else if (this.mode === 'month') {\r\n this.openChooseYear = false;\r\n this.openChooseMonth = true;\r\n if (!this.selectedDate) {\r\n this.selectedDate = new Date();\r\n }\r\n if (this.maxDate.getTime() < this.selectedDate.getTime()) {\r\n this.selectedDate = new Date(this.maxDate);\r\n }\r\n if (this.minDate.getTime() > this.selectedDate.getTime()) {\r\n this.selectedDate = new Date(this.minDate);\r\n }\r\n } else {\r\n this.openChooseYear = this.openChooseMonth = false;\r\n }\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges) {\r\n if (changes?.selectedDate?.currentValue) {\r\n this.writeValue(this.selectedDate);\r\n }\r\n }\r\n\r\n @HostListener('document:click', ['$event'])\r\n onDocumentClick($event) {\r\n if (!this.elementRef.nativeElement.contains($event.target)) {\r\n this.openChooseYear = this.openChooseMonth = false;\r\n this.resetYearOptions();\r\n }\r\n }\r\n\r\n @HostListener('click', ['$event'])\r\n onClick($event) {\r\n $event.stopPropagation();\r\n }\r\n\r\n @Input() set showTime(showTime: boolean) {\r\n this._showTime = showTime;\r\n }\r\n\r\n get showTime() {\r\n return typeof this._showTime === 'boolean' ? this._showTime : this.dateConfig.timePicker;\r\n }\r\n\r\n @Input() set dateConfig(dateConfig: any) {\r\n if (this.checkDateConfig(dateConfig)) {\r\n this._dateConfig = dateConfig;\r\n } else {\r\n this._dateConfig = this.datePickerConfig.dateConfig;\r\n }\r\n }\r\n\r\n get dateConfig() {\r\n return this._dateConfig;\r\n }\r\n\r\n checkDateConfig(dateConfig: any) {\r\n if (!dateConfig) {\r\n return false;\r\n }\r\n if (typeof dateConfig.timePicker !== 'boolean' || !dateConfig.max || !dateConfig.min) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n @Input() set minDate(date: Date | any) {\r\n const parseDate = this.dateConverter.parse(date, this.dateFormat);\r\n if (parseDate) {\r\n this._minDate = parseDate;\r\n this.onYearRangeChange();\r\n }\r\n }\r\n get minDate() {\r\n return this._minDate;\r\n }\r\n\r\n @Input() set maxDate(date: Date | any) {\r\n const parseDate = this.dateConverter.parse(date, this.dateFormat);\r\n if (parseDate) {\r\n this._maxDate = parseDate;\r\n this.onYearRangeChange();\r\n }\r\n }\r\n get maxDate() {\r\n return this._maxDate;\r\n }\r\n\r\n set currentHour(hour: number | string) {\r\n this._currentHour = hour;\r\n }\r\n\r\n get currentHour() {\r\n return unshiftString(String(this._currentHour), 2, '0');\r\n }\r\n\r\n set currentMinute(min: number | string) {\r\n this._currentMinute = min;\r\n }\r\n\r\n get currentMinute() {\r\n return unshiftString(String(this._currentMinute), 2, '0');\r\n }\r\n\r\n set currentSecond(sec: number | string) {\r\n this._currentSecond = sec;\r\n }\r\n\r\n get currentSecond() {\r\n return unshiftString(String(this._currentSecond), 2, '0');\r\n }\r\n\r\n protected resetYearOptions() {\r\n this.initMode();\r\n const baseYear = this.selectedDate ? this.selectedDate.getFullYear() : new Date().getFullYear();\r\n this.currentYear = baseYear;\r\n this.nowMinYear =\r\n baseYear - Math.floor(this._yearNumber / 2) < this.minDate.getFullYear()\r\n ? this.minDate.getFullYear()\r\n : baseYear - Math.floor(this._yearNumber / 2);\r\n this.nowMaxYear =\r\n baseYear + Math.floor(this._yearNumber / 2) > this.maxDate.getFullYear()\r\n ? this.maxDate.getFullYear()\r\n : baseYear + Math.floor(this._yearNumber / 2);\r\n this.onYearRangeChange();\r\n }\r\n\r\n onYearRangeChange() {\r\n if (!this.nowMinYear || !this.nowMaxYear) {\r\n return;\r\n }\r\n let baseYear = Math.round((this.nowMinYear + this.nowMaxYear) / 2);\r\n if (this.nowMaxYear - this.nowMinYear < this._yearNumber - 1) {\r\n if (this.nowMinYear === this.minDate.getFullYear() && this.nowMaxYear === this.maxDate.getFullYear()) {\r\n baseYear = this.nowMinYear + Math.round((this.nowMaxYear - this.nowMinYear) / 2);\r\n } else if (this.nowMinYear === this.minDate.getFullYear()) {\r\n baseYear = this.nowMaxYear - this._yearNumber / 2 + 1;\r\n } else if (this.nowMaxYear === this.maxDate.getFullYear()) {\r\n baseYear = this.nowMinYear + this._yearNumber / 2;\r\n }\r\n }\r\n this.yearOptions = new Array(this._yearNumber).fill(0).map((value, index) => {\r\n const title = baseYear - this._yearNumber / 2 + index;\r\n return {\r\n title: title,\r\n disabled: false,\r\n };\r\n });\r\n if (this._yearNumber > this.nowMaxYear - this.nowMinYear + 1) {\r\n this.yearOptions.forEach((value, index) => {\r\n if (index < 6) {\r\n value.disabled = value.title < this.nowMinYear;\r\n } else {\r\n value.disabled = value.title > this.nowMaxYear;\r\n }\r\n });\r\n }\r\n }\r\n\r\n writeValue(obj: any): void {\r\n if (!obj) {\r\n return;\r\n }\r\n this.selectedDate = this.dateConverter.parse(obj, this.dateFormat);\r\n this.onSelectDateChanged();\r\n this.onDisplayWeeksChange();\r\n this.availableMonths = this.onDisplayMonthsChange();\r\n this.changeDetectorRef.markForCheck();\r\n }\r\n\r\n registerOnChange(fn: any): void {\r\n this.onChange = fn;\r\n }\r\n\r\n registerOnTouched(fn: any): void {\r\n this.onTouched = fn;\r\n }\r\n\r\n hasPreMonth() {\r\n if (this.currentYear > this.minDate.getFullYear()) {\r\n return true;\r\n } else if (this.currentYear === this.minDate.getFullYear() && this.currentMonthIndex > this.minDate.getMonth()) {\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n onPreMonth() {\r\n if (!this.hasPreMonth()) {\r\n return;\r\n }\r\n\r\n const date = new Date(this.currentYear, this.currentMonthIndex);\r\n date.setMonth(date.getMonth() - 1);\r\n this.currentMonthIndex = date.getMonth();\r\n this.currentYear = date.getFullYear();\r\n this.onDisplayWeeksChange();\r\n }\r\n\r\n hasNextMonth() {\r\n if (this.currentYear < this.maxDate.getFullYear()) {\r\n return true;\r\n } else if (this.currentYear === this.maxDate.getFullYear() && this.currentMonthIndex < this.maxDate.getMonth()) {\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n onNextMonth(currentDate?: Date, invocation?: any) {\r\n if (!this.hasNextMonth() && invocation !== 'init') {\r\n return;\r\n }\r\n let date;\r\n if (currentDate) {\r\n date = new Date(currentDate.getTime());\r\n } else {\r\n date = new Date(this.currentYear, this.currentMonthIndex);\r\n }\r\n date.setMonth(date.getMonth() + 1);\r\n this.currentMonthIndex = date.getMonth();\r\n this.currentYear = date.getFullYear();\r\n this.onDisplayWeeksChange();\r\n }\r\n\r\n hasPreYearOption() {\r\n if (this.openChooseYear) {\r\n return this.yearOptions[0].title.toString() > this.minDate.getFullYear();\r\n } else {\r\n return Number(this.currentYear) > this.minDate.getFullYear();\r\n }\r\n }\r\n\r\n onPreYearOption() {\r\n if (!this.hasPreYearOption()) {\r\n return;\r\n }\r\n if (this.openChooseYear) {\r\n if (this.nowMinYear - this._yearNumber >= this.minDate.getFullYear()) {\r\n this.nowMaxYear = this.nowMinYear - 1;\r\n this.nowMinYear = this.nowMinYear - this._yearNumber;\r\n } else {\r\n this.nowMaxYear = this.nowMinYear - 1;\r\n this.nowMinYear = this.minDate.getFullYear();\r\n }\r\n this.onYearRangeChange();\r\n } else {\r\n this.onSelectYear(Number(this.currentYear) - 1);\r\n }\r\n }\r\n\r\n hasNextYearOption() {\r\n if (this.openChooseYear) {\r\n return this.yearOptions[11].title.toString() < this.maxDate.getFullYear();\r\n } else {\r\n return Number(this.currentYear) < this.maxDate.getFullYear();\r\n }\r\n }\r\n\r\n onNextYearOption() {\r\n if (!this.hasNextYearOption()) {\r\n return;\r\n }\r\n if (this.openChooseYear) {\r\n if (this.nowMaxYear + this._yearNumber <= this.maxDate.getFullYear()) {\r\n this.nowMinYear = this.nowMaxYear + 1;\r\n this.nowMaxYear = this.nowMaxYear + this._yearNumber;\r\n } else {\r\n this.nowMinYear = this.nowMaxYear + 1;\r\n this.nowMaxYear = this.maxDate.getFullYear();\r\n }\r\n this.onYearRangeChange();\r\n } else {\r\n this.onSelectYear(Number(this.currentYear) + 1);\r\n }\r\n }\r\n\r\n onSelectYear(year, $event?: Event) {\r\n if ($event) {\r\n $event.stopPropagation();\r\n }\r\n const yearDisabled = typeof year === 'object' ? year.disabled : false;\r\n const yearTitle = typeof year === 'object' ? year.title : year;\r\n if (yearDisabled) {\r\n return;\r\n }\r\n this.currentYear = yearTitle;\r\n if (this.mode === 'year') {\r\n this.onSelectDate($event, new Date(yearTitle, 0, 1));\r\n } else if (this.mode === 'month') {\r\n this.openChooseYear = false;\r\n this.availableMonths = this.onDisplayMonthsChange();\r\n this.currentMonthIndex = null;\r\n this.openChooseMonth = true;\r\n } else {\r\n this.onDisplayWeeksChange();\r\n this.availableMonths = this.onDisplayMonthsChange();\r\n this.openChooseYear = false;\r\n this.openChooseMonth = !!$event;\r\n }\r\n }\r\n\r\n protected onSelectDateChanged() {\r\n let date = this.selectedDate || new Date();\r\n if (date.getTime() < this.minDate.getTime()) {\r\n date = this.minDate;\r\n }\r\n if (date.getTime() > this.maxDate.getTime()) {\r\n date = this.maxDate;\r\n }\r\n this.currentYear = date.getFullYear();\r\n this.currentMonthIndex = date.getMonth();\r\n this.currentHour = this.showTime ? date.getHours() : 0;\r\n this.currentMinute = this.showTime ? date.getMinutes() : 0;\r\n this.currentSecond = this.showTime ? date.getSeconds() : 0;\r\n }\r\n\r\n public onDisplayWeeksChange() {\r\n const today = new Date();\r\n const firstDayOfMonth = new Date(this.currentYear, this.currentMonthIndex, 1);\r\n const weekOfDay = firstDayOfMonth.getDay();\r\n const startDate = new Date(firstDayOfMonth.getTime() - weekOfDay * DatepickerComponent.DAY_DURATION);\r\n const displayWeeks = [];\r\n for (let i = 0; i < 6; i++) {\r\n const startWeekDate = startDate.getTime() + i * 7 * DatepickerComponent.DAY_DURATION;\r\n const weekDays = new Array(7).fill(0).map((value, index) => {\r\n const currentDate = new Date(startWeekDate + index * DatepickerComponent.DAY_DURATION);\r\n return {\r\n day: this.fillLeft(currentDate.getDate()),\r\n date: currentDate,\r\n inMonth: currentDate.getMonth().toString() === this.currentMonthIndex.toString(),\r\n isToday:\r\n currentDate.getFullYear() === today.getFullYear() &&\r\n currentDate.getMonth() === today.getMonth() &&\r\n currentDate.getDate() === today.getDate(),\r\n };\r\n });\r\n displayWeeks.push(weekDays);\r\n }\r\n this.displayWeeks = displayWeeks;\r\n }\r\n\r\n public onDisplayMonthsChange() {\r\n const all = new Array(12).fill(0).map((value, index) => {\r\n return {\r\n index: index,\r\n title: this.i18nText.monthsOfYear[index],\r\n disabled: false,\r\n };\r\n });\r\n\r\n if (this.currentYear < this.minDate.getFullYear() || this.currentYear > this.maxDate.getFullYear()) {\r\n all.forEach((month) => {\r\n month.disabled = true;\r\n });\r\n }\r\n\r\n if (this.currentYear === this.minDate.getFullYear()) {\r\n all.forEach((month) => {\r\n month.disabled = month.index < this.minDate.getMonth();\r\n });\r\n }\r\n\r\n if (this.currentYear === this.maxDate.getFullYear()) {\r\n all.forEach((month) => {\r\n month.disabled = month.index > this.maxDate.getMonth();\r\n });\r\n }\r\n return all;\r\n }\r\n\r\n protected fillLeft(num: number) {\r\n return num < 10 ? `0${num}` : `${num}`;\r\n }\r\n\r\n isDisabledDay(date) {\r\n if (this.disabled) {\r\n return true;\r\n }\r\n if (!date) {\r\n return false;\r\n }\r\n const minDate = new Date(this.minDate.getFullYear(), this.minDate.getMonth(), this.minDate.getDate());\r\n const maxDate = new Date(this.maxDate.getFullYear(), this.maxDate.getMonth(), this.maxDate.getDate(), 23, 59, 59);\r\n const dis = date.getTime() < minDate.getTime();\r\n return this.disabled || date.getTime() < minDate.getTime() || date.getTime() > maxDate.getTime();\r\n }\r\n\r\n isSelectDay(date) {\r\n if (!this.selectedDate || !date) {\r\n return false;\r\n }\r\n return (\r\n date.getFullYear() === this.selectedDate.getFullYear() &&\r\n date.getMonth() === this.selectedDate.getMonth() &&\r\n date.getDate() === this.selectedDate.getDate()\r\n );\r\n }\r\n\r\n /*\r\n ** @param invocation:调用时机\r\n */\r\n onSelectDate($event, date, invocation?: any, reason?: SelectDateChangeReason) {\r\n if ($event.stopPropagation) {\r\n $event.stopPropagation();\r\n }\r\n if (this.isDisabledDay(date)) {\r\n return;\r\n }\r\n this.selectedDate = new Date(\r\n date.getFullYear(),\r\n date.getMonth(),\r\n date.getDate(),\r\n Number(this.currentHour),\r\n Number(this.currentMinute),\r\n Number(this.currentSecond)\r\n );\r\n const currentReason = typeof reason === 'number' ? reason : SelectDateChangeReason.date;\r\n const dateObj = {\r\n reason: currentReason,\r\n selectedDate: this.selectedDate,\r\n };\r\n this.onTouched();\r\n this.writeValue(this.selectedDate);\r\n // 初始化的时候不触发emit和ngModelChange\r\n if (invocation !== 'init') {\r\n this.onChange(dateObj);\r\n this.selectedDateChange.emit(dateObj);\r\n }\r\n if (this.currentMonthIndex !== this.selectedDate.getMonth() || this.currentYear !== this.selectedDate.getFullYear()) {\r\n this.currentYear = this.selectedDate.getFullYear();\r\n this.currentMonthIndex = this.selectedDate.getMonth();\r\n this.onDisplayWeeksChange();\r\n }\r\n }\r\n\r\n fixTime(event, type) {\r\n // 由于keypress不监听微软输入法需要使用keydown\r\n // 而keydown中微软输入法的key是'Process',且keydown没有charCode,所以需要用code判断\r\n // 故退格和输入使用同一个事件\r\n let timeType: string;\r\n const min = 0;\r\n let max = 59;\r\n switch (type) {\r\n case 'h': {\r\n timeType = 'currentHour';\r\n max = 23;\r\n break;\r\n }\r\n case 'm': {\r\n timeType = 'currentMinute';\r\n break;\r\n }\r\n case 's': {\r\n timeType = 'currentSecond';\r\n break;\r\n }\r\n default:\r\n }\r\n let value = event.target.value;\r\n const selectionStart = event.target.selectionStart;\r\n const selectionEnd = event.target.selectionEnd;\r\n // 是数字的时候再处理,分为小键盘和数字键\r\n if (/^(Digit|Numpad)\\d$/.test(event.code)) {\r\n event.preventDefault();\r\n let input;\r\n if (event.clipboardData) {\r\n input = event.clipboardData.getData('text');\r\n } else if (event.code) {\r\n input = event.code.slice(event.code.length - 1);\r\n }\r\n value = value.substring(0, selectionStart) + input + value.substring(selectionEnd);\r\n if (value.length === 3 && value.indexOf('0') === 0) {\r\n value = value.slice(1);\r\n }\r\n } else if (event.keyCode === 8) {\r\n event.preventDefault();\r\n value = value.substring(0, selectionStart - 1) + value.substring(selectionEnd);\r\n if (value.length < 2) {\r\n value = '0' + value;\r\n }\r\n } else if (!(event.keyCode >= 37 && event.keyCode <= 40)) {\r\n // 如果不是上下左右,就阻拦,执行自己的处理\r\n event.preventDefault();\r\n }\r\n if (/^(Digit|Numpad)\\d$/.test(event.code) || event.keyCode === 8) {\r\n if (Number(value) >= min && Number(value) <= max) {\r\n this[timeType] = value;\r\n this.onTimeChange();\r\n }\r\n }\r\n }\r\n\r\n onTimeChange() {\r\n const date = this.selectedDate || new Date();\r\n this.selectedDate = new Date(\r\n date.getFullYear(),\r\n date.getMonth(),\r\n date.getDate(),\r\n Number(this.currentHour),\r\n Number(this.currentMinute),\r\n Number(this.currentSecond)\r\n );\r\n const dateObj = {\r\n reason: SelectDateChangeReason.time,\r\n selectedDate: this.selectedDate,\r\n };\r\n this.onTouched();\r\n this.writeValue(this.selectedDate);\r\n this.onChange(dateObj);\r\n this.selectedDateChange.emit(dateObj);\r\n }\r\n\r\n timeUp(type) {\r\n switch (type) {\r\n case 'h': {\r\n Number(this.currentHour) < 23 ? (this.currentHour = Number(this.currentHour) + 1) : (this.currentHour = 0);\r\n break;\r\n }\r\n case 'm': {\r\n Number(this.currentMinute) < 59 ? (this.currentMinute = Number(this.currentMinute) + 1) : (this.currentMinute = 0);\r\n break;\r\n }\r\n case 's': {\r\n Number(this.currentSecond) < 59 ? (this.currentSecond = Number(this.currentSecond) + 1) : (this.currentSecond = 0);\r\n break;\r\n }\r\n default:\r\n }\r\n this.onTimeChange();\r\n }\r\n\r\n timeDown(type) {\r\n switch (type) {\r\n case 'h': {\r\n Number(this.currentHour) > 0 ? (this.currentHour = Number(this.currentHour) - 1) : (this.currentHour = 23);\r\n break;\r\n }\r\n case 'm': {\r\n Number(this.currentMinute) > 0 ? (this.currentMinute = Number(this.currentMinute) - 1) : (this.currentMinute = 59);\r\n break;\r\n }\r\n case 's': {\r\n Number(this.currentSecond) > 0 ? (this.currentSecond = Number(this.currentSecond) - 1) : (this.currentSecond = 59);\r\n break;\r\n }\r\n default:\r\n }\r\n this.onTimeChange();\r\n }\r\n\r\n clearAll = (reason?: SelectDateChangeReason) => {\r\n this.writeValue(null);\r\n this.selectedDate = null;\r\n const currentReason = typeof reason === 'number' ? reason : SelectDateChangeReason.custom;\r\n const dateObj = {\r\n reason: currentReason,\r\n selectedDate: null,\r\n };\r\n // 清空时将null作为ngModelChange参数传出\r\n this.onChange(dateObj);\r\n this.selectedDateChange.emit(dateObj);\r\n };\r\n\r\n toggle($event: Event, which) {\r\n $event.stopPropagation();\r\n if (which === 'year') {\r\n if (this.mode === 'year') {\r\n return;\r\n } else if (this.mode === 'month') {\r\n this.openChooseYear = true;\r\n this.openChooseMonth = false;\r\n return;\r\n } else {\r\n this.openChooseYear = !this.openChooseYear;\r\n this.openChooseMonth = false;\r\n }\r\n } else {\r\n if (this.mode === 'month') {\r\n return;\r\n }\r\n this.openChooseMonth = !this.openChooseMonth;\r\n this.openChooseYear = false;\r\n }\r\n }\r\n\r\n isTodayDisable() {\r\n return this.isDisabledDay(new Date());\r\n }\r\n\r\n isDisabledTime() {\r\n return this.isDisabledDay(this.selectedDate);\r\n }\r\n\r\n initDatePicker() {\r\n this.selectedDate = this.selectedDate ? this.selectedDate : new Date();\r\n if (this.isDisabledDay(this.selectedDate)) {\r\n return;\r\n }\r\n this.selectedDate = this.selectedDate ? this.selectedDate : new Date();\r\n this.onSelectDateChanged();\r\n this.onSelectDate({}, this.selectedDate, 'init');\r\n }\r\n\r\n confirmTime(event) {\r\n event.stopPropagation();\r\n const dateObj = {\r\n reason: SelectDateChangeReason.button,\r\n selectedDate: this.selectedDate,\r\n };\r\n this.writeValue(this.selectedDate);\r\n this.onChange(dateObj);\r\n this.selectedDateChange.emit(dateObj);\r\n }\r\n\r\n chooseToday() {\r\n const today = new Date();\r\n if (this.isDisabledDay(today)) {\r\n return;\r\n }\r\n this.selectedDate = today;\r\n this.onSelectDateChanged();\r\n this.onSelectDate({}, today, undefined, SelectDateChangeReason.button);\r\n }\r\n\r\n onSelectMonth(month) {\r\n if (month.disabled) {\r\n return;\r\n }\r\n this.currentMonthIndex = month.index;\r\n if (this.mode === 'month') {\r\n this.onSelectDate({}, new Date(this.currentYear, this.currentMonthIndex, 1));\r\n } else {\r\n this.onDisplayWeeksChange();\r\n this.openChooseMonth = false;\r\n }\r\n }\r\n\r\n chooseDate = (date: string, event = {}, reason = SelectDateChangeReason.custom) => {\r\n const parseDate = this.dateConverter.parse(date, this.dateFormat);\r\n this.selectedDate = parseDate || new Date();\r\n this.onSelectDateChanged();\r\n this.onSelectDate(event, parseDate, undefined, reason);\r\n };\r\n\r\n get minDateDefined() {\r\n return this.minDate.getTime() !== new Date(this.dateConfig.min, 0, 1, 0, 0, 0).getTime();\r\n }\r\n\r\n get maxDateDefined() {\r\n return this.maxDate.getTime() !== new Date(this.dateConfig.max, 11, 31, 23, 59, 59).getTime();\r\n }\r\n\r\n setI18nText() {\r\n this.i18nText = this.i18n.getI18nText().datePicker;\r\n this.i18nLocale = this.i18n.getI18nText().locale;\r\n this.i18nCommonText = this.i18n.getI18nText().common;\r\n this.i18nSubscription = this.i18n.langChange().subscribe((data) => {\r\n this.i18nText = data.datePicker;\r\n this.i18nLocale = data.locale;\r\n this.i18nCommonText = data.common;\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n if (this.i18nSubscription) {\r\n this.i18nSubscription.unsubscribe();\r\n }\r\n }\r\n}\r\n","<div class=\"devui-month-view {{ cssClass }}\">\n <table class=\"devui-table devui-month-view-table\">\n <thead class=\"devui-noSelect\">\n <tr class=\"devui-date-header\">\n <td>\n <a\n class=\"devui-btn-link\"\n aria-hidden=\"true\"\n (click)=\"onPreYearOption()\"\n [ngClass]=\"{\n 'devui-year-month-disabled': !hasPreYearOption()\n }\"\n >\n <svg\n width=\"10px\"\n height=\"10px\"\n viewBox=\"0 0 10 10\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n >\n <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g transform=\"translate(-1.000000, -1.000000)\">\n <path\n d=\"M11,1.83333333 L11,10.1666667 L7,7.38833333 L7,10.1666667 L1,6 L7,1.83333333 L7,4.61033333 L11,1.83333333 Z\"\n ></path>\n </g>\n </g>\n </svg>\n </a>\n </td>\n <td>\n <a\n *ngIf=\"!openChooseYear && !openChooseMonth\"\n class=\"devui-btn-link devui-btn-left\"\n aria-hidden=\"true\"\n (click)=\"onPreMonth()\"\n [ngClass]=\"{ 'devui-year-month-disabled': !hasPreMonth() }\"\n >\n <svg\n width=\"6px\"\n height=\"10px\"\n viewBox=\"0 0 6 10\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n >\n <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g transform=\"translate(-3.000000, -1.000000)\">\n <polygon\n transform=\"translate(6.000000, 6.000000) rotate(-90.000000) translate(-6.000000, -6.000000) \"\n points=\"6 3 10.1666667 9 1.83333333 9\"\n ></polygon>\n </g>\n </g>\n </svg>\n </a>\n </td>\n <td colspan=\"3\" class=\"devui-dropdown\">\n <span class=\"devui-date-title\" (click)=\"toggle($event, 'month')\" *ngIf=\"mode !== 'year' && i18nLocale === 'en-us'\">{{\n (i18nText?.monthsOfYear)[currentMonthIndex]\n }}</span>\n <span class=\"devui-date-title\" (click)=\"toggle($event, 'year')\"> {{ i18nText?.yearDisplay(currentYear) }} </span>\n <span class=\"devui-date-title\" (click)=\"toggle($event, 'month')\" *ngIf=\"mode !== 'year' && i18nLocale === 'zh-cn'\">{{\n (i18nText?.monthsOfYear)[currentMonthIndex]\n }}</span>\n <ul class=\"devui-monthOption text-center\" [style.display]=\"openChooseMonth ? 'block' : 'none'\">\n <li\n *ngFor=\"let month of availableMonths\"\n [ngClass]=\"{ active: currentMonthIndex == month.index, disabled: month.disabled }\"\n (click)=\"onSelectMonth(month)\"\n >\n {{ month.title }}\n </li>\n </ul>\n <ul class=\"devui-yearOption text-center\" [style.display]=\"openChooseYear ? 'block' : 'none'\">\n <li\n *ngFor=\"let item of yearOptions\"\n [ngClass]=\"{ active: currentYear == item.title, disabled: item.disabled }\"\n (click)=\"onSelectYear(item, $event)\"\n >\n {{ item.title }}\n </li>\n </ul>\n </td>\n <td>\n <a\n *ngIf=\"!openChooseYear && !openChooseMonth\"\n class=\"devui-btn-link devui-btn-right\"\n aria-hidden=\"true\"\n (click)=\"onNextMonth()\"\n [ngClass]=\"{ 'devui-year-month-disabled': !hasNextMonth() }\"\n >\n <svg\n width=\"6px\"\n height=\"9px\"\n viewBox=\"0 0 6 9\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n >\n <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g transform=\"translate(-3.000000, -2.000000)\">\n <polygon\n transform=\"translate(6.000000, 6.166667) scale(-1, 1) rotate(-90.000000) translate(-6.000000, -6.166667) \"\n points=\"6 3.16666667 10.1666667 9.16666667 1.83333333 9.16666667\"\n ></polygon>\n </g>\n </g>\n </svg>\n </a>\n </td>\n <td>\n <a\n class=\"devui-btn-link\"\n aria-hidden=\"true\"\n (click)=\"onNextYearOption()\"\n [ngClass]=\"{\n 'devui-year-month-disabled': !hasNextYearOption()\n }\"\n >\n <svg\n width=\"10px\"\n height=\"9px\"\n viewBox=\"0 0 10 9\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n >\n <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g transform=\"translate(-1.000000, -2.000000)\">\n <polygon points=\"5 4.77777778 5 2 11 6.16666667 5 10.3333333 5 7.55555556 1 10.3333333 1 2\"></polygon>\n </g>\n </g>\n </svg>\n </a>\n </td>\n </tr>\n <tr class=\"small text-center devui-week-header\">\n <td *ngFor=\"let item of i18nText?.daysOfWeek\">{{ item }}</td>\n </tr>\n </thead>\n <tbody class=\"devui-noSelect\">\n <tr *ngFor=\"let week of displayWeeks\">\n <td\n *ngFor=\"let day of week\"\n class=\"devui-day\"\n [ngClass]=\"{\n 'devui-out-of-month': !day.inMonth,\n 'devui-in-month-day': day.inMonth,\n active: isSelectDay(day.date),\n disabled: isDisabledDay(day.date),\n 'devui-today': day.isToday\n }\"\n (click)=\"onSelectDate($event, day.date)\"\n >\n <div class=\"devui-calendar-date\">{{ day.day }}</div>\n </td>\n </tr>\n </tbody>\n <tfoot [ngClass]=\"{ 'devui-noSelect': !customViewTemplate }\">\n <tr class=\"time-picker-view\" (click)=\"!customViewTemplate && $event.stopPropagation()\" *ngIf=\"showTime || !customViewTemplate\">\n <td colspan=\"4\">\n <div class=\"devui-timepicker\" *ngIf=\"showTime\" [ngClass]=\"{ 'devui-timepicker-disabled': isDisabledTime() }\">\n <div class=\"devui-time\">\n <input [ngModel]=\"currentHour\" (keydown)=\"fixTime($event, 'h')\" [disabled]=\"isDisabledTime()\" />\n <div class=\"devui-btn-nav\" *ngIf=\"!isDisabledTime()\">\n <div class=\"btn-up\" (click)=\"timeUp('h')\"></div>\n <div class=\"btn-down\" (click)=\"timeDown('h')\"></div>\n </div>\n </div>\n <div class=\"devui-time\">\n <input class=\"devui-minutes\" [ngModel]=\"currentMinute\" (keydown)=\"fixTime($event, 'm')\" [disabled]=\"isDisabledTime()\" />\n <div class=\"devui-btn-nav\" *ngIf=\"!isDisabledTime()\">\n <div class=\"btn-up\" (click)=\"timeUp('m')\"></div>\n <div class=\"btn-down\" (click)=\"timeDown('m')\"></div>\n </div>\n </div>\n <div class=\"devui-time\">\n <input class=\"devui-seconds\" [ngModel]=\"currentSecond\" (keydown)=\"fixTime($event, 's')\" [disabled]=\"isDisabledTime()\" />\n <div class=\"devui-btn-nav\" *ngIf=\"!isDisabledTime()\">\n <div class=\"btn-up\" (click)=\"timeUp('s')\"></div>\n <div class=\"btn-down\" (click)=\"timeDown('s')\"></div>\n </div>\n </div>\n </div>\n </td>\n <td colspan=\"3\">\n <div class=\"devui-btn-wrapper\" *ngIf=\"showTime\">\n <d-button bsStyle=\"common\" [disabled]=\"disabled\" (btnClick)=\"confirmTime($event)\" bsSize=\"sm\"\n >{{ i18nCommonText?.btnConfirm }}\n </d-button>\n </div>\n <div class=\"devui-btn-wrapper\" *ngIf=\"!showTime\">\n <d-button bsStyle=\"common\" [disabled]=\"isTodayDisable() || disabled\" (btnClick)=\"chooseToday()\" bsSize=\"sm\"\n >{{ i18nText?.today }}\n </d-button>\n </div>\n </td>\n </tr>\n <tr class=\"time-picker-view devui-custom-area\" *ngIf=\"customViewTemplate\">\n <td colspan=\"7\">\n <ng-template\n [ngTemplateOutlet]=\"customViewTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: this, chooseDate: chooseDate, clearAll: clearAll }\"\n ></ng-template>\n </td>\n </tr>\n </tfoot>\n </table>\n</div>\n","import {\r\n ChangeDetectorRef,\r\n Component,\r\n ElementRef,\r\n EventEmitter,\r\n forwardRef,\r\n Input,\r\n OnChanges,\r\n OnInit,\r\n Output,\r\n Renderer2,\r\n SimpleChanges,\r\n} from '@angular/core';\r\nimport { NG_VALUE_ACCESSOR } from '@angular/forms';\r\nimport { I18nService } from 'ng-devui/i18n';\r\nimport { DatePickerConfigService as DatePickerConfig } from './date-picker.config.service';\r\nimport { SelectDateRangeChangeEventArgs, SelectDateRangeChangeReason } from './date-range-change-event-args.model';\r\nimport { DatepickerComponent as SingleDatepickerComponent } from './datepicker.component';\r\n\r\nexport interface SimpleDate {\r\n year: number;\r\n month: number;\r\n}\r\n\r\n@Component({\r\n selector: 'd-datepicker-range-single',\r\n templateUrl: './single-date-range-picker.component.html',\r\n styleUrls: ['./single-date-range-picker.component.scss'],\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => SingleDateRangePickerComponent),\r\n multi: true,\r\n },\r\n ],\r\n preserveWhitespaces: false,\r\n})\r\nexport class SingleDateRangePickerComponent extends SingleDatepickerComponent implements OnChanges, OnInit {\r\n @Input() selectedRange: Date[] = Array(2);\r\n @Input() rangePicker = false;\r\n @Input() isAuxiliary = false;\r\n @Input() currentCalendars = Array(2);\r\n @Output() hoverOnDate = new EventEmitter<any>();\r\n @Output() rangeSelected = new EventEmitter<SelectDateRangeChangeEventArgs>();\r\n @Output() rangeSelecting = new EventEmitter<SelectDateRangeChangeEventArgs>();\r\n @Output() syncPickerPair = new EventEmitter<{}>();\r\n @Output() consolidateTime = new EventEmitter<any>();\r\n public rangeStart;\r\n public rangeEnd;\r\n public previewEnd;\r\n private timer;\r\n protected selectingRange: boolean;\r\n\r\n constructor(\r\n protected elementRef: ElementRef,\r\n protected renderer: Renderer2,\r\n protected datePickerConfig: DatePickerConfig,\r\n protected changeDetectorRef: ChangeDetectorRef,\r\n protected i18n: I18nService\r\n ) {\r\n super(elementRef, renderer, datePickerConfig, changeDetectorRef, i18n);\r\n this.setI18nText();\r\n }\r\n\r\n ngOnInit() {\r\n [this.rangeStart, this.rangeEnd] = this.selectedRange;\r\n const nowDate = this.selectedDate || new Date();\r\n this.nowMinYear =\r\n nowDate.getFullYear() - Math.floor(this._yearNumber / 2) < this.minDate.getFullYear()\r\n ? this.minDate.getFullYear()\r\n : nowDate.getFullYear() - Math.floor(this._yearNumber / 2);\r\n this.nowMaxYear =\r\n nowDate.getFullYear() + Math.floor(this._yearNumber / 2) > this.maxDate.getFullYear()\r\n ? this.maxDate.getFullYear()\r\n : nowDate.getFullYear() + Math.floor(this._yearNumber / 2);\r\n if (!this.isAuxiliary && !this.rangeStart) {\r\n // 主面板,未选择开始日期的情况\r\n this.onSelectDateChanged();\r\n this.onDisplayWeeksChange();\r\n this.onYearRangeChange();\r\n this.initDatePicker();\r\n } else if (this.isAuxiliary && !this.rangeEnd) {\r\n // 副面板,未选择结束日期的情况\r\n this.onSelectDateChanged();\r\n this.initDatePicker();\r\n this.onYearRangeChange();\r\n this.onNextMonth('init');\r\n this.selectedDate = new Date(this.currentYear, this.currentMonthIndex);\r\n } else if (!this.isAuxiliary && this.rangeStart) {\r\n // 主面板,已选择开始日期的情况\r\n this.selectedDate = this.rangeStart;\r\n super.ngOnInit();\r\n } else if (this.isAuxiliary && this.rangeEnd) {\r\n // 副面板,已选择结束日期的情况\r\n const rangeStart = this.convertDate(this.rangeStart);\r\n const rangeEnd = this.convertDate(this.rangeEnd);\r\n this.currentYear = rangeEnd.getFullYear();\r\n this.currentMonthIndex = rangeEnd.getMonth();\r\n this.selectedDate = new Date(this.currentYear, this.currentMonthIndex);\r\n super.ngOnInit();\r\n // 处理选择的日期范围开始和结束在同一个月的情况\r\n if (rangeStart && rangeEnd && rangeStart.getFullYear() === rangeEnd.getFullYear() && rangeStart.getMonth() === rangeEnd.getMonth()) {\r\n this.onNextMonth('init');\r\n }\r\n this.selectedDate = new Date(this.currentYear, this.currentMonthIndex);\r\n }\r\n this.availableMonths = this.onDisplayMonthsChange();\r\n this.notifyCalenderChange();\r\n }\r\n\r\n /*\r\n ** @param invocation:调用时机\r\n */\r\n onSelectDate($event, date, invocation?: any) {\r\n if ($event.stopPropagation) {\r\n $event.stopPropagation();\r\n }\r\n\r\n if (invocation !== 'init') {\r\n if (this.isDisabledDay(date)) {\r\n $event.preventDefault();\r\n return;\r\n }\r\n const curDate = this.showTime && date ? this.setTime(date) : date;\r\n this.selectRange(curDate);\r\n this.selectedDate = this.isAuxiliary ? this.rangeEnd : this.rangeStart;\r\n }\r\n }\r\n\r\n emitHoverDate($event, date) {\r\n if (this.selectingRange && date.getTime() <= this.maxDate.getTime() && date.getTime() >= this.minDate.getTime()) {\r\n this.hoverOnDate.emit(date);\r\n }\r\n }\r\n\r\n selectStart(date) {\r\n this.rangeStart = new Date(this.convertDate(date).setHours(0, 0, 0));\r\n }\r\n\r\n selectEnd(date) {\r\n this.selectingRange = false;\r\n this.rangeEnd = new Date(this.convertDate(date).setHours(23, 59, 59));\r\n if (!!this.rangeStart && !!this.rangeEnd) {\r\n this.rangeChange(this.ensureRangeValueOrder([this.rangeStart, this.rangeEnd], true), SelectDateRangeChangeReason.date);\r\n }\r\n }\r\n\r\n convertDate(date) {\r\n return date ? this.dateConverter.parse(date) : null;\r\n }\r\n\r\n selectRange(date, passive = false) {\r\n if (this.disabled) {\r\n return;\r\n }\r\n if (!this.rangeStart || (!!this.rangeStart && !!this.rangeEnd)) {\r\n this.rangeEnd = null;\r\n this.rangeStart = null;\r\n this.selectStart(date);\r\n this.selectingRange = true;\r\n if (!passive) {\r\n this.rangeSelecting.emit(this.rangeStart);\r\n }\r\n } else {\r\n this.selectEnd(date);\r\n }\r\n }\r\n\r\n rangeChange(range, reason?) {\r\n this.selectedRange = range;\r\n this.notifyValueChange(range, reason);\r\n }\r\n\r\n writeValue(selectedRange: any): void {\r\n this.selectedRange = selectedRange;\r\n }\r\n\r\n protected notifyValueChange(selectedRange: Date[], reason?) {\r\n const currentReason = typeof reason === 'number' ? reason : SelectDateRangeChangeReason.time;\r\n this.onChange(selectedRange);\r\n this.rangeSelected.emit({\r\n reason: currentReason,\r\n selectedRange: selectedRange,\r\n });\r\n }\r\n\r\n isSelectDay(date) {\r\n let rangeSource = this.selectedRange;\r\n if (this.selectingRange) {\r\n rangeSource = [this.rangeStart, this.previewEnd];\r\n }\r\n if (!Array.isArray(rangeSource)) {\r\n return;\r\n }\r\n return rangeSource.some((selectedDate) => {\r\n if (!selectedDate || !date) {\r\n return false;\r\n }\r\n return (\r\n date.getFullYear() === selectedDate.getFullYear() &&\r\n date.getMonth() === selectedDate.getMonth() &&\r\n date.getDate() === selectedDate.getDate()\r\n );\r\n });\r\n }\r\n\r\n isBetweenDay(date) {\r\n if (Array.isArray(this.selectedRange) && this.selectedRange.every((day) => !!day)) {\r\n const index = this.selectedRange.findIndex((day) => {\r\n return date.getFullYear() === day.getFullYear() && date.getMonth() === day.getMonth() && date.getDate() === day.getDate();\r\n });\r\n return ['devui-day-start', 'devui-day-end'][index];\r\n } else {\r\n return;\r\n }\r\n }\r\n\r\n isDisabledTime() {\r\n const selectedSide = this.isAuxiliary ? this.rangeEnd : this.rangeStart;\r\n return selectedSide ? super.isDisabledDay(selectedSide) : true;\r\n }\r\n\r\n timeUp(type) {\r\n switch (type) {\r\n case 'h': {\r\n Number(this.currentHour) < 23 ? (this.currentHour = Number(this.currentHour) + 1) : (this.currentHour = 0);\r\n break;\r\n }\r\n case 'm': {\r\n Number(this.currentMinute) < 59 ? (this.currentMinute = Number(this.currentMinute) + 1) : (this.currentMinute = 0);\r\n break;\r\n }\r\n case 's': {\r\n Number(this.currentSecond) < 59 ? (this.currentSecond = Number(this.currentSecond) + 1) : (this.currentSecond = 0);\r\n break;\r\n }\r\n default:\r\n }\r\n this.timeChange();\r\n }\r\n\r\n timeDown(type) {\r\n switch (type) {\r\n case 'h': {\r\n Number(this.currentHour) > 0 ? (this.currentHour = Number(this.currentHour) - 1) : (this.currentHour = 23);\r\n break;\r\n }\r\n case 'm': {\r\n Number(this.currentMinute) > 0 ? (this.currentMinute = Number(this.currentMinute) - 1) : (this.currentMinute = 59);\r\n break;\r\n }\r\n case 's': {\r\n Number(this.currentSecond) > 0 ? (this.currentSecond = Number(this.currentSecond) - 1) : (this.currentSecond = 59);\r\n break;\r\n }\r\n default:\r\n }\r\n this.timeChange();\r\n }\r\n\r\n fixTime(event, type) {\r\n // 由于keypress不监听微软输入法需要使用keydown\r\n // 而keydown中微软输入法的key是'Process',且keydown没有charCode,所以需要用code判断\r\n // 故退格和输入使用同一个事件\r\n let timeType: string;\r\n const min = 0;\r\n let max = 59;\r\n switch (type) {\r\n case 'h': {\r\n timeType = 'currentHour';\r\n max = 23;\r\n break;\r\n }\r\n case 'm': {\r\n timeType = 'currentMinute';\r\n break;\r\n }\r\n case 's': {\r\n timeType = 'currentSecond';\r\n break;\r\n }\r\n default:\r\n }\r\n let value = event.target.value;\r\n const selectionStart = event.target.selectionStart;\r\n const selectionEnd = event.target.selectionEnd;\r\n // 是数字的时候再处理,分为小键盘和数字键\r\n if (/^(Digit|Numpad)\\d$/.test(event.code)) {\r\n event.preventDefault();\r\n let input;\r\n if (event.clipboardData) {\r\n input = event.clipboardData.getData('text');\r\n } else if (event.code) {\r\n input = event.code.slice(event.code.length - 1);\r\n }\r\n value = value.substring(0, selectionStart) + input + value.substring(selectionEnd);\r\n if (value.length === 3 && value.indexOf('0') === 0) {\r\n value = value.slice(1);\r\n }\r\n } else if (event.keyCode === 8) {\r\n event.preventDefault();\r\n value = value.substring(0, selectionStart - 1) + value.substring(selectionEnd);\r\n if (value.length < 2) {\r\n value = '0' + value;\r\n }\r\n } else if (!(event.keyCode >= 37 && event.keyCode <= 40)) {\r\n // 如果不是上下左右,就阻拦,执行自己的处理\r\n event.preventDefault();\r\n }\r\n if (/^(Digit|Numpad)\\d$/.test(event.code) || event.keyCode === 8) {\r\n if (Number(value) >= min && Number(value) <= max) {\r\n this[timeType] = value;\r\n // 防抖,防止提前校验导致错误的校验\r\n clearTimeout(this.timer);\r\n this.timer = setTimeout(() => {\r\n this.timeChange();\r\n }, 300);\r\n }\r\n }\r\n }\r\n\r\n timeChange() {\r\n if (!this.isAuxiliary) {\r\n this.rangeStart = new Date(\r\n this.rangeStart.getFullYear(),\r\n this.rangeStart.getMonth(),\r\n this.rangeStart.getDate(),\r\n Number(this.currentHour),\r\n Number(this.currentMinute),\r\n Number(this.currentSecond)\r\n );\r\n } else {\r\n this.rangeEnd = new Date(\r\n this.rangeEnd.getFullYear(),\r\n this.rangeEnd.getMonth(),\r\n this.rangeEnd.getDate(),\r\n Number(this.currentHour),\r\n Number(this.currentMinute),\r\n Number(this.currentSecond)\r\n );\r\n }\r\n this.rangeChange(this.ensureRangeValueOrder([this.rangeStart, this.rangeEnd]));\r\n }\r\n\r\n isSameDate(date1: Date, date2: Date): boolean {\r\n return date1?.getFullYear() === date2?.getFullYear() && date1.getMonth() === date2.getMonth() && date1.getDate() === date2.getDate();\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges) {\r\n if (Object.prototype.hasOwnProperty.call(changes, 'selectedRange')) {\r\n this.selectingRange = false;\r\n [this.rangeStart, this.rangeEnd] = changes.selectedRange.currentValue;\r\n }\r\n }\r\n\r\n isInRange(dateParam) {\r\n let date = dateParam;\r\n const rangeStart = this