import dayjs from 'dayjs'; // 月份配置 - 月份对应的天数 const monthConfig = [ { month: 1, day: 31 }, { month: 2, day: 29 }, { month: 3, day: 31 }, { month: 4, day: 30 }, { month: 5, day: 31 }, { month: 6, day: 30 }, { month: 7, day: 31 }, { month: 8, day: 31 }, { month: 9, day: 30 }, { month: 10, day: 31 }, { month: 11, day: 30 }, { month: 12, day: 31 }, ]; /** * 组装极联选择组件默认选项 * example: [ * { * value: '1', * label: '1月', * children: [ * { value: '1', label: '1日' }, * ... // 1月份的每一天 * ] * }, * ... // 其他月份的选项 * ] */ export function getMonthDayPickerDefaultOptions() { return monthConfig.map( (item) => ({ value: item.month.toString(), label: `${ item.month }月`, children: Array.from( { length: item.day }, (_, i) => ( { value: `${ i + 1 }`, label: `${ i + 1 }日` } ) ) }) ); } /** * 组装日期范围级联选择组件禁用选项 * @param date 日期 - 级联选择组件值 * @param isStartDate 区分传递的date是 开始日期 / 结束日期 * @param digits 时间范围 n个月 */ export function disableOutOfRangeOptions({ date = [], isStartDate = false, digits = 3 }: { date: string[], isStartDate?: boolean, digits: number }) { // 写死一个闰年年份 仅用于比较时间 // 如果非闰年 dayjs('year-02-29') 会输出 year-3-1 导致日期范围选择器出错 const year = 2024; const baseMonthDay = 30; const options = getMonthDayPickerDefaultOptions(); return options.map( (month) => { const children = month.children.map( (day) => { // 组装日期 - 当前这个选项对应的完整日期 const currentDate = dayjs([year, month.value, day.value].join('-')); // 是否需要禁用当前日期 let disabled = false; // 如果有传入日期,则判断是否在禁用日期范围内 if (date.length > 0) { // 组装日期 - 传入日期对应的完整日期 const baseDate = dayjs([year, ...date].join('-')); // 如果是开始时间,则结束时间范围为 baseDate + digits // 如果是结束时间,则开始时间范围为 baseDate - digits if (isStartDate) { const maxDate = baseDate.add(digits * baseMonthDay - 1, 'day'); // 推算时间范围超过12月31号,结束时间可选年初时间 if (maxDate.year() > year) { disabled = currentDate.isAfter(maxDate.subtract(366, 'day'), 'day') && currentDate.isBefore(baseDate, 'day'); } else { disabled = currentDate.isAfter(maxDate, 'day') || currentDate.isBefore(baseDate, 'day'); } } else { const minDate = baseDate.subtract(digits * baseMonthDay - 1, 'day'); // 推算时间范围在1月1号前,开始时间可选年末时间 if (minDate.year() < year) { disabled = currentDate.isBefore(minDate.add(366, 'day'), 'day') && currentDate.isAfter(baseDate, 'day'); } else { disabled = currentDate.isBefore(minDate, 'day') || currentDate.isAfter(baseDate, 'day'); } } } return { ...day, disabled }; } ); // 如果当前月份每天都是禁用日期,则整个月份禁用 const disabled = children.every((day) => day.disabled); return { ...month, disabled, children }; } ); } /** * 格式化月日级联选择组件值 MM-dd * @param date 日期 - 级联选择组件值 * @returns 格式化后的日期字符串 */ export function formatMonthDayPickerValue(date: string[]) { return date .map( (str) => str.padStart(2, '0') ) .join('-'); }