8fc64e9285a881dc08a064c14a696dd69d40938a36c8498477163b1eb9444c81b6ee8d9ea10c67d6abfb9119bde9bff7cde5140c066f987d78927f111e1889 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. <template>
  2. <transition name="el-zoom-in-top" @after-leave="$emit('dodestroy')">
  3. <div
  4. v-show="visible"
  5. class="el-picker-panel el-date-range-picker el-popper"
  6. :class="[{
  7. 'has-sidebar': $slots.sidebar || shortcuts,
  8. 'has-time': showTime
  9. }, popperClass]">
  10. <div class="el-picker-panel__body-wrapper">
  11. <slot name="sidebar" class="el-picker-panel__sidebar"></slot>
  12. <div class="el-picker-panel__sidebar" v-if="shortcuts">
  13. <button
  14. type="button"
  15. class="el-picker-panel__shortcut"
  16. v-for="(shortcut, key) in shortcuts"
  17. :key="key"
  18. @click="handleShortcutClick(shortcut)">{{shortcut.text}}</button>
  19. </div>
  20. <div class="el-picker-panel__body">
  21. <div class="el-date-range-picker__time-header" v-if="showTime">
  22. <span class="el-date-range-picker__editors-wrap">
  23. <span class="el-date-range-picker__time-picker-wrap">
  24. <el-input
  25. size="small"
  26. :disabled="rangeState.selecting"
  27. ref="minInput"
  28. :placeholder="t('el.datepicker.startDate')"
  29. class="el-date-range-picker__editor"
  30. :value="minVisibleDate"
  31. @input="val => handleDateInput(val, 'min')"
  32. @change="val => handleDateChange(val, 'min')" />
  33. </span>
  34. <span class="el-date-range-picker__time-picker-wrap" v-clickoutside="handleMinTimeClose">
  35. <el-input
  36. size="small"
  37. class="el-date-range-picker__editor"
  38. :disabled="rangeState.selecting"
  39. :placeholder="t('el.datepicker.startTime')"
  40. :value="minVisibleTime"
  41. @focus="minTimePickerVisible = true"
  42. @input="val => handleTimeInput(val, 'min')"
  43. @change="val => handleTimeChange(val, 'min')" />
  44. <time-picker
  45. ref="minTimePicker"
  46. @pick="handleMinTimePick"
  47. :time-arrow-control="arrowControl"
  48. :visible="minTimePickerVisible"
  49. @mounted="$refs.minTimePicker.format=timeFormat">
  50. </time-picker>
  51. </span>
  52. </span>
  53. <span class="el-icon-arrow-right"></span>
  54. <span class="el-date-range-picker__editors-wrap is-right">
  55. <span class="el-date-range-picker__time-picker-wrap">
  56. <el-input
  57. size="small"
  58. class="el-date-range-picker__editor"
  59. :disabled="rangeState.selecting"
  60. :placeholder="t('el.datepicker.endDate')"
  61. :value="maxVisibleDate"
  62. :readonly="!minDate"
  63. @input="val => handleDateInput(val, 'max')"
  64. @change="val => handleDateChange(val, 'max')" />
  65. </span>
  66. <span class="el-date-range-picker__time-picker-wrap" v-clickoutside="handleMaxTimeClose">
  67. <el-input
  68. size="small"
  69. class="el-date-range-picker__editor"
  70. :disabled="rangeState.selecting"
  71. :placeholder="t('el.datepicker.endTime')"
  72. :value="maxVisibleTime"
  73. :readonly="!minDate"
  74. @focus="minDate && (maxTimePickerVisible = true)"
  75. @input="val => handleTimeInput(val, 'max')"
  76. @change="val => handleTimeChange(val, 'max')" />
  77. <time-picker
  78. ref="maxTimePicker"
  79. @pick="handleMaxTimePick"
  80. :time-arrow-control="arrowControl"
  81. :visible="maxTimePickerVisible"
  82. @mounted="$refs.maxTimePicker.format=timeFormat">
  83. </time-picker>
  84. </span>
  85. </span>
  86. </div>
  87. <div class="el-picker-panel__content el-date-range-picker__content is-left">
  88. <div class="el-date-range-picker__header">
  89. <button
  90. type="button"
  91. @click="leftPrevYear"
  92. class="el-picker-panel__icon-btn el-icon-d-arrow-left"></button>
  93. <button
  94. type="button"
  95. @click="leftPrevMonth"
  96. class="el-picker-panel__icon-btn el-icon-arrow-left"></button>
  97. <button
  98. type="button"
  99. @click="leftNextYear"
  100. v-if="unlinkPanels"
  101. :disabled="!enableYearArrow"
  102. :class="{ 'is-disabled': !enableYearArrow }"
  103. class="el-picker-panel__icon-btn el-icon-d-arrow-right"></button>
  104. <button
  105. type="button"
  106. @click="leftNextMonth"
  107. v-if="unlinkPanels"
  108. :disabled="!enableMonthArrow"
  109. :class="{ 'is-disabled': !enableMonthArrow }"
  110. class="el-picker-panel__icon-btn el-icon-arrow-right"></button>
  111. <div>{{ leftLabel }}</div>
  112. </div>
  113. <date-table
  114. selection-mode="range"
  115. :date="leftDate"
  116. :default-value="defaultValue"
  117. :min-date="minDate"
  118. :max-date="maxDate"
  119. :range-state="rangeState"
  120. :disabled-date="disabledDate"
  121. :cell-class-name="cellClassName"
  122. @changerange="handleChangeRange"
  123. :first-day-of-week="firstDayOfWeek"
  124. @pick="handleRangePick">
  125. </date-table>
  126. </div>
  127. <div class="el-picker-panel__content el-date-range-picker__content is-right">
  128. <div class="el-date-range-picker__header">
  129. <button
  130. type="button"
  131. @click="rightPrevYear"
  132. v-if="unlinkPanels"
  133. :disabled="!enableYearArrow"
  134. :class="{ 'is-disabled': !enableYearArrow }"
  135. class="el-picker-panel__icon-btn el-icon-d-arrow-left"></button>
  136. <button
  137. type="button"
  138. @click="rightPrevMonth"
  139. v-if="unlinkPanels"
  140. :disabled="!enableMonthArrow"
  141. :class="{ 'is-disabled': !enableMonthArrow }"
  142. class="el-picker-panel__icon-btn el-icon-arrow-left"></button>
  143. <button
  144. type="button"
  145. @click="rightNextYear"
  146. class="el-picker-panel__icon-btn el-icon-d-arrow-right"></button>
  147. <button
  148. type="button"
  149. @click="rightNextMonth"
  150. class="el-picker-panel__icon-btn el-icon-arrow-right"></button>
  151. <div>{{ rightLabel }}</div>
  152. </div>
  153. <date-table
  154. selection-mode="range"
  155. :date="rightDate"
  156. :default-value="defaultValue"
  157. :min-date="minDate"
  158. :max-date="maxDate"
  159. :range-state="rangeState"
  160. :disabled-date="disabledDate"
  161. :cell-class-name="cellClassName"
  162. @changerange="handleChangeRange"
  163. :first-day-of-week="firstDayOfWeek"
  164. @pick="handleRangePick">
  165. </date-table>
  166. </div>
  167. </div>
  168. </div>
  169. <div class="el-picker-panel__footer" v-if="showTime">
  170. <el-button
  171. size="mini"
  172. type="text"
  173. class="el-picker-panel__link-btn"
  174. @click="handleClear">
  175. {{ t('el.datepicker.clear') }}
  176. </el-button>
  177. <el-button
  178. plain
  179. size="mini"
  180. class="el-picker-panel__link-btn"
  181. :disabled="btnDisabled"
  182. @click="handleConfirm(false)">
  183. {{ t('el.datepicker.confirm') }}
  184. </el-button>
  185. </div>
  186. </div>
  187. </transition>
  188. </template>
  189. <script type="text/babel">
  190. import {
  191. formatDate,
  192. parseDate,
  193. isDate,
  194. modifyDate,
  195. modifyTime,
  196. modifyWithTimeString,
  197. prevYear,
  198. nextYear,
  199. prevMonth,
  200. nextMonth,
  201. nextDate,
  202. extractDateFormat,
  203. extractTimeFormat
  204. } from 'element-ui/src/utils/date-util';
  205. import Clickoutside from 'element-ui/src/utils/clickoutside';
  206. import Locale from 'element-ui/src/mixins/locale';
  207. import TimePicker from './time';
  208. import DateTable from '../basic/date-table';
  209. import ElInput from 'element-ui/packages/input';
  210. import ElButton from 'element-ui/packages/button';
  211. const calcDefaultValue = (defaultValue) => {
  212. if (Array.isArray(defaultValue)) {
  213. return [new Date(defaultValue[0]), new Date(defaultValue[1])];
  214. } else if (defaultValue) {
  215. return [new Date(defaultValue), nextDate(new Date(defaultValue), 1)];
  216. } else {
  217. return [new Date(), nextDate(new Date(), 1)];
  218. }
  219. };
  220. export default {
  221. mixins: [Locale],
  222. directives: { Clickoutside },
  223. computed: {
  224. btnDisabled() {
  225. return !(this.minDate && this.maxDate && !this.selecting && this.isValidValue([this.minDate, this.maxDate]));
  226. },
  227. leftLabel() {
  228. return this.leftDate.getFullYear() + ' ' + this.t('el.datepicker.year') + ' ' + this.t(`el.datepicker.month${ this.leftDate.getMonth() + 1 }`);
  229. },
  230. rightLabel() {
  231. return this.rightDate.getFullYear() + ' ' + this.t('el.datepicker.year') + ' ' + this.t(`el.datepicker.month${ this.rightDate.getMonth() + 1 }`);
  232. },
  233. leftYear() {
  234. return this.leftDate.getFullYear();
  235. },
  236. leftMonth() {
  237. return this.leftDate.getMonth();
  238. },
  239. leftMonthDate() {
  240. return this.leftDate.getDate();
  241. },
  242. rightYear() {
  243. return this.rightDate.getFullYear();
  244. },
  245. rightMonth() {
  246. return this.rightDate.getMonth();
  247. },
  248. rightMonthDate() {
  249. return this.rightDate.getDate();
  250. },
  251. minVisibleDate() {
  252. if (this.dateUserInput.min !== null) return this.dateUserInput.min;
  253. if (this.minDate) return formatDate(this.minDate, this.dateFormat);
  254. return '';
  255. },
  256. maxVisibleDate() {
  257. if (this.dateUserInput.max !== null) return this.dateUserInput.max;
  258. if (this.maxDate || this.minDate) return formatDate(this.maxDate || this.minDate, this.dateFormat);
  259. return '';
  260. },
  261. minVisibleTime() {
  262. if (this.timeUserInput.min !== null) return this.timeUserInput.min;
  263. if (this.minDate) return formatDate(this.minDate, this.timeFormat);
  264. return '';
  265. },
  266. maxVisibleTime() {
  267. if (this.timeUserInput.max !== null) return this.timeUserInput.max;
  268. if (this.maxDate || this.minDate) return formatDate(this.maxDate || this.minDate, this.timeFormat);
  269. return '';
  270. },
  271. timeFormat() {
  272. if (this.format) {
  273. return extractTimeFormat(this.format);
  274. } else {
  275. return 'HH:mm:ss';
  276. }
  277. },
  278. dateFormat() {
  279. if (this.format) {
  280. return extractDateFormat(this.format);
  281. } else {
  282. return 'yyyy-MM-dd';
  283. }
  284. },
  285. enableMonthArrow() {
  286. const nextMonth = (this.leftMonth + 1) % 12;
  287. const yearOffset = this.leftMonth + 1 >= 12 ? 1 : 0;
  288. return this.unlinkPanels && new Date(this.leftYear + yearOffset, nextMonth) < new Date(this.rightYear, this.rightMonth);
  289. },
  290. enableYearArrow() {
  291. return this.unlinkPanels && this.rightYear * 12 + this.rightMonth - (this.leftYear * 12 + this.leftMonth + 1) >= 12;
  292. }
  293. },
  294. data() {
  295. return {
  296. popperClass: '',
  297. value: [],
  298. defaultValue: null,
  299. defaultTime: null,
  300. minDate: '',
  301. maxDate: '',
  302. leftDate: new Date(),
  303. rightDate: nextMonth(new Date()),
  304. rangeState: {
  305. endDate: null,
  306. selecting: false,
  307. row: null,
  308. column: null
  309. },
  310. showTime: false,
  311. shortcuts: '',
  312. visible: '',
  313. disabledDate: '',
  314. cellClassName: '',
  315. firstDayOfWeek: 7,
  316. minTimePickerVisible: false,
  317. maxTimePickerVisible: false,
  318. format: '',
  319. arrowControl: false,
  320. unlinkPanels: false,
  321. dateUserInput: {
  322. min: null,
  323. max: null
  324. },
  325. timeUserInput: {
  326. min: null,
  327. max: null
  328. }
  329. };
  330. },
  331. watch: {
  332. minDate(val) {
  333. this.dateUserInput.min = null;
  334. this.timeUserInput.min = null;
  335. this.$nextTick(() => {
  336. if (this.$refs.maxTimePicker && this.maxDate && this.maxDate < this.minDate) {
  337. const format = 'HH:mm:ss';
  338. this.$refs.maxTimePicker.selectableRange = [
  339. [
  340. parseDate(formatDate(this.minDate, format), format),
  341. parseDate('23:59:59', format)
  342. ]
  343. ];
  344. }
  345. });
  346. if (val && this.$refs.minTimePicker) {
  347. this.$refs.minTimePicker.date = val;
  348. this.$refs.minTimePicker.value = val;
  349. }
  350. },
  351. maxDate(val) {
  352. this.dateUserInput.max = null;
  353. this.timeUserInput.max = null;
  354. if (val && this.$refs.maxTimePicker) {
  355. this.$refs.maxTimePicker.date = val;
  356. this.$refs.maxTimePicker.value = val;
  357. }
  358. },
  359. minTimePickerVisible(val) {
  360. if (val) {
  361. this.$nextTick(() => {
  362. this.$refs.minTimePicker.date = this.minDate;
  363. this.$refs.minTimePicker.value = this.minDate;
  364. this.$refs.minTimePicker.adjustSpinners();
  365. });
  366. }
  367. },
  368. maxTimePickerVisible(val) {
  369. if (val) {
  370. this.$nextTick(() => {
  371. this.$refs.maxTimePicker.date = this.maxDate;
  372. this.$refs.maxTimePicker.value = this.maxDate;
  373. this.$refs.maxTimePicker.adjustSpinners();
  374. });
  375. }
  376. },
  377. value(newVal) {
  378. if (!newVal) {
  379. this.minDate = null;
  380. this.maxDate = null;
  381. } else if (Array.isArray(newVal)) {
  382. this.minDate = isDate(newVal[0]) ? new Date(newVal[0]) : null;
  383. this.maxDate = isDate(newVal[1]) ? new Date(newVal[1]) : null;
  384. if (this.minDate) {
  385. this.leftDate = this.minDate;
  386. if (this.unlinkPanels && this.maxDate) {
  387. const minDateYear = this.minDate.getFullYear();
  388. const minDateMonth = this.minDate.getMonth();
  389. const maxDateYear = this.maxDate.getFullYear();
  390. const maxDateMonth = this.maxDate.getMonth();
  391. this.rightDate = minDateYear === maxDateYear && minDateMonth === maxDateMonth
  392. ? nextMonth(this.maxDate)
  393. : this.maxDate;
  394. } else {
  395. this.rightDate = nextMonth(this.leftDate);
  396. }
  397. } else {
  398. this.leftDate = calcDefaultValue(this.defaultValue)[0];
  399. this.rightDate = nextMonth(this.leftDate);
  400. }
  401. }
  402. },
  403. defaultValue(val) {
  404. if (!Array.isArray(this.value)) {
  405. const [left, right] = calcDefaultValue(val);
  406. this.leftDate = left;
  407. this.rightDate = val && val[1] && this.unlinkPanels
  408. ? right
  409. : nextMonth(this.leftDate);
  410. }
  411. }
  412. },
  413. methods: {
  414. handleClear() {
  415. this.minDate = null;
  416. this.maxDate = null;
  417. this.leftDate = calcDefaultValue(this.defaultValue)[0];
  418. this.rightDate = nextMonth(this.leftDate);
  419. this.$emit('pick', null);
  420. },
  421. handleChangeRange(val) {
  422. this.minDate = val.minDate;
  423. this.maxDate = val.maxDate;
  424. this.rangeState = val.rangeState;
  425. },
  426. handleDateInput(value, type) {
  427. this.dateUserInput[type] = value;
  428. if (value.length !== this.dateFormat.length) return;
  429. const parsedValue = parseDate(value, this.dateFormat);
  430. if (parsedValue) {
  431. if (typeof this.disabledDate === 'function' &&
  432. this.disabledDate(new Date(parsedValue))) {
  433. return;
  434. }
  435. if (type === 'min') {
  436. this.minDate = modifyDate(this.minDate || new Date(), parsedValue.getFullYear(), parsedValue.getMonth(), parsedValue.getDate());
  437. this.leftDate = new Date(parsedValue);
  438. if (!this.unlinkPanels) {
  439. this.rightDate = nextMonth(this.leftDate);
  440. }
  441. } else {
  442. this.maxDate = modifyDate(this.maxDate || new Date(), parsedValue.getFullYear(), parsedValue.getMonth(), parsedValue.getDate());
  443. this.rightDate = new Date(parsedValue);
  444. if (!this.unlinkPanels) {
  445. this.leftDate = prevMonth(parsedValue);
  446. }
  447. }
  448. }
  449. },
  450. handleDateChange(value, type) {
  451. const parsedValue = parseDate(value, this.dateFormat);
  452. if (parsedValue) {
  453. if (type === 'min') {
  454. this.minDate = modifyDate(this.minDate, parsedValue.getFullYear(), parsedValue.getMonth(), parsedValue.getDate());
  455. if (this.minDate > this.maxDate) {
  456. this.maxDate = this.minDate;
  457. }
  458. } else {
  459. this.maxDate = modifyDate(this.maxDate, parsedValue.getFullYear(), parsedValue.getMonth(), parsedValue.getDate());
  460. if (this.maxDate < this.minDate) {
  461. this.minDate = this.maxDate;
  462. }
  463. }
  464. }
  465. },
  466. handleTimeInput(value, type) {
  467. this.timeUserInput[type] = value;
  468. if (value.length !== this.timeFormat.length) return;
  469. const parsedValue = parseDate(value, this.timeFormat);
  470. if (parsedValue) {
  471. if (type === 'min') {
  472. this.minDate = modifyTime(this.minDate, parsedValue.getHours(), parsedValue.getMinutes(), parsedValue.getSeconds());
  473. this.$nextTick(_ => this.$refs.minTimePicker.adjustSpinners());
  474. } else {
  475. this.maxDate = modifyTime(this.maxDate, parsedValue.getHours(), parsedValue.getMinutes(), parsedValue.getSeconds());
  476. this.$nextTick(_ => this.$refs.maxTimePicker.adjustSpinners());
  477. }
  478. }
  479. },
  480. handleTimeChange(value, type) {
  481. const parsedValue = parseDate(value, this.timeFormat);
  482. if (parsedValue) {
  483. if (type === 'min') {
  484. this.minDate = modifyTime(this.minDate, parsedValue.getHours(), parsedValue.getMinutes(), parsedValue.getSeconds());
  485. if (this.minDate > this.maxDate) {
  486. this.maxDate = this.minDate;
  487. }
  488. this.$refs.minTimePicker.value = this.minDate;
  489. this.minTimePickerVisible = false;
  490. } else {
  491. this.maxDate = modifyTime(this.maxDate, parsedValue.getHours(), parsedValue.getMinutes(), parsedValue.getSeconds());
  492. if (this.maxDate < this.minDate) {
  493. this.minDate = this.maxDate;
  494. }
  495. this.$refs.maxTimePicker.value = this.minDate;
  496. this.maxTimePickerVisible = false;
  497. }
  498. }
  499. },
  500. handleRangePick(val, close = true) {
  501. const defaultTime = this.defaultTime || [];
  502. const minDate = modifyWithTimeString(val.minDate, defaultTime[0]);
  503. const maxDate = modifyWithTimeString(val.maxDate, defaultTime[1]);
  504. if (this.maxDate === maxDate && this.minDate === minDate) {
  505. return;
  506. }
  507. this.onPick && this.onPick(val);
  508. this.maxDate = maxDate;
  509. this.minDate = minDate;
  510. // workaround for https://github.com/ElemeFE/element/issues/7539, should remove this block when we don't have to care about Chromium 55 - 57
  511. setTimeout(() => {
  512. this.maxDate = maxDate;
  513. this.minDate = minDate;
  514. }, 10);
  515. if (!close || this.showTime) return;
  516. this.handleConfirm();
  517. },
  518. handleShortcutClick(shortcut) {
  519. if (shortcut.onClick) {
  520. shortcut.onClick(this);
  521. }
  522. },
  523. handleMinTimePick(value, visible, first) {
  524. this.minDate = this.minDate || new Date();
  525. if (value) {
  526. this.minDate = modifyTime(this.minDate, value.getHours(), value.getMinutes(), value.getSeconds());
  527. }
  528. if (!first) {
  529. this.minTimePickerVisible = visible;
  530. }
  531. if (!this.maxDate || this.maxDate && this.maxDate.getTime() < this.minDate.getTime()) {
  532. this.maxDate = new Date(this.minDate);
  533. }
  534. },
  535. handleMinTimeClose() {
  536. this.minTimePickerVisible = false;
  537. },
  538. handleMaxTimePick(value, visible, first) {
  539. if (this.maxDate && value) {
  540. this.maxDate = modifyTime(this.maxDate, value.getHours(), value.getMinutes(), value.getSeconds());
  541. }
  542. if (!first) {
  543. this.maxTimePickerVisible = visible;
  544. }
  545. if (this.maxDate && this.minDate && this.minDate.getTime() > this.maxDate.getTime()) {
  546. this.minDate = new Date(this.maxDate);
  547. }
  548. },
  549. handleMaxTimeClose() {
  550. this.maxTimePickerVisible = false;
  551. },
  552. // leftPrev*, rightNext* need to take care of `unlinkPanels`
  553. leftPrevYear() {
  554. this.leftDate = prevYear(this.leftDate);
  555. if (!this.unlinkPanels) {
  556. this.rightDate = nextMonth(this.leftDate);
  557. }
  558. },
  559. leftPrevMonth() {
  560. this.leftDate = prevMonth(this.leftDate);
  561. if (!this.unlinkPanels) {
  562. this.rightDate = nextMonth(this.leftDate);
  563. }
  564. },
  565. rightNextYear() {
  566. if (!this.unlinkPanels) {
  567. this.leftDate = nextYear(this.leftDate);
  568. this.rightDate = nextMonth(this.leftDate);
  569. } else {
  570. this.rightDate = nextYear(this.rightDate);
  571. }
  572. },
  573. rightNextMonth() {
  574. if (!this.unlinkPanels) {
  575. this.leftDate = nextMonth(this.leftDate);
  576. this.rightDate = nextMonth(this.leftDate);
  577. } else {
  578. this.rightDate = nextMonth(this.rightDate);
  579. }
  580. },
  581. // leftNext*, rightPrev* are called when `unlinkPanels` is true
  582. leftNextYear() {
  583. this.leftDate = nextYear(this.leftDate);
  584. },
  585. leftNextMonth() {
  586. this.leftDate = nextMonth(this.leftDate);
  587. },
  588. rightPrevYear() {
  589. this.rightDate = prevYear(this.rightDate);
  590. },
  591. rightPrevMonth() {
  592. this.rightDate = prevMonth(this.rightDate);
  593. },
  594. handleConfirm(visible = false) {
  595. if (this.isValidValue([this.minDate, this.maxDate])) {
  596. this.$emit('pick', [this.minDate, this.maxDate], visible);
  597. }
  598. },
  599. isValidValue(value) {
  600. return Array.isArray(value) &&
  601. value && value[0] && value[1] &&
  602. isDate(value[0]) && isDate(value[1]) &&
  603. value[0].getTime() <= value[1].getTime() && (
  604. typeof this.disabledDate === 'function'
  605. ? !this.disabledDate(value[0]) && !this.disabledDate(value[1])
  606. : true
  607. );
  608. },
  609. resetView() {
  610. // NOTE: this is a hack to reset {min, max}Date on picker open.
  611. // TODO: correct way of doing so is to refactor {min, max}Date to be dependent on value and internal selection state
  612. // an alternative would be resetView whenever picker becomes visible, should also investigate date-panel's resetView
  613. if (this.minDate && this.maxDate == null) this.rangeState.selecting = false;
  614. this.minDate = this.value && isDate(this.value[0]) ? new Date(this.value[0]) : null;
  615. this.maxDate = this.value && isDate(this.value[0]) ? new Date(this.value[1]) : null;
  616. }
  617. },
  618. components: { TimePicker, DateTable, ElInput, ElButton }
  619. };
  620. </script>