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
pull/16263/head
hetech 2019-07-22 13:36:32 +08:00 committed by Zhi Cun
parent e13de1688b
commit adabeff9ed
6 changed files with 50 additions and 19 deletions

View File

@ -56,7 +56,7 @@ Display date.
| Attribute | Description | Type | Accepted Values | Default | | Attribute | Description | Type | Accepted Values | Default |
|-----------------|------------------- |---------- |---------------------- |--------- | |-----------------|------------------- |---------- |---------------------- |--------- |
| value / v-model | binding value | Date/string/number | — | — | | 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 | | first-day-of-week | fisrt day of week| Number | 1 to 7 | 1 |
### dateCell scoped slot 参数 ### dateCell scoped slot 参数

View File

@ -57,7 +57,7 @@ Muestra fechas.
| Atributo | Descripción | Tipo | Valores aceptados | Por defecto | | Atributo | Descripción | Tipo | Valores aceptados | Por defecto |
|-----------------|------------------- |---------- |---------------------- |------------ | |-----------------|------------------- |---------- |---------------------- |------------ |
| value / v-model | valor vinculante | Date/string/number | — | — | | 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 | | first-day-of-week | fisrt day of week| Number | 1 to 7 | 1 |
### dateCell scoped slot ### dateCell scoped slot

View File

@ -57,7 +57,7 @@ Affiche un calendrier.
| Attribut | Description | Type | Valeurs acceptées | Défaut | | Attribut | Description | Type | Valeurs acceptées | Défaut |
|------------------ |-------------- |---------- |---------------------- |--------- | |------------------ |-------------- |---------- |---------------------- |--------- |
| value / v-model | Valeur liée. | Date/string/number | — | — | | 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 | | first-day-of-week | fisrt day of week| Number | 1 to 7 | 1 |
### Slot dateCell ### Slot dateCell

View File

@ -45,7 +45,7 @@
### 自定义范围 ### 自定义范围
:::demo 设置 `range` 属性指定日历的显示范围。开始时间必须是周一,结束时间必须是周日,且时间跨度不能超过两个月。 :::demo 设置 `range` 属性指定日历的显示范围。开始时间必须是周起始日,结束时间必须是周结束日,且时间跨度不能超过两个月。
```html ```html
<el-calendar :range="['2019-03-04', '2019-03-24']"> <el-calendar :range="['2019-03-04', '2019-03-24']">
</el-calendar> </el-calendar>

View File

@ -50,6 +50,7 @@
:selected-day="realSelectedDay" :selected-day="realSelectedDay"
:range="range" :range="range"
:hide-header="index !== 0" :hide-header="index !== 0"
:first-day-of-week="realFirstDayOfWeek"
@pick="pickDay" /> @pick="pickDay" />
</div> </div>
</div> </div>
@ -62,6 +63,7 @@ import DateTable from './date-table';
import { validateRangeInOneMonth } from 'element-ui/src/utils/date-util'; import { validateRangeInOneMonth } from 'element-ui/src/utils/date-util';
const validTypes = ['prev-month', 'today', 'next-month']; const validTypes = ['prev-month', 'today', 'next-month'];
const weekDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
const oneDay = 86400000; const oneDay = 86400000;
export default { export default {
@ -127,6 +129,17 @@ export default {
throw new Error('invalid val'); throw new Error('invalid val');
} }
return val instanceof Date ? val : new Date(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() { validatedRange() {
let range = this.range; let range = this.range;
if (!range) return []; 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) => { range = range.reduce((prev, val, index) => {
const date = this.toDate(val); const date = this.toDate(val);
if (date.getDay() !== expetedMap[index].value) { if (this.rangeValidator(date, index === 0)) {
console.warn('[ElementCalendar]', expetedMap[index].message, ' invalid range will be ignored');
} else {
prev = prev.concat(date); prev = prev.concat(date);
} }
return prev; return prev;
@ -227,12 +228,23 @@ export default {
console.warn('[ElementCalendar]start time and end time interval must not exceed two months'); console.warn('[ElementCalendar]start time and end time interval must not exceed two months');
return []; return [];
} }
//
data.push([ data.push([
start, start,
lastDay 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); startDay = this.toDate(startDay.getTime() + interval * oneDay);
if (startDay.getDate() < end.getDate()) { if (startDay.getDate() < end.getDate()) {
data.push([ data.push([

View File

@ -85,5 +85,24 @@ describe('Calendar', () => {
expect(firstRow.firstElementChild.innerText).to.be.equal('31'); expect(firstRow.firstElementChild.innerText).to.be.equal('31');
expect(firstRow.lastElementChild.innerText).to.be.equal('6'); expect(firstRow.lastElementChild.innerText).to.be.equal('6');
}); });
it('firstDayOfWeek in range mode', async() => {
vm = createVue({
template: `
<el-calendar v-model="value" :first-day-of-week="7" :range="['2019-02-03', '2019-03-23']"></el-calendar>
`,
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');
});
}); });