123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- <script>
- import fecha from 'element-ui/src/utils/date';
- import { range as rangeArr, getFirstDayOfMonth, getPrevMonthLastDays, getMonthDays, getI18nSettings, validateRangeInOneMonth } from 'element-ui/src/utils/date-util';
- export default {
- props: {
- selectedDay: String, // formated date yyyy-MM-dd
- range: {
- type: Array,
- validator(val) {
- if (!(val && val.length)) return true;
- const [start, end] = val;
- return validateRangeInOneMonth(start, end);
- }
- },
- date: Date,
- hideHeader: Boolean,
- firstDayOfWeek: Number
- },
- inject: ['elCalendar'],
- methods: {
- toNestedArr(days) {
- return rangeArr(days.length / 7).map((_, index) => {
- const start = index * 7;
- return days.slice(start, start + 7);
- });
- },
- getFormateDate(day, type) {
- if (!day || ['prev', 'current', 'next'].indexOf(type) === -1) {
- throw new Error('invalid day or type');
- }
- let prefix = this.curMonthDatePrefix;
- if (type === 'prev') {
- prefix = this.prevMonthDatePrefix;
- } else if (type === 'next') {
- prefix = this.nextMonthDatePrefix;
- }
- day = `00${day}`.slice(-2);
- return `${prefix}-${day}`;
- },
- getCellClass({ text, type}) {
- const classes = [type];
- if (type === 'current') {
- const date = this.getFormateDate(text, type);
- if (date === this.selectedDay) {
- classes.push('is-selected');
- }
- if (date === this.formatedToday) {
- classes.push('is-today');
- }
- }
- return classes;
- },
- pickDay({ text, type }) {
- const date = this.getFormateDate(text, type);
- this.$emit('pick', date);
- },
- cellRenderProxy({ text, type }) {
- let render = this.elCalendar.$scopedSlots.dateCell;
- if (!render) return <span>{ text }</span>;
- const day = this.getFormateDate(text, type);
- const date = new Date(day);
- const data = {
- isSelected: this.selectedDay === day,
- type: `${type}-month`,
- day
- };
- return render({ date, data });
- }
- },
- computed: {
- WEEK_DAYS() {
- return getI18nSettings().dayNames;
- },
- prevMonthDatePrefix() {
- const temp = new Date(this.date.getTime());
- temp.setDate(0);
- return fecha.format(temp, 'yyyy-MM');
- },
- curMonthDatePrefix() {
- return fecha.format(this.date, 'yyyy-MM');
- },
- nextMonthDatePrefix() {
- const temp = new Date(this.date.getFullYear(), this.date.getMonth() + 1, 1);
- return fecha.format(temp, 'yyyy-MM');
- },
- formatedToday() {
- return this.elCalendar.formatedToday;
- },
- isInRange() {
- return this.range && this.range.length;
- },
- rows() {
- let days = [];
- // if range exists, should render days in range.
- if (this.isInRange) {
- const [start, end] = this.range;
- const currentMonthRange = rangeArr(end.getDate() - start.getDate() + 1).map((_, index) => ({
- text: start.getDate() + index,
- type: 'current'
- }));
- let remaining = currentMonthRange.length % 7;
- remaining = remaining === 0 ? 0 : 7 - remaining;
- const nextMonthRange = rangeArr(remaining).map((_, index) => ({
- text: index + 1,
- type: 'next'
- }));
- days = currentMonthRange.concat(nextMonthRange);
- } else {
- const date = this.date;
- let firstDay = getFirstDayOfMonth(date);
- firstDay = firstDay === 0 ? 7 : firstDay;
- const firstDayOfWeek = typeof this.firstDayOfWeek === 'number' ? this.firstDayOfWeek : 1;
- const offset = (7 + firstDay - firstDayOfWeek) % 7;
- const prevMonthDays = getPrevMonthLastDays(date, offset).map(day => ({
- text: day,
- type: 'prev'
- }));
- const currentMonthDays = getMonthDays(date).map(day => ({
- text: day,
- type: 'current'
- }));
- days = [...prevMonthDays, ...currentMonthDays];
- const nextMonthDays = rangeArr(42 - days.length).map((_, index) => ({
- text: index + 1,
- type: 'next'
- }));
- days = days.concat(nextMonthDays);
- }
- return this.toNestedArr(days);
- },
- weekDays() {
- const start = this.firstDayOfWeek;
- const { WEEK_DAYS } = this;
- if (typeof start !== 'number' || start === 0) {
- return WEEK_DAYS.slice();
- } else {
- return WEEK_DAYS.slice(start).concat(WEEK_DAYS.slice(0, start));
- }
- }
- },
- render() {
- const thead = this.hideHeader ? null : (<thead>
- {
- this.weekDays.map(day => <th key={day}>{ day }</th>)
- }
- </thead>);
- return (
- <table
- class={{
- 'el-calendar-table': true,
- 'is-range': this.isInRange
- }}
- cellspacing="0"
- cellpadding="0">
- {
- thead
- }
- <tbody>
- {
- this.rows.map((row, index) => <tr
- class={{
- 'el-calendar-table__row': true,
- 'el-calendar-table__row--hide-border': index === 0 && this.hideHeader
- }}
- key={index}>
- {
- row.map((cell, key) => <td key={key}
- class={ this.getCellClass(cell) }
- onClick={this.pickDay.bind(this, cell)}>
- <div class="el-calendar-day">
- {
- this.cellRenderProxy(cell)
- }
- </div>
- </td>)
- }
- </tr>)
- }
- </tbody>
- </table>);
- }
- };
- </script>
|