mirror of
https://github.com/element-plus/element-plus.git
synced 2024-11-21 01:02:59 +08:00
refactor(components): Improve calendar date range validate (#3156)
* fix(components): Improve calendar date range validate method * chore(components): Add some comments and references * fix(components): change `console.warn` to `warn`
This commit is contained in:
parent
8654e7d54a
commit
21cdf61d20
@ -43,6 +43,18 @@ describe('Calendar.vue', () => {
|
||||
expect(wrapper.element.querySelector('.el-calendar__button-group')).toBeNull()
|
||||
})
|
||||
|
||||
// https://github.com/element-plus/element-plus/issues/3155
|
||||
it('range when the start date will be calculated to last month', () => {
|
||||
const wrapper = _mount(`
|
||||
<el-calendar :range="[new Date(2021, 1, 2), new Date(2021, 1, 28)]"></el-calendar>
|
||||
`)
|
||||
const titleEl = wrapper.find('.el-calendar__title')
|
||||
expect(/2021.*January/.test((titleEl.element as HTMLElement).innerHTML)).toBeTruthy()
|
||||
const rows = wrapper.element.querySelectorAll('.el-calendar-table__row')
|
||||
expect(rows.length).toBe(5)
|
||||
expect(wrapper.element.querySelector('.el-calendar__button-group')).toBeNull()
|
||||
})
|
||||
|
||||
it('range tow monthes', async() => {
|
||||
const wrapper = _mount(`
|
||||
<el-calendar :range="[new Date(2019, 3, 14), new Date(2019, 4, 18)]"></el-calendar>
|
||||
@ -62,6 +74,26 @@ describe('Calendar.vue', () => {
|
||||
expect(cell.classList.contains('is-selected')).toBeTruthy()
|
||||
})
|
||||
|
||||
// https://github.com/element-plus/element-plus/issues/3155
|
||||
it('range tow monthes when the start date will be calculated to last month', async() => {
|
||||
const wrapper = _mount(`
|
||||
<el-calendar :range="[new Date(2021, 1, 2), new Date(2021, 2, 21)]"></el-calendar>
|
||||
`)
|
||||
const titleEl = wrapper.find('.el-calendar__title')
|
||||
expect(/2021.*January/.test((titleEl.element as HTMLElement).innerHTML)).toBeTruthy()
|
||||
const dateTables = wrapper.element.querySelectorAll('.el-calendar-table.is-range')
|
||||
expect(dateTables.length).toBe(3)
|
||||
const rows = wrapper.element.querySelectorAll('.el-calendar-table__row')
|
||||
expect(rows.length).toBe(8)
|
||||
const cell = rows[rows.length - 1].firstElementChild;
|
||||
(cell as HTMLElement).click()
|
||||
|
||||
await nextTick()
|
||||
|
||||
expect(/2021.*March/.test((titleEl.element as HTMLElement).innerHTML)).toBeTruthy()
|
||||
expect(cell.classList.contains('is-selected')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('firstDayOfWeek', async () => {
|
||||
// default en locale, weekStart 0 Sunday
|
||||
const wrapper = _mount(`
|
||||
|
@ -64,6 +64,7 @@ import dayjs from 'dayjs'
|
||||
|
||||
import ElButton from '@element-plus/components/button'
|
||||
import { useLocaleInject } from '@element-plus/hooks'
|
||||
import { warn } from '@element-plus/utils/error'
|
||||
import DateTable from './date-table.vue'
|
||||
|
||||
import type { Dayjs } from 'dayjs'
|
||||
@ -149,47 +150,77 @@ export default defineComponent({
|
||||
}
|
||||
})
|
||||
|
||||
// https://github.com/element-plus/element-plus/issues/3155
|
||||
// Calculate the validate date range according to the start and end dates
|
||||
const calculateValidatedDateRange = (startDayjs: dayjs.Dayjs,endDayjs: dayjs.Dayjs) => {
|
||||
const firstDay = startDayjs.startOf('week')
|
||||
const lastDay = endDayjs.endOf('week')
|
||||
const firstMonth = firstDay.get('month')
|
||||
const lastMonth = lastDay.get('month')
|
||||
|
||||
// Current mouth
|
||||
if(firstMonth === lastMonth){
|
||||
return [[firstDay, lastDay]]
|
||||
}
|
||||
// Two adjacent months
|
||||
else if(firstMonth + 1 === lastMonth ){
|
||||
|
||||
const firstMonthLastDay = firstDay.endOf('month')
|
||||
const lastMonthFirstDay = lastDay.startOf('month')
|
||||
|
||||
// Whether the last day of the first month and the first day of the last month is in the same week
|
||||
const isSameWeek = firstMonthLastDay.isSame(lastMonthFirstDay, 'week')
|
||||
const lastMonthStartDay = isSameWeek ? lastMonthFirstDay.add(1, 'week') : lastMonthFirstDay
|
||||
|
||||
return [[firstDay, firstMonthLastDay], [lastMonthStartDay.startOf('week'), lastDay]]
|
||||
}
|
||||
// Three consecutive months (compatible: 2021-01-30 to 2021-02-28)
|
||||
else if(firstMonth + 2 === lastMonth ){
|
||||
|
||||
const firstMonthLastDay = firstDay.endOf('month')
|
||||
const secondMonthFisrtDay = firstDay.add(1,'month').startOf('month')
|
||||
|
||||
// Whether the last day of the first month and the second month is in the same week
|
||||
const secondMonthStartDay = firstMonthLastDay.isSame(secondMonthFisrtDay, 'week') ? secondMonthFisrtDay.add(1, 'week') : secondMonthFisrtDay
|
||||
|
||||
const secondMonthLastDay = secondMonthStartDay.endOf('month')
|
||||
const lastMonthFirstDay = lastDay.startOf('month')
|
||||
|
||||
// Whether the last day of the second month and the last day of the last month is in the same week
|
||||
const lastMonthStartDay = secondMonthLastDay.isSame(lastMonthFirstDay, 'week') ? lastMonthFirstDay.add(1, 'week') : lastMonthFirstDay
|
||||
|
||||
return [
|
||||
[firstDay, firstMonthLastDay],
|
||||
[secondMonthStartDay.startOf('week'), secondMonthLastDay],
|
||||
[lastMonthStartDay.startOf('week'), lastDay],
|
||||
]
|
||||
}
|
||||
// Other cases
|
||||
else {
|
||||
warn('ElCalendar', 'start time and end time interval must not exceed two months')
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
// if range is valid, we get a two-digit array
|
||||
const validatedRange = computed(() => {
|
||||
if (!props.range) return []
|
||||
const rangeArrDayjs = props.range.map(_ => dayjs(_).locale(lang.value))
|
||||
const [startDayjs, endDayjs] = rangeArrDayjs
|
||||
if (startDayjs.isAfter(endDayjs)) {
|
||||
console.warn(
|
||||
'[ElementCalendar]end time should be greater than start time',
|
||||
)
|
||||
warn('ElCalendar', 'end time should be greater than start time')
|
||||
return []
|
||||
}
|
||||
if (startDayjs.isSame(endDayjs, 'month')) {
|
||||
// same month
|
||||
return [[
|
||||
startDayjs.startOf('week'),
|
||||
endDayjs.endOf('week'),
|
||||
]]
|
||||
return calculateValidatedDateRange(startDayjs, endDayjs)
|
||||
} else {
|
||||
// two months
|
||||
if (startDayjs.add(1, 'month').month() !== endDayjs.month()) {
|
||||
console.warn(
|
||||
'[ElementCalendar]start time and end time interval must not exceed two months',
|
||||
)
|
||||
warn('ElCalendar', 'start time and end time interval must not exceed two months')
|
||||
return []
|
||||
}
|
||||
const endMonthFirstDay = endDayjs.startOf('month')
|
||||
const endMonthFirstWeekDay = endMonthFirstDay.startOf('week')
|
||||
let endMonthStart = endMonthFirstDay
|
||||
if (!endMonthFirstDay.isSame(endMonthFirstWeekDay, 'month')) {
|
||||
endMonthStart = endMonthFirstDay.endOf('week').add(1, 'day')
|
||||
}
|
||||
return [
|
||||
[
|
||||
startDayjs.startOf('week'),
|
||||
startDayjs.endOf('month'),
|
||||
],
|
||||
[
|
||||
endMonthStart,
|
||||
endDayjs.endOf('week'),
|
||||
],
|
||||
]
|
||||
return calculateValidatedDateRange(startDayjs, endDayjs)
|
||||
}
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user