You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
633 lines
22 KiB
633 lines
22 KiB
<template>
|
|
<view>
|
|
<van-popup
|
|
v-if="poppable"
|
|
:custom-class="'van-calendar__popup--' + position"
|
|
close-icon-class="van-calendar__close-icon"
|
|
:show="show"
|
|
:round="round"
|
|
:position="position"
|
|
:closeable="showTitle || showSubtitle"
|
|
:close-on-click-overlay="closeOnClickOverlay"
|
|
:safe-area-inset-bottom="safeAreaInsetBottom"
|
|
@enter="onOpen"
|
|
@close="onClose"
|
|
@after-enter="onOpened"
|
|
@after-leave="onClosed"
|
|
>
|
|
<!-- parse <include src="./calendar.wxml"/> -->
|
|
<block>
|
|
<view class="van-calendar">
|
|
<header
|
|
:title="title"
|
|
:showTitle="showTitle"
|
|
:subtitle="subtitle"
|
|
:showSubtitle="showSubtitle"
|
|
:firstDayOfWeek="firstDayOfWeek"
|
|
@click-subtitle="onClickSubtitle"
|
|
>
|
|
<slot name="title" slot="title"></slot>
|
|
</header>
|
|
|
|
<scroll-view class="van-calendar__body" scroll-y :scroll-into-view="scrollIntoView">
|
|
<month
|
|
:id="'month' + index"
|
|
class="month"
|
|
:data-date="item"
|
|
:date="item"
|
|
:type="type"
|
|
:color="color"
|
|
:minDate="minDate"
|
|
:maxDate="maxDate"
|
|
:showMark="showMark"
|
|
:formatter="formatter"
|
|
:rowHeight="rowHeight"
|
|
:currentDate="currentDate"
|
|
:showSubtitle="showSubtitle"
|
|
:allowSameDay="allowSameDay"
|
|
:showMonthTitle="index !== 0 || !showSubtitle"
|
|
:firstDayOfWeek="firstDayOfWeek"
|
|
@click="onClickDay($event, { date: item, tagId: 'month' + index })"
|
|
v-for="(item, index) in computed.getMonths(minDate, maxDate)"
|
|
:key="index"
|
|
></month>
|
|
</scroll-view>
|
|
|
|
<view :class="utils.bem('calendar__footer', { safeAreaInsetBottom })">
|
|
<slot name="footer"></slot>
|
|
</view>
|
|
|
|
<view :class="utils.bem('calendar__footer', { safeAreaInsetBottom })">
|
|
<van-button
|
|
v-if="showConfirm"
|
|
round
|
|
block
|
|
type="danger"
|
|
:color="color"
|
|
custom-class="van-calendar__confirm"
|
|
:disabled="computed.getButtonDisabled(type, currentDate, minRange)"
|
|
nativeType="text"
|
|
@click="onConfirm"
|
|
>
|
|
{{ computed.getButtonDisabled(type, currentDate, minRange) ? confirmDisabledText : confirmText }}
|
|
</van-button>
|
|
</view>
|
|
</view>
|
|
</block>
|
|
</van-popup>
|
|
|
|
<!-- parse <include v-else src="./calendar.wxml"/> -->
|
|
<block v-else>
|
|
<view class="van-calendar">
|
|
<header :title="title" :showTitle="showTitle" :subtitle="subtitle" :showSubtitle="showSubtitle" :firstDayOfWeek="firstDayOfWeek" @click-subtitle="onClickSubtitle">
|
|
<slot name="title" slot="title"></slot>
|
|
</header>
|
|
|
|
<scroll-view class="van-calendar__body" scroll-y :scroll-into-view="scrollIntoView">
|
|
<month
|
|
:id="'month' + index"
|
|
class="month"
|
|
:data-date="item"
|
|
:date="item"
|
|
:type="type"
|
|
:color="color"
|
|
:minDate="minDate"
|
|
:maxDate="maxDate"
|
|
:showMark="showMark"
|
|
:formatter="formatter"
|
|
:rowHeight="rowHeight"
|
|
:currentDate="currentDate"
|
|
:showSubtitle="showSubtitle"
|
|
:allowSameDay="allowSameDay"
|
|
:showMonthTitle="index !== 0 || !showSubtitle"
|
|
:firstDayOfWeek="firstDayOfWeek"
|
|
@click="onClickDay($event, { date: item, tagId: 'month' + index })"
|
|
v-for="(item, index) in computed.getMonths(minDate, maxDate)"
|
|
:key="index"
|
|
></month>
|
|
</scroll-view>
|
|
|
|
<view :class="utils.bem('calendar__footer', { safeAreaInsetBottom })">
|
|
<slot name="footer"></slot>
|
|
</view>
|
|
|
|
<view :class="utils.bem('calendar__footer', { safeAreaInsetBottom })">
|
|
<van-button
|
|
v-if="showConfirm"
|
|
round
|
|
block
|
|
type="danger"
|
|
:color="color"
|
|
custom-class="van-calendar__confirm"
|
|
:disabled="computed.getButtonDisabled(type, currentDate, minRange)"
|
|
nativeType="text"
|
|
@click="onConfirm"
|
|
>
|
|
{{ computed.getButtonDisabled(type, currentDate, minRange) ? confirmDisabledText : confirmText }}
|
|
</van-button>
|
|
</view>
|
|
</view>
|
|
</block>
|
|
|
|
<van-toast id="van-toast" />
|
|
</view>
|
|
</template>
|
|
<script module="computed" lang="wxs" src="@/miniprogram_npm/@vant/weapp/calendar/index.wxs"></script>
|
|
<script module="utils" lang="wxs" src="@/miniprogram_npm/@vant/weapp/wxs/utils.wxs"></script>
|
|
<script>
|
|
'use strict';
|
|
import header from './components/header/index';
|
|
import month from './components/month/index';
|
|
var __spreadArray =
|
|
(this && this.__spreadArray) ||
|
|
function (to, from, pack) {
|
|
if (pack || arguments.length === 2) {
|
|
for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
if (ar || !(i in from)) {
|
|
if (!ar) {
|
|
ar = Array.prototype.slice.call(from, 0, i);
|
|
}
|
|
ar[i] = from[i];
|
|
}
|
|
}
|
|
}
|
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
};
|
|
var __importDefault =
|
|
(this && this.__importDefault) ||
|
|
function (mod) {
|
|
return mod && mod.__esModule
|
|
? mod
|
|
: {
|
|
default: mod
|
|
};
|
|
};
|
|
Object.defineProperty(exports, '__esModule', {
|
|
value: true
|
|
});
|
|
var component_1 = require('../common/component');
|
|
var utils_1 = require('./utils');
|
|
var toast_1 = __importDefault(require('../toast/toast'));
|
|
var utils_2 = require('../common/utils');
|
|
var initialMinDate = (0, utils_1.getToday)().getTime();
|
|
var initialMaxDate = (function () {
|
|
var now = (0, utils_1.getToday)();
|
|
return new Date(now.getFullYear(), now.getMonth() + 6, now.getDate()).getTime();
|
|
})();
|
|
var getTime = function (date) {
|
|
return date instanceof Date ? date.getTime() : date;
|
|
};
|
|
export default {
|
|
components: {
|
|
header,
|
|
month
|
|
},
|
|
data() {
|
|
return {
|
|
subtitle: '',
|
|
currentDate: null,
|
|
scrollIntoView: ''
|
|
};
|
|
},
|
|
props: {
|
|
title: {
|
|
type: String,
|
|
default: '日期选择'
|
|
},
|
|
color: String,
|
|
show: {
|
|
type: Boolean
|
|
},
|
|
formatter: null,
|
|
confirmText: {
|
|
type: String,
|
|
default: '确定'
|
|
},
|
|
confirmDisabledText: {
|
|
type: String,
|
|
default: '确定'
|
|
},
|
|
rangePrompt: String,
|
|
showRangePrompt: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
defaultDate: {
|
|
type: null,
|
|
default: (0, utils_1.getToday)().getTime()
|
|
},
|
|
allowSameDay: Boolean,
|
|
type: {
|
|
type: String,
|
|
default: 'single'
|
|
},
|
|
minDate: {
|
|
type: Number,
|
|
default: initialMinDate
|
|
},
|
|
maxDate: {
|
|
type: Number,
|
|
default: initialMaxDate
|
|
},
|
|
position: {
|
|
type: String,
|
|
default: 'bottom'
|
|
},
|
|
rowHeight: {
|
|
type: null,
|
|
default: utils_1.ROW_HEIGHT
|
|
},
|
|
round: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
poppable: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
showMark: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
showTitle: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
showConfirm: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
showSubtitle: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
safeAreaInsetBottom: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
closeOnClickOverlay: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
maxRange: {
|
|
type: null,
|
|
default: null
|
|
},
|
|
minRange: {
|
|
type: Number,
|
|
default: 1
|
|
},
|
|
firstDayOfWeek: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
readonly: Boolean
|
|
},
|
|
watch: {
|
|
minDate: function () {
|
|
this.initRect();
|
|
},
|
|
|
|
maxDate: function () {
|
|
this.initRect();
|
|
},
|
|
|
|
show: {
|
|
handler: function (val) {
|
|
if (val) {
|
|
this.initRect();
|
|
this.scrollIntoViewFun();
|
|
}
|
|
},
|
|
|
|
immediate: true
|
|
},
|
|
|
|
defaultDate: {
|
|
handler: function (val) {
|
|
this.setData({
|
|
currentDate: val
|
|
});
|
|
this.scrollIntoViewFun();
|
|
},
|
|
|
|
immediate: true
|
|
},
|
|
|
|
type: {
|
|
handler: function () {
|
|
this.setData({
|
|
currentDate: this.getInitialDate(this.defaultDate)
|
|
});
|
|
this.scrollIntoViewFun();
|
|
},
|
|
|
|
immediate: true
|
|
}
|
|
},
|
|
created: function () {
|
|
this.setData({
|
|
currentDate: this.getInitialDate(this.defaultDate)
|
|
});
|
|
},
|
|
mounted: function () {
|
|
if (this.show || !this.poppable) {
|
|
this.initRect();
|
|
this.scrollIntoViewFun();
|
|
}
|
|
},
|
|
methods: {
|
|
reset: function () {
|
|
this.setData({
|
|
currentDate: this.getInitialDate(this.defaultDate)
|
|
});
|
|
this.scrollIntoViewFun();
|
|
},
|
|
initRect: function () {
|
|
var that = this;
|
|
if (this.contentObserver != null) {
|
|
this.contentObserver.disconnect();
|
|
}
|
|
var contentObserver = this.createIntersectionObserver({
|
|
thresholds: [0, 0.1, 0.9, 1],
|
|
observeAll: true
|
|
});
|
|
this.contentObserver = contentObserver;
|
|
contentObserver.relativeTo('.van-calendar__body');
|
|
contentObserver.observe('.month', function (res) {
|
|
if (res.boundingClientRect.top <= res.relativeRect.top) {
|
|
// @ts-ignore
|
|
that.setData({
|
|
subtitle: (0, utils_1.formatMonthTitle)(res.dataset.date)
|
|
});
|
|
}
|
|
});
|
|
},
|
|
limitDateRange: function (date, minDate, maxDate) {
|
|
if (minDate === void 0) {
|
|
minDate = null;
|
|
}
|
|
if (maxDate === void 0) {
|
|
maxDate = null;
|
|
}
|
|
minDate = minDate || this.minDate;
|
|
maxDate = maxDate || this.maxDate;
|
|
if ((0, utils_1.compareDay)(date, minDate) === -1) {
|
|
return minDate;
|
|
}
|
|
if ((0, utils_1.compareDay)(date, maxDate) === 1) {
|
|
return maxDate;
|
|
}
|
|
return date;
|
|
},
|
|
getInitialDate: function (defaultDate) {
|
|
var that = this;
|
|
if (defaultDate === void 0) {
|
|
defaultDate = null;
|
|
}
|
|
var _a = this;
|
|
var type = _a.type;
|
|
var minDate = _a.minDate;
|
|
var maxDate = _a.maxDate;
|
|
var allowSameDay = _a.allowSameDay;
|
|
if (!defaultDate) {
|
|
return [];
|
|
}
|
|
var now = (0, utils_1.getToday)().getTime();
|
|
if (type === 'range') {
|
|
if (!Array.isArray(defaultDate)) {
|
|
defaultDate = [];
|
|
}
|
|
var _b = defaultDate || [];
|
|
var startDay = _b[0];
|
|
var endDay = _b[1];
|
|
var startDate = getTime(startDay || now);
|
|
var start = this.limitDateRange(startDate, minDate, allowSameDay ? startDate : (0, utils_1.getPrevDay)(new Date(maxDate)).getTime());
|
|
var date = getTime(endDay || now);
|
|
var end = this.limitDateRange(date, allowSameDay ? date : (0, utils_1.getNextDay)(new Date(minDate)).getTime());
|
|
return [start, end];
|
|
}
|
|
if (type === 'multiple') {
|
|
if (Array.isArray(defaultDate)) {
|
|
return defaultDate.map(function (date) {
|
|
return that.limitDateRange(date);
|
|
});
|
|
}
|
|
return [this.limitDateRange(now)];
|
|
}
|
|
if (!defaultDate || Array.isArray(defaultDate)) {
|
|
defaultDate = now;
|
|
}
|
|
return this.limitDateRange(defaultDate);
|
|
},
|
|
scrollIntoViewFun: function () {
|
|
var that = this;
|
|
(0, utils_2.requestAnimationFrame)(function () {
|
|
var _a = that;
|
|
var currentDate = _a.currentDate;
|
|
var type = _a.type;
|
|
var show = _a.show;
|
|
var poppable = _a.poppable;
|
|
var minDate = _a.minDate;
|
|
var maxDate = _a.maxDate;
|
|
if (!currentDate) {
|
|
return;
|
|
}
|
|
// @ts-ignore
|
|
var targetDate = type === 'single' ? currentDate : currentDate[0];
|
|
var displayed = show || !poppable;
|
|
if (!targetDate || !displayed) {
|
|
return;
|
|
}
|
|
var months = (0, utils_1.getMonths)(minDate, maxDate);
|
|
months.some(function (month, index) {
|
|
if ((0, utils_1.compareMonth)(month, targetDate) === 0) {
|
|
that.setData({
|
|
scrollIntoView: 'month'.concat(index)
|
|
});
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
});
|
|
},
|
|
onOpen: function () {
|
|
this.$emit('open');
|
|
},
|
|
onOpened: function () {
|
|
this.$emit('opened');
|
|
},
|
|
onClose: function () {
|
|
this.$emit('close');
|
|
},
|
|
onClosed: function () {
|
|
this.$emit('closed');
|
|
},
|
|
onClickDay: function (event, _dataset) {
|
|
/* ---处理dataset begin--- */
|
|
this.handleDataset(event, _dataset);
|
|
/* ---处理dataset end--- */
|
|
if (this.readonly) {
|
|
return;
|
|
}
|
|
var date = event.detail.date;
|
|
var _a = this;
|
|
var type = _a.type;
|
|
var currentDate = _a.currentDate;
|
|
var allowSameDay = _a.allowSameDay;
|
|
if (type === 'range') {
|
|
// @ts-ignore
|
|
var startDay_1 = currentDate[0];
|
|
var endDay = currentDate[1];
|
|
if (startDay_1 && !endDay) {
|
|
var compareToStart = (0, utils_1.compareDay)(date, startDay_1);
|
|
if (compareToStart === 1) {
|
|
var days_1 = this.zpSelectComponent('.month').data.days;
|
|
days_1.some(function (day, index) {
|
|
var isDisabled = day.type === 'disabled' && getTime(startDay_1) < getTime(day.date) && getTime(day.date) < getTime(date);
|
|
if (isDisabled) {
|
|
date = days_1[index - 1].date;
|
|
}
|
|
return isDisabled;
|
|
});
|
|
this.select([startDay_1, date], true);
|
|
} else if (compareToStart === -1) {
|
|
this.select([date, null]);
|
|
} else if (allowSameDay) {
|
|
this.select([date, date], true);
|
|
}
|
|
} else {
|
|
this.select([date, null]);
|
|
}
|
|
} else if (type === 'multiple') {
|
|
var selectedIndex_1;
|
|
// @ts-ignore
|
|
var selected = currentDate.some(function (dateItem, index) {
|
|
var equal = (0, utils_1.compareDay)(dateItem, date) === 0;
|
|
if (equal) {
|
|
selectedIndex_1 = index;
|
|
}
|
|
return equal;
|
|
});
|
|
if (selected) {
|
|
// @ts-ignore
|
|
var cancelDate = currentDate.splice(selectedIndex_1, 1);
|
|
this.setData({
|
|
currentDate: currentDate
|
|
});
|
|
this.unselect(cancelDate);
|
|
} else {
|
|
// @ts-ignore
|
|
this.select(__spreadArray(__spreadArray([], currentDate, true), [date], false));
|
|
}
|
|
} else {
|
|
this.select(date, true);
|
|
}
|
|
},
|
|
unselect: function (dateArray) {
|
|
var date = dateArray[0];
|
|
if (date) {
|
|
this.$emit('unselect', (0, utils_1.copyDates)(date));
|
|
}
|
|
},
|
|
select: function (date, complete) {
|
|
if (complete && this.type === 'range') {
|
|
var valid = this.checkRange(date);
|
|
if (!valid) {
|
|
// auto selected to max range if showConfirm
|
|
if (this.showConfirm) {
|
|
this.emit([date[0], (0, utils_1.getDayByOffset)(date[0], this.maxRange - 1)]);
|
|
} else {
|
|
this.emit(date);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
this.emit(date);
|
|
if (complete && !this.showConfirm) {
|
|
this.onConfirm();
|
|
}
|
|
},
|
|
emit: function (date) {
|
|
this.setData({
|
|
currentDate: Array.isArray(date) ? date.map(getTime) : getTime(date)
|
|
});
|
|
this.$emit('select', (0, utils_1.copyDates)(date));
|
|
},
|
|
checkRange: function (date) {
|
|
var _a = this;
|
|
var maxRange = _a.maxRange;
|
|
var rangePrompt = _a.rangePrompt;
|
|
var showRangePrompt = _a.showRangePrompt;
|
|
if (maxRange && (0, utils_1.calcDateNum)(date) > maxRange) {
|
|
if (showRangePrompt) {
|
|
(0, toast_1.default)({
|
|
context: this,
|
|
message: rangePrompt || '\u9009\u62E9\u5929\u6570\u4E0D\u80FD\u8D85\u8FC7 '.concat(maxRange, ' \u5929')
|
|
});
|
|
}
|
|
this.$emit('over-range');
|
|
return false;
|
|
}
|
|
return true;
|
|
},
|
|
onConfirm: function () {
|
|
var that = this;
|
|
if (this.type === 'range' && !this.checkRange(this.currentDate)) {
|
|
return;
|
|
}
|
|
this.$nextTick(function () {
|
|
// @ts-ignore
|
|
that.$emit('confirm', (0, utils_1.copyDates)(that.currentDate));
|
|
});
|
|
},
|
|
onClickSubtitle: function (event) {
|
|
this.$emit('click-subtitle', event);
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
<style>
|
|
@import '../common/index.css';
|
|
.van-calendar {
|
|
background-color: var(--calendar-background-color, #fff);
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: var(--calendar-height, 100%);
|
|
}
|
|
.van-calendar__close-icon {
|
|
top: 11px;
|
|
}
|
|
.van-calendar__popup--bottom,
|
|
.van-calendar__popup--top {
|
|
height: var(--calendar-popup-height, 90%);
|
|
}
|
|
.van-calendar__popup--left,
|
|
.van-calendar__popup--right {
|
|
height: 100%;
|
|
}
|
|
.van-calendar__body {
|
|
-webkit-overflow-scrolling: touch;
|
|
flex: 1;
|
|
overflow: auto;
|
|
}
|
|
.van-calendar__footer {
|
|
flex-shrink: 0;
|
|
padding: 0 var(--padding-md, 16px);
|
|
}
|
|
.van-calendar__footer--safe-area-inset-bottom {
|
|
padding-bottom: env(safe-area-inset-bottom);
|
|
}
|
|
.van-calendar__footer + .van-calendar__footer,
|
|
.van-calendar__footer:empty {
|
|
display: none;
|
|
}
|
|
.van-calendar__footer:empty + .van-calendar__footer {
|
|
display: block !important;
|
|
}
|
|
.van-calendar__confirm {
|
|
height: var(--calendar-confirm-button-height, 36px) !important;
|
|
line-height: var(--calendar-confirm-button-line-height, 34px) !important;
|
|
margin: var(--calendar-confirm-button-margin, 7px 0) !important;
|
|
}
|
|
</style>
|
|
|