From adabeff9ed17c136ab09352c5e59ea049cd3f00a Mon Sep 17 00:00:00 2001 From: hetech Date: Mon, 22 Jul 2019 13:36:32 +0800 Subject: [PATCH] Calendar: Display correct header when range is specified (#16354) * Calendar: display correct header when range is specified * firstOfWeek is supported * update docs * update test * update * fix typo --- examples/docs/en-US/calendar.md | 2 +- examples/docs/es/calendar.md | 2 +- examples/docs/fr-FR/calendar.md | 2 +- examples/docs/zh-CN/calendar.md | 2 +- packages/calendar/src/main.vue | 42 ++++++++++++++++++++------------ test/unit/specs/calendar.spec.js | 19 +++++++++++++++ 6 files changed, 50 insertions(+), 19 deletions(-) diff --git a/examples/docs/en-US/calendar.md b/examples/docs/en-US/calendar.md index e94ff119a..4516c59ee 100644 --- a/examples/docs/en-US/calendar.md +++ b/examples/docs/en-US/calendar.md @@ -56,7 +56,7 @@ Display date. | Attribute | Description | Type | Accepted Values | Default | |-----------------|------------------- |---------- |---------------------- |--------- | | value / v-model | binding value | Date/string/number | — | — | -| range | time range, including start time and end time. Start time must be Monday, end time must be Sunday, the time span cannot exceed two months | Array | — | — | +| range | time range, including start time and end time. Start time must be start day of week, end time must be end day of week, the time span cannot exceed two months. | Array | — | — | | first-day-of-week | fisrt day of week| Number | 1 to 7 | 1 | ### dateCell scoped slot 参数 diff --git a/examples/docs/es/calendar.md b/examples/docs/es/calendar.md index d9b1834a6..717861461 100644 --- a/examples/docs/es/calendar.md +++ b/examples/docs/es/calendar.md @@ -57,7 +57,7 @@ Muestra fechas. | Atributo | Descripción | Tipo | Valores aceptados | Por defecto | |-----------------|------------------- |---------- |---------------------- |------------ | | value / v-model | valor vinculante | Date/string/number | — | — | -| range | rango de tiempo, incluyendo el tiempo de inicio y el tiempo final. El tiempo de inicio debe ser el lunes, el tiempo final debe ser el domingo, el período no puede exceder los dos meses. | Array | — | — | +| range | rango de tiempo, incluyendo el tiempo de inicio y el tiempo final. Start time must be start day of week, end time must be end day of week, the time span cannot exceed two months | Array | — | — | | first-day-of-week | fisrt day of week| Number | 1 to 7 | 1 | ### dateCell scoped slot diff --git a/examples/docs/fr-FR/calendar.md b/examples/docs/fr-FR/calendar.md index a32a20153..a198b2be9 100644 --- a/examples/docs/fr-FR/calendar.md +++ b/examples/docs/fr-FR/calendar.md @@ -57,7 +57,7 @@ Affiche un calendrier. | Attribut | Description | Type | Valeurs acceptées | Défaut | |------------------ |-------------- |---------- |---------------------- |--------- | | value / v-model | Valeur liée. | Date/string/number | — | — | -| range | Intervalle de dates, début et fin inclus. Le début doit être un lundi et la fin un dimanche, l'intervalle ne pouvant excéder deux mois. | Array | — | — | +| range | Intervalle de dates, début et fin inclus. Start time must be start day of week, end time must be end day of week, the time span cannot exceed two months. | Array | — | — | | first-day-of-week | fisrt day of week| Number | 1 to 7 | 1 | ### Slot dateCell diff --git a/examples/docs/zh-CN/calendar.md b/examples/docs/zh-CN/calendar.md index b7b36e9d4..2dc53b511 100644 --- a/examples/docs/zh-CN/calendar.md +++ b/examples/docs/zh-CN/calendar.md @@ -45,7 +45,7 @@ ### 自定义范围 -:::demo 设置 `range` 属性指定日历的显示范围。开始时间必须是周一,结束时间必须是周日,且时间跨度不能超过两个月。 +:::demo 设置 `range` 属性指定日历的显示范围。开始时间必须是周起始日,结束时间必须是周结束日,且时间跨度不能超过两个月。 ```html diff --git a/packages/calendar/src/main.vue b/packages/calendar/src/main.vue index 766747dae..4bb41c2df 100644 --- a/packages/calendar/src/main.vue +++ b/packages/calendar/src/main.vue @@ -50,6 +50,7 @@ :selected-day="realSelectedDay" :range="range" :hide-header="index !== 0" + :first-day-of-week="realFirstDayOfWeek" @pick="pickDay" /> @@ -62,6 +63,7 @@ import DateTable from './date-table'; import { validateRangeInOneMonth } from 'element-ui/src/utils/date-util'; const validTypes = ['prev-month', 'today', 'next-month']; +const weekDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; const oneDay = 86400000; export default { @@ -127,6 +129,17 @@ export default { throw new Error('invalid val'); } return val instanceof Date ? val : new Date(val); + }, + + rangeValidator(date, isStart) { + const firstDayOfWeek = this.realFirstDayOfWeek; + const expected = isStart ? firstDayOfWeek : (firstDayOfWeek === 0 ? 6 : firstDayOfWeek - 1); + const message = `${isStart ? 'start' : 'end'} of range should be ${weekDays[expected]}.`; + if (date.getDay() !== expected) { + console.warn('[ElementCalendar]', message, 'Invalid range will be ignored.'); + return false; + } + return true; } }, @@ -189,21 +202,9 @@ export default { validatedRange() { let range = this.range; if (!range) return []; - const expetedMap = { - 0: { - value: 1, - message: 'start of range should be Monday.' - }, - 1: { - value: 0, - message: 'end of range should be Sunday.' - } - }; range = range.reduce((prev, val, index) => { const date = this.toDate(val); - if (date.getDay() !== expetedMap[index].value) { - console.warn('[ElementCalendar]', expetedMap[index].message, ' invalid range will be ignored'); - } else { + if (this.rangeValidator(date, index === 0)) { prev = prev.concat(date); } return prev; @@ -227,12 +228,23 @@ export default { console.warn('[ElementCalendar]start time and end time interval must not exceed two months'); return []; } + // 第一个月的时间范围 data.push([ start, lastDay ]); - let interval = startDay.getDay(); - interval = interval <= 1 ? Math.abs(interval - 1) : (8 - interval); + // 下一月的时间范围,需要计算一下该月的第一个周起始日 + const firstDayOfWeek = this.realFirstDayOfWeek; + const nextMontFirstDay = startDay.getDay(); + let interval = 0; + if (nextMontFirstDay !== firstDayOfWeek) { + if (firstDayOfWeek === 0) { + interval = 7 - nextMontFirstDay; + } else { + interval = firstDayOfWeek - nextMontFirstDay; + interval = interval > 0 ? interval : 7 + interval; + } + } startDay = this.toDate(startDay.getTime() + interval * oneDay); if (startDay.getDate() < end.getDate()) { data.push([ diff --git a/test/unit/specs/calendar.spec.js b/test/unit/specs/calendar.spec.js index b869447d2..a393e9640 100644 --- a/test/unit/specs/calendar.spec.js +++ b/test/unit/specs/calendar.spec.js @@ -85,5 +85,24 @@ describe('Calendar', () => { expect(firstRow.firstElementChild.innerText).to.be.equal('31'); expect(firstRow.lastElementChild.innerText).to.be.equal('6'); }); + + it('firstDayOfWeek in range mode', async() => { + vm = createVue({ + template: ` + + `, + data() { + return { + value: new Date('2019-03-04') + }; + } + }, true); + const head = vm.$el.querySelector('.el-calendar-table thead'); + expect(head.firstElementChild.innerText).to.be.equal('日'); + expect(head.lastElementChild.innerText).to.be.equal('六'); + const firstRow = vm.$el.querySelector('.el-calendar-table__row'); + expect(firstRow.firstElementChild.innerText).to.be.equal('3'); + expect(firstRow.lastElementChild.innerText).to.be.equal('9'); + }); });