347 lines
9.2 KiB
JavaScript
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
|
|
});
|
|
}
|
|
}
|
|
});
|