<script lang="ts" setup>
|
import { computed, ref, unref, watch } from 'vue';
|
|
import { useAttrs } from '@jnpf/hooks';
|
import { getDateFormat, getDateTimeUnit } from '@jnpf/utils';
|
|
import { DatePicker } from 'ant-design-vue';
|
import dayjs, { Dayjs } from 'dayjs';
|
|
import { datePickerProps } from './props';
|
|
defineOptions({ inheritAttrs: false, name: 'JnpfDatePicker' });
|
const props = defineProps(datePickerProps);
|
const emit = defineEmits(['update:value', 'change']);
|
const attrs: any = useAttrs({ excludeDefaultKeys: false });
|
const innerValue = ref('');
|
|
const getFormat = computed(() => getDateFormat(props.format || 'YYYY-MM-DD'));
|
const getShowTime = computed(() => unref(getFormat) === 'YYYY-MM-DD HH:mm' || unref(getFormat) === 'YYYY-MM-DD HH:mm:ss');
|
const getPicker = computed(() => {
|
if (unref(getFormat) === 'YYYY') return 'year';
|
if (unref(getFormat) === 'YYYY-MM') return 'month';
|
return 'date';
|
});
|
const getRealStartTime = computed(() => {
|
const format = unref(getFormat);
|
if (!props.startTime || format === 'YYYY-MM-DD HH:mm:ss') return props.startTime;
|
const startTime = dayjs(props.startTime).startOf(getDateTimeUnit(format)).valueOf();
|
return startTime;
|
});
|
const getRealEndTime = computed(() => {
|
const format = unref(getFormat);
|
if (!props.endTime || format === 'YYYY-MM-DD HH:mm:ss') return props.endTime;
|
const endTime = dayjs(props.endTime).endOf(getDateTimeUnit(format)).valueOf();
|
return endTime;
|
});
|
const getBindValue = computed(() => {
|
const bindValue = {
|
...unref(attrs),
|
disabledDate: (current: Dayjs) => {
|
const startTime = unref(getRealStartTime);
|
const endTime = unref(getRealEndTime);
|
if ((!startTime && !endTime) || !current) return false;
|
const currentDate = current.startOf(getDateTimeUnit(unref(getFormat))).valueOf();
|
if (startTime && endTime) return startTime > currentDate || endTime < currentDate;
|
if (startTime) return startTime > currentDate;
|
if (endTime) return endTime < currentDate;
|
return false;
|
},
|
disabledTime: (current: Dayjs) => ({
|
disabledHours: () => {
|
const startTime = unref(getRealStartTime);
|
const endTime = unref(getRealEndTime);
|
if ((!startTime && !endTime) || !current) return [];
|
const hours: number[] = [];
|
if (startTime && current.format('YYYY-MM-DD') === dayjs(startTime).format('YYYY-MM-DD')) {
|
const startHour = dayjs(startTime).hour();
|
for (let i = 0; i < startHour; i++) {
|
hours.push(i);
|
}
|
}
|
if (endTime && current.format('YYYY-MM-DD') === dayjs(endTime).format('YYYY-MM-DD')) {
|
const endHour = dayjs(endTime).hour();
|
for (let i = 0; i < 24; i++) {
|
if (i > endHour) hours.push(i);
|
}
|
}
|
return hours;
|
},
|
disabledMinutes: (selectedHour) => {
|
const startTime = unref(getRealStartTime);
|
const endTime = unref(getRealEndTime);
|
if ((!startTime && !endTime) || !current) return [];
|
const minutes: number[] = [];
|
if (startTime && current.format('YYYY-MM-DD') === dayjs(startTime).format('YYYY-MM-DD')) {
|
const startHour = dayjs(startTime).hour();
|
const startMinute = dayjs(startTime).minute();
|
if (selectedHour < startHour) {
|
for (let i = 0; i < 60; i++) {
|
minutes.push(i);
|
}
|
return minutes;
|
}
|
if (selectedHour === startHour) {
|
for (let i = 0; i < startMinute; i++) {
|
minutes.push(i);
|
}
|
}
|
}
|
if (endTime && current.format('YYYY-MM-DD') === dayjs(endTime).format('YYYY-MM-DD')) {
|
const endHour = dayjs(endTime).hour();
|
const endMinute = dayjs(endTime).minute();
|
if (selectedHour === endHour) {
|
for (let i = 0; i < 60; i++) {
|
if (i > endMinute) minutes.push(i);
|
}
|
return minutes;
|
}
|
if (selectedHour > endHour) {
|
for (let i = 0; i < 60; i++) {
|
minutes.push(i);
|
}
|
return minutes;
|
}
|
}
|
return minutes;
|
},
|
disabledSeconds: (selectedHour, selectedMinute) => {
|
const startTime = unref(getRealStartTime);
|
const endTime = unref(getRealEndTime);
|
if ((!startTime && !endTime) || !current || unref(getFormat) === 'YYYY-MM-DD HH:mm') return [];
|
const seconds: number[] = [];
|
const selectedHourMinute = padZero(selectedHour) + padZero(selectedMinute);
|
if (startTime && current.format('YYYY-MM-DD') === dayjs(startTime).format('YYYY-MM-DD')) {
|
const startHourMinute = padZero(dayjs(startTime).hour()) + padZero(dayjs(startTime).minute());
|
const startSecond = dayjs(startTime).second();
|
if (selectedHourMinute < startHourMinute) {
|
for (let i = 0; i < 60; i++) {
|
seconds.push(i);
|
}
|
return seconds;
|
}
|
if (selectedHourMinute === startHourMinute) {
|
for (let i = 0; i < startSecond; i++) {
|
seconds.push(i);
|
}
|
}
|
}
|
if (endTime && current.format('YYYY-MM-DD') === dayjs(endTime).format('YYYY-MM-DD')) {
|
const endHourMinute = padZero(dayjs(endTime).hour()) + padZero(dayjs(endTime).minute());
|
const endSecond = dayjs(endTime).second();
|
if (selectedHourMinute === endHourMinute) {
|
for (let i = 0; i < 60; i++) {
|
if (i > endSecond) seconds.push(i);
|
}
|
return seconds;
|
}
|
if (selectedHourMinute > endHourMinute) {
|
for (let i = 0; i < 60; i++) {
|
seconds.push(i);
|
}
|
return seconds;
|
}
|
}
|
return seconds;
|
},
|
}),
|
format: unref(getFormat),
|
showNow: !props.startTime && !props.endTime,
|
showTime: unref(getShowTime),
|
showToday: !props.startTime && !props.endTime,
|
valueFormat: unref(getFormat),
|
};
|
if (Reflect.has(unref(attrs), 'disabledDate')) bindValue.disabledDate = unref(attrs).disabledDate;
|
if (Reflect.has(unref(attrs), 'disabledTime')) bindValue.disabledTime = unref(attrs).disabledTime;
|
return bindValue;
|
});
|
|
watch(
|
() => unref(props.value),
|
(val) => {
|
setValue(val);
|
},
|
{ immediate: true },
|
);
|
watch(
|
() => unref(getFormat),
|
() => {
|
setValue(props.value);
|
},
|
);
|
|
function setValue(value) {
|
innerValue.value = value || value === 0 ? dayjs(Number(value)).format(unref(getFormat)) : '';
|
}
|
function onChange(date) {
|
const timestamp = date ? dayjs(date).valueOf() : null;
|
emit('update:value', timestamp);
|
emit('change', timestamp);
|
}
|
function padZero(str) {
|
return /^\d$/.test(str) ? `0${str}` : str.toString();
|
}
|
</script>
|
|
<template>
|
<DatePicker v-bind="getBindValue" v-model:value="innerValue" :picker="getPicker" @change="onChange" />
|
</template>
|