@fesjs/fes-design
Version:
fes-design for PC
489 lines (483 loc) • 17.2 kB
JavaScript
import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
import { reactive, watch, ref, computed } from 'vue';
import { isNil } from 'lodash-es';
import { endOfMonth } from 'date-fns';
import getPrefixCls from '../_util/getPrefixCls';
import { useNormalModel } from '../_util/use/useModel';
import { useLocale } from '../config-provider/useLocale';
import { PickerType } from './pickerHandler';
import { YEAR_COUNT, SELECTED_STATUS, RANGE_POSITION } from './const';
import { parseDate, transformDateToTimestamp, fillDate, contrastDate, timeFormat, transformTimeToDate } from './helper';
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
const prefixCls = getPrefixCls('date-picker-calendar');
const WEEK_NAMES = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
const useCurrentDate = (props, emit) => {
const currentDate = reactive(parseDate(props.activeDate));
const [innerActiveDate, updateActiveDate] = useNormalModel(props, emit, {
prop: 'activeDate'
});
const mergeCurrentDate = date => {
Object.assign(currentDate, date);
currentDate.day = 1;
};
const updateCurrentDate = date => {
mergeCurrentDate(date);
updateActiveDate(transformDateToTimestamp(currentDate));
};
watch(innerActiveDate, () => {
mergeCurrentDate(parseDate(innerActiveDate.value));
});
watch(() => props.modelValue, () => {
var _props$modelValue;
if (((_props$modelValue = props.modelValue) === null || _props$modelValue === void 0 ? void 0 : _props$modelValue.length) === 1 && !props.rangePosition) {
updateCurrentDate(parseDate(props.modelValue[0]));
}
});
return {
currentDate,
updateCurrentDate
};
};
const useSelectedDates = (props, emit, picker) => {
const selectedDates = ref([]);
const updateRangeSelectedDates = (date, index) => {
if (!selectedDates.value.length || index === 0 && transformDateToTimestamp(date) > transformDateToTimestamp(selectedDates.value[1]) || index === 1 && transformDateToTimestamp(date) < transformDateToTimestamp(selectedDates.value[0])) {
selectedDates.value = [date, _objectSpread({}, date)];
} else {
selectedDates.value.splice(index, 1, date);
}
};
const updateSelectedDates = function (date, index) {
let option = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
const newDate = Object.assign({}, selectedDates.value[index], date);
if (picker.value.isRange && option.isTime) {
updateRangeSelectedDates(newDate, index);
} else if (picker.value.isRange && option.isDateInput && props.selectedStatus === SELECTED_STATUS.END) {
updateRangeSelectedDates(newDate, index);
} else if (picker.value.isRange && (!selectedDates.value.length || props.selectedStatus === SELECTED_STATUS.END)) {
const anotherDate = fillDate({
dateObj: newDate,
format: picker.value.format,
defaultTime: props.defaultTime,
rangePosition: props.rangePosition === RANGE_POSITION.LEFT ? RANGE_POSITION.RIGHT : RANGE_POSITION.LEFT
});
if (props.rangePosition === RANGE_POSITION.LEFT) {
selectedDates.value = [newDate, anotherDate];
} else {
selectedDates.value = [anotherDate, newDate];
}
emit('selectedDay');
} else if (picker.value.name === PickerType.datemultiple) {
const selectedDateIndex = selectedDates.value.findIndex(item => {
return item.year === newDate.year && item.month === newDate.month && item.day === newDate.day;
});
if (selectedDateIndex !== -1) {
selectedDates.value.splice(selectedDateIndex, 1);
} else {
selectedDates.value.push(newDate);
}
} else if (!picker.value.isRange) {
selectedDates.value = [newDate];
} else {
if (
// 变更日期的时候,继承当前位置的时间
transformDateToTimestamp(selectedDates.value[0]) > transformDateToTimestamp(newDate)) {
selectedDates.value.splice(0, 1, picker.value.getRangeSelectedDate(newDate, selectedDates.value[0]));
} else {
selectedDates.value.splice(1, 1, picker.value.getRangeSelectedDate(newDate, selectedDates.value[1]));
}
emit('selectedDay');
}
if (picker.value.isRange) {
emit('change', [transformDateToTimestamp(selectedDates.value[0]), transformDateToTimestamp(selectedDates.value[1], true)]);
} else if (picker.value.name === PickerType.datemultiple) {
emit('change', selectedDates.value.map(item => {
return transformDateToTimestamp(item);
}));
} else {
emit('change', [transformDateToTimestamp(selectedDates.value[0])]);
}
};
watch(() => props.modelValue, () => {
const dates = props.modelValue || [];
selectedDates.value = dates.map(item => item ? parseDate(item) : null);
}, {
immediate: true
});
return {
selectedDates,
updateSelectedDates
};
};
function useYear(_ref) {
let {
props,
selectedDates,
updateSelectedDates,
activeIndex,
currentDate,
updateCurrentDate
} = _ref;
const isYearSelect = computed(() => props.type === PickerType.year);
// 年份相关
const selectYear = year => {
updateCurrentDate({
year
});
updateSelectedDates({
year
}, activeIndex.value);
};
const yearStart = computed(() => currentDate.year - currentDate.year % YEAR_COUNT);
const yearEnd = computed(() => yearStart.value + YEAR_COUNT);
const years = computed(() => {
const arr = [];
let start = yearStart.value;
while (arr.length < 16) {
arr.push(start++);
}
return arr;
});
const disabled = year => {
const date = new Date(year, 0);
return props.disabledDate && props.disabledDate(date, 'yyyy');
};
const isSelectedYear = year => {
if (props.type === PickerType.year) {
return !!selectedDates.value.find(item => (item === null || item === void 0 ? void 0 : item.year) === year);
}
return false;
};
const yearCls = year => [`${prefixCls}-date`, disabled(year) && `${prefixCls}-date-disabled`, isSelectedYear(year) && `${prefixCls}-date-selected`, year === new Date().getFullYear() && [`${prefixCls}-date-now`]];
return {
years,
yearStart,
yearEnd,
selectYear,
isYearSelect,
yearCls
};
}
function useCommonRange(_ref2) {
let {
props,
selectedDates,
picker
} = _ref2;
const startDate = computed(() => selectedDates.value[0] && new Date(transformDateToTimestamp(selectedDates.value[0])));
const endDate = computed(() => selectedDates.value[1] && new Date(transformDateToTimestamp(selectedDates.value[1])));
// 样式计算
const inRangeDate = (date, format) => {
if (picker.value.isRange && startDate.value && endDate.value) {
return contrastDate(date, startDate.value, format) === 1 && contrastDate(date, endDate.value, format) === -1;
}
return false;
};
const completeRangeSelected = computed(() => props.selectedStatus === SELECTED_STATUS.END);
return {
completeRangeSelected,
inRangeDate
};
}
function useMonth(_ref3) {
let {
props,
selectedDates,
updateSelectedDates,
activeIndex,
currentDate,
updateCurrentDate,
picker
} = _ref3;
// 月份相关
const format = 'yyyy-MM';
const isMonthSelect = computed(() => {
return props.type === PickerType.month || props.type === PickerType.datemonthrange;
});
const selectMonth = month => {
updateSelectedDates({
year: currentDate.year,
month,
day: props.type === PickerType.month || props.rangePosition === RANGE_POSITION.LEFT ? 1 : endOfMonth(new Date(currentDate.year, month, 1)).getDate()
}, activeIndex.value);
};
const monthToNext = () => {
if (currentDate.month < 11) {
updateCurrentDate({
year: currentDate.year,
month: currentDate.month + 1
});
} else {
updateCurrentDate({
year: currentDate.year + 1,
month: 0
});
}
};
const monthToPre = () => {
if (currentDate.month > 0) {
updateCurrentDate({
year: currentDate.year,
month: currentDate.month - 1
});
} else {
updateCurrentDate({
month: 11,
year: currentDate.year - 1
});
}
};
const disabled = month => {
const date = new Date(currentDate.year, month);
return props.disabledDate && props.disabledDate(date, format);
};
const isSelectedMonth = month => {
if (isMonthSelect.value) {
return selectedDates.value.findIndex(item => item && item.year === currentDate.year && item.month === month);
}
return -1;
};
const {
completeRangeSelected,
inRangeDate
} = useCommonRange({
props,
selectedDates,
picker
});
const monthCls = month => {
const selectedIndex = isSelectedMonth(month);
const date = new Date(currentDate.year, month);
return {
[`${prefixCls}-date`]: true,
[`${prefixCls}-date-disabled`]: disabled(month),
[`${prefixCls}-date-selected`]: selectedIndex !== -1,
'is-start': picker.value.isRange && completeRangeSelected.value && selectedIndex === 0,
'is-end': picker.value.isRange && completeRangeSelected.value && selectedIndex === 1,
[`${prefixCls}-date-now`]: timeFormat(new Date(currentDate.year, month), format) === timeFormat(new Date(), format),
[`${prefixCls}-date-on`]: inRangeDate(date, format)
};
};
return {
isMonthSelect,
selectMonth,
monthToNext,
monthToPre,
monthCls
};
}
function useDay(_ref4) {
let {
props,
selectedDates,
currentDate,
picker
} = _ref4;
const {
t
} = useLocale();
// TODO 英文一个星期的第一天是 周日
const weekFirstDay = ref(1);
// 展示数据
const weekNames = computed(() => {
const weekFirstDayValue = weekFirstDay.value;
return WEEK_NAMES.concat(WEEK_NAMES).slice(weekFirstDayValue, weekFirstDayValue + 7).map(_ => t(`datePicker.weeks.${_}`));
});
const isDaySelect = computed(() => [PickerType.date, PickerType.datetime, PickerType.daterange, PickerType.datetimerange, PickerType.datemultiple].some(type => props.type === type));
const days = computed(() => {
const daysTemp = [];
const {
year,
month
} = currentDate;
const time = new Date(year, month, 1);
const weekFirstDayValue = weekFirstDay.value;
time.setDate(0); // switch to the last day of last month
let lastDay = time.getDate();
const week = time.getDay() || 7;
let count = weekFirstDayValue <= week ? week - weekFirstDayValue + 1 : week + (7 - weekFirstDayValue + 1);
while (count > 0 && count < 7) {
daysTemp.push({
day: lastDay - count + 1,
year: month > 0 ? year : year - 1,
month: month > 0 ? month - 1 : 11,
pre: true
});
count--;
}
time.setMonth(time.getMonth() + 2, 0); // switch to the last day of the current month
lastDay = time.getDate();
let i = 1;
for (i = 1; i <= lastDay; i++) {
daysTemp.push({
day: i,
year,
month
});
}
for (i = 1; daysTemp.length < 42; i++) {
daysTemp.push({
day: i,
year: month < 11 ? year : year + 1,
month: month < 11 ? month + 1 : 0,
next: true
});
}
return daysTemp;
});
const isSelected = (selectedDate, dayItem) => dayItem.year === (selectedDate === null || selectedDate === void 0 ? void 0 : selectedDate.year) && dayItem.month === (selectedDate === null || selectedDate === void 0 ? void 0 : selectedDate.month) && dayItem.month === currentDate.month && dayItem.day === (selectedDate === null || selectedDate === void 0 ? void 0 : selectedDate.day);
const findSelectedIndex = dayItem => selectedDates.value.findIndex(selectedDate => isSelected(selectedDate, dayItem));
const computedSelectedStart = dayItem => {
return picker.value.isRange && completeRangeSelected.value && isSelected(selectedDates.value[0], dayItem);
};
const computedSelectedEnd = dayItem => {
return picker.value.isRange && completeRangeSelected.value && isSelected(selectedDates.value[1], dayItem);
};
const {
completeRangeSelected,
inRangeDate
} = useCommonRange({
props,
selectedDates,
picker
});
const dayCls = item => {
const format = 'yyyy-MM-dd';
const {
year,
month
} = item;
const date = new Date(year, month, item.day);
const selectedIndex = findSelectedIndex(item);
return {
[`${prefixCls}-date-out`]: item.pre || item.next,
[`${prefixCls}-date`]: true,
[`${prefixCls}-date-disabled`]: props.disabledDate && props.disabledDate(date, format),
[`${prefixCls}-date-selected`]: selectedIndex !== -1,
'is-start': computedSelectedStart(item),
'is-end': computedSelectedEnd(item),
[`${prefixCls}-date-now`]: timeFormat(date, format) === timeFormat(new Date(), format),
[`${prefixCls}-date-on`]: inRangeDate(date, format) && date.getMonth() === currentDate.month
};
};
return {
days,
isDaySelect,
weekNames,
dayCls
};
}
const useQuarter = (props, selectedDates, updateSelectedDates, activeIndex, currentDate) => {
const isQuarterSelect = computed(() => props.type === PickerType.quarter);
const format = 'yyyy-MM';
const quarterList = [{
name: 'Q1',
value: 1
}, {
name: 'Q2',
value: 2
}, {
name: 'Q3',
value: 3
}, {
name: 'Q4',
value: 4
}];
const selectQuarter = item => {
updateSelectedDates({
year: currentDate.year,
month: (item.value - 1) * 3
}, activeIndex.value);
};
const isSelected = item => !!selectedDates.value.find(selectedDate => selectedDate && selectedDate.year === currentDate.year && item.value === Math.floor(selectedDate.month / 3) + 1);
const isNow = item => {
const now = parseDate();
return now.year === currentDate.year && Math.floor(now.month / 3) + 1 === item.value;
};
// 季度置灰判断
const isDisabled = item => {
const year = currentDate.year;
const month = (item.value - 1) * 3;
const date = new Date(year, month);
return props.disabledDate && props.disabledDate(date, format);
};
const quarterCls = item => ({
[`${prefixCls}-date`]: true,
[`${prefixCls}-date-selected`]: isSelected(item),
[`${prefixCls}-date-now`]: isNow(item),
[`${prefixCls}-date-disabled`]: isDisabled(item)
});
return {
isQuarterSelect,
quarterList,
selectQuarter,
quarterCls
};
};
const transformDateToTime = selectedDate => {
if (!selectedDate) {
return '';
}
const times = [];
if (!isNil(selectedDate.hour)) {
times.push(`${selectedDate.hour}`.padStart(2, '0'));
}
if (!isNil(selectedDate.minute)) {
times.push(`${selectedDate.minute}`.padStart(2, '0'));
}
if (!isNil(selectedDate.second)) {
times.push(`${selectedDate.second}`.padStart(2, '0'));
}
return times.join(':');
};
const useTime = _ref5 => {
let {
props,
selectedDates,
updateSelectedDates,
activeIndex,
picker
} = _ref5;
const currentTime = ref('');
watch([selectedDates], () => {
currentTime.value = transformDateToTime(selectedDates.value[activeIndex.value]);
}, {
immediate: true,
deep: true
});
const changeTime = time => {
if (time) {
var _selectedDates$value$;
const selectedDate = _objectSpread(_objectSpread({}, selectedDates.value[activeIndex.value]), transformTimeToDate(time));
if (!((_selectedDates$value$ = selectedDates.value[activeIndex.value]) !== null && _selectedDates$value$ !== void 0 && _selectedDates$value$.year)) {
const date = new Date();
Object.assign(selectedDate, {
year: date.getFullYear(),
month: date.getMonth(),
day: date.getDate()
});
}
updateSelectedDates(selectedDate, activeIndex.value, {
isTime: true
});
}
};
const innerDisabledTime = computed(() => {
if (!props.disabledTime) {
return null;
}
if (picker.value.isRange) {
return props.disabledTime(new Date(transformDateToTimestamp(selectedDates.value[activeIndex.value])), props.rangePosition, selectedDates.value.map(val => {
return new Date(transformDateToTimestamp(val));
}));
}
return props.disabledTime(new Date(transformDateToTimestamp(selectedDates.value[0])));
});
return {
currentTime,
changeTime,
innerDisabledTime
};
};
export { useCommonRange, useCurrentDate, useDay, useMonth, useQuarter, useSelectedDates, useTime, useYear };