123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- <template>
- <transition name="el-zoom-in-top" @after-leave="$emit('dodestroy')">
- <div
- v-show="visible"
- class="el-picker-panel el-date-range-picker el-popper"
- :class="[{
- 'has-sidebar': $slots.sidebar || shortcuts
- }, popperClass]">
- <div class="el-picker-panel__body-wrapper">
- <slot name="sidebar" class="el-picker-panel__sidebar"></slot>
- <div class="el-picker-panel__sidebar" v-if="shortcuts">
- <button
- type="button"
- class="el-picker-panel__shortcut"
- v-for="(shortcut, key) in shortcuts"
- :key="key"
- @click="handleShortcutClick(shortcut)">{{shortcut.text}}</button>
- </div>
- <div class="el-picker-panel__body">
- <div class="el-picker-panel__content el-date-range-picker__content is-left">
- <div class="el-date-range-picker__header">
- <button
- type="button"
- @click="leftPrevYear"
- class="el-picker-panel__icon-btn el-icon-d-arrow-left"></button>
- <button
- type="button"
- v-if="unlinkPanels"
- @click="leftNextYear"
- :disabled="!enableYearArrow"
- :class="{ 'is-disabled': !enableYearArrow }"
- class="el-picker-panel__icon-btn el-icon-d-arrow-right"></button>
- <div>{{ leftLabel }}</div>
- </div>
- <month-table
- selection-mode="range"
- :date="leftDate"
- :default-value="defaultValue"
- :min-date="minDate"
- :max-date="maxDate"
- :range-state="rangeState"
- :disabled-date="disabledDate"
- @changerange="handleChangeRange"
- @pick="handleRangePick">
- </month-table>
- </div>
- <div class="el-picker-panel__content el-date-range-picker__content is-right">
- <div class="el-date-range-picker__header">
- <button
- type="button"
- v-if="unlinkPanels"
- @click="rightPrevYear"
- :disabled="!enableYearArrow"
- :class="{ 'is-disabled': !enableYearArrow }"
- class="el-picker-panel__icon-btn el-icon-d-arrow-left"></button>
- <button
- type="button"
- @click="rightNextYear"
- class="el-picker-panel__icon-btn el-icon-d-arrow-right"></button>
- <div>{{ rightLabel }}</div>
- </div>
- <month-table
- selection-mode="range"
- :date="rightDate"
- :default-value="defaultValue"
- :min-date="minDate"
- :max-date="maxDate"
- :range-state="rangeState"
- :disabled-date="disabledDate"
- @changerange="handleChangeRange"
- @pick="handleRangePick">
- </month-table>
- </div>
- </div>
- </div>
- </div>
- </transition>
- </template>
- <script type="text/babel">
- import {
- isDate,
- modifyWithTimeString,
- prevYear,
- nextYear,
- nextMonth
- } from 'element-ui/src/utils/date-util';
- import Clickoutside from 'element-ui/src/utils/clickoutside';
- import Locale from 'element-ui/src/mixins/locale';
- import MonthTable from '../basic/month-table';
- import ElInput from 'element-ui/packages/input';
- import ElButton from 'element-ui/packages/button';
- const calcDefaultValue = (defaultValue) => {
- if (Array.isArray(defaultValue)) {
- return [new Date(defaultValue[0]), new Date(defaultValue[1])];
- } else if (defaultValue) {
- return [new Date(defaultValue), nextMonth(new Date(defaultValue))];
- } else {
- return [new Date(), nextMonth(new Date())];
- }
- };
- export default {
- mixins: [Locale],
- directives: { Clickoutside },
- computed: {
- btnDisabled() {
- return !(this.minDate && this.maxDate && !this.selecting && this.isValidValue([this.minDate, this.maxDate]));
- },
- leftLabel() {
- return this.leftDate.getFullYear() + ' ' + this.t('el.datepicker.year');
- },
- rightLabel() {
- return this.rightDate.getFullYear() + ' ' + this.t('el.datepicker.year');
- },
- leftYear() {
- return this.leftDate.getFullYear();
- },
- rightYear() {
- return this.rightDate.getFullYear() === this.leftDate.getFullYear() ? this.leftDate.getFullYear() + 1 : this.rightDate.getFullYear();
- },
- enableYearArrow() {
- return this.unlinkPanels && this.rightYear > this.leftYear + 1;
- }
- },
- data() {
- return {
- popperClass: '',
- value: [],
- defaultValue: null,
- defaultTime: null,
- minDate: '',
- maxDate: '',
- leftDate: new Date(),
- rightDate: nextYear(new Date()),
- rangeState: {
- endDate: null,
- selecting: false,
- row: null,
- column: null
- },
- shortcuts: '',
- visible: '',
- disabledDate: '',
- format: '',
- arrowControl: false,
- unlinkPanels: false
- };
- },
- watch: {
- value(newVal) {
- if (!newVal) {
- this.minDate = null;
- this.maxDate = null;
- } else if (Array.isArray(newVal)) {
- this.minDate = isDate(newVal[0]) ? new Date(newVal[0]) : null;
- this.maxDate = isDate(newVal[1]) ? new Date(newVal[1]) : null;
- if (this.minDate) {
- this.leftDate = this.minDate;
- if (this.unlinkPanels && this.maxDate) {
- const minDateYear = this.minDate.getFullYear();
- const maxDateYear = this.maxDate.getFullYear();
- this.rightDate = minDateYear === maxDateYear
- ? nextYear(this.maxDate)
- : this.maxDate;
- } else {
- this.rightDate = nextYear(this.leftDate);
- }
- } else {
- this.leftDate = calcDefaultValue(this.defaultValue)[0];
- this.rightDate = nextYear(this.leftDate);
- }
- }
- },
- defaultValue(val) {
- if (!Array.isArray(this.value)) {
- const [left, right] = calcDefaultValue(val);
- this.leftDate = left;
- this.rightDate = val && val[1] && left.getFullYear() !== right.getFullYear() && this.unlinkPanels
- ? right
- : nextYear(this.leftDate);
- }
- }
- },
- methods: {
- handleClear() {
- this.minDate = null;
- this.maxDate = null;
- this.leftDate = calcDefaultValue(this.defaultValue)[0];
- this.rightDate = nextYear(this.leftDate);
- this.$emit('pick', null);
- },
- handleChangeRange(val) {
- this.minDate = val.minDate;
- this.maxDate = val.maxDate;
- this.rangeState = val.rangeState;
- },
- handleRangePick(val, close = true) {
- const defaultTime = this.defaultTime || [];
- const minDate = modifyWithTimeString(val.minDate, defaultTime[0]);
- const maxDate = modifyWithTimeString(val.maxDate, defaultTime[1]);
- if (this.maxDate === maxDate && this.minDate === minDate) {
- return;
- }
- this.onPick && this.onPick(val);
- this.maxDate = maxDate;
- this.minDate = minDate;
- // workaround for https://github.com/ElemeFE/element/issues/7539, should remove this block when we don't have to care about Chromium 55 - 57
- setTimeout(() => {
- this.maxDate = maxDate;
- this.minDate = minDate;
- }, 10);
- if (!close) return;
- this.handleConfirm();
- },
- handleShortcutClick(shortcut) {
- if (shortcut.onClick) {
- shortcut.onClick(this);
- }
- },
- // leftPrev*, rightNext* need to take care of `unlinkPanels`
- leftPrevYear() {
- this.leftDate = prevYear(this.leftDate);
- if (!this.unlinkPanels) {
- this.rightDate = prevYear(this.rightDate);
- }
- },
- rightNextYear() {
- if (!this.unlinkPanels) {
- this.leftDate = nextYear(this.leftDate);
- }
- this.rightDate = nextYear(this.rightDate);
- },
- // leftNext*, rightPrev* are called when `unlinkPanels` is true
- leftNextYear() {
- this.leftDate = nextYear(this.leftDate);
- },
- rightPrevYear() {
- this.rightDate = prevYear(this.rightDate);
- },
- handleConfirm(visible = false) {
- if (this.isValidValue([this.minDate, this.maxDate])) {
- this.$emit('pick', [this.minDate, this.maxDate], visible);
- }
- },
- isValidValue(value) {
- return Array.isArray(value) &&
- value && value[0] && value[1] &&
- isDate(value[0]) && isDate(value[1]) &&
- value[0].getTime() <= value[1].getTime() && (
- typeof this.disabledDate === 'function'
- ? !this.disabledDate(value[0]) && !this.disabledDate(value[1])
- : true
- );
- },
- resetView() {
- // NOTE: this is a hack to reset {min, max}Date on picker open.
- // TODO: correct way of doing so is to refactor {min, max}Date to be dependent on value and internal selection state
- // an alternative would be resetView whenever picker becomes visible, should also investigate date-panel's resetView
- this.minDate = this.value && isDate(this.value[0]) ? new Date(this.value[0]) : null;
- this.maxDate = this.value && isDate(this.value[0]) ? new Date(this.value[1]) : null;
- }
- },
- components: { MonthTable, ElInput, ElButton }
- };
- </script>
|