shop-applet/components/mpvue-calendar/mpvue-calendar.vue

1163 lines
44 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="mpvue-calendar" ref="calendar">
<div class="calendar-tools" v-if="!isMonthRange">
<div class="calendar-prev" @click="prev">
<image :src="arrowLeft" v-if="!!arrowLeft">
<i class="iconfont icon-arrow-left" v-else></i>
</div>
<div class="calendar-next" @click="next">
<image :src="arrowRight" v-if="!!arrowRight">
<i class="iconfont icon-arrow-right" v-else></i>
</div>
<div class="calendar-info" @click.stop="changeYear">
<div class="mc-month">
<div :class="['mc-month-inner', oversliding ? '' : 'month-transition']" :style="{'top': monthPosition + unit}" v-if="isIos">
<span v-for="(m, i) in monthsLoop" :key="i" >{{m}}</span>
</div>
<div class="mc-month-text" v-else>{{monthText}}</div>
</div>
<div class="mc-year">{{year}}</div>
</div>
</div>
<table cellpadding="5">
<div class="mc-head" :class="['mc-head', {'mc-month-range-mode-head': isMonthRange}]">
<div class="mc-head-box">
<div v-for="(week, index) in weeks" :key="index" class="mc-week">{{week}}</div>
</div>
</div>
<div :class="['mc-body', {'mc-range-mode': range, 'week-switch': weekSwitch && !isMonthRange, 'month-range-mode': isMonthRange}]" v-for="(days, index) in monthRangeDays" :key='index'>
<div class="month-rang-head" v-if="isMonthRange">{{rangeOfMonths[index][2]}}</div>
<tr v-for="(day,k1) in days" :key="k1" :class="{'gregorianStyle': !lunar}">
<td v-for="(child,k2) in day" :key="k2" :class="[{'selected': child.selected, 'mc-today-element': child.isToday, 'disabled': child.disabled, 'mc-range-select-one': rangeBgHide && child.selected, 'lunarStyle': lunar, 'mc-range-row-first': k2 === 0 && child.selected, 'month-last-date': child.lastDay, 'month-first-date': 1 === child.day, 'mc-range-row-last': k2 === 6 && child.selected, 'mc-last-month': child.lastMonth, 'mc-next-month': child.nextMonth}, child.className, child.rangeClassName]" @click="select(k1, k2, child, $event, index)" class="mc-day" :style="itemStyle">
<span v-if="showToday.show && child.isToday" class="mc-today calendar-date">{{showToday.text}}</span>
<span :class="[{'mc-date-red': k2 === (monFirst ? 5 : 0) || k2 === 6}, 'calendar-date']" v-else>{{child.day}}</span>
<div class="slot-element" v-if="!!child.content">{{child.content}}</div>
<div class="mc-text remark-text" v-if="child.eventName && !clean">{{child.eventName}}</div>
<div class="mc-dot" v-if="child.eventName && clean"></div>
<div class="mc-text" :class="{'isLunarFestival': child.isAlmanac || child.isLunarFestival,'isGregorianFestival': child.isGregorianFestival,'isTerm': child.isTerm}" v-if="lunar && (!child.eventName || clean)">{{child.almanac || child.lunar}}</div>
<div class="mc-range-bg" v-if="range && child.selected"/>
</td>
</tr>
</div>
</table>
<div class="mpvue-calendar-change" :class="{'show': yearsShow}">
<div class="calendar-years" v-if="!weekSwitch">
<span v-for="y in years" :key="y" @click.stop="selectYear(y)" :class="{'active': y === year}">{{y}}</span>
</div>
<div :class="['calendar-months', {'calendar-week-switch-months': weekSwitch}]">
<span v-for="(m, i) in months" :key="m" @click.stop="changeMonth(i)" :class="{'active': i === month}">{{m}}</span>
</div>
</div>
</div>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import calendar from './calendarinit.js';
import './icon.css';
const isBrowser = !!window;
const now = new Date();
const todayString = [now.getFullYear(), now.getMonth() + 1, now.getDate()].join('-');
export default {
props: {
multi: {
type: Boolean,
default: false
},
arrowLeft: {
type: String,
default: ''
},
arrowRight: {
type: String,
default: ''
},
clean: {
type: Boolean,
default: false
},
now: {
type: [String, Boolean],
default: true
},
range:{
type: Boolean,
default: false
},
completion:{
type: Boolean,
default: false
},
value: {
type: Array,
default: function(){
return []
}
},
begin: {
type: Array,
default: function(){
return []
}
},
end: {
type: Array,
default: function(){
return []
}
},
zero:{
type: Boolean,
default: false
},
disabled:{
type: Array,
default: function(){
return []
}
},
almanacs:{
type: Object,
default: function(){
return {}
}
},
tileContent:{
type: Array,
default: function(){
return []
}
},
lunar: {
type: Boolean,
default: false
},
monFirst: {
type: Boolean,
default: false
},
weeks: {
type: Array,
default:function(){
return this.monFirst ? ['一', '二', '三', '四', '五', '六', '日'] : ['日', '一', '二', '三', '四', '五', '六']
}
},
months:{
type: Array,
default:function(){
return ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月']
}
},
events: {
type: Object,
default: function(){
return {}
}
},
weekSwitch: {
type: Boolean,
default: false
},
monthRange: {
type: Array,
default: function(){
return []
}
},
responsive: {
type: Boolean,
default: false
},
rangeMonthFormat: {
type: String,
default: ''
}
},
data() {
return {
years:[],
yearsShow:false,
year: 0,
month: 0,
monthPosition: 0,
day: 0,
days: [],
multiDays:[],
today: [],
handleMultiDay: [],
firstRender: true,
isIos: true,
showToday: {},
monthText: '',
festival:{
lunar:{
"1-1":"春节",
"1-15":"元宵节",
"2-2":"龙头节",
"5-5":"端午节",
"7-7":"七夕节",
"7-15":"中元节",
"8-15":"中秋节",
"9-9":"重阳节",
"10-1":"寒衣节",
"10-15":"下元节",
"12-8":"腊八节",
"12-23":"小年",
},
gregorian:{
"1-1":"元旦",
"2-14":"情人节",
"3-8":"妇女节",
"3-12":"植树节",
"5-1":"劳动节",
"5-4":"青年节",
"6-1":"儿童节",
"7-1":"建党节",
"8-1":"建军节",
"9-10":"教师节",
"10-1":"国庆节",
"12-24":"平安夜",
"12-25":"圣诞节",
},
},
rangeBegin: [],
rangeEnd: [],
multiDaysData: [],
monthsLoop: [],
itemWidth: 50,
unit: isBrowser ? 'px' : 'rpx',
positionH: isBrowser ? -24 : -40,
monthIndex: 0,
oversliding: false,
rangeBgHide: false,
monthRangeDays: [],
rangeOfMonths: [],
monthDays: [],
weekIndex: 0,
startWeekIndex: 0,
positionWeek: true,
isMonthRange: false,
}
},
computed: {
itemStyle() {
return {width: this.itemWidth + 'px', height: this.itemWidth + 'px', fontSize: this.itemWidth / 4 + 'px', lineHeight: this.lunar ? (this.itemWidth / 1.5 + 'px') : (this.itemWidth + 'px')}
}
},
watch:{
events() {
if (this.isRendeRangeMode()) return;
this.render(this.year, this.month, '_WATCHRENDER_', 'events');
},
disabled() {
if (this.isRendeRangeMode()) return;
this.render(this.year, this.month, '_WATCHRENDER_', 'disabled');
},
value() {
if (this.isRendeRangeMode('_WATCHRENDERVALUE_')) return;
const value = this.value;
let year = value[0], month = value[1] - 1;
if (this.multi) {
year = value[value.length - 1][0];
month = value[value.length - 1][1] - 1;
} else if (this.range) {
if (this.isUserSelect) {
year = this.year;
month = this.month;
this.isUserSelect = false;
} else {
year = value[0][0];
month = value[0][1] - 1;
const day = value[0][2];
return this.render(year, month, '_WATCHRENDERVALUE_', [year, month, day]);
}
}
this.render(year, month, '_WATCHRENDERVALUE_');
},
tileContent() {
if (this.isRendeRangeMode()) return;
this.render(this.year, this.month, '_WATCHRENDER_', 'tileContent');
},
almanacs() {
if (this.isRendeRangeMode()) return;
this.render(this.year, this.month, '_WATCHRENDER_', 'almanacs');
},
monthRange() {
if (this.isRendeRangeMode()) return;
this.render(this.year, this.month, '_WATCHRENDER_', 'almanacs');
},
responsive() {
if (this.responsive) this.addResponsiveListener();
}
},
created() {
this.isMonthRange = !!this.monthRange.length;
const loopArray = this.months.concat();
loopArray.unshift(this.months[this.months.length - 1]);
loopArray.push(this.months[0]);
this.monthsLoop = loopArray;
this.monthsLoopCopy = this.monthsLoop.concat();
},
mounted() {
const self = this;
this.resize();
if (!isBrowser) {
wx.getSystemInfo({
success: function(res) {
self.isIos = (res.system.split(' ') || [])[0] === 'iOS';
}
});
} else if (this.responsive) {
this.addResponsiveListener();
}
this.oversliding = true;
this.initRender = true;
this.init();
},
beforeDestroy() {
if (isBrowser) {
window.removeEventListener('resize', this.resize)
}
},
methods: {
init() {
let now = new Date();
this.year = now.getFullYear();
this.month = now.getMonth();
this.day = now.getDate();
this.monthIndex = this.month + 1;
if (this.value.length || this.multi) {
if (this.range) {
this.year = Number(this.value[0][0]);
this.month = this.value[0][1] - 1;
this.day = Number(this.value[0][2]);
const yearEnd = Number(this.value[1][0]);
const monthEnd = this.value[1][1] - 1;
const dayEnd = this.value[1][2];
this.rangeBegin = [this.year, this.month, this.day];
this.rangeEnd = [yearEnd, monthEnd, dayEnd];
} else if (this.multi) {
this.multiDays = this.value;
const handleMultiDay = this.handleMultiDay;
if (this.firstRender) {
this.firstRender = false;
const thatYear = (this.value[0] || [])[0];
const thatMonth = (this.value[0] || [])[1];
if (isFinite(thatYear) && isFinite(thatMonth)) {
this.month = parseInt(thatMonth) - 1;
this.year = parseInt(thatYear);
}
} else if (this.handleMultiDay.length) {
this.month = parseInt(handleMultiDay[handleMultiDay.length - 1][1]) - 1;
this.year = parseInt(handleMultiDay[handleMultiDay.length - 1][0]);
this.handleMultiDay = [];
} else {
this.month = parseInt(this.value[this.value.length - 1][1]) - 1;
this.year = parseInt(this.value[this.value.length - 1][0]);
}
this.day = parseInt((this.value[0] || [])[2]);
} else {
this.year = parseInt(this.value[0]);
this.month = parseInt(this.value[1]) - 1;
this.day = parseInt(this.value[2]);
}
}
this.updateHeadMonth();
if (this.isRendeRangeMode()) return;
this.render(this.year, this.month);
},
renderOption(year, month, i, playload) {
const weekSwitch = this.monthRange.length ? false : this.weekSwitch;
const seletSplit = this.value;
const isMonthModeCurrentMonth = !weekSwitch && !playload;
const disabledFilter = (disabled) => {
return disabled.find(v => {
const dayArr = v.split('-');
return year === Number(dayArr[0]) && month === (dayArr[1] - 1) && i === Number(dayArr[2]);
});
};
if (this.range) {
const lastDay = new Date(year, month + 1, 0).getDate() === i ? {lastDay: true} : null;
const options = Object.assign(
{day: i},
this.getLunarInfo(year, month + 1, i),
this.getEvents(year, month + 1, i),
lastDay
);
const {date, day} = options;
const copyRangeBegin = this.rangeBegin.concat();
const copyRangeEnd = this.rangeEnd.concat();
copyRangeBegin[1] = copyRangeBegin[1] + 1;
copyRangeEnd[1] = copyRangeEnd[1] + 1;
if (weekSwitch || isMonthModeCurrentMonth) {
(copyRangeEnd.join('-') === date) && (options.rangeClassName = 'mc-range-end');
(copyRangeBegin.join('-') === date) && (options.rangeClassName = 'mc-range-begin');
}
if (year === copyRangeEnd[0] && (month + 1) === copyRangeEnd[1] && day === (copyRangeEnd[2] - 1)) {
options.rangeClassName = options.rangeClassName ? ['mc-range-begin', 'mc-range-second-to-last'] : 'mc-range-second-to-last';
}
if (this.rangeBegin.length) {
const beginTime = +new Date(this.rangeBegin[0], this.rangeBegin[1], this.rangeBegin[2]);
const endTime = +new Date(this.rangeEnd[0], this.rangeEnd[1], this.rangeEnd[2]);
const stepTime = +new Date(year, month, i);
if (beginTime <= stepTime && endTime >= stepTime) {
options.selected = true;
}
}
if (this.begin.length) {
const beginTime = +new Date(parseInt(this.begin[0]), parseInt(this.begin[1]) - 1, parseInt(this.begin[2]));
if (beginTime > +new Date(year, month, i)) {
options.disabled = true;
}
}
if (this.end.length) {
let endTime = Number(new Date(parseInt(this.end[0]), parseInt(this.end[1]) - 1, parseInt(this.end[2])));
if (endTime < Number(new Date(year, month, i))) {
options.disabled = true;
}
}
if (playload && !weekSwitch) {
options.disabled = true;
} else if (this.disabled.length && disabledFilter(this.disabled)) {
options.disabled = true;
}
const monthFirstDay = year + '-' + (month + 1) + '-' + 1;
const monthLastDay = year + '-' + (month + 1) + '-' + new Date(year, month + 1, 0).getDate();
(monthFirstDay === date && options.selected && !options.rangeClassName) && (options.rangeClassName = 'mc-range-month-first');
(monthLastDay === date && options.selected && !options.rangeClassName) && (options.rangeClassName = 'mc-range-month-last');
this.isCurrentMonthToday(options) && (options.isToday = true);
(!weekSwitch && playload) && (options.selected = false);
return options;
} else if(this.multi) {
let options;
if (this.value.find(v => year === v[0] && month === v[1]-1 && i === v[2])){
options = Object.assign(
{day: i, selected: true},
this.getLunarInfo(year, month + 1, i),
this.getEvents(year, month + 1, i)
);
} else {
options = Object.assign(
{day: i, selected: false},
this.getLunarInfo(year, month + 1, i),
this.getEvents(year, month + 1, i)
);
if (this.begin.length) {
const beginTime = +new Date(parseInt(this.begin[0]), parseInt(this.begin[1]) - 1, parseInt(this.begin[2]));
if (beginTime > +(new Date(year, month, i))) {
options.disabled = true;
}
}
if (this.end.length){
const endTime = +new Date(parseInt(this.end[0]), parseInt(this.end[1]) - 1, parseInt(this.end[2]));
if (endTime < +(new Date(year, month, i))) {
options.disabled = true;
}
}
if (playload && !weekSwitch) {
options.disabled = true;
} else if (this.disabled.length && disabledFilter(this.disabled)) {
options.disabled = true;
}
}
if (options.selected && this.multiDaysData.length !== this.value.length) {
this.multiDaysData.push(options);
}
this.isCurrentMonthToday(options) && (options.isToday = true);
(!weekSwitch && playload) && (options.selected = false);
return options;
} else {
const options = {};
const monthHuman = month + 1;
if (seletSplit[0] === year && seletSplit[1] === monthHuman && seletSplit[2] === i) {
Object.assign(
options,
{day: i, selected: true},
this.getLunarInfo(year, monthHuman, i),
this.getEvents(year, monthHuman, i)
);
} else {
Object.assign(
options,
{day: i, selected: false},
this.getLunarInfo(year, monthHuman, i),
this.getEvents(year, monthHuman, i)
);
if (this.begin.length) {
const beginTime = +new Date(parseInt(this.begin[0]), parseInt(this.begin[1]) - 1, parseInt(this.begin[2]));
if (beginTime > Number(new Date(year, month, i))) {
options.disabled = true;
}
}
if (this.end.length){
const endTime = +new Date(parseInt(this.end[0]), parseInt(this.end[1]) - 1, parseInt(this.end[2]));
if (endTime < +(new Date(year, month, i))) {
options.disabled = true;
}
}
if (playload && !weekSwitch) {
options.disabled = true;
} else if (this.disabled.length && disabledFilter(this.disabled)) {
options.disabled = true;
}
}
this.isCurrentMonthToday(options) && (options.isToday = true);
(!weekSwitch && playload) && (options.selected = false);
return options;
}
},
isCurrentMonthToday(options) {
const isToday = todayString === options.date;
if (!isToday) return false;
return this.weekSwitch ? isToday : (Number(todayString.split('-')[1]) === this.month + 1);
},
watchRender(type) {
const weekSwitch = this.weekSwitch;
const daysDeepCopy = JSON.parse(JSON.stringify(this.monthDays));
if (type === 'events') {
const events = this.events || {};
Object.keys(events).forEach(value => {
daysDeepCopy.some(v => v.some(vv => {
if (vv.date === value) {
vv.eventName = events[value];
return true;
}
}))
});
this.monthDays = daysDeepCopy;
} else if (type === 'disabled') {
const disabled = this.disabled || [];
disabled.forEach(value => {
daysDeepCopy.some(v => v.some(vv => {
if (vv.date === value) {
vv.disabled = true;
return true;
}
}))
});
} else if (type === 'almanacs') {
const almanacs = this.almanacs || {};
Object.keys(almanacs).forEach(value => {
daysDeepCopy.some(v => v.some(vv => {
if (vv.date.slice(5, 20) === value) {
vv.lunar = almanacs[value];
return true;
}
}))
});
} else if (type === 'tileContent') {
const tileContent = this.tileContent || [];
tileContent.forEach(value => {
daysDeepCopy.some(v => v.some(vv => {
if (vv.date === value.date) {
vv.className = value.className;
vv.content = value.content;
return true;
}
}))
});
}
if (weekSwitch) {
this.monthDays = daysDeepCopy;
this.days = [daysDeepCopy[this.weekIndex]];
this.monthRangeDays = [this.days];
} else {
this.days = daysDeepCopy;
this.monthRangeDays = [this.days];
}
},
render(y, m, renderer, payload) {
const weekSwitch = this.weekSwitch;
const isCustomRender = renderer === 'CUSTOMRENDER';
const isWatchRenderValue = renderer === '_WATCHRENDERVALUE_';
this.year = y;
this.month = m;
if (renderer === '_WATCHRENDER_') return this.watchRender(payload);
if (this.range && isWatchRenderValue) {
if (!Array.isArray((this.value || [])[0])) {
this.rangeBegin = [];
this.rangeEnd = [];
} else {
this.rangeBegin = [this.value[0][0], this.value[0][1] - 1, this.value[0][2]];
this.rangeEnd = [this.value[1][0], this.value[1][1] - 1, this.value[1][2]];
}
}
if (isWatchRenderValue && weekSwitch) {
this.positionWeek = true;
}
if (isCustomRender) {
this.year = y;
this.month = m;
this.positionWeek = true;
if (weekSwitch && !payload) {
this.startWeekIndex = 0;
this.weekIndex = 0;
}
this.updateHeadMonth();
}
let firstDayOfMonth = new Date(y, m, 1).getDay();
const lastDateOfMonth = new Date(y, m + 1, 0).getDate();
let lastDayOfLastMonth = new Date(y, m, 0).getDate();
this.year = y;
let i = 1, line = 0, temp = [], nextMonthPushDays = 1;
for (i; i <= lastDateOfMonth; i++) {
let day = new Date(y, m, i).getDay();
let k;
if (day === 0) {
temp[line] = [];
} else if (i === 1) {
temp[line] = [];
k = lastDayOfLastMonth - firstDayOfMonth + 1;
for (let j = 0; j < firstDayOfMonth; j++) { //generate prev month surplus option
temp[line].push(Object.assign(
this.renderOption(this.computedPrevYear(y, m), this.computedPrevMonth(false, m), k, 'prevMonth'),
{lastMonth: true}
));
k++;
}
}
temp[line].push(this.renderOption(y, m, i)); //generate current month option
if (day === 6 && i < lastDateOfMonth) {
line++;
} else if (i === lastDateOfMonth) {
let k = 1;
const lastDateOfMonthLength = this.monFirst ? 7 : 6;
for (let d = day; d < lastDateOfMonthLength; d++) { //generate next month surplus option
temp[line].push(Object.assign(
this.renderOption(this.computedNextYear(y, m), this.computedNextMonth(false, m), k, 'nextMonth'),
{nextMonth: true}
));
k++;
}
nextMonthPushDays = k;
}
}
const completion = this.completion;
if (this.monFirst) {
if (!firstDayOfMonth) {
let lastMonthDay = lastDayOfLastMonth;
const LastMonthItems = [];
for (let i = 1; i <= 7; i++) {
LastMonthItems.unshift(Object.assign(
this.renderOption(this.computedPrevYear(y, m), this.computedPrevMonth(false, m), lastMonthDay, 'prevMonth'),
{lastMonth: true}
));
lastMonthDay --;
}
temp.unshift(LastMonthItems);
}
temp.forEach((item, index) => {
if (!index) {
return item.splice(0, 1);
};
temp[index-1].length < 7 && temp[index-1].push(item.splice(0, 1)[0]);
});
if (this.isMonthRange && temp[temp.length - 1][0].nextMonth) {
temp.splice(temp.length - 1, 1); //if the first day of last line is nextMonth, delete this line
}
if (!completion && !weekSwitch) {
const lastIndex = temp.length - 1;
const secondToLastIndex = lastIndex - 1;
const differentMonth = temp[lastIndex][0].date.split('-')[1] !== temp[secondToLastIndex][6].date.split('-')[1];
differentMonth && temp.splice(lastIndex, 1);
}
}
if (completion && !weekSwitch && temp.length <= 5 && nextMonthPushDays > 0) {
for (let i = temp.length; i<=5; i++) {
temp[i] = [];
let start = nextMonthPushDays + (i - line -1) * 7;
for (let d = start; d <= start + 6; d++) {
temp[i].push(Object.assign(
{day: d, disabled: true, nextMonth: true},
this.getLunarInfo(this.computedNextYear(), this.computedNextMonth(true), d),
this.getEvents(this.computedNextYear(), this.computedNextMonth(true), d)
));
}
}
}
if (this.tileContent.length) {
temp.forEach((item, index) => {
item.forEach((v, i) => {
const contents = this.tileContent.find(val => val.date === v.date);
if (contents) {
const {className, content} = contents || {};
v.className = className;
v.content = content;
}
});
});
}
if (weekSwitch) {
const tempLength = temp.length;
const lastLineMonth = temp[tempLength - 1][0].date.split('-')[1]; // last line month
const secondLastMonth = temp[tempLength - 2][0].date.split('-')[1]; // second-to-last line month
lastLineMonth !== secondLastMonth && temp.splice(tempLength - 1, 1);
}
this.monthDays = temp;
if (weekSwitch && !this.isMonthRange) {
if (this.positionWeek) {
let payloadDay = '';
let searchIndex = true;
if (Array.isArray(payload)) { //range
payloadDay = [payload[0], payload[1] + 1, payload[2]].join('-');
} else if (this.multi || isWatchRenderValue) {
if (this.thisTimeSelect) {
payloadDay = this.thisTimeSelect;
} else {
payloadDay = this.multi ? this.value[this.value.length - 1].join('-') : this.value.join('-') ;
}
}
if (payload === 'SETTODAY') {
payloadDay = todayString;
} else if (isCustomRender) {
if (typeof payload === 'string') {
payloadDay = [y, Number(m) + 1, payload].join('-');
searchIndex = true;
} else if (typeof payload === 'number') {
const setIndex = payload > temp.length ? temp.length - 1 : payload;
this.startWeekIndex = setIndex;
this.weekIndex = setIndex;
this.positionWeek = false;
searchIndex = false;
}
}
const positionDay = payloadDay || todayString;
if (searchIndex) {
temp.some((v, i) => {
const isWeekNow = v.find(vv => vv.date === positionDay);
if (isWeekNow) {
this.startWeekIndex = i;
this.weekIndex = i;
return true;
}
});
}
this.positionWeek = false;
}
this.days = [temp[this.startWeekIndex]];
if (this.initRender) {
this.setMonthRangeofWeekSwitch();
this.initRender = false;
}
} else {
this.days = temp;
}
const todayText = '今';
if (typeof this.now === 'boolean' && !this.now) {
this.showToday = {show: false};
} else if (typeof this.now === 'string') {
this.showToday = {
show: true,
text: this.now || todayText
};
} else {
this.showToday = {
show: true,
text: todayText
};
}
this.monthRangeDays = [this.days];
isWatchRenderValue && this.updateHeadMonth();
return this.days;
},
rendeRange(renderer) {
const range = [];
const self = this;
const monthRange = this.monthRange;
function formatDateText(fYear, fMonth) {
const reg = /([y]+)(.*?)([M]+)(.*?)$/i;
const rangeMonthFormat = self.rangeMonthFormat || 'yyyy-MM';
reg.exec(rangeMonthFormat);
return String(fYear).substring(4 - RegExp.$1.length) + RegExp.$2 + String(fMonth).substring(2 - RegExp.$3.length) + RegExp.$4;
}
if (monthRange[0] === monthRange[1]) {
const [y, m] = monthRange[0].split('-');
range.push([Number(y), Number(m), formatDateText(y, m)])
} else {
const monthRangeOfStart = monthRange[0].split('-');
const monthRangeOfEnd = monthRange[1].split('-');
let startYear = +monthRangeOfStart[0];
let startMonth = +monthRangeOfStart[1];
let endYear = +monthRangeOfEnd[0];
let endtMonth = +monthRangeOfEnd[1] > 12 ? 12 : +monthRangeOfEnd[1];
while (startYear < endYear || startMonth <= endtMonth) {
range.push([startYear, startMonth, formatDateText(startYear, startMonth)]);
if (startMonth === 12 && startYear !== endYear) {
startYear++;
startMonth = 0;
}
startMonth++;
}
}
this.rangeOfMonths = range;
const monthsRange = range.map(item => {
const [yearParam, monthParam] = item;
return this.render(yearParam, monthParam - 1, renderer);
});
this.monthRangeDays = monthsRange;
},
isRendeRangeMode(renderer) {
this.isMonthRange = !!this.monthRange.length;
if (this.isMonthRange) {
this.rendeRange(renderer);
return true;
}
},
renderer(y, m, w) {
const renderY = y || this.year;
const renderM = typeof parseInt(m) === 'number' ? (m - 1) : this.month;
this.initRender = true;
this.render(renderY, renderM, 'CUSTOMRENDER', w);
!this.weekSwitch && (this.monthsLoop = this.monthsLoopCopy.concat());
},
computedPrevYear(year, month) {
let value = year;
if((month - 1) < 0){
value--;
}
return value;
},
computedPrevMonth(isString, month) {
let value = month;
if((month - 1) < 0){
value = 11;
} else {
value--;
}
if(isString) {
return value + 1;
}
return value;
},
computedNextYear(year, month) {
let value = year;
if((month + 1) > 11){
value++;
}
return value;
},
computedNextMonth(isString, month) {
let value = month;
if((month + 1) > 11){
value = 0;
} else {
value++;
}
if(isString) {
return value + 1;
}
return value;
},
getLunarInfo(y, m, d) {
let lunarInfo = calendar.solar2lunar(y, m, d);
let yearEve = '';
if (lunarInfo.lMonth === 12 && lunarInfo.lDay === calendar.monthDays(lunarInfo.lYear, 12)) {
yearEve = '除夕';
}
let lunarValue = lunarInfo.IDayCn;
let Term = lunarInfo.Term;
let isLunarFestival = false;
let isGregorianFestival = false;
if(this.festival.lunar[lunarInfo.lMonth + "-" + lunarInfo.lDay]) {
lunarValue = this.festival.lunar[lunarInfo.lMonth + "-" + lunarInfo.lDay];
isLunarFestival = true;
} else if(this.festival.gregorian[m + "-" + d]) {
lunarValue = this.festival.gregorian[m + "-" + d];
isGregorianFestival = true;
}
const lunarInfoObj = {
date: `${y}-${m}-${d}`,
lunar: yearEve || Term || lunarValue,
isLunarFestival: isLunarFestival,
isGregorianFestival: isGregorianFestival,
isTerm: !!yearEve || lunarInfo.isTerm
};
if (Object.keys(this.almanacs).length) {
Object.assign(lunarInfoObj, {
almanac: this.almanacs[m + "-" + d] || '',
isAlmanac: !!this.almanacs[m + "-" + d]
});
}
return lunarInfoObj;
},
getEvents(y, m, d){
if(Object.keys(this.events).length == 0) return false;
let eventName = this.events[y + "-" + m + "-" + d];
let data = {};
if(eventName!=undefined){
data.eventName = eventName;
}
return data;
},
prev(e) {
e && e.stopPropagation();
if (this.isMonthRange) return;
const weekSwitch = this.weekSwitch;
const changeMonth = (changed) => {
if (this.monthIndex === 1) {
this.oversliding = false;
this.month = 11;
this.year = parseInt(this.year) - 1;
this.monthIndex = this.monthIndex - 1;
} else if (this.monthIndex === 0) {
this.oversliding = true;
this.monthIndex = 12;
setTimeout(() => this.prev(e), 50);
return this.updateHeadMonth('custom');
} else if (this.monthIndex === 13) {
this.month = 11;
this.year = parseInt(this.year) - 1;
this.monthIndex = this.monthIndex - 1;
} else {
this.oversliding = false;
this.month = parseInt(this.month) - 1;
this.monthIndex = this.monthIndex - 1;
}
this.updateHeadMonth('custom');
this.render(this.year, this.month);
(typeof changed === 'function') && changed();
const weekIndex = weekSwitch ? this.weekIndex : undefined;
this.$emit('prev', this.year, this.month + 1, weekIndex);
}
if (!this.weekSwitch) return changeMonth();
const changeWeek = () => {
this.weekIndex = this.weekIndex - 1;
this.days = [this.monthDays[this.weekIndex]];
this.monthRangeDays = [this.days];
this.setMonthRangeofWeekSwitch();
this.$emit('prev', this.year, this.month + 1, this.weekIndex);
}
const currentWeek = (this.days[0] || [])[0] || {};
if (currentWeek.lastMonth || currentWeek.day === 1) {
const monthChenged = () => {
const lastMonthLength = this.monthDays.length;
const startWeekIndex = currentWeek.lastMonth ? lastMonthLength - 1: lastMonthLength;
this.startWeekIndex = startWeekIndex;
this.weekIndex = startWeekIndex;
changeWeek();
}
changeMonth(monthChenged);
} else {
changeWeek();
}
},
next(e) {
e && e.stopPropagation();
if (this.isMonthRange) return;
const weekSwitch = this.weekSwitch;
const changeMonth = () => {
if (this.monthIndex === 12) {
this.oversliding = false;
this.month = 0;
this.year = parseInt(this.year) + 1;
this.monthIndex = this.monthIndex + 1;
} else if (this.monthIndex === 0 && this.month === 11) {
this.oversliding = false;
this.month = 0;
this.year = parseInt(this.year) + 1;
this.monthIndex = this.monthIndex + 1;
} else if (this.monthIndex === 13) {
this.oversliding = true;
this.monthIndex = 1;
setTimeout(() => this.next(e), 50);
return this.updateHeadMonth('custom');
} else {
this.oversliding = false;
this.month = parseInt(this.month) + 1;
this.monthIndex = this.monthIndex + 1;
}
this.updateHeadMonth('custom');
this.render(this.year, this.month);
const weekIndex = weekSwitch ? this.weekIndex : undefined;
this.$emit('next', this.year, this.month + 1, weekIndex);
}
if (!this.weekSwitch) return changeMonth();
const changeWeek = () => {
this.weekIndex = this.weekIndex + 1;
this.days = [this.monthDays[this.weekIndex]];
this.monthRangeDays = [this.days];
this.setMonthRangeofWeekSwitch();
this.$emit('next', this.year, this.month + 1, this.weekIndex);
}
const currentWeek = (this.days[0] || [])[6] || {};
if (currentWeek.nextMonth || currentWeek.day === (new Date(this.year, this.month + 1, 0).getDate())) {
const startWeekIndex = currentWeek.nextMonth ? 1 : 0;
this.startWeekIndex = startWeekIndex;
this.weekIndex = startWeekIndex;
changeMonth();
} else {
changeWeek();
}
},
select(k1, k2, data, e, monthIndex) {
e && e.stopPropagation();
const weekSwitch = this.weekSwitch;
if (data.lastMonth && !weekSwitch) {
return this.prev(e);
} else if (data.nextMonth && !weekSwitch) {
return this.next(e);
}
if (data.disabled) return;
(data || {}).event = (this.events || {})[data.date] || '';
const {selected, day, date} = data;
const selectedDates = date.split('-');
const selectYear = Number(selectedDates[0]);
const selectMonth = selectedDates[1] - 1;
const selectMonthHuman = Number(selectedDates[1]);
const selectDay = Number(selectedDates[2]);;
if (this.range) {
this.isUserSelect = true;
if (this.rangeBegin.length === 0 || this.rangeEndTemp !== 0) {
this.rangeBegin = [selectYear, selectMonth, selectDay];
this.rangeBeginTemp = this.rangeBegin;
this.rangeEnd = [selectYear, selectMonth, selectDay];
this.thisTimeSelect = this.rangeEnd;
this.rangeEndTemp = 0;
} else {
this.rangeEnd = [selectYear, selectMonth, selectDay];
this.thisTimeSelect = [selectYear, selectMonth, selectDay];
if (this.rangeBegin.join('-') === this.rangeEnd.join('-')) {
return this.rangeEndTemp = 0;
}
this.rangeEndTemp = 1;
if (+new Date(this.rangeEnd[0], this.rangeEnd[1], this.rangeEnd[2]) < +new Date(this.rangeBegin[0], this.rangeBegin[1], this.rangeBegin[2])) {
this.rangeBegin = this.rangeEnd;
this.rangeEnd = this.rangeBeginTemp;
}
const rangeDate = (date) => {
return date.map((v, k) =>{
const value = k === 1 ? v + 1 : v;
return this.zero ? this.zeroPad(value) : value;
});
}
const begin = rangeDate(this.rangeBegin);
const end = rangeDate(this.rangeEnd);
this.value.splice(0, 1, begin)
this.value.splice(1, 1, end)
this.$emit('select', begin, end);
}
this.rangeBgHide = !this.rangeEndTemp || (this.rangeBegin.join('-') === this.rangeEnd.join('-'));
this.positionWeek = true;
if (this.isMonthRange) {
this.rendeRange();
} else {
this.render(this.year, this.month, undefined, this.thisTimeSelect);
}
} else if (this.multi) {
const filterDayIndex = this.value.findIndex(v => v.join('-') === date);
if(~filterDayIndex) {
this.handleMultiDay = this.value.splice(filterDayIndex, 1);
} else {
this.value.push([Number(Number(selectedDates[0])), Number(selectedDates[1]), day]);
}
this.days[k1][k2].selected = !selected;
if (this.monthDays[k1][k2].selected) {
this.multiDaysData.push(data);
} else {
this.multiDaysData = this.multiDaysData.filter(item => item.date !== date);
}
this.thisTimeSelect = date;
this.$emit('select', this.value, this.multiDaysData);
} else {
const currentSelected = this.value.join('-');
this.monthRangeDays.some(value => value.some(v => !!v.find(vv => {
if (vv.date === currentSelected) {
vv.selected = false;
return true;
}
})));
this.monthRangeDays[monthIndex][k1][k2].selected = true;
this.day = day;
const selectDate = [selectYear, selectMonthHuman, selectDay];
this.value[0] = selectYear;
this.value[1] = selectMonthHuman;
this.value[2] = selectDay;
this.today = [k1, k2];
this.$emit('select', selectDate, data);
}
},
changeYear() {
if(this.yearsShow) {
this.yearsShow = false;
return false;
}
this.yearsShow = true;
this.years = [];
for (let i = this.year - 5; i < this.year + 7; i++){
this.years.push(i);
}
},
changeMonth(value) {
this.oversliding && (this.oversliding = false);
this.yearsShow = false;
this.month = value;
this.render(this.year, this.month, 'CUSTOMRENDER', 0);
this.updateHeadMonth();
this.weekSwitch && this.setMonthRangeofWeekSwitch();
this.$emit('selectMonth', this.month + 1, this.year);
},
selectYear(value) {
this.yearsShow = false;
this.year = value;
this.render(this.year, this.month);
this.$emit('selectYear', value);
},
setToday() {
const now = new Date();
this.year = now.getFullYear();
this.month = now.getMonth();
this.day = now.getDate();
this.positionWeek = true;
this.render(this.year, this.month, undefined, 'SETTODAY');
this.updateHeadMonth();
},
setMonthRangeofWeekSwitch() {
this.monthsLoop = this.monthsLoopCopy.concat();
this.days[0].reduce((prev, current) => {
if (!prev) return;
const prveDate = ((prev || {}).date || '').split('-');
const prevYear = prveDate[0];
const prevMonth = prveDate[1];
const currentMonth = ((current || {}).date || '').split('-')[1];
if (prevMonth === currentMonth) {
return current;
} else {
const prevMonthText = this.months[prevMonth - 1];
const currentMonthText = this.months[currentMonth - 1];
this.monthsLoop[this.monthIndex] = prevMonthText + '~' + currentMonthText;
}
});
},
dateInfo(y, m, d) {
return calendar.solar2lunar(y, m, d);
},
zeroPad(n) {
return String(n < 10 ? '0' + n : n)
},
updateHeadMonth(type) {
if (!type) this.monthIndex = this.month + 1;
this.monthPosition = this.monthIndex * this.positionH;
this.monthText = this.months[this.month];
},
addResponsiveListener() {
window.addEventListener('resize', this.resize);
},
resize() {
const calendar = this.$refs.calendar;
this.itemWidth = (calendar.clientWidth/7 - 4).toFixed(5);
}
}
}
</script>