|
|
@@ -72,6 +72,7 @@ import { createComponent } from '@/packages/utils/create';
|
|
|
const { create, translate } = createComponent('calendar-item');
|
|
|
import Taro from '@tarojs/taro';
|
|
|
import Utils from '@/packages/utils/date';
|
|
|
+import { useExpose } from '@/packages/utils/useExpose/index';
|
|
|
import requestAniFrame from '@/packages/utils/raf';
|
|
|
let TARO_ENV = process.env.TARO_ENV;
|
|
|
|
|
|
@@ -125,6 +126,10 @@ export default create({
|
|
|
type: Boolean,
|
|
|
default: false
|
|
|
},
|
|
|
+ toDateAnimation: {
|
|
|
+ type: Boolean,
|
|
|
+ default: true
|
|
|
+ },
|
|
|
poppable: {
|
|
|
type: Boolean,
|
|
|
default: true
|
|
|
@@ -178,10 +183,6 @@ export default create({
|
|
|
const scalePx = ref(2);
|
|
|
const viewHeight = ref(0);
|
|
|
const months = ref<null | HTMLElement>(null);
|
|
|
-
|
|
|
- const compConthsData = computed(() => {
|
|
|
- return state.monthsData.slice(state.defaultRange[0], state.defaultRange[1]);
|
|
|
- });
|
|
|
const showTopBtn = computed(() => {
|
|
|
return slots.btn;
|
|
|
});
|
|
|
@@ -237,28 +238,38 @@ export default create({
|
|
|
const isEnd = (currDate: string) => {
|
|
|
return Utils.isEqual(state.currDate[1], currDate);
|
|
|
};
|
|
|
-
|
|
|
+ const isMultiple = (currDate: string) => {
|
|
|
+ if (state.currDate.length > 0) {
|
|
|
+ return state.currDate.some((item: any) => {
|
|
|
+ return Utils.isEqual(item, currDate);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ };
|
|
|
// 获取当前数据
|
|
|
- const getCurrDate = (day: Day, month: MonthInfo, isRange?: boolean) => {
|
|
|
+ const getCurrDate = (day: Day, month: MonthInfo) => {
|
|
|
return month.curData[0] + '-' + month.curData[1] + '-' + Utils.getNumTwoBit(+day.day);
|
|
|
};
|
|
|
|
|
|
// 获取样式
|
|
|
- const getClass = (day: Day, month: MonthInfo, isRange?: boolean) => {
|
|
|
- const currDate = getCurrDate(day, month, isRange);
|
|
|
+ const getClass = (day: Day, month: MonthInfo) => {
|
|
|
+ const currDate = getCurrDate(day, month);
|
|
|
+ const { type } = props;
|
|
|
if (day.type == 'curr') {
|
|
|
if (
|
|
|
- (!state.isRange && Utils.isEqual(state.currDate as string, currDate)) ||
|
|
|
- (state.isRange && (isStart(currDate) || isEnd(currDate)))
|
|
|
+ Utils.isEqual(state.currDate as string, currDate) ||
|
|
|
+ (type == 'range' && (isStart(currDate) || isEnd(currDate))) ||
|
|
|
+ (type == 'multiple' && isMultiple(currDate))
|
|
|
) {
|
|
|
return `${state.dayPrefix}-active`;
|
|
|
} else if (
|
|
|
- (props.startDate && Utils.compareDate(currDate, props.startDate)) ||
|
|
|
- (props.endDate && Utils.compareDate(props.endDate, currDate))
|
|
|
+ (state.propStartDate && Utils.compareDate(currDate, state.propStartDate)) ||
|
|
|
+ (state.propEndDate && Utils.compareDate(state.propEndDate, currDate))
|
|
|
) {
|
|
|
return `${state.dayPrefix}-disabled`;
|
|
|
} else if (
|
|
|
- state.isRange &&
|
|
|
+ type == 'range' &&
|
|
|
Array.isArray(state.currDate) &&
|
|
|
Object.values(state.currDate).length == 2 &&
|
|
|
Utils.compareDate(state.currDate[0], currDate) &&
|
|
|
@@ -274,8 +285,10 @@ export default create({
|
|
|
};
|
|
|
|
|
|
const confirm = () => {
|
|
|
- if ((state.isRange && state.chooseData.length == 2) || !state.isRange) {
|
|
|
- emit('choose', state.chooseData);
|
|
|
+ const { type } = props;
|
|
|
+ if ((type == 'range' && state.chooseData.length == 2) || type != 'range') {
|
|
|
+ let chooseData = state.chooseData.slice(0);
|
|
|
+ emit('choose', chooseData);
|
|
|
if (props.poppable) {
|
|
|
emit('update');
|
|
|
}
|
|
|
@@ -284,17 +297,38 @@ export default create({
|
|
|
|
|
|
// 选中数据
|
|
|
const chooseDay = (day: Day, month: MonthInfo, isFirst: boolean, isRange?: boolean) => {
|
|
|
- if (getClass(day, month, isRange) != `${state.dayPrefix}-disabled`) {
|
|
|
+ if (getClass(day, month) != `${state.dayPrefix}-disabled`) {
|
|
|
+ const { type } = props;
|
|
|
let days = [...month.curData];
|
|
|
- // days = isRange ? days.splice(3) : days.splice(0, 3);
|
|
|
days[2] = typeof day.day == 'number' ? Utils.getNumTwoBit(day.day) : day.day;
|
|
|
days[3] = `${days[0]}-${days[1]}-${days[2]}`;
|
|
|
days[4] = Utils.getWhatDay(+days[0], +days[1], +days[2]);
|
|
|
- if (!state.isRange) {
|
|
|
- state.currDate = days[3];
|
|
|
- state.chooseData = [...days];
|
|
|
- } else {
|
|
|
- if (Object.values(state.currDate).length == 2) {
|
|
|
+ if (type == 'multiple') {
|
|
|
+ if (state.currDate.length > 0) {
|
|
|
+ let hasIndex: any = '';
|
|
|
+ state.currDate.forEach((item: any, index: number) => {
|
|
|
+ if (item == days[3]) {
|
|
|
+ hasIndex = index;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (isFirst) {
|
|
|
+ state.chooseData.push([...days]);
|
|
|
+ } else {
|
|
|
+ if (hasIndex !== '') {
|
|
|
+ state.currDate.splice(hasIndex, 1);
|
|
|
+ state.chooseData.splice(hasIndex, 1);
|
|
|
+ } else {
|
|
|
+ state.currDate.push(days[3]);
|
|
|
+ state.chooseData.push([...days]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ state.currDate = [days[3]];
|
|
|
+ state.chooseData = [[...days]];
|
|
|
+ }
|
|
|
+ } else if (type == 'range') {
|
|
|
+ let curDataLength = Object.values(state.currDate).length;
|
|
|
+ if (curDataLength == 2 || curDataLength == 0) {
|
|
|
state.currDate = [days[3]];
|
|
|
} else {
|
|
|
if (Utils.compareDate(state.currDate[0], days[3])) {
|
|
|
@@ -303,21 +337,25 @@ export default create({
|
|
|
Array.isArray(state.currDate) && state.currDate.unshift(days[3]);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
if (state.chooseData.length == 2 || !state.chooseData.length) {
|
|
|
- state.chooseData = [...days];
|
|
|
+ state.chooseData = [[...days]];
|
|
|
} else {
|
|
|
- if (Utils.compareDate(state.chooseData[3], days[3])) {
|
|
|
- state.chooseData = [[...state.chooseData], [...days]];
|
|
|
+ if (Utils.compareDate(state.chooseData[0][3], days[3])) {
|
|
|
+ state.chooseData = [...state.chooseData, [...days]];
|
|
|
} else {
|
|
|
- state.chooseData = [[...days], [...state.chooseData]];
|
|
|
+ state.chooseData = [[...days], ...state.chooseData];
|
|
|
}
|
|
|
}
|
|
|
+ } else {
|
|
|
+ state.currDate = days[3];
|
|
|
+ state.chooseData = [...days];
|
|
|
}
|
|
|
|
|
|
if (!isFirst) {
|
|
|
// 点击日期 触发
|
|
|
emit('select', state.chooseData);
|
|
|
- if (props.isAutoBackFill) {
|
|
|
+ if (props.isAutoBackFill || !props.poppable) {
|
|
|
confirm();
|
|
|
}
|
|
|
}
|
|
|
@@ -456,11 +494,10 @@ export default create({
|
|
|
state.propEndDate = propEndDate;
|
|
|
state.startData = splitDate(propStartDate);
|
|
|
state.endData = splitDate(propEndDate);
|
|
|
+
|
|
|
// 根据是否存在默认时间,初始化当前日期,
|
|
|
- if (!props.defaultValue || (Array.isArray(props.defaultValue) && props.defaultValue.length <= 0)) {
|
|
|
- state.currDate = state.isRange ? [Utils.date2Str(new Date()), Utils.getDay(1)] : Utils.date2Str(new Date());
|
|
|
- } else {
|
|
|
- state.currDate = state.isRange ? [...props.defaultValue] : props.defaultValue;
|
|
|
+ if (props.defaultValue || (Array.isArray(props.defaultValue) && props.defaultValue.length > 0)) {
|
|
|
+ state.currDate = props.type != 'one' ? [...props.defaultValue] : props.defaultValue;
|
|
|
}
|
|
|
// 判断时间范围内存在多少个月
|
|
|
const startDate = {
|
|
|
@@ -475,7 +512,9 @@ export default create({
|
|
|
if (endDate.year - startDate.year > 0) {
|
|
|
monthsNum = monthsNum + 12 * (endDate.year - startDate.year);
|
|
|
}
|
|
|
-
|
|
|
+ if (monthsNum <= 0) {
|
|
|
+ monthsNum = 1;
|
|
|
+ }
|
|
|
// 设置月份数据
|
|
|
getMonth(state.startData, 'next');
|
|
|
|
|
|
@@ -486,45 +525,84 @@ export default create({
|
|
|
state.monthsNum = monthsNum;
|
|
|
|
|
|
// 日期转化为数组,限制初始日期。判断时间范围
|
|
|
- if (state.isRange && Array.isArray(state.currDate)) {
|
|
|
- if (propStartDate && Utils.compareDate(state.currDate[0], propStartDate)) {
|
|
|
- state.currDate.splice(0, 1, propStartDate);
|
|
|
+ if (props.type == 'range' && Array.isArray(state.currDate)) {
|
|
|
+ if (state.currDate.length > 0) {
|
|
|
+ if (propStartDate && Utils.compareDate(state.currDate[0], propStartDate)) {
|
|
|
+ state.currDate.splice(0, 1, propStartDate);
|
|
|
+ }
|
|
|
+ if (propEndDate && Utils.compareDate(propEndDate, state.currDate[1])) {
|
|
|
+ state.currDate.splice(1, 1, propEndDate);
|
|
|
+ }
|
|
|
+ state.defaultData = [...splitDate(state.currDate[0]), ...splitDate(state.currDate[1])];
|
|
|
}
|
|
|
- if (propEndDate && Utils.compareDate(propEndDate, state.currDate[1])) {
|
|
|
- state.currDate.splice(1, 1, propEndDate);
|
|
|
+ } else if (props.type == 'multiple' && Array.isArray(state.currDate)) {
|
|
|
+ if (state.currDate.length > 0) {
|
|
|
+ let defaultArr: string[] = [];
|
|
|
+ let obj: any = {};
|
|
|
+ state.currDate.forEach((item: string, index: number) => {
|
|
|
+ if (
|
|
|
+ propStartDate &&
|
|
|
+ !Utils.compareDate(item, propStartDate) &&
|
|
|
+ propEndDate &&
|
|
|
+ !Utils.compareDate(propEndDate, item)
|
|
|
+ ) {
|
|
|
+ if (!obj.hasOwnProperty(item)) {
|
|
|
+ defaultArr.push(item);
|
|
|
+ obj[item] = item;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ state.currDate = [...defaultArr];
|
|
|
+ state.defaultData = [...splitDate(defaultArr[0])];
|
|
|
}
|
|
|
- state.defaultData = [...splitDate(state.currDate[0]), ...splitDate(state.currDate[1])];
|
|
|
} else {
|
|
|
- if (propStartDate && Utils.compareDate(state.currDate as string, propStartDate)) {
|
|
|
- state.currDate = propStartDate;
|
|
|
- } else if (propEndDate && !Utils.compareDate(state.currDate as string, propEndDate)) {
|
|
|
- state.currDate = propEndDate;
|
|
|
+ if (state.currDate) {
|
|
|
+ if (propStartDate && Utils.compareDate(state.currDate as string, propStartDate)) {
|
|
|
+ state.currDate = propStartDate;
|
|
|
+ } else if (propEndDate && !Utils.compareDate(state.currDate as string, propEndDate)) {
|
|
|
+ state.currDate = propEndDate;
|
|
|
+ }
|
|
|
+ state.defaultData = [...splitDate(state.currDate as string)];
|
|
|
}
|
|
|
- state.defaultData = [...splitDate(state.currDate as string)];
|
|
|
}
|
|
|
|
|
|
+ // 设置默认可见区域
|
|
|
let current = 0;
|
|
|
let lastCurrent = 0;
|
|
|
- state.monthsData.forEach((item, index) => {
|
|
|
- if (item.title == translate('monthTitle', state.defaultData[0], state.defaultData[1])) {
|
|
|
- current = index;
|
|
|
- }
|
|
|
- if (state.isRange) {
|
|
|
- if (item.title == translate('monthTitle', state.defaultData[3], state.defaultData[4])) {
|
|
|
- lastCurrent = index;
|
|
|
+ if (state.defaultData.length > 0) {
|
|
|
+ state.monthsData.forEach((item, index) => {
|
|
|
+ if (item.title == translate('monthTitle', state.defaultData[0], state.defaultData[1])) {
|
|
|
+ current = index;
|
|
|
}
|
|
|
- }
|
|
|
- });
|
|
|
+ if (props.type == 'range') {
|
|
|
+ if (item.title == translate('monthTitle', state.defaultData[3], state.defaultData[4])) {
|
|
|
+ lastCurrent = index;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
setDefaultRange(monthsNum, current);
|
|
|
state.currentIndex = current;
|
|
|
state.yearMonthTitle = state.monthsData[state.currentIndex].title;
|
|
|
-
|
|
|
- // 设置当前选中日期
|
|
|
- if (state.isRange) {
|
|
|
- chooseDay({ day: state.defaultData[2], type: 'curr' }, state.monthsData[state.currentIndex], true);
|
|
|
- chooseDay({ day: state.defaultData[5], type: 'curr' }, state.monthsData[lastCurrent], true, true);
|
|
|
- } else {
|
|
|
- chooseDay({ day: state.defaultData[2], type: 'curr' }, state.monthsData[state.currentIndex], true);
|
|
|
+ if (state.defaultData.length > 0) {
|
|
|
+ // 设置当前选中日期
|
|
|
+ if (state.isRange) {
|
|
|
+ chooseDay({ day: state.defaultData[2], type: 'curr' }, state.monthsData[state.currentIndex], true);
|
|
|
+ chooseDay({ day: state.defaultData[5], type: 'curr' }, state.monthsData[lastCurrent], true);
|
|
|
+ } else if (props.type == 'multiple') {
|
|
|
+ [...state.currDate].forEach((item: any) => {
|
|
|
+ let dateArr = splitDate(item);
|
|
|
+ let current = state.currentIndex;
|
|
|
+ state.monthsData.forEach((item, index) => {
|
|
|
+ if (item.title == translate('monthTitle', dateArr[0], dateArr[1])) {
|
|
|
+ current = index;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ chooseDay({ day: dateArr[2], type: 'curr' }, state.monthsData[current], true);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ chooseDay({ day: state.defaultData[2], type: 'curr' }, state.monthsData[state.currentIndex], true);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
let lastItem = state.monthsData[state.monthsData.length - 1];
|
|
|
@@ -537,17 +615,53 @@ export default create({
|
|
|
if (months?.value) {
|
|
|
viewHeight.value = months.value.clientHeight;
|
|
|
}
|
|
|
- if (TARO_ENV === 'h5') {
|
|
|
- Taro.nextTick(() => {
|
|
|
- Taro.createSelectorQuery()
|
|
|
- .select('.nut-calendar-content')
|
|
|
- .boundingClientRect((res) => {
|
|
|
- viewHeight.value = res.height;
|
|
|
- })
|
|
|
- .exec();
|
|
|
- });
|
|
|
+ };
|
|
|
+ const scrollToDate = (date: string) => {
|
|
|
+ if (Utils.compareDate(date, state.propStartDate)) {
|
|
|
+ date = state.propStartDate;
|
|
|
+ } else if (!Utils.compareDate(date, state.propEndDate)) {
|
|
|
+ date = state.propEndDate;
|
|
|
}
|
|
|
+ console.log(date);
|
|
|
+ let dateArr = splitDate(date);
|
|
|
+ state.monthsData.forEach((item, index) => {
|
|
|
+ if (item.title == translate('monthTitle', dateArr[0], dateArr[1])) {
|
|
|
+ // if (months.value) {
|
|
|
+
|
|
|
+ if (props.toDateAnimation) {
|
|
|
+ Taro.createSelectorQuery()
|
|
|
+ .select('.nut-calendar-content')
|
|
|
+ .scrollOffset((res) => {
|
|
|
+ let scrollTop = res.scrollTop;
|
|
|
+ let distance = state.monthsData[index].cssScrollHeight - scrollTop;
|
|
|
+ let flag = 0;
|
|
|
+ let interval = setInterval(() => {
|
|
|
+ flag++;
|
|
|
+ if (months.value) {
|
|
|
+ let offset = distance / 10;
|
|
|
+ console.log('scrolltodate ', distance, offset);
|
|
|
+
|
|
|
+ state.scrollTop = state.scrollTop + offset;
|
|
|
+ }
|
|
|
+ if (flag >= 10) {
|
|
|
+ clearInterval(interval);
|
|
|
+ if (months.value) {
|
|
|
+ state.scrollTop = state.monthsData[index].cssScrollHeight;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, 40);
|
|
|
+ })
|
|
|
+ .exec();
|
|
|
+ } else {
|
|
|
+ state.scrollTop = state.monthsData[index].cssScrollHeight;
|
|
|
+ }
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ });
|
|
|
};
|
|
|
+ useExpose({
|
|
|
+ scrollToDate
|
|
|
+ });
|
|
|
const setDefaultRange = (monthsNum: number, current: number) => {
|
|
|
let rangeArr: any[] = [];
|
|
|
if (monthsNum >= 3) {
|
|
|
@@ -559,7 +673,7 @@ export default create({
|
|
|
rangeArr = [current - 2, current + 2];
|
|
|
}
|
|
|
} else {
|
|
|
- rangeArr = [0, monthsNum + 1];
|
|
|
+ rangeArr = [0, monthsNum + 2];
|
|
|
}
|
|
|
if (JSON.stringify(state.defaultRange) !== JSON.stringify(rangeArr)) {
|
|
|
state.defaultRange[0] = rangeArr[0];
|
|
|
@@ -571,7 +685,7 @@ export default create({
|
|
|
};
|
|
|
// 区间选择&&当前月&&选中态
|
|
|
const isActive = (day: Day, month: MonthInfo) => {
|
|
|
- return state.isRange && day.type == 'curr' && getClass(day, month) == 'calendar-month-day-active';
|
|
|
+ return props.type == 'range' && day.type == 'curr' && getClass(day, month) == 'calendar-month-day-active';
|
|
|
};
|
|
|
|
|
|
// 是否有开始提示
|
|
|
@@ -599,6 +713,9 @@ export default create({
|
|
|
};
|
|
|
|
|
|
const mothsViewScroll = (e: any) => {
|
|
|
+ if (state.monthsData.length <= 1) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
const currentScrollTop = e.target.scrollTop;
|
|
|
let current = Math.floor(currentScrollTop / state.avgHeight);
|
|
|
if (current == 0) {
|
|
|
@@ -613,6 +730,14 @@ export default create({
|
|
|
current -= 1;
|
|
|
}
|
|
|
} else {
|
|
|
+ if (!viewHeight.value || viewHeight.value < 0) {
|
|
|
+ Taro.createSelectorQuery()
|
|
|
+ .select('.nut-calendar-content')
|
|
|
+ .boundingClientRect((res) => {
|
|
|
+ viewHeight.value = res.height;
|
|
|
+ })
|
|
|
+ .exec();
|
|
|
+ }
|
|
|
const viewPosition = Math.round(currentScrollTop + viewHeight.value);
|
|
|
if (
|
|
|
viewPosition < state.monthsData[current].cssScrollHeight + state.monthsData[current].cssHeight &&
|
|
|
@@ -626,7 +751,7 @@ export default create({
|
|
|
) {
|
|
|
current += 1;
|
|
|
}
|
|
|
- if (currentScrollTop < state.monthsData[current - 1].cssScrollHeight) {
|
|
|
+ if (current >= 1 && currentScrollTop < state.monthsData[current - 1].cssScrollHeight) {
|
|
|
current -= 1;
|
|
|
}
|
|
|
}
|