333 lines
8.5 KiB
JavaScript
333 lines
8.5 KiB
JavaScript
![]() |
import { createNamespace, addUnit } from '../../utils';
|
||
|
import { setScrollTop } from '../../utils/dom/scroll';
|
||
|
import { t, bem, compareDay, getPrevDay, getNextDay, formatMonthTitle } from '../utils';
|
||
|
import { getMonthEndDay } from '../../datetime-picker/utils';
|
||
|
|
||
|
var _createNamespace = createNamespace('calendar-month'),
|
||
|
createComponent = _createNamespace[0];
|
||
|
|
||
|
export default createComponent({
|
||
|
props: {
|
||
|
date: Date,
|
||
|
type: String,
|
||
|
color: String,
|
||
|
minDate: Date,
|
||
|
maxDate: Date,
|
||
|
showMark: Boolean,
|
||
|
rowHeight: [Number, String],
|
||
|
formatter: Function,
|
||
|
lazyRender: Boolean,
|
||
|
currentDate: [Date, Array],
|
||
|
allowSameDay: Boolean,
|
||
|
showSubtitle: Boolean,
|
||
|
showMonthTitle: Boolean,
|
||
|
firstDayOfWeek: Number
|
||
|
},
|
||
|
data: function data() {
|
||
|
return {
|
||
|
visible: false
|
||
|
};
|
||
|
},
|
||
|
computed: {
|
||
|
title: function title() {
|
||
|
return formatMonthTitle(this.date);
|
||
|
},
|
||
|
rowHeightWithUnit: function rowHeightWithUnit() {
|
||
|
return addUnit(this.rowHeight);
|
||
|
},
|
||
|
offset: function offset() {
|
||
|
var firstDayOfWeek = this.firstDayOfWeek;
|
||
|
var realDay = this.date.getDay();
|
||
|
|
||
|
if (!firstDayOfWeek) {
|
||
|
return realDay;
|
||
|
}
|
||
|
|
||
|
return (realDay + 7 - this.firstDayOfWeek) % 7;
|
||
|
},
|
||
|
totalDay: function totalDay() {
|
||
|
return getMonthEndDay(this.date.getFullYear(), this.date.getMonth() + 1);
|
||
|
},
|
||
|
shouldRender: function shouldRender() {
|
||
|
return this.visible || !this.lazyRender;
|
||
|
},
|
||
|
placeholders: function placeholders() {
|
||
|
var rows = [];
|
||
|
var count = Math.ceil((this.totalDay + this.offset) / 7);
|
||
|
|
||
|
for (var day = 1; day <= count; day++) {
|
||
|
rows.push({
|
||
|
type: 'placeholder'
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return rows;
|
||
|
},
|
||
|
days: function days() {
|
||
|
var days = [];
|
||
|
var year = this.date.getFullYear();
|
||
|
var month = this.date.getMonth();
|
||
|
|
||
|
for (var day = 1; day <= this.totalDay; day++) {
|
||
|
var date = new Date(year, month, day);
|
||
|
var type = this.getDayType(date);
|
||
|
var config = {
|
||
|
date: date,
|
||
|
type: type,
|
||
|
text: day,
|
||
|
bottomInfo: this.getBottomInfo(type)
|
||
|
};
|
||
|
|
||
|
if (this.formatter) {
|
||
|
config = this.formatter(config);
|
||
|
}
|
||
|
|
||
|
days.push(config);
|
||
|
}
|
||
|
|
||
|
return days;
|
||
|
}
|
||
|
},
|
||
|
methods: {
|
||
|
getHeight: function getHeight() {
|
||
|
var _this$$el;
|
||
|
|
||
|
return ((_this$$el = this.$el) == null ? void 0 : _this$$el.getBoundingClientRect().height) || 0;
|
||
|
},
|
||
|
scrollIntoView: function scrollIntoView(body) {
|
||
|
var _this$$refs = this.$refs,
|
||
|
days = _this$$refs.days,
|
||
|
month = _this$$refs.month;
|
||
|
var el = this.showSubtitle ? days : month;
|
||
|
var scrollTop = el.getBoundingClientRect().top - body.getBoundingClientRect().top + body.scrollTop;
|
||
|
setScrollTop(body, scrollTop);
|
||
|
},
|
||
|
getMultipleDayType: function getMultipleDayType(day) {
|
||
|
var _this = this;
|
||
|
|
||
|
var isSelected = function isSelected(date) {
|
||
|
return _this.currentDate.some(function (item) {
|
||
|
return compareDay(item, date) === 0;
|
||
|
});
|
||
|
};
|
||
|
|
||
|
if (isSelected(day)) {
|
||
|
var prevDay = getPrevDay(day);
|
||
|
var nextDay = getNextDay(day);
|
||
|
var prevSelected = isSelected(prevDay);
|
||
|
var nextSelected = isSelected(nextDay);
|
||
|
|
||
|
if (prevSelected && nextSelected) {
|
||
|
return 'multiple-middle';
|
||
|
}
|
||
|
|
||
|
if (prevSelected) {
|
||
|
return 'end';
|
||
|
}
|
||
|
|
||
|
return nextSelected ? 'start' : 'multiple-selected';
|
||
|
}
|
||
|
|
||
|
return '';
|
||
|
},
|
||
|
getRangeDayType: function getRangeDayType(day) {
|
||
|
var _this$currentDate = this.currentDate,
|
||
|
startDay = _this$currentDate[0],
|
||
|
endDay = _this$currentDate[1];
|
||
|
|
||
|
if (!startDay) {
|
||
|
return '';
|
||
|
}
|
||
|
|
||
|
var compareToStart = compareDay(day, startDay);
|
||
|
|
||
|
if (!endDay) {
|
||
|
return compareToStart === 0 ? 'start' : '';
|
||
|
}
|
||
|
|
||
|
var compareToEnd = compareDay(day, endDay);
|
||
|
|
||
|
if (compareToStart === 0 && compareToEnd === 0 && this.allowSameDay) {
|
||
|
return 'start-end';
|
||
|
}
|
||
|
|
||
|
if (compareToStart === 0) {
|
||
|
return 'start';
|
||
|
}
|
||
|
|
||
|
if (compareToEnd === 0) {
|
||
|
return 'end';
|
||
|
}
|
||
|
|
||
|
if (compareToStart > 0 && compareToEnd < 0) {
|
||
|
return 'middle';
|
||
|
}
|
||
|
},
|
||
|
getDayType: function getDayType(day) {
|
||
|
var type = this.type,
|
||
|
minDate = this.minDate,
|
||
|
maxDate = this.maxDate,
|
||
|
currentDate = this.currentDate;
|
||
|
|
||
|
if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) {
|
||
|
return 'disabled';
|
||
|
}
|
||
|
|
||
|
if (currentDate === null) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (type === 'single') {
|
||
|
return compareDay(day, currentDate) === 0 ? 'selected' : '';
|
||
|
}
|
||
|
|
||
|
if (type === 'multiple') {
|
||
|
return this.getMultipleDayType(day);
|
||
|
}
|
||
|
/* istanbul ignore else */
|
||
|
|
||
|
|
||
|
if (type === 'range') {
|
||
|
return this.getRangeDayType(day);
|
||
|
}
|
||
|
},
|
||
|
getBottomInfo: function getBottomInfo(type) {
|
||
|
if (this.type === 'range') {
|
||
|
if (type === 'start' || type === 'end') {
|
||
|
return t(type);
|
||
|
}
|
||
|
|
||
|
if (type === 'start-end') {
|
||
|
return t('startEnd');
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
getDayStyle: function getDayStyle(type, index) {
|
||
|
var style = {
|
||
|
height: this.rowHeightWithUnit
|
||
|
};
|
||
|
|
||
|
if (type === 'placeholder') {
|
||
|
style.width = '100%';
|
||
|
return style;
|
||
|
}
|
||
|
|
||
|
if (index === 0) {
|
||
|
style.marginLeft = 100 * this.offset / 7 + "%";
|
||
|
}
|
||
|
|
||
|
if (this.color) {
|
||
|
if (type === 'start' || type === 'end' || type === 'start-end' || type === 'multiple-selected' || type === 'multiple-middle') {
|
||
|
style.background = this.color;
|
||
|
} else if (type === 'middle') {
|
||
|
style.color = this.color;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return style;
|
||
|
},
|
||
|
genTitle: function genTitle() {
|
||
|
var h = this.$createElement;
|
||
|
|
||
|
if (this.showMonthTitle) {
|
||
|
return h("div", {
|
||
|
"class": bem('month-title')
|
||
|
}, [this.title]);
|
||
|
}
|
||
|
},
|
||
|
genMark: function genMark() {
|
||
|
var h = this.$createElement;
|
||
|
|
||
|
if (this.showMark && this.shouldRender) {
|
||
|
return h("div", {
|
||
|
"class": bem('month-mark')
|
||
|
}, [this.date.getMonth() + 1]);
|
||
|
}
|
||
|
},
|
||
|
genDays: function genDays() {
|
||
|
var h = this.$createElement;
|
||
|
var days = this.shouldRender ? this.days : this.placeholders;
|
||
|
return h("div", {
|
||
|
"ref": "days",
|
||
|
"attrs": {
|
||
|
"role": "grid"
|
||
|
},
|
||
|
"class": bem('days')
|
||
|
}, [this.genMark(), days.map(this.genDay)]);
|
||
|
},
|
||
|
genTopInfo: function genTopInfo(item) {
|
||
|
var h = this.$createElement;
|
||
|
var slot = this.$scopedSlots['top-info'];
|
||
|
|
||
|
if (item.topInfo || slot) {
|
||
|
return h("div", {
|
||
|
"class": bem('top-info')
|
||
|
}, [slot ? slot(item) : item.topInfo]);
|
||
|
}
|
||
|
},
|
||
|
genBottomInfo: function genBottomInfo(item) {
|
||
|
var h = this.$createElement;
|
||
|
var slot = this.$scopedSlots['bottom-info'];
|
||
|
|
||
|
if (item.bottomInfo || slot) {
|
||
|
return h("div", {
|
||
|
"class": bem('bottom-info')
|
||
|
}, [slot ? slot(item) : item.bottomInfo]);
|
||
|
}
|
||
|
},
|
||
|
genDay: function genDay(item, index) {
|
||
|
var _this2 = this;
|
||
|
|
||
|
var h = this.$createElement;
|
||
|
var type = item.type;
|
||
|
var style = this.getDayStyle(type, index);
|
||
|
var disabled = type === 'disabled';
|
||
|
|
||
|
var onClick = function onClick() {
|
||
|
if (!disabled) {
|
||
|
_this2.$emit('click', item);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if (type === 'selected') {
|
||
|
return h("div", {
|
||
|
"attrs": {
|
||
|
"role": "gridcell",
|
||
|
"tabindex": -1
|
||
|
},
|
||
|
"style": style,
|
||
|
"class": [bem('day'), item.className],
|
||
|
"on": {
|
||
|
"click": onClick
|
||
|
}
|
||
|
}, [h("div", {
|
||
|
"class": bem('selected-day'),
|
||
|
"style": {
|
||
|
width: this.rowHeightWithUnit,
|
||
|
height: this.rowHeightWithUnit,
|
||
|
background: this.color
|
||
|
}
|
||
|
}, [this.genTopInfo(item), item.text, this.genBottomInfo(item)])]);
|
||
|
}
|
||
|
|
||
|
return h("div", {
|
||
|
"attrs": {
|
||
|
"role": "gridcell",
|
||
|
"tabindex": disabled ? null : -1
|
||
|
},
|
||
|
"style": style,
|
||
|
"class": [bem('day', type), item.className],
|
||
|
"on": {
|
||
|
"click": onClick
|
||
|
}
|
||
|
}, [this.genTopInfo(item), item.text, this.genBottomInfo(item)]);
|
||
|
}
|
||
|
},
|
||
|
render: function render() {
|
||
|
var h = arguments[0];
|
||
|
return h("div", {
|
||
|
"class": bem('month'),
|
||
|
"ref": "month"
|
||
|
}, [this.genTitle(), this.genDays()]);
|
||
|
}
|
||
|
});
|