oak-general-business/lib/miniprogram_npm/lin-ui/calendar/index.js

347 lines
9.2 KiB
JavaScript

import eventBus from '../core/utils/event-bus.js';
import validator from '../behaviors/validator';
import rules from '../behaviors/rules';
import * as config from './config';
import formatFlags from './dete';
import { getDayByOffset, getDate, compareDay, calcDateNum, copyDates, getTime, formatMonthTitle, compareMonth, getMonths } from './util';
Component({
externalClasses: [
'l-class'
],
behaviors: ['wx://form-field', validator, rules],
properties: {
show: {
type: Boolean,
value: false,
observer(val) {
if (val) {
this.initRect();
this.scrollIntoView();
}
}
},
type: {
type: String,
value: config.TYPE_SINGLE,
options: [config.TYPE_SINGLE, config.TYPE_MULTIPLE, config.TYPE_RANGE],
observer() {
this.setData({ currentDate: this.initCurrentDate() });
}
},
color: {
type: String,
value: ''
},
defaultDate: {
optionalTypes: [String, Number, Date, Array],
value: '',
observer() {
this.setData({ currentDate: this.initCurrentDate() });
}
},
format: {
type: String,
value: 'timestamp'
},
formatter: {
type: Function,
optionalTypes: [null],
value: null
},
minDate: {
type: String,
optionalTypes: [null, Number],
value: Date.now()
},
maxDate: {
type: String,
optionalTypes: [null, Number],
value: new Date(
new Date().getFullYear(),
new Date().getMonth() + 6,
new Date().getDate()
).getTime()
},
minSelect: {
type: Number,
optionalTypes: [null],
value: null
},
maxSelect: {
type: Number,
optionalTypes: [null],
value: null
},
allowSameDay: Boolean,
showConfirm: {
type: Boolean,
value: true
},
confirmText: {
type: String,
value: '确认'
},
maxLimitMessage: {
type: String
},
minLimitMessage: {
type: String
},
showTitle: {
type: Boolean,
value: true
},
showSubtitle: {
type: Boolean,
value: true
},
title: {
type: String,
value: '日期选择'
}
},
lifetimes: {
attached() {
this.setData({
currentDate: this.initCurrentDate()
});
},
ready() {
if (this.data.show) {
this.initRect();
this.scrollIntoView();
}
}
},
data: {
currentDate: null,
types: config,
subTitle: '',
scrollIntoViewIndex: ''
},
methods: {
clickDay(event) {
const { type, currentDate, maxLimitMessage, maxSelect, allowSameDay } = this.data;
const { date } = event.detail;
if(type === config.TYPE_SINGLE) {
this.setData({
currentDate: getTime(date)
});
this.triggerEvent('linclickday', copyDates(date));
this.triggerEvent('linselect', copyDates(date));
}
if(type === config.TYPE_MULTIPLE) {
let _index = null;
const isSelected = currentDate.some((item, index) => {
const res = compareDay(item, date) === 0;
if(res) {
_index = index;
}
return res;
});
if(isSelected) {
// 取消选择
currentDate.splice(_index, 1);
this.setData({
currentDate: getTime(currentDate)
});
this.triggerEvent('linunselect', copyDates(currentDate));
} else {
if(maxSelect && currentDate.length >= maxSelect) {
wx.lin.showToast({
title: maxLimitMessage || `选择天数不能超过 ${ maxSelect }`
});
this.triggerEvent('linclickday', copyDates(date));
return;
}
// 添加
this.setData({
currentDate: getTime([...currentDate, date])
});
this.triggerEvent('linselect', copyDates([...currentDate, date]));
}
this.triggerEvent('linclickday', copyDates(date));
}
if(type === config.TYPE_RANGE) {
const [startDay, endDay] = currentDate;
if (startDay && !endDay) {
const compareToStart = compareDay(date, startDay);
if (compareToStart === 1) {
if(this.checkSelectRange([startDay, date])) {
this.setData({
currentDate: getTime([startDay, date])
});
this.triggerEvent('linselect', copyDates([startDay, date]));
}
}
else if (compareToStart === -1) {
// 选择结束日期在开始日期之前 重新开始选择
this.setData({
currentDate: getTime([date, null])
});
} else if(allowSameDay){
this.setData({
currentDate: getTime([date, date])
});
}
}
else {
// 重新开始选择
this.setData({
currentDate: getTime([date, null])
});
}
}
},
checkSelectRange(date) {
const { maxSelect, maxLimitMessage, minSelect, minLimitMessage } = this.data;
if (maxSelect && calcDateNum(date) > maxSelect) {
wx.lin.showToast({
title: maxLimitMessage || `选择天数不能超过 ${ maxSelect }`
});
return false;
}
if (minSelect && calcDateNum(date) < minSelect) {
wx.lin.showToast({
title: minLimitMessage || `选择天数不能少于 ${ minSelect }`
});
return false;
}
return true;
},
initCurrentDate() {
const { type, minDate, defaultDate, maxDate } = this.data;
const defaultDateIsArr = Array.isArray(defaultDate);
if (type === config.TYPE_SINGLE) {
if(!defaultDate) {
return minDate;
}
if(defaultDateIsArr) {
return minDate;
}
if(compareDay(defaultDate, minDate) === -1) {
return minDate;
}
if(compareDay(defaultDate, maxDate) === 1) {
return maxDate;
}
return defaultDate;
}
if(type === config.TYPE_MULTIPLE) {
if(!defaultDate) {
return [];
}
if(defaultDateIsArr) {
return defaultDate.filter(item => {
return compareDay(item, minDate) === 1 && compareDay(item, maxDate) === -1;
});
}
if(compareDay(defaultDate, minDate) === -1) {
return [minDate];
}
if(compareDay(defaultDate, maxDate) === 1) {
return [maxDate];
}
return [minDate];
}
if(type === config.TYPE_RANGE) {
if(defaultDateIsArr) {
let [startDay = minDate, endDay] = defaultDate;
if(compareDay(startDay, minDate) === -1 || compareDay(startDay, maxDate) !== -1) {
startDay = minDate;
}
if(!endDay) {
endDay = getDayByOffset(getDate(startDay), 1).getTime();
}
if(compareDay(endDay, maxDate) === 1 || compareDay(endDay, minDate) === -1) {
endDay = getDayByOffset(getDate(startDay), 1).getTime();
}
return [
startDay,
endDay
];
}
return [
minDate,
getDayByOffset(getDate(minDate), 1).getTime()
];
}
},
initRect() {
if (!this.contentObserver !== null && this.contentObserver !== undefined) {
this.contentObserver.disconnect();
}
const contentObserver = this.createIntersectionObserver({
thresholds: [0, 0.1, 0.9, 1],
observeAll: true
});
this.contentObserver = contentObserver;
contentObserver.relativeTo('.calendar-body-wrap');
contentObserver.observe('.month', res => {
if (res.boundingClientRect.top <= res.relativeRect.top) {
// @ts-ignore
this.setData({ subTitle: formatMonthTitle(res.dataset.date) });
}
});
},
scrollIntoView() {
setTimeout(() => {
const { currentDate, type, show, minDate, maxDate } = this.data;
const targetDate = type === 'single' ? currentDate : currentDate[0];
const displayed = show;
if (!targetDate || !displayed) {
return;
}
const months = getMonths(minDate, maxDate);
months.some((month, index) => {
if (compareMonth(month, targetDate) === 0) {
this.setData({ scrollIntoViewIndex: `month${index}` });
return true;
}
return false;
});
}, 100);
},
closePicker() {
this.setData({
show: false
});
},
onClickConfirm() {
const {format, type, currentDate} = this.data;
eventBus.emit(`lin-form-blur-${this.id}`, this.id);
let value = null;
if(type === 'single') {
value = format !== 'timestamp' ? formatFlags.format('yyyy-MM-dd', currentDate) : currentDate;
} else {
value = currentDate.map(item => {
return format !== 'timestamp' ? formatFlags.format('yyyy-MM-dd', item) : item;
});
}
this.triggerEvent('linconfirm', value);
},
getValues() {
return this.data.currentDate;
},
reset() {
this.setData({
currentDate: null
});
}
}
});