/// import * as React from 'react'; import view from '../picker/view'; import { createYearArray, createMinutesAndSecondsArray, createHoursArray, createMonthArray, getDaysInMonth, getDefaultValue, valueFormat, getTodayDate } from '../util/date'; // import { setTranslate } from '../util/transform'; import PickerCore from '../picker/core'; const prefix = 'tsp-component-Picker'; function formatLabel(selected: TspComponentPickerValues[]): string { let label = ''; for (let i = 0; i < selected.length; i++) { const value = selected[i].value; if (i < 2) { label += value + '-'; } else if (i === 3) { label += ' ' + value; } else if (i === 4) { label += ':' + value; } else { label += value; } } return label; } class DatePicker extends React.Component { constructor(props: TspComponentDatePickerProps, state: any) { super(props, state); this.onPanStart = this.onPanStart.bind(this); this.onPan = this.onPan.bind(this); this.onPanEnd = this.onPanEnd.bind(this); this.onOk = this.onOk.bind(this); this.onCancel = this.onCancel.bind(this); this.onOpen = this.onOpen.bind(this); this.onTransitionEnd = this.onTransitionEnd.bind(this); } public static defaultProps: TspComponentDatePickerProps = { id: '', cascade: false, defaultValue: getDefaultValue(), startDate: getTodayDate(), endDate: getTodayDate(), enableStartDate: false, enableEndDate: false, mode: 'yyMMddHHmm', //defaultLabel: formatLabel(getDefaultValue()), formatLabel }; /** * PickerCore实例 */ private core: PickerCore; /** * 触发transitionEnd的timeout返回对象 */ private transitionEndTimeout: number; public shouldComponentUpdate(nextProps: TspComponentDatePickerProps): boolean { return this.props.updateId !== nextProps.updateId; } public componentDidMount(): void { const value = this.props.defaultValue.slice(0, 5).map((item) => item.value).join(''); const startDate = this.props.startDate.join(''); const endDate = this.props.endDate.join(''); if (value < startDate && this.props.enableStartDate) { console.error('value设定值不能小于startDate的设定值'); return; } if (value > endDate && this.props.enableEndDate) { console.error('value设定值不能超过endDate的设定值'); return; } this.core = new PickerCore({ id: this.props.id, cascade: false, defaultValue: this.props.defaultValue, onOk: this.props.onOk, defaultLabel: this.props.defaultLabel, data: [], sliderElem: this.refs.slider as HTMLElement, containerElem: this.refs.container['elem'] as HTMLElement, labelElem: this.refs.label as HTMLElement, formatLabel: this.props.formatLabel }); this.core.data = this.setMode(); this.core.init(); // this.onTransitionEnd(); this.core.sliderElem.addEventListener('webkitTransitionEnd', this.onTransitionEnd); } public componentWillReceiveProps(nextProps: TspComponentDatePickerProps): void { // this.core.componentWillReceiveProps(this.props, nextProps); } public componentDidUpdate(prevProps: TspComponentDatePickerProps): void { this.core.data = this.setMode(); this.core.componentWillReceiveProps(prevProps, this.props); } /** * 开始拖动 */ public onPanStart(evt: TspComponentSliderEvt): void { evt.preventDefault(); this.core.panStart(evt); } /** * 拖动中 */ public onPan(evt: TspComponentSliderEvt): void { evt.preventDefault(); this.core.pan(evt); } /** * 拖动结束后 */ public onPanEnd(evt: TspComponentSliderEvt): void { evt.preventDefault(); this.core.panEnd(evt); if (this.core.isPanEnd && this.core.touchElementCol !== undefined) { this.transitionEndTimeout = setTimeout(() => { if (!this.core.isTransitionEnd) { this.onTransitionEnd(); } }, 300); } } /** * 监听translate完成事件 */ public onTransitionEnd(): void { this.core.transitionEnd(this.transitionEndTimeout); this.reset(); } /** * 重置 */ public reset(): void { switch (this.props.mode) { case 'yyMMdd': case 'yyMMddHH': case 'yyMMddHHmm': if (this.props.enableStartDate || this.props.enableEndDate) { if (this.core.touchElementCol === 0 || this.core.touchElementCol === 1) { const year = parseInt(this.core.data[0][this.core.getValueIndex(0, this.core.selected)].value.toString()); const month = parseInt(this.core.data[1][this.core.getValueIndex(1, this.core.selected)].value.toString()) - 1; const day = parseInt(this.core.data[2][this.core.getValueIndex(2, this.core.selected)].value.toString()); if (this.core.touchElementCol === 0) { this.replaceMonth(year); } else if (this.core.touchElementCol === 1) { this.replaceDays(year, month, day); } } } else { this.renderDays(); } break; default: break; } } /** * 确定 */ public onOk(): void { this.core.ok(); } /** * 取消 */ public onCancel(): void { this.core.cancel(); } /** * 打开 */ public onOpen(): void { if (!this.props.disabled) { this.reset(); this.core['value'] = this.core.selected; this.core.open(); } } /** 设置日期模式 */ // tslint:disable-next-line:max-line-length // tslint:disable-next-line:array-type public setMode(yearIndex: number = this.props.defaultValue[0].index, monthIndex: number = this.props.defaultValue[1].index): { value: string | number, label: number | string }[][] { const mode = this.props.mode; const startYear = parseInt(this.props.startDate[0].toString()); const endYear = parseInt(this.props.endDate[0].toString()); const startMonth = parseInt(this.props.startDate[1].toString()); const endMonth = parseInt(this.props.endDate[1].toString()); const startDay = parseInt(this.props.startDate[2].toString()); const endDay = parseInt(this.props.endDate[2].toString()); let year = yearIndex !== undefined ? startYear + yearIndex : this.props.defaultValue[0].value; let month = monthIndex !== undefined ? monthIndex : parseInt(this.props.defaultValue[1].value.toString()) - 1; let [yy, MM, dd, HH, mm] = [undefined, undefined, undefined, undefined, undefined]; if (mode.indexOf('yy') >= 0) { const startDate = parseInt(this.props.startDate[0]); const endDate = parseInt(this.props.endDate[0]); yy = createYearArray(startDate, endDate, 'array').map((value) => valueFormat(value, 'object', '年')); } year = parseInt(year.toString()); month = parseInt(month.toString()); if (mode.indexOf('MM') >= 0) { MM = createMonthArray('array').map((value) => valueFormat(value + 1, 'object', '月')); if (this.props.enableStartDate && year === startYear) { if (this.props.startDate.length >= 2) { MM = MM.slice(startMonth - 1); } else { console.error('startDate设置错误,startDate数组长度不足2维'); } } if (this.props.enableEndDate && year === endYear) { if (this.props.endDate.length >= 2) { MM = MM.slice(0, endMonth - startMonth + 1); } else { console.error('endDate设置错误,endDate数组长度不足2维'); } } } if (mode.indexOf('dd') >= 0) { dd = getDaysInMonth(year, month, 'array').map((value) => valueFormat(value, 'object', '日')); if (this.props.enableStartDate && year === startYear && month === startMonth - 1) { if (this.props.startDate.length >= 3) { dd = dd.slice(startDay - 1); } else { console.error('startDate设置错误,startDate数组长度不等于3维'); } } if (this.props.enableEndDate && year === endYear && month === endMonth - 1) { if (this.props.endDate.length >= 3) { dd = dd.slice(0, endDay); } else { console.error('endDate设置错误,endDate数组长度不足3维'); } } } if (mode.indexOf('HH') >= 0) { HH = createHoursArray('array').map((value) => valueFormat(value, 'object', '时')); } if (mode.indexOf('mm') >= 0) { mm = createMinutesAndSecondsArray('array').map((value) => valueFormat(value, 'object', '分')); } switch (mode) { case 'yy': return [yy]; case 'yyMM': return [yy, MM]; case 'yyMMdd': return [yy, MM, dd]; case 'yyMMddHH': return [yy, MM, dd, HH]; case 'yyMMddHHmm': return [yy, MM, dd, HH, mm]; case 'HHmm': return [HH, mm]; default: break; } } /** * 渲染天数 */ public renderDays(): void { const data = this.core.data; const year = parseInt(data[0][this.core.getValueIndex(0, this.core.selected)].value.toString()); const month = parseInt(data[1][this.core.getValueIndex(1, this.core.selected)].value.toString()) - 1; const days = getDaysInMonth(year, month, 'array').map((value) => valueFormat(value, 'object', '日')); const oldLength = data[2].length; const newLength = days.length; const parent = this.core.sliderElem.children[2]; const fragment = document.createDocumentFragment(); const length = oldLength > newLength ? oldLength : newLength; const flag = oldLength > newLength ? 1 : 2; if (oldLength === newLength) { return; } parent.innerHTML = null; for (let i = 0; i < length; i++) { const tempElem = document.createElement('div'); tempElem.classList.add(`${prefix}-body-col-item`); tempElem.innerText = valueFormat(i + 1, 'string', '日'); fragment.appendChild(tempElem); } parent.appendChild(fragment); this.core.data[2] = days; const selected = this.core.getValueIndex(2, this.core.selected); this.core.pickerTranslateInitial(2, this.core.data[2][selected] ? selected : 0); } public replaceMonth(year: number): void { const { startDate, endDate, enableStartDate, enableEndDate } = this.props; const startYear = parseInt(startDate[0].toString()); const endYear = parseInt(endDate[0].toString()); const enableStartYear = year === startYear && enableStartDate; const enableEndYear = year === endYear && enableEndDate; const startMonth = parseInt(startDate[1].toString()); const endMonth = parseInt(endDate[1].toString()); const selectedMonth = parseInt(this.core.selected[1].value.toString()); let [month, day] = [undefined, undefined]; if (enableStartYear || enableEndYear) { if (enableStartYear) { month = selectedMonth < startMonth ? startMonth : selectedMonth; } else { month = selectedMonth > endMonth ? endMonth : selectedMonth; } this.core.data = this.setMode(this.core.selected[0].index, month - 1); this.core.renderCol(this.core.data[1], 1, 'replace'); if (!enableStartYear) { this.core.selected[1].index = undefined; this.core.selected[1].value = valueFormat(month, 'string', '月'); } this.core.pickerTranslateInitial(1, this.core.getValueIndex(1, this.core.selected)); const dayValueIndex = this.core.getValueIndex(2, this.core.selected); const dayIndex = this.core.data[2].length > dayValueIndex ? dayValueIndex : 0; day = parseInt(this.core.data[2][dayIndex].value.toString()); this.replaceDays(year, month - 1, day); } else { this.renderDays(); this.core.data = this.setMode(this.core.selected[0].index, selectedMonth - 1); this.core.renderCol(this.core.data[1], 1, 'replace'); this.core.pickerTranslateInitial(1, this.core.getValueIndex(1, this.core.selected)); } } public replaceDays(year: number, month: number, day: number): void { const { startDate, endDate, enableStartDate, enableEndDate } = this.props; const startYear = parseInt(startDate[0].toString()); const endYear = parseInt(endDate[0].toString()); const startMonth = parseInt(startDate[1].toString()) - 1; const endMonth = parseInt(endDate[1].toString()) - 1; const startMatch = year === startYear && month === startMonth && enableStartDate; const endMatch = year === endYear && month === endMonth && enableEndDate; if (startMatch || endMatch) { this.core.data = this.setMode(this.core.selected[0].index, month); this.core.renderCol(this.core.data[2], 2, 'replace'); this.core.selected[2].index = undefined; this.core.selected[2].value = valueFormat(day, 'string', '月'); this.core.pickerTranslateInitial(2, this.core.getValueIndex(2, this.core.selected)); } else { this.renderDays(); } } public render(): JSX.Element { return view(this); } } export default DatePicker;