import { getCurrentInstance, nextTick, ref, watch } from 'vue' import dayjs from '../../../../libs/dayjs' import { CHANGE_EVENT, UPDATE_MODEL_EVENT } from '../../../../constants' import { innerDefaultDateTimeFormat } from '../types' import { useDateTimeData } from './use-date-time-data' import { useHandleMinMaxTime } from './use-handle-min-max-time' import type { Dayjs } from '../../../../libs/dayjs' import type { DateTimePickerProps } from '../date-time-picker' import type { TnPickerInstance } from '../../../picker' export const MIN_MAX_VALUE = ( minValue: number, maxValue: number, currentValue: number ) => Math.min(Math.max(minValue, currentValue), maxValue) export const useDateTimePicker = (props: DateTimePickerProps) => { const { emit } = getCurrentInstance()! const { pickerData, minTimeDayjs, maxTimeDayjs, generatePickerData, fillDateTime, } = useDateTimeData(props) const { handlePickerChangeMinMaxTime } = useHandleMinMaxTime( minTimeDayjs, maxTimeDayjs ) const pickerRef = ref() // 显示/隐藏日期时间选择器 const showPicker = ref(false) watch( () => props.open, (val) => { showPicker.value = val } ) const _closePicker = () => { emit('update:open', false) } // picker弹框关闭事件 const handlePickerCloseEvent = () => { _closePicker() initDateTimePicker(false) emit('close') } // 如果最小值/最大值发生改变,则重新初始化日期时间选择器 watch( () => [props.minTime, props.maxTime, props.modelValue], () => { initDateTimePicker(false) } ) // picker选中的数据 const pickerSelectData = ref>([]) // 获取picker选中的值 const getDateTimeValue = (dateTime: Dayjs) => { const year = dateTime.year() const month = String(dateTime.month() + 1).padStart(2, '0') const date = String(dateTime.date()).padStart(2, '0') const hour = String(dateTime.hour()).padStart(2, '0') const minute = String(dateTime.minute()).padStart(2, '0') const second = String(dateTime.second()).padStart(2, '0') if (props.mode === 'year') return `${year}` if (props.mode === 'yearmonth') return dayjs(`${year}/${month}`).format(props.format || 'YYYY/MM') if (props.mode === 'date') return dayjs(`${year}/${month}/${date}`).format( props.format || 'YYYY/MM/DD' ) if (props.mode === 'datetimeNoSecond') return dayjs(`${year}/${month}/${date} ${hour}:${minute}`).format( props.format || 'YYYY/MM/DD HH:mm' ) if (props.mode === 'time') return `${hour}:${minute}:${second}` if (props.mode === 'timeNoSecond') return `${hour}:${minute}` return dayjs(`${year}/${month}/${date} ${hour}:${minute}:${second}`).format( props.format || innerDefaultDateTimeFormat ) } // 设置默认picker选中的值 const setDefaultPickerSelectValue = (dateTime: Dayjs) => { const year = dateTime.year() const month = dateTime.month() + 1 const date = dateTime.date() const hour = dateTime.hour() const minute = dateTime.minute() const second = dateTime.second() if (props.mode === 'year') pickerSelectData.value = [year] if (props.mode === 'yearmonth') pickerSelectData.value = [year, month] if (props.mode === 'date') pickerSelectData.value = [year, month, date] if (props.mode === 'time') pickerSelectData.value = [hour, minute, second] if (props.mode === 'datetime') pickerSelectData.value = [year, month, date, hour, minute, second] if (props.mode === 'timeNoSecond') pickerSelectData.value = [hour, minute] if (props.mode === 'datetimeNoSecond') pickerSelectData.value = [year, month, date, hour, minute] } // 初始化日期时间选择器 const initDateTimePicker = (updateModelValue = true) => { let defaultTime = dayjs() // 如果有传递默认值,则使用默认值,没有则使用当前时间 if (props.modelValue) { defaultTime = fillDateTime(props.modelValue, props.format) } // 设置defaultTime最小和最大时间 if (props.mode !== 'time' && props.mode !== 'timeNoSecond') { defaultTime = defaultTime.year( MIN_MAX_VALUE( minTimeDayjs.value.year(), maxTimeDayjs.value.year(), defaultTime.year() ) ) if (defaultTime.year() === minTimeDayjs.value.year()) { if (defaultTime.month() < minTimeDayjs.value.month()) { defaultTime = defaultTime .month(minTimeDayjs.value.month()) .date(minTimeDayjs.value.date()) .hour(minTimeDayjs.value.hour()) .minute(minTimeDayjs.value.minute()) .second(minTimeDayjs.value.second()) } else if (defaultTime.month() === minTimeDayjs.value.month()) { if (defaultTime.date() < minTimeDayjs.value.date()) { defaultTime = defaultTime .date(minTimeDayjs.value.date()) .hour(minTimeDayjs.value.hour()) .minute(minTimeDayjs.value.minute()) .second(minTimeDayjs.value.second()) } else if (defaultTime.date() === minTimeDayjs.value.date()) { defaultTime = defaultTime .hour(minTimeDayjs.value.hour()) .minute(minTimeDayjs.value.minute()) .second(minTimeDayjs.value.second()) if (defaultTime.hour() === minTimeDayjs.value.hour()) { defaultTime = defaultTime.minute( Math.max(minTimeDayjs.value.minute(), defaultTime.minute()) ) if (defaultTime.minute() === minTimeDayjs.value.minute()) { defaultTime = defaultTime.second( Math.max(minTimeDayjs.value.second(), defaultTime.second()) ) } } } } } if (defaultTime.year() === maxTimeDayjs.value.year()) { if (defaultTime.month() > maxTimeDayjs.value.month()) { defaultTime = defaultTime .month(maxTimeDayjs.value.month()) .date(1) .hour(0) .minute(0) .second(0) } else if (defaultTime.month() === maxTimeDayjs.value.month()) { if (defaultTime.date() > maxTimeDayjs.value.date()) { defaultTime = defaultTime .date(maxTimeDayjs.value.date()) .hour(maxTimeDayjs.value.hour()) .minute(maxTimeDayjs.value.minute()) .second(maxTimeDayjs.value.second()) } else if (defaultTime.date() === maxTimeDayjs.value.date()) { defaultTime = defaultTime .hour(maxTimeDayjs.value.hour()) .minute(maxTimeDayjs.value.minute()) .second(maxTimeDayjs.value.second()) if (defaultTime.hour() === maxTimeDayjs.value.hour()) { defaultTime = defaultTime.minute( Math.min(maxTimeDayjs.value.minute(), defaultTime.minute()) ) if (defaultTime.minute() === maxTimeDayjs.value.minute()) { defaultTime = defaultTime.second(0) } } } } } if (props.mode === 'datetimeNoSecond') { defaultTime = defaultTime.second(0) } } else { defaultTime = defaultTime.hour( MIN_MAX_VALUE( minTimeDayjs.value.hour(), maxTimeDayjs.value.hour(), defaultTime.hour() ) ) if (defaultTime.hour() === minTimeDayjs.value.hour()) { defaultTime = defaultTime.minute( Math.max(minTimeDayjs.value.minute(), defaultTime.minute()) ) if (defaultTime.minute() === minTimeDayjs.value.minute()) { defaultTime = defaultTime.second( Math.max(minTimeDayjs.value.second(), defaultTime.second()) ) } } if (defaultTime.hour() === maxTimeDayjs.value.hour()) { defaultTime = defaultTime.minute( Math.min(maxTimeDayjs.value.minute(), defaultTime.minute()) ) if (defaultTime.minute() === maxTimeDayjs.value.minute()) { defaultTime = defaultTime.second(0) } } if (props.mode === 'timeNoSecond') { defaultTime = defaultTime.second(0) } } generatePickerData(defaultTime) // 设置默认picker选中的值 setDefaultPickerSelectValue(defaultTime) // 更新用户modelValue if (updateModelValue) { emit(UPDATE_MODEL_EVENT, getDateTimeValue(defaultTime)) } } // 获取修改填充后的日期时间Dayjs对象 const getFillDateTimeDayjs = (value: (string | number)[]): Dayjs => { let dateTimeValue = '' if (props.mode === 'year') { dateTimeValue = `${value[0]}` } if (props.mode === 'yearmonth') { dateTimeValue = `${value[0]}/${value[1]}` } if (props.mode === 'date') { const year = Number(value[0]) const month = Number(value[1]) const date = Math.min( dayjs() .year(year) .month(month - 1) .daysInMonth(), Number(value[2]) ) dateTimeValue = `${value[0]}/${month}/${date}` } if (props.mode === 'time' || props.mode === 'timeNoSecond') { dateTimeValue = `${value[0]}:${value[1]}:${ props.mode === 'time' ? value[2] : '00' }` } if (props.mode === 'datetime' || props.mode === 'datetimeNoSecond') { const year = Number(value[0]) const month = Number(value[1]) const date = Math.min( dayjs() .year(year) .month(month - 1) .daysInMonth(), Number(value[2]) ) dateTimeValue = `${value[0]}/${month}/${date} ${value[3]}:${value[4]}:${ props.mode === 'datetime' ? value[5] : '00' }` } return fillDateTime(dateTimeValue) } // picker选择发生改变回调 const pickerValueChangeEvent = ( value: string | number | (string | number)[] ) => { let timeValue = getFillDateTimeDayjs(value as (string | number)[]) // 处理最小/最大值 timeValue = handlePickerChangeMinMaxTime(props.mode, timeValue) // 回填处理后的数据 if (props.mode === 'year') { pickerSelectData.value = [timeValue.year()] } if (props.mode === 'yearmonth') { pickerSelectData.value = [timeValue.year(), timeValue.month() + 1] } if (props.mode === 'date') { pickerSelectData.value = [ timeValue.year(), timeValue.month() + 1, timeValue.date(), ] } if (props.mode === 'time') { pickerSelectData.value = [ timeValue.hour(), timeValue.minute(), timeValue.second(), ] } if (props.mode === 'datetime') { pickerSelectData.value = [ timeValue.year(), timeValue.month() + 1, timeValue.date(), timeValue.hour(), timeValue.minute(), timeValue.second(), ] } if (props.mode === 'timeNoSecond') { pickerSelectData.value = [timeValue.hour(), timeValue.minute()] } if (props.mode === 'datetimeNoSecond') { pickerSelectData.value = [ timeValue.year(), timeValue.month() + 1, timeValue.date(), timeValue.hour(), timeValue.minute(), ] } // 重新生成数据 nextTick(() => { generatePickerData(timeValue) }) const dateTimeValue = getDateTimeValue(timeValue) // emit(UPDATE_MODEL_EVENT, dateTimeValue) emit(CHANGE_EVENT, dateTimeValue) } // 确认日期时间回调 const handlePickerConfirmEvent = ( value: string | number | (string | number)[] ) => { const timeValue = getFillDateTimeDayjs(value as (string | number)[]) const dateTimeValue = getDateTimeValue(timeValue) emit(UPDATE_MODEL_EVENT, dateTimeValue) nextTick(() => { emit('confirm', dateTimeValue) }) _closePicker() } // 取消日期时间回调 const handlePickerCancelEvent = () => { initDateTimePicker(false) emit('cancel') _closePicker() } return { pickerRef, showPicker, pickerData, pickerSelectData, handlePickerCloseEvent, initDateTimePicker, pickerValueChangeEvent, handlePickerConfirmEvent, handlePickerCancelEvent, } }